From f29c8aeb806ad7ae4c019b039f653986e7d31989 Mon Sep 17 00:00:00 2001 From: Karthik Pullela Date: Sat, 20 Jan 2018 13:54:35 -0800 Subject: [PATCH] Got Http requests working. --- flex/bin/chardetect | 11 + flex/bin/flask | 11 + .../home/__pycache__/views.cpython-36.pyc | Bin 371 -> 473 bytes flex/flex/home/templates/home/home.html | 2 + flex/flex/home/views.py | 6 +- .../Flask-0.12.2.dist-info/DESCRIPTION.rst | 46 + .../Flask-0.12.2.dist-info/INSTALLER | 1 + .../Flask-0.12.2.dist-info/LICENSE.txt | 33 + .../Flask-0.12.2.dist-info/METADATA | 75 + .../Flask-0.12.2.dist-info/RECORD | 52 + .../Flask-0.12.2.dist-info/WHEEL | 6 + .../Flask-0.12.2.dist-info/entry_points.txt | 4 + .../Flask-0.12.2.dist-info/metadata.json | 1 + .../Flask-0.12.2.dist-info/top_level.txt | 1 + .../Jinja2-2.10.dist-info/DESCRIPTION.rst | 37 + .../Jinja2-2.10.dist-info/INSTALLER | 1 + .../Jinja2-2.10.dist-info/LICENSE.txt | 31 + .../Jinja2-2.10.dist-info/METADATA | 68 + .../Jinja2-2.10.dist-info/RECORD | 63 + .../site-packages/Jinja2-2.10.dist-info/WHEEL | 6 + .../Jinja2-2.10.dist-info/entry_points.txt | 4 + .../Jinja2-2.10.dist-info/metadata.json | 1 + .../Jinja2-2.10.dist-info/top_level.txt | 1 + .../MarkupSafe-1.0.dist-info/DESCRIPTION.rst | 115 + .../MarkupSafe-1.0.dist-info/INSTALLER | 1 + .../MarkupSafe-1.0.dist-info/LICENSE.txt | 33 + .../MarkupSafe-1.0.dist-info/METADATA | 135 + .../MarkupSafe-1.0.dist-info/RECORD | 18 + .../MarkupSafe-1.0.dist-info/WHEEL | 5 + .../MarkupSafe-1.0.dist-info/metadata.json | 1 + .../MarkupSafe-1.0.dist-info/top_level.txt | 1 + .../Werkzeug-0.14.1.dist-info/DESCRIPTION.rst | 80 + .../Werkzeug-0.14.1.dist-info/INSTALLER | 1 + .../Werkzeug-0.14.1.dist-info/LICENSE.txt | 31 + .../Werkzeug-0.14.1.dist-info/METADATA | 116 + .../Werkzeug-0.14.1.dist-info/RECORD | 97 + .../Werkzeug-0.14.1.dist-info/WHEEL | 6 + .../Werkzeug-0.14.1.dist-info/metadata.json | 1 + .../Werkzeug-0.14.1.dist-info/top_level.txt | 1 + .../__pycache__/itsdangerous.cpython-36.pyc | Bin 0 -> 29356 bytes .../DESCRIPTION.rst | 48 + .../certifi-2018.1.18.dist-info/INSTALLER | 1 + .../certifi-2018.1.18.dist-info/LICENSE.txt | 21 + .../certifi-2018.1.18.dist-info/METADATA | 71 + .../certifi-2018.1.18.dist-info/RECORD | 15 + .../certifi-2018.1.18.dist-info/WHEEL | 6 + .../certifi-2018.1.18.dist-info/metadata.json | 1 + .../certifi-2018.1.18.dist-info/top_level.txt | 1 + .../site-packages/certifi/__init__.py | 3 + .../site-packages/certifi/__main__.py | 2 + .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 271 bytes .../__pycache__/__main__.cpython-36.pyc | Bin 0 -> 242 bytes .../certifi/__pycache__/core.cpython-36.pyc | Bin 0 -> 1206 bytes .../site-packages/certifi/cacert.pem | 4433 ++++++++++ .../python3.6/site-packages/certifi/core.py | 37 + .../chardet-3.0.4.dist-info/DESCRIPTION.rst | 70 + .../chardet-3.0.4.dist-info/INSTALLER | 1 + .../chardet-3.0.4.dist-info/METADATA | 96 + .../chardet-3.0.4.dist-info/RECORD | 91 + .../chardet-3.0.4.dist-info/WHEEL | 6 + .../chardet-3.0.4.dist-info/entry_points.txt | 3 + .../chardet-3.0.4.dist-info/metadata.json | 1 + .../chardet-3.0.4.dist-info/top_level.txt | 1 + .../site-packages/chardet/__init__.py | 39 + .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 838 bytes .../__pycache__/big5freq.cpython-36.pyc | Bin 0 -> 54725 bytes .../__pycache__/big5prober.cpython-36.pyc | Bin 0 -> 1114 bytes .../chardistribution.cpython-36.pyc | Bin 0 -> 6310 bytes .../charsetgroupprober.cpython-36.pyc | Bin 0 -> 2221 bytes .../__pycache__/charsetprober.cpython-36.pyc | Bin 0 -> 3447 bytes .../codingstatemachine.cpython-36.pyc | Bin 0 -> 2878 bytes .../chardet/__pycache__/compat.cpython-36.pyc | Bin 0 -> 354 bytes .../__pycache__/cp949prober.cpython-36.pyc | Bin 0 -> 1121 bytes .../chardet/__pycache__/enums.cpython-36.pyc | Bin 0 -> 2612 bytes .../__pycache__/escprober.cpython-36.pyc | Bin 0 -> 2603 bytes .../chardet/__pycache__/escsm.cpython-36.pyc | Bin 0 -> 7360 bytes .../__pycache__/eucjpprober.cpython-36.pyc | Bin 0 -> 2407 bytes .../__pycache__/euckrfreq.cpython-36.pyc | Bin 0 -> 24111 bytes .../__pycache__/euckrprober.cpython-36.pyc | Bin 0 -> 1122 bytes .../__pycache__/euctwfreq.cpython-36.pyc | Bin 0 -> 54734 bytes .../__pycache__/euctwprober.cpython-36.pyc | Bin 0 -> 1122 bytes .../__pycache__/gb2312freq.cpython-36.pyc | Bin 0 -> 38376 bytes .../__pycache__/gb2312prober.cpython-36.pyc | Bin 0 -> 1130 bytes .../__pycache__/hebrewprober.cpython-36.pyc | Bin 0 -> 2964 bytes .../__pycache__/jisfreq.cpython-36.pyc | Bin 0 -> 44520 bytes .../chardet/__pycache__/jpcntx.cpython-36.pyc | Bin 0 -> 38659 bytes .../langbulgarianmodel.cpython-36.pyc | Bin 0 -> 24874 bytes .../langcyrillicmodel.cpython-36.pyc | Bin 0 -> 30425 bytes .../__pycache__/langgreekmodel.cpython-36.pyc | Bin 0 -> 24552 bytes .../langhebrewmodel.cpython-36.pyc | Bin 0 -> 23406 bytes .../langhungarianmodel.cpython-36.pyc | Bin 0 -> 24848 bytes .../__pycache__/langthaimodel.cpython-36.pyc | Bin 0 -> 23385 bytes .../langturkishmodel.cpython-36.pyc | Bin 0 -> 23403 bytes .../__pycache__/latin1prober.cpython-36.pyc | Bin 0 -> 2935 bytes .../mbcharsetprober.cpython-36.pyc | Bin 0 -> 2226 bytes .../mbcsgroupprober.cpython-36.pyc | Bin 0 -> 1117 bytes .../chardet/__pycache__/mbcssm.cpython-36.pyc | Bin 0 -> 17570 bytes .../sbcharsetprober.cpython-36.pyc | Bin 0 -> 2979 bytes .../sbcsgroupprober.cpython-36.pyc | Bin 0 -> 1607 bytes .../__pycache__/sjisprober.cpython-36.pyc | Bin 0 -> 2433 bytes .../universaldetector.cpython-36.pyc | Bin 0 -> 5828 bytes .../__pycache__/utf8prober.cpython-36.pyc | Bin 0 -> 1964 bytes .../__pycache__/version.cpython-36.pyc | Bin 0 -> 433 bytes .../site-packages/chardet/big5freq.py | 386 + .../site-packages/chardet/big5prober.py | 47 + .../site-packages/chardet/chardistribution.py | 233 + .../chardet/charsetgroupprober.py | 106 + .../site-packages/chardet/charsetprober.py | 145 + .../site-packages/chardet/cli/__init__.py | 1 + .../cli/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 190 bytes .../cli/__pycache__/chardetect.cpython-36.pyc | Bin 0 -> 2661 bytes .../site-packages/chardet/cli/chardetect.py | 85 + .../chardet/codingstatemachine.py | 88 + .../python3.6/site-packages/chardet/compat.py | 34 + .../site-packages/chardet/cp949prober.py | 49 + .../python3.6/site-packages/chardet/enums.py | 76 + .../site-packages/chardet/escprober.py | 101 + .../python3.6/site-packages/chardet/escsm.py | 246 + .../site-packages/chardet/eucjpprober.py | 92 + .../site-packages/chardet/euckrfreq.py | 195 + .../site-packages/chardet/euckrprober.py | 47 + .../site-packages/chardet/euctwfreq.py | 387 + .../site-packages/chardet/euctwprober.py | 46 + .../site-packages/chardet/gb2312freq.py | 283 + .../site-packages/chardet/gb2312prober.py | 46 + .../site-packages/chardet/hebrewprober.py | 292 + .../site-packages/chardet/jisfreq.py | 325 + .../python3.6/site-packages/chardet/jpcntx.py | 233 + .../chardet/langbulgarianmodel.py | 228 + .../chardet/langcyrillicmodel.py | 333 + .../site-packages/chardet/langgreekmodel.py | 225 + .../site-packages/chardet/langhebrewmodel.py | 200 + .../chardet/langhungarianmodel.py | 225 + .../site-packages/chardet/langthaimodel.py | 199 + .../site-packages/chardet/langturkishmodel.py | 193 + .../site-packages/chardet/latin1prober.py | 145 + .../site-packages/chardet/mbcharsetprober.py | 91 + .../site-packages/chardet/mbcsgroupprober.py | 54 + .../python3.6/site-packages/chardet/mbcssm.py | 572 ++ .../site-packages/chardet/sbcharsetprober.py | 132 + .../site-packages/chardet/sbcsgroupprober.py | 73 + .../site-packages/chardet/sjisprober.py | 92 + .../chardet/universaldetector.py | 286 + .../site-packages/chardet/utf8prober.py | 82 + .../site-packages/chardet/version.py | 9 + .../click-6.7.dist-info/DESCRIPTION.rst | 3 + .../click-6.7.dist-info/INSTALLER | 1 + .../click-6.7.dist-info/METADATA | 16 + .../site-packages/click-6.7.dist-info/RECORD | 41 + .../site-packages/click-6.7.dist-info/WHEEL | 6 + .../click-6.7.dist-info/metadata.json | 1 + .../click-6.7.dist-info/top_level.txt | 1 + .../python3.6/site-packages/click/__init__.py | 98 + .../click/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 2735 bytes .../__pycache__/_bashcomplete.cpython-36.pyc | Bin 0 -> 2387 bytes .../click/__pycache__/_compat.cpython-36.pyc | Bin 0 -> 15448 bytes .../__pycache__/_termui_impl.cpython-36.pyc | Bin 0 -> 12980 bytes .../__pycache__/_textwrap.cpython-36.pyc | Bin 0 -> 1349 bytes .../__pycache__/_unicodefun.cpython-36.pyc | Bin 0 -> 3279 bytes .../__pycache__/_winconsole.cpython-36.pyc | Bin 0 -> 7492 bytes .../click/__pycache__/core.cpython-36.pyc | Bin 0 -> 56584 bytes .../__pycache__/decorators.cpython-36.pyc | Bin 0 -> 11514 bytes .../__pycache__/exceptions.cpython-36.pyc | Bin 0 -> 7746 bytes .../__pycache__/formatting.cpython-36.pyc | Bin 0 -> 8567 bytes .../click/__pycache__/globals.cpython-36.pyc | Bin 0 -> 1897 bytes .../click/__pycache__/parser.cpython-36.pyc | Bin 0 -> 11496 bytes .../click/__pycache__/termui.cpython-36.pyc | Bin 0 -> 18941 bytes .../click/__pycache__/testing.cpython-36.pyc | Bin 0 -> 10256 bytes .../click/__pycache__/types.cpython-36.pyc | Bin 0 -> 17560 bytes .../click/__pycache__/utils.cpython-36.pyc | Bin 0 -> 14119 bytes .../site-packages/click/_bashcomplete.py | 83 + .../python3.6/site-packages/click/_compat.py | 648 ++ .../site-packages/click/_termui_impl.py | 547 ++ .../site-packages/click/_textwrap.py | 38 + .../site-packages/click/_unicodefun.py | 118 + .../site-packages/click/_winconsole.py | 273 + .../lib/python3.6/site-packages/click/core.py | 1744 ++++ .../site-packages/click/decorators.py | 304 + .../site-packages/click/exceptions.py | 201 + .../site-packages/click/formatting.py | 256 + .../python3.6/site-packages/click/globals.py | 48 + .../python3.6/site-packages/click/parser.py | 426 + .../python3.6/site-packages/click/termui.py | 539 ++ .../python3.6/site-packages/click/testing.py | 322 + .../python3.6/site-packages/click/types.py | 550 ++ .../python3.6/site-packages/click/utils.py | 415 + .../en/__pycache__/__init__.cpython-36.pyc | Bin 199 -> 194 bytes .../en/__pycache__/formats.cpython-36.pyc | Bin 829 -> 824 bytes .../python3.6/site-packages/flask/__init__.py | 49 + .../python3.6/site-packages/flask/__main__.py | 15 + .../flask/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 1841 bytes .../flask/__pycache__/__main__.cpython-36.pyc | Bin 0 -> 467 bytes .../flask/__pycache__/_compat.cpython-36.pyc | Bin 0 -> 3163 bytes .../flask/__pycache__/app.cpython-36.pyc | Bin 0 -> 62944 bytes .../__pycache__/blueprints.cpython-36.pyc | Bin 0 -> 19967 bytes .../flask/__pycache__/cli.cpython-36.pyc | Bin 0 -> 15450 bytes .../flask/__pycache__/config.cpython-36.pyc | Bin 0 -> 9991 bytes .../flask/__pycache__/ctx.cpython-36.pyc | Bin 0 -> 12681 bytes .../__pycache__/debughelpers.cpython-36.pyc | Bin 0 -> 6140 bytes .../flask/__pycache__/exthook.cpython-36.pyc | Bin 0 -> 4573 bytes .../flask/__pycache__/globals.cpython-36.pyc | Bin 0 -> 1764 bytes .../flask/__pycache__/helpers.cpython-36.pyc | Bin 0 -> 31277 bytes .../flask/__pycache__/json.cpython-36.pyc | Bin 0 -> 9227 bytes .../flask/__pycache__/logging.cpython-36.pyc | Bin 0 -> 3391 bytes .../flask/__pycache__/sessions.cpython-36.pyc | Bin 0 -> 12777 bytes .../flask/__pycache__/signals.cpython-36.pyc | Bin 0 -> 2428 bytes .../__pycache__/templating.cpython-36.pyc | Bin 0 -> 4977 bytes .../flask/__pycache__/testing.cpython-36.pyc | Bin 0 -> 4637 bytes .../flask/__pycache__/views.cpython-36.pyc | Bin 0 -> 4776 bytes .../flask/__pycache__/wrappers.cpython-36.pyc | Bin 0 -> 6674 bytes .../python3.6/site-packages/flask/_compat.py | 96 + flex/lib/python3.6/site-packages/flask/app.py | 2003 +++++ .../site-packages/flask/blueprints.py | 413 + flex/lib/python3.6/site-packages/flask/cli.py | 517 ++ .../python3.6/site-packages/flask/config.py | 263 + flex/lib/python3.6/site-packages/flask/ctx.py | 410 + .../site-packages/flask/debughelpers.py | 155 + .../site-packages/flask/ext/__init__.py | 29 + .../ext/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 1075 bytes .../python3.6/site-packages/flask/exthook.py | 143 + .../python3.6/site-packages/flask/globals.py | 61 + .../python3.6/site-packages/flask/helpers.py | 966 +++ .../lib/python3.6/site-packages/flask/json.py | 269 + .../python3.6/site-packages/flask/logging.py | 94 + .../python3.6/site-packages/flask/sessions.py | 366 + .../python3.6/site-packages/flask/signals.py | 56 + .../site-packages/flask/templating.py | 149 + .../python3.6/site-packages/flask/testing.py | 143 + .../python3.6/site-packages/flask/views.py | 149 + .../python3.6/site-packages/flask/wrappers.py | 205 + .../idna-2.6.dist-info/DESCRIPTION.rst | 213 + .../idna-2.6.dist-info/INSTALLER | 1 + .../site-packages/idna-2.6.dist-info/METADATA | 239 + .../site-packages/idna-2.6.dist-info/RECORD | 23 + .../site-packages/idna-2.6.dist-info/WHEEL | 6 + .../idna-2.6.dist-info/metadata.json | 1 + .../idna-2.6.dist-info/top_level.txt | 1 + .../python3.6/site-packages/idna/__init__.py | 2 + .../idna/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 249 bytes .../idna/__pycache__/codec.cpython-36.pyc | Bin 0 -> 3096 bytes .../idna/__pycache__/compat.cpython-36.pyc | Bin 0 -> 609 bytes .../idna/__pycache__/core.cpython-36.pyc | Bin 0 -> 8966 bytes .../idna/__pycache__/idnadata.cpython-36.pyc | Bin 0 -> 24498 bytes .../idna/__pycache__/intranges.cpython-36.pyc | Bin 0 -> 1810 bytes .../__pycache__/package_data.cpython-36.pyc | Bin 0 -> 203 bytes .../idna/__pycache__/uts46data.cpython-36.pyc | Bin 0 -> 225898 bytes .../lib/python3.6/site-packages/idna/codec.py | 118 + .../python3.6/site-packages/idna/compat.py | 12 + flex/lib/python3.6/site-packages/idna/core.py | 387 + .../python3.6/site-packages/idna/idnadata.py | 1585 ++++ .../python3.6/site-packages/idna/intranges.py | 53 + .../site-packages/idna/package_data.py | 2 + .../python3.6/site-packages/idna/uts46data.py | 7634 +++++++++++++++++ .../DESCRIPTION.rst | 3 + .../itsdangerous-0.24.dist-info/INSTALLER | 1 + .../itsdangerous-0.24.dist-info/METADATA | 16 + .../itsdangerous-0.24.dist-info/RECORD | 9 + .../itsdangerous-0.24.dist-info/WHEEL | 5 + .../itsdangerous-0.24.dist-info/metadata.json | 1 + .../itsdangerous-0.24.dist-info/top_level.txt | 1 + .../python3.6/site-packages/itsdangerous.py | 872 ++ .../site-packages/jinja2/__init__.py | 83 + .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 2548 bytes .../jinja2/__pycache__/_compat.cpython-36.pyc | Bin 0 -> 3358 bytes .../__pycache__/_identifier.cpython-36.pyc | Bin 0 -> 1861 bytes .../__pycache__/asyncfilters.cpython-36.pyc | Bin 0 -> 4829 bytes .../__pycache__/asyncsupport.cpython-36.pyc | Bin 0 -> 8178 bytes .../jinja2/__pycache__/bccache.cpython-36.pyc | Bin 0 -> 12734 bytes .../__pycache__/compiler.cpython-36.pyc | Bin 0 -> 46915 bytes .../__pycache__/constants.cpython-36.pyc | Bin 0 -> 1724 bytes .../jinja2/__pycache__/debug.cpython-36.pyc | Bin 0 -> 9357 bytes .../__pycache__/defaults.cpython-36.pyc | Bin 0 -> 1474 bytes .../__pycache__/environment.cpython-36.pyc | Bin 0 -> 43285 bytes .../__pycache__/exceptions.cpython-36.pyc | Bin 0 -> 5034 bytes .../jinja2/__pycache__/ext.cpython-36.pyc | Bin 0 -> 20125 bytes .../jinja2/__pycache__/filters.cpython-36.pyc | Bin 0 -> 34432 bytes .../__pycache__/idtracking.cpython-36.pyc | Bin 0 -> 9963 bytes .../jinja2/__pycache__/lexer.cpython-36.pyc | Bin 0 -> 18587 bytes .../jinja2/__pycache__/loaders.cpython-36.pyc | Bin 0 -> 16594 bytes .../jinja2/__pycache__/meta.cpython-36.pyc | Bin 0 -> 3685 bytes .../__pycache__/nativetypes.cpython-36.pyc | Bin 0 -> 5148 bytes .../jinja2/__pycache__/nodes.cpython-36.pyc | Bin 0 -> 36682 bytes .../__pycache__/optimizer.cpython-36.pyc | Bin 0 -> 2054 bytes .../jinja2/__pycache__/parser.cpython-36.pyc | Bin 0 -> 25359 bytes .../jinja2/__pycache__/runtime.cpython-36.pyc | Bin 0 -> 24624 bytes .../jinja2/__pycache__/sandbox.cpython-36.pyc | Bin 0 -> 14011 bytes .../jinja2/__pycache__/tests.cpython-36.pyc | Bin 0 -> 4430 bytes .../jinja2/__pycache__/utils.cpython-36.pyc | Bin 0 -> 20887 bytes .../jinja2/__pycache__/visitor.cpython-36.pyc | Bin 0 -> 3370 bytes .../python3.6/site-packages/jinja2/_compat.py | 99 + .../site-packages/jinja2/_identifier.py | 2 + .../site-packages/jinja2/asyncfilters.py | 146 + .../site-packages/jinja2/asyncsupport.py | 256 + .../python3.6/site-packages/jinja2/bccache.py | 362 + .../site-packages/jinja2/compiler.py | 1721 ++++ .../site-packages/jinja2/constants.py | 32 + .../python3.6/site-packages/jinja2/debug.py | 372 + .../site-packages/jinja2/defaults.py | 56 + .../site-packages/jinja2/environment.py | 1276 +++ .../site-packages/jinja2/exceptions.py | 146 + .../lib/python3.6/site-packages/jinja2/ext.py | 627 ++ .../python3.6/site-packages/jinja2/filters.py | 1190 +++ .../site-packages/jinja2/idtracking.py | 286 + .../python3.6/site-packages/jinja2/lexer.py | 739 ++ .../python3.6/site-packages/jinja2/loaders.py | 481 ++ .../python3.6/site-packages/jinja2/meta.py | 106 + .../site-packages/jinja2/nativetypes.py | 220 + .../python3.6/site-packages/jinja2/nodes.py | 999 +++ .../site-packages/jinja2/optimizer.py | 49 + .../python3.6/site-packages/jinja2/parser.py | 903 ++ .../python3.6/site-packages/jinja2/runtime.py | 813 ++ .../python3.6/site-packages/jinja2/sandbox.py | 475 + .../python3.6/site-packages/jinja2/tests.py | 175 + .../python3.6/site-packages/jinja2/utils.py | 647 ++ .../python3.6/site-packages/jinja2/visitor.py | 87 + .../site-packages/markupsafe/__init__.py | 305 + .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 11422 bytes .../__pycache__/_compat.cpython-36.pyc | Bin 0 -> 814 bytes .../__pycache__/_constants.cpython-36.pyc | Bin 0 -> 4382 bytes .../__pycache__/_native.cpython-36.pyc | Bin 0 -> 1447 bytes .../site-packages/markupsafe/_compat.py | 26 + .../site-packages/markupsafe/_constants.py | 267 + .../site-packages/markupsafe/_native.py | 46 + .../site-packages/markupsafe/_speedups.c | 239 + .../_speedups.cpython-36m-darwin.so | Bin 0 -> 31080 bytes .../pip/__pycache__/__init__.cpython-36.pyc | Bin 8427 -> 8425 bytes .../__pycache__/basecommand.cpython-36.pyc | Bin 7262 -> 7260 bytes .../pip/__pycache__/baseparser.cpython-36.pyc | Bin 9323 -> 9321 bytes .../pip/__pycache__/cmdoptions.cpython-36.pyc | Bin 12981 -> 12979 bytes .../pip/__pycache__/download.cpython-36.pyc | Bin 20362 -> 20360 bytes .../pip/__pycache__/exceptions.cpython-36.pyc | Bin 10535 -> 10533 bytes .../pip/__pycache__/index.cpython-36.pyc | Bin 30285 -> 30283 bytes .../pip/__pycache__/locations.cpython-36.pyc | Bin 3921 -> 3919 bytes .../pip/__pycache__/pep425tags.cpython-36.pyc | Bin 7516 -> 7514 bytes .../__pycache__/status_codes.cpython-36.pyc | Bin 390 -> 388 bytes .../pip/__pycache__/wheel.cpython-36.pyc | Bin 21707 -> 21705 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 2793 -> 2791 bytes .../__pycache__/appdirs.cpython-36.pyc | Bin 18612 -> 18610 bytes .../__pycache__/pyparsing.cpython-36.pyc | Bin 201108 -> 201106 bytes .../__pycache__/retrying.cpython-36.pyc | Bin 8094 -> 8092 bytes .../_vendor/__pycache__/six.cpython-36.pyc | Bin 24483 -> 24481 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 552 -> 550 bytes .../__pycache__/adapter.cpython-36.pyc | Bin 2888 -> 2886 bytes .../__pycache__/cache.cpython-36.pyc | Bin 1763 -> 1761 bytes .../__pycache__/compat.cpython-36.pyc | Bin 619 -> 617 bytes .../__pycache__/controller.cpython-36.pyc | Bin 7763 -> 7761 bytes .../__pycache__/filewrapper.cpython-36.pyc | Bin 2156 -> 2154 bytes .../__pycache__/serialize.cpython-36.pyc | Bin 4475 -> 4473 bytes .../__pycache__/wrapper.cpython-36.pyc | Bin 571 -> 569 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 609 -> 607 bytes .../__pycache__/file_cache.cpython-36.pyc | Bin 2806 -> 2804 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 446 -> 444 bytes .../colorama/__pycache__/ansi.cpython-36.pyc | Bin 3344 -> 3342 bytes .../__pycache__/ansitowin32.cpython-36.pyc | Bin 7076 -> 7074 bytes .../__pycache__/initialise.cpython-36.pyc | Bin 1667 -> 1665 bytes .../colorama/__pycache__/win32.cpython-36.pyc | Bin 3637 -> 3635 bytes .../__pycache__/winterm.cpython-36.pyc | Bin 4569 -> 4567 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 1044 -> 1042 bytes .../distlib/__pycache__/compat.cpython-36.pyc | Bin 32005 -> 32003 bytes .../__pycache__/resources.cpython-36.pyc | Bin 10911 -> 10909 bytes .../__pycache__/scripts.cpython-36.pyc | Bin 10078 -> 10076 bytes .../distlib/__pycache__/util.cpython-36.pyc | Bin 44505 -> 44503 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 965 -> 963 bytes .../__pycache__/_ihatexml.cpython-36.pyc | Bin 13859 -> 13857 bytes .../__pycache__/_inputstream.cpython-36.pyc | Bin 22713 -> 22711 bytes .../__pycache__/_tokenizer.cpython-36.pyc | Bin 42163 -> 42161 bytes .../__pycache__/_utils.cpython-36.pyc | Bin 3372 -> 3370 bytes .../__pycache__/constants.cpython-36.pyc | Bin 66322 -> 66320 bytes .../__pycache__/html5parser.cpython-36.pyc | Bin 98007 -> 98005 bytes .../__pycache__/serializer.cpython-36.pyc | Bin 9368 -> 9366 bytes .../_trie/__pycache__/__init__.cpython-36.pyc | Bin 428 -> 426 bytes .../_trie/__pycache__/_base.cpython-36.pyc | Bin 1517 -> 1515 bytes .../_trie/__pycache__/datrie.cpython-36.pyc | Bin 2030 -> 2028 bytes .../_trie/__pycache__/py.cpython-36.pyc | Bin 2235 -> 2233 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 3137 -> 3135 bytes .../__pycache__/base.cpython-36.pyc | Bin 11180 -> 11178 bytes .../__pycache__/etree.cpython-36.pyc | Bin 11870 -> 11868 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 3828 -> 3826 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 9912 -> 9910 bytes .../__pycache__/linklockfile.cpython-36.pyc | Bin 2291 -> 2289 bytes .../__pycache__/mkdirlockfile.cpython-36.pyc | Bin 2653 -> 2651 bytes .../__pycache__/__about__.cpython-36.pyc | Bin 722 -> 720 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 560 -> 558 bytes .../__pycache__/_compat.cpython-36.pyc | Bin 1007 -> 1005 bytes .../__pycache__/_structures.cpython-36.pyc | Bin 2864 -> 2862 bytes .../__pycache__/markers.cpython-36.pyc | Bin 8878 -> 8876 bytes .../__pycache__/requirements.cpython-36.pyc | Bin 3865 -> 3863 bytes .../__pycache__/specifiers.cpython-36.pyc | Bin 19826 -> 19824 bytes .../__pycache__/utils.cpython-36.pyc | Bin 491 -> 489 bytes .../__pycache__/version.cpython-36.pyc | Bin 10601 -> 10599 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 95310 -> 95308 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 3848 -> 3846 bytes .../progress/__pycache__/bar.cpython-36.pyc | Bin 2467 -> 2465 bytes .../__pycache__/helpers.cpython-36.pyc | Bin 2977 -> 2975 bytes .../__pycache__/spinner.cpython-36.pyc | Bin 1233 -> 1231 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 2340 -> 2338 bytes .../__pycache__/adapters.cpython-36.pyc | Bin 15810 -> 15808 bytes .../requests/__pycache__/api.cpython-36.pyc | Bin 6041 -> 6039 bytes .../requests/__pycache__/auth.cpython-36.pyc | Bin 7155 -> 7153 bytes .../requests/__pycache__/certs.cpython-36.pyc | Bin 827 -> 825 bytes .../__pycache__/compat.cpython-36.pyc | Bin 1413 -> 1411 bytes .../__pycache__/cookies.cpython-36.pyc | Bin 18479 -> 18477 bytes .../__pycache__/exceptions.cpython-36.pyc | Bin 4883 -> 4881 bytes .../requests/__pycache__/hooks.cpython-36.pyc | Bin 1000 -> 998 bytes .../__pycache__/models.cpython-36.pyc | Bin 21914 -> 21912 bytes .../__pycache__/sessions.cpython-36.pyc | Bin 17972 -> 17970 bytes .../__pycache__/status_codes.cpython-36.pyc | Bin 3661 -> 3659 bytes .../__pycache__/structures.cpython-36.pyc | Bin 4408 -> 4406 bytes .../requests/__pycache__/utils.cpython-36.pyc | Bin 18796 -> 18794 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 1606 -> 1604 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 699 -> 697 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 2529 -> 2527 bytes .../__pycache__/_collections.cpython-36.pyc | Bin 10612 -> 10610 bytes .../__pycache__/connection.cpython-36.pyc | Bin 8471 -> 8469 bytes .../__pycache__/connectionpool.cpython-36.pyc | Bin 22755 -> 22753 bytes .../__pycache__/exceptions.cpython-36.pyc | Bin 8928 -> 8926 bytes .../urllib3/__pycache__/fields.cpython-36.pyc | Bin 5886 -> 5884 bytes .../__pycache__/filepost.cpython-36.pyc | Bin 2689 -> 2687 bytes .../__pycache__/poolmanager.cpython-36.pyc | Bin 10875 -> 10873 bytes .../__pycache__/request.cpython-36.pyc | Bin 5631 -> 5629 bytes .../__pycache__/response.cpython-36.pyc | Bin 13808 -> 13806 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 220 -> 218 bytes .../contrib/__pycache__/socks.cpython-36.pyc | Bin 4535 -> 4533 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 346 -> 344 bytes .../packages/__pycache__/six.cpython-36.pyc | Bin 24518 -> 24516 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 507 -> 505 bytes .../util/__pycache__/__init__.cpython-36.pyc | Bin 1018 -> 1016 bytes .../__pycache__/connection.cpython-36.pyc | Bin 3304 -> 3302 bytes .../util/__pycache__/request.cpython-36.pyc | Bin 2003 -> 2001 bytes .../util/__pycache__/response.cpython-36.pyc | Bin 1875 -> 1873 bytes .../util/__pycache__/retry.cpython-36.pyc | Bin 9159 -> 9157 bytes .../util/__pycache__/ssl_.cpython-36.pyc | Bin 8784 -> 8782 bytes .../util/__pycache__/timeout.cpython-36.pyc | Bin 8790 -> 8788 bytes .../util/__pycache__/url.cpython-36.pyc | Bin 4939 -> 4937 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 9678 -> 9676 bytes .../__pycache__/labels.cpython-36.pyc | Bin 4092 -> 4090 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 2080 -> 2078 bytes .../commands/__pycache__/check.cpython-36.pyc | Bin 1321 -> 1319 bytes .../__pycache__/completion.cpython-36.pyc | Bin 2652 -> 2650 bytes .../__pycache__/download.cpython-36.pyc | Bin 5437 -> 5435 bytes .../__pycache__/freeze.cpython-36.pyc | Bin 2634 -> 2632 bytes .../commands/__pycache__/hash.cpython-36.pyc | Bin 1975 -> 1973 bytes .../commands/__pycache__/help.cpython-36.pyc | Bin 1126 -> 1124 bytes .../__pycache__/install.cpython-36.pyc | Bin 9908 -> 9906 bytes .../commands/__pycache__/list.cpython-36.pyc | Bin 9737 -> 9735 bytes .../__pycache__/search.cpython-36.pyc | Bin 4216 -> 4214 bytes .../commands/__pycache__/show.cpython-36.pyc | Bin 5387 -> 5385 bytes .../__pycache__/uninstall.cpython-36.pyc | Bin 2612 -> 2610 bytes .../commands/__pycache__/wheel.cpython-36.pyc | Bin 5474 -> 5472 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 4009 -> 4007 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 275 -> 273 bytes .../models/__pycache__/index.cpython-36.pyc | Bin 879 -> 877 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 189 -> 187 bytes .../__pycache__/check.cpython-36.pyc | Bin 1476 -> 1474 bytes .../__pycache__/freeze.cpython-36.pyc | Bin 2933 -> 2931 bytes .../req/__pycache__/__init__.cpython-36.pyc | Bin 456 -> 454 bytes .../req/__pycache__/req_file.cpython-36.pyc | Bin 8471 -> 8469 bytes .../__pycache__/req_install.cpython-36.pyc | Bin 30172 -> 30170 bytes .../req/__pycache__/req_set.cpython-36.pyc | Bin 21019 -> 21017 bytes .../__pycache__/req_uninstall.cpython-36.pyc | Bin 6334 -> 6332 bytes .../utils/__pycache__/__init__.cpython-36.pyc | Bin 22250 -> 22248 bytes .../utils/__pycache__/appdirs.cpython-36.pyc | Bin 7753 -> 7751 bytes .../utils/__pycache__/build.cpython-36.pyc | Bin 1367 -> 1365 bytes .../__pycache__/deprecation.cpython-36.pyc | Bin 1780 -> 1778 bytes .../utils/__pycache__/encoding.cpython-36.pyc | Bin 1070 -> 1068 bytes .../__pycache__/filesystem.cpython-36.pyc | Bin 635 -> 633 bytes .../utils/__pycache__/glibc.cpython-36.pyc | Bin 1418 -> 1416 bytes .../utils/__pycache__/hashes.cpython-36.pyc | Bin 3294 -> 3292 bytes .../utils/__pycache__/logging.cpython-36.pyc | Bin 3950 -> 3948 bytes .../utils/__pycache__/outdated.cpython-36.pyc | Bin 4275 -> 4273 bytes .../__pycache__/packaging.cpython-36.pyc | Bin 2038 -> 2036 bytes .../setuptools_build.cpython-36.pyc | Bin 379 -> 377 bytes .../pip/utils/__pycache__/ui.cpython-36.pyc | Bin 9635 -> 9633 bytes .../vcs/__pycache__/__init__.cpython-36.pyc | Bin 11154 -> 11152 bytes .../pip/vcs/__pycache__/bazaar.cpython-36.pyc | Bin 3707 -> 3705 bytes .../pip/vcs/__pycache__/git.cpython-36.pyc | Bin 8847 -> 8845 bytes .../vcs/__pycache__/mercurial.cpython-36.pyc | Bin 3620 -> 3618 bytes .../vcs/__pycache__/subversion.cpython-36.pyc | Bin 7159 -> 7157 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 95359 -> 95350 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 203 -> 194 bytes .../__pycache__/appdirs.cpython-36.pyc | Bin 18629 -> 18620 bytes .../__pycache__/pyparsing.cpython-36.pyc | Bin 201125 -> 201116 bytes .../_vendor/__pycache__/six.cpython-36.pyc | Bin 24500 -> 24491 bytes .../__pycache__/__about__.cpython-36.pyc | Bin 739 -> 730 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 577 -> 568 bytes .../__pycache__/_compat.cpython-36.pyc | Bin 1024 -> 1015 bytes .../__pycache__/_structures.cpython-36.pyc | Bin 2881 -> 2872 bytes .../__pycache__/markers.cpython-36.pyc | Bin 8043 -> 8034 bytes .../__pycache__/requirements.cpython-36.pyc | Bin 3900 -> 3891 bytes .../__pycache__/specifiers.cpython-36.pyc | Bin 19843 -> 19834 bytes .../__pycache__/version.cpython-36.pyc | Bin 10618 -> 10609 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 2434 -> 2425 bytes .../requests-2.18.4.dist-info/DESCRIPTION.rst | 1645 ++++ .../requests-2.18.4.dist-info/INSTALLER | 1 + .../requests-2.18.4.dist-info/METADATA | 1680 ++++ .../requests-2.18.4.dist-info/RECORD | 43 + .../requests-2.18.4.dist-info/WHEEL | 6 + .../requests-2.18.4.dist-info/metadata.json | 1 + .../requests-2.18.4.dist-info/top_level.txt | 1 + .../site-packages/requests/__init__.py | 121 + .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 3260 bytes .../__pycache__/__version__.cpython-36.pyc | Bin 0 -> 546 bytes .../_internal_utils.cpython-36.pyc | Bin 0 -> 1304 bytes .../__pycache__/adapters.cpython-36.pyc | Bin 0 -> 16447 bytes .../requests/__pycache__/api.cpython-36.pyc | Bin 0 -> 6471 bytes .../requests/__pycache__/auth.cpython-36.pyc | Bin 0 -> 7832 bytes .../requests/__pycache__/certs.cpython-36.pyc | Bin 0 -> 617 bytes .../__pycache__/compat.cpython-36.pyc | Bin 0 -> 1557 bytes .../__pycache__/cookies.cpython-36.pyc | Bin 0 -> 18554 bytes .../__pycache__/exceptions.cpython-36.pyc | Bin 0 -> 5307 bytes .../requests/__pycache__/help.cpython-36.pyc | Bin 0 -> 2644 bytes .../requests/__pycache__/hooks.cpython-36.pyc | Bin 0 -> 993 bytes .../__pycache__/models.cpython-36.pyc | Bin 0 -> 23904 bytes .../__pycache__/packages.cpython-36.pyc | Bin 0 -> 428 bytes .../__pycache__/sessions.cpython-36.pyc | Bin 0 -> 18467 bytes .../__pycache__/status_codes.cpython-36.pyc | Bin 0 -> 3669 bytes .../__pycache__/structures.cpython-36.pyc | Bin 0 -> 4401 bytes .../requests/__pycache__/utils.cpython-36.pyc | Bin 0 -> 20647 bytes .../site-packages/requests/__version__.py | 14 + .../site-packages/requests/_internal_utils.py | 42 + .../site-packages/requests/adapters.py | 525 ++ .../python3.6/site-packages/requests/api.py | 152 + .../python3.6/site-packages/requests/auth.py | 293 + .../python3.6/site-packages/requests/certs.py | 18 + .../site-packages/requests/compat.py | 69 + .../site-packages/requests/cookies.py | 542 ++ .../site-packages/requests/exceptions.py | 122 + .../python3.6/site-packages/requests/help.py | 120 + .../python3.6/site-packages/requests/hooks.py | 34 + .../site-packages/requests/models.py | 948 ++ .../site-packages/requests/packages.py | 14 + .../site-packages/requests/sessions.py | 737 ++ .../site-packages/requests/status_codes.py | 91 + .../site-packages/requests/structures.py | 105 + .../python3.6/site-packages/requests/utils.py | 904 ++ .../__pycache__/__init__.cpython-36.pyc | Bin 5705 -> 5696 bytes .../__pycache__/archive_util.cpython-36.pyc | Bin 5168 -> 5159 bytes .../__pycache__/depends.cpython-36.pyc | Bin 5838 -> 5829 bytes .../__pycache__/dist.cpython-36.pyc | Bin 32178 -> 32169 bytes .../__pycache__/extension.cpython-36.pyc | Bin 1985 -> 1976 bytes .../__pycache__/glob.cpython-36.pyc | Bin 3853 -> 3844 bytes .../__pycache__/lib2to3_ex.cpython-36.pyc | Bin 2443 -> 2434 bytes .../__pycache__/monkey.cpython-36.pyc | Bin 4533 -> 4524 bytes .../__pycache__/msvc.cpython-36.pyc | Bin 31286 -> 31277 bytes .../__pycache__/namespaces.cpython-36.pyc | Bin 3201 -> 3192 bytes .../__pycache__/package_index.cpython-36.pyc | Bin 32500 -> 32491 bytes .../__pycache__/py26compat.cpython-36.pyc | Bin 1073 -> 1064 bytes .../__pycache__/py27compat.cpython-36.pyc | Bin 622 -> 613 bytes .../__pycache__/py31compat.cpython-36.pyc | Bin 1903 -> 1894 bytes .../__pycache__/sandbox.cpython-36.pyc | Bin 15543 -> 15534 bytes .../__pycache__/ssl_support.cpython-36.pyc | Bin 6369 -> 6360 bytes .../__pycache__/unicode_utils.cpython-36.pyc | Bin 1179 -> 1170 bytes .../__pycache__/version.cpython-36.pyc | Bin 333 -> 324 bytes .../windows_support.cpython-36.pyc | Bin 1021 -> 1012 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 722 -> 713 bytes .../__pycache__/bdist_egg.cpython-36.pyc | Bin 13674 -> 13665 bytes .../__pycache__/build_py.cpython-36.pyc | Bin 8583 -> 8574 bytes .../__pycache__/easy_install.cpython-36.pyc | Bin 63994 -> 63985 bytes .../__pycache__/egg_info.cpython-36.pyc | Bin 21067 -> 21058 bytes .../__pycache__/install.cpython-36.pyc | Bin 3984 -> 3975 bytes .../install_egg_info.cpython-36.pyc | Bin 2449 -> 2440 bytes .../__pycache__/install_lib.cpython-36.pyc | Bin 4094 -> 4085 bytes .../install_scripts.cpython-36.pyc | Bin 2289 -> 2280 bytes .../__pycache__/py36compat.cpython-36.pyc | Bin 4634 -> 4625 bytes .../command/__pycache__/sdist.cpython-36.pyc | Bin 6119 -> 6110 bytes .../command/__pycache__/setopt.cpython-36.pyc | Bin 4613 -> 4604 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 343 -> 334 bytes .../urllib3-1.22.dist-info/DESCRIPTION.rst | 995 +++ .../urllib3-1.22.dist-info/INSTALLER | 1 + .../urllib3-1.22.dist-info/METADATA | 1031 +++ .../urllib3-1.22.dist-info/RECORD | 79 + .../urllib3-1.22.dist-info/WHEEL | 6 + .../urllib3-1.22.dist-info/metadata.json | 1 + .../urllib3-1.22.dist-info/top_level.txt | 1 + .../site-packages/urllib3/__init__.py | 97 + .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 2503 bytes .../__pycache__/_collections.cpython-36.pyc | Bin 0 -> 10537 bytes .../__pycache__/connection.cpython-36.pyc | Bin 0 -> 8836 bytes .../__pycache__/connectionpool.cpython-36.pyc | Bin 0 -> 23731 bytes .../__pycache__/exceptions.cpython-36.pyc | Bin 0 -> 10394 bytes .../urllib3/__pycache__/fields.cpython-36.pyc | Bin 0 -> 5865 bytes .../__pycache__/filepost.cpython-36.pyc | Bin 0 -> 2664 bytes .../__pycache__/poolmanager.cpython-36.pyc | Bin 0 -> 12807 bytes .../__pycache__/request.cpython-36.pyc | Bin 0 -> 5559 bytes .../__pycache__/response.cpython-36.pyc | Bin 0 -> 16228 bytes .../site-packages/urllib3/_collections.py | 319 + .../site-packages/urllib3/connection.py | 373 + .../site-packages/urllib3/connectionpool.py | 905 ++ .../site-packages/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 194 bytes .../__pycache__/appengine.cpython-36.pyc | Bin 0 -> 8808 bytes .../__pycache__/ntlmpool.cpython-36.pyc | Bin 0 -> 3242 bytes .../__pycache__/pyopenssl.cpython-36.pyc | Bin 0 -> 14128 bytes .../securetransport.cpython-36.pyc | Bin 0 -> 18013 bytes .../contrib/__pycache__/socks.cpython-36.pyc | Bin 0 -> 4803 bytes .../contrib/_securetransport/__init__.py | 0 .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 211 bytes .../__pycache__/bindings.cpython-36.pyc | Bin 0 -> 10426 bytes .../__pycache__/low_level.cpython-36.pyc | Bin 0 -> 7451 bytes .../contrib/_securetransport/bindings.py | 593 ++ .../contrib/_securetransport/low_level.py | 343 + .../urllib3/contrib/appengine.py | 296 + .../site-packages/urllib3/contrib/ntlmpool.py | 112 + .../urllib3/contrib/pyopenssl.py | 455 + .../urllib3/contrib/securetransport.py | 810 ++ .../site-packages/urllib3/contrib/socks.py | 188 + .../site-packages/urllib3/exceptions.py | 246 + .../python3.6/site-packages/urllib3/fields.py | 178 + .../site-packages/urllib3/filepost.py | 94 + .../urllib3/packages/__init__.py | 5 + .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 320 bytes .../__pycache__/ordered_dict.cpython-36.pyc | Bin 0 -> 8397 bytes .../packages/__pycache__/six.cpython-36.pyc | Bin 0 -> 24492 bytes .../urllib3/packages/backports/__init__.py | 0 .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 205 bytes .../__pycache__/makefile.cpython-36.pyc | Bin 0 -> 1305 bytes .../urllib3/packages/backports/makefile.py | 53 + .../urllib3/packages/ordered_dict.py | 259 + .../site-packages/urllib3/packages/six.py | 868 ++ .../packages/ssl_match_hostname/__init__.py | 19 + .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 581 bytes .../_implementation.cpython-36.pyc | Bin 0 -> 3284 bytes .../ssl_match_hostname/_implementation.py | 157 + .../site-packages/urllib3/poolmanager.py | 440 + .../site-packages/urllib3/request.py | 148 + .../site-packages/urllib3/response.py | 626 ++ .../site-packages/urllib3/util/__init__.py | 54 + .../util/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 1124 bytes .../__pycache__/connection.cpython-36.pyc | Bin 0 -> 3122 bytes .../util/__pycache__/request.cpython-36.pyc | Bin 0 -> 3216 bytes .../util/__pycache__/response.cpython-36.pyc | Bin 0 -> 1897 bytes .../util/__pycache__/retry.cpython-36.pyc | Bin 0 -> 12312 bytes .../util/__pycache__/selectors.cpython-36.pyc | Bin 0 -> 16411 bytes .../util/__pycache__/ssl_.cpython-36.pyc | Bin 0 -> 8957 bytes .../util/__pycache__/timeout.cpython-36.pyc | Bin 0 -> 8765 bytes .../util/__pycache__/url.cpython-36.pyc | Bin 0 -> 5184 bytes .../util/__pycache__/wait.cpython-36.pyc | Bin 0 -> 1659 bytes .../site-packages/urllib3/util/connection.py | 130 + .../site-packages/urllib3/util/request.py | 118 + .../site-packages/urllib3/util/response.py | 81 + .../site-packages/urllib3/util/retry.py | 401 + .../site-packages/urllib3/util/selectors.py | 581 ++ .../site-packages/urllib3/util/ssl_.py | 341 + .../site-packages/urllib3/util/timeout.py | 242 + .../site-packages/urllib3/util/url.py | 230 + .../site-packages/urllib3/util/wait.py | 40 + .../site-packages/werkzeug/__init__.py | 151 + .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 4748 bytes .../__pycache__/_compat.cpython-36.pyc | Bin 0 -> 7151 bytes .../__pycache__/_internal.cpython-36.pyc | Bin 0 -> 12637 bytes .../__pycache__/_reloader.cpython-36.pyc | Bin 0 -> 8901 bytes .../__pycache__/datastructures.cpython-36.pyc | Bin 0 -> 100088 bytes .../__pycache__/exceptions.cpython-36.pyc | Bin 0 -> 22982 bytes .../__pycache__/filesystem.cpython-36.pyc | Bin 0 -> 2259 bytes .../__pycache__/formparser.cpython-36.pyc | Bin 0 -> 16205 bytes .../werkzeug/__pycache__/http.cpython-36.pyc | Bin 0 -> 33511 bytes .../werkzeug/__pycache__/local.cpython-36.pyc | Bin 0 -> 18728 bytes .../__pycache__/posixemulation.cpython-36.pyc | Bin 0 -> 2820 bytes .../__pycache__/routing.cpython-36.pyc | Bin 0 -> 60202 bytes .../__pycache__/script.cpython-36.pyc | Bin 0 -> 10118 bytes .../__pycache__/security.cpython-36.pyc | Bin 0 -> 8570 bytes .../__pycache__/serving.cpython-36.pyc | Bin 0 -> 26554 bytes .../werkzeug/__pycache__/test.cpython-36.pyc | Bin 0 -> 31088 bytes .../__pycache__/testapp.cpython-36.pyc | Bin 0 -> 9477 bytes .../werkzeug/__pycache__/urls.cpython-36.pyc | Bin 0 -> 33362 bytes .../__pycache__/useragents.cpython-36.pyc | Bin 0 -> 6094 bytes .../werkzeug/__pycache__/utils.cpython-36.pyc | Bin 0 -> 21215 bytes .../__pycache__/websocket.cpython-36.pyc | Bin 0 -> 8257 bytes .../__pycache__/wrappers.cpython-36.pyc | Bin 0 -> 76462 bytes .../werkzeug/__pycache__/wsgi.cpython-36.pyc | Bin 0 -> 44717 bytes .../site-packages/werkzeug/_compat.py | 206 + .../site-packages/werkzeug/_internal.py | 419 + .../site-packages/werkzeug/_reloader.py | 277 + .../werkzeug/contrib/__init__.py | 16 + .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 803 bytes .../contrib/__pycache__/atom.cpython-36.pyc | Bin 0 -> 14115 bytes .../contrib/__pycache__/cache.cpython-36.pyc | Bin 0 -> 32428 bytes .../contrib/__pycache__/fixers.cpython-36.pyc | Bin 0 -> 10120 bytes .../contrib/__pycache__/iterio.cpython-36.pyc | Bin 0 -> 11002 bytes .../__pycache__/jsrouting.cpython-36.pyc | Bin 0 -> 8311 bytes .../__pycache__/limiter.cpython-36.pyc | Bin 0 -> 1774 bytes .../contrib/__pycache__/lint.cpython-36.pyc | Bin 0 -> 11938 bytes .../__pycache__/profiler.cpython-36.pyc | Bin 0 -> 5300 bytes .../__pycache__/securecookie.cpython-36.pyc | Bin 0 -> 10352 bytes .../__pycache__/sessions.cpython-36.pyc | Bin 0 -> 12940 bytes .../__pycache__/testtools.cpython-36.pyc | Bin 0 -> 2686 bytes .../__pycache__/wrappers.cpython-36.pyc | Bin 0 -> 10431 bytes .../site-packages/werkzeug/contrib/atom.py | 355 + .../site-packages/werkzeug/contrib/cache.py | 913 ++ .../site-packages/werkzeug/contrib/fixers.py | 254 + .../site-packages/werkzeug/contrib/iterio.py | 352 + .../werkzeug/contrib/jsrouting.py | 264 + .../site-packages/werkzeug/contrib/limiter.py | 41 + .../site-packages/werkzeug/contrib/lint.py | 343 + .../werkzeug/contrib/profiler.py | 147 + .../werkzeug/contrib/securecookie.py | 323 + .../werkzeug/contrib/sessions.py | 352 + .../werkzeug/contrib/testtools.py | 73 + .../werkzeug/contrib/wrappers.py | 284 + .../site-packages/werkzeug/datastructures.py | 2762 ++++++ .../site-packages/werkzeug/debug/__init__.py | 470 + .../debug/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 12763 bytes .../debug/__pycache__/console.cpython-36.pyc | Bin 0 -> 7377 bytes .../debug/__pycache__/repr.cpython-36.pyc | Bin 0 -> 8681 bytes .../debug/__pycache__/tbtools.cpython-36.pyc | Bin 0 -> 15699 bytes .../site-packages/werkzeug/debug/console.py | 215 + .../site-packages/werkzeug/debug/repr.py | 280 + .../werkzeug/debug/shared/FONT_LICENSE | 96 + .../werkzeug/debug/shared/console.png | Bin 0 -> 507 bytes .../werkzeug/debug/shared/debugger.js | 205 + .../werkzeug/debug/shared/jquery.js | 5 + .../werkzeug/debug/shared/less.png | Bin 0 -> 191 bytes .../werkzeug/debug/shared/more.png | Bin 0 -> 200 bytes .../werkzeug/debug/shared/source.png | Bin 0 -> 818 bytes .../werkzeug/debug/shared/style.css | 143 + .../werkzeug/debug/shared/ubuntu.ttf | Bin 0 -> 70220 bytes .../site-packages/werkzeug/debug/tbtools.py | 556 ++ .../site-packages/werkzeug/exceptions.py | 719 ++ .../site-packages/werkzeug/filesystem.py | 66 + .../site-packages/werkzeug/formparser.py | 534 ++ .../python3.6/site-packages/werkzeug/http.py | 1158 +++ .../python3.6/site-packages/werkzeug/local.py | 420 + .../site-packages/werkzeug/posixemulation.py | 106 + .../site-packages/werkzeug/routing.py | 1792 ++++ .../site-packages/werkzeug/script.py | 318 + .../site-packages/werkzeug/security.py | 270 + .../site-packages/werkzeug/serving.py | 862 ++ .../python3.6/site-packages/werkzeug/test.py | 948 ++ .../site-packages/werkzeug/testapp.py | 230 + .../python3.6/site-packages/werkzeug/urls.py | 1007 +++ .../site-packages/werkzeug/useragents.py | 212 + .../python3.6/site-packages/werkzeug/utils.py | 628 ++ .../site-packages/werkzeug/websocket.py | 337 + .../site-packages/werkzeug/wrappers.py | 2028 +++++ .../python3.6/site-packages/werkzeug/wsgi.py | 1364 +++ .../wheel/__pycache__/__init__.cpython-36.pyc | Bin 204 -> 200 bytes .../wheel/__pycache__/archive.cpython-36.pyc | Bin 2067 -> 2063 bytes .../__pycache__/bdist_wheel.cpython-36.pyc | Bin 13206 -> 13202 bytes .../wheel/__pycache__/metadata.cpython-36.pyc | Bin 8651 -> 8647 bytes .../__pycache__/pep425tags.cpython-36.pyc | Bin 4636 -> 4632 bytes .../wheel/__pycache__/pkginfo.cpython-36.pyc | Bin 1575 -> 1571 bytes .../wheel/__pycache__/util.cpython-36.pyc | Bin 5642 -> 5638 bytes 742 files changed, 93021 insertions(+), 2 deletions(-) create mode 100755 flex/bin/chardetect create mode 100755 flex/bin/flask create mode 100644 flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/DESCRIPTION.rst create mode 100644 flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/INSTALLER create mode 100644 flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/LICENSE.txt create mode 100644 flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/METADATA create mode 100644 flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/RECORD create mode 100644 flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/WHEEL create mode 100644 flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/entry_points.txt create mode 100644 flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/metadata.json create mode 100644 flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/top_level.txt create mode 100644 flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/DESCRIPTION.rst create mode 100644 flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/INSTALLER create mode 100644 flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/LICENSE.txt create mode 100644 flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/METADATA create mode 100644 flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/RECORD create mode 100644 flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/WHEEL create mode 100644 flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/entry_points.txt create mode 100644 flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/metadata.json create mode 100644 flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/top_level.txt create mode 100644 flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/DESCRIPTION.rst create mode 100644 flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/INSTALLER create mode 100644 flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/LICENSE.txt create mode 100644 flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/METADATA create mode 100644 flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/RECORD create mode 100644 flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/WHEEL create mode 100644 flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/metadata.json create mode 100644 flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/top_level.txt create mode 100644 flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/DESCRIPTION.rst create mode 100644 flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/INSTALLER create mode 100644 flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/LICENSE.txt create mode 100644 flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/METADATA create mode 100644 flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/RECORD create mode 100644 flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/WHEEL create mode 100644 flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/metadata.json create mode 100644 flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/top_level.txt create mode 100644 flex/lib/python3.6/site-packages/__pycache__/itsdangerous.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/DESCRIPTION.rst create mode 100644 flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/INSTALLER create mode 100644 flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/LICENSE.txt create mode 100644 flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/METADATA create mode 100644 flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/RECORD create mode 100644 flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/WHEEL create mode 100644 flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/metadata.json create mode 100644 flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/top_level.txt create mode 100644 flex/lib/python3.6/site-packages/certifi/__init__.py create mode 100644 flex/lib/python3.6/site-packages/certifi/__main__.py create mode 100644 flex/lib/python3.6/site-packages/certifi/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/certifi/__pycache__/__main__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/certifi/__pycache__/core.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/certifi/cacert.pem create mode 100644 flex/lib/python3.6/site-packages/certifi/core.py create mode 100644 flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/DESCRIPTION.rst create mode 100644 flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/INSTALLER create mode 100644 flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/METADATA create mode 100644 flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/RECORD create mode 100644 flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/WHEEL create mode 100644 flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/entry_points.txt create mode 100644 flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/metadata.json create mode 100644 flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/top_level.txt create mode 100644 flex/lib/python3.6/site-packages/chardet/__init__.py create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/big5freq.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/big5prober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/chardistribution.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/charsetgroupprober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/charsetprober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/codingstatemachine.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/compat.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/cp949prober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/enums.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/escprober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/escsm.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/eucjpprober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/euckrfreq.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/euckrprober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/euctwfreq.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/euctwprober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/gb2312freq.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/gb2312prober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/hebrewprober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/jisfreq.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/jpcntx.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/langbulgarianmodel.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/langcyrillicmodel.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/langgreekmodel.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/langhebrewmodel.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/langhungarianmodel.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/langthaimodel.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/langturkishmodel.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/latin1prober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/mbcharsetprober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/mbcsgroupprober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/mbcssm.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/sbcharsetprober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/sbcsgroupprober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/sjisprober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/universaldetector.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/utf8prober.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/__pycache__/version.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/big5freq.py create mode 100644 flex/lib/python3.6/site-packages/chardet/big5prober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/chardistribution.py create mode 100644 flex/lib/python3.6/site-packages/chardet/charsetgroupprober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/charsetprober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/cli/__init__.py create mode 100644 flex/lib/python3.6/site-packages/chardet/cli/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/cli/__pycache__/chardetect.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/chardet/cli/chardetect.py create mode 100644 flex/lib/python3.6/site-packages/chardet/codingstatemachine.py create mode 100644 flex/lib/python3.6/site-packages/chardet/compat.py create mode 100644 flex/lib/python3.6/site-packages/chardet/cp949prober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/enums.py create mode 100644 flex/lib/python3.6/site-packages/chardet/escprober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/escsm.py create mode 100644 flex/lib/python3.6/site-packages/chardet/eucjpprober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/euckrfreq.py create mode 100644 flex/lib/python3.6/site-packages/chardet/euckrprober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/euctwfreq.py create mode 100644 flex/lib/python3.6/site-packages/chardet/euctwprober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/gb2312freq.py create mode 100644 flex/lib/python3.6/site-packages/chardet/gb2312prober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/hebrewprober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/jisfreq.py create mode 100644 flex/lib/python3.6/site-packages/chardet/jpcntx.py create mode 100644 flex/lib/python3.6/site-packages/chardet/langbulgarianmodel.py create mode 100644 flex/lib/python3.6/site-packages/chardet/langcyrillicmodel.py create mode 100644 flex/lib/python3.6/site-packages/chardet/langgreekmodel.py create mode 100644 flex/lib/python3.6/site-packages/chardet/langhebrewmodel.py create mode 100644 flex/lib/python3.6/site-packages/chardet/langhungarianmodel.py create mode 100644 flex/lib/python3.6/site-packages/chardet/langthaimodel.py create mode 100644 flex/lib/python3.6/site-packages/chardet/langturkishmodel.py create mode 100644 flex/lib/python3.6/site-packages/chardet/latin1prober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/mbcharsetprober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/mbcsgroupprober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/mbcssm.py create mode 100644 flex/lib/python3.6/site-packages/chardet/sbcharsetprober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/sbcsgroupprober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/sjisprober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/universaldetector.py create mode 100644 flex/lib/python3.6/site-packages/chardet/utf8prober.py create mode 100644 flex/lib/python3.6/site-packages/chardet/version.py create mode 100644 flex/lib/python3.6/site-packages/click-6.7.dist-info/DESCRIPTION.rst create mode 100644 flex/lib/python3.6/site-packages/click-6.7.dist-info/INSTALLER create mode 100644 flex/lib/python3.6/site-packages/click-6.7.dist-info/METADATA create mode 100644 flex/lib/python3.6/site-packages/click-6.7.dist-info/RECORD create mode 100644 flex/lib/python3.6/site-packages/click-6.7.dist-info/WHEEL create mode 100644 flex/lib/python3.6/site-packages/click-6.7.dist-info/metadata.json create mode 100644 flex/lib/python3.6/site-packages/click-6.7.dist-info/top_level.txt create mode 100644 flex/lib/python3.6/site-packages/click/__init__.py create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/_bashcomplete.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/_compat.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/_termui_impl.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/_textwrap.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/_unicodefun.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/_winconsole.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/core.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/decorators.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/exceptions.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/formatting.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/globals.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/parser.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/termui.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/testing.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/types.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/__pycache__/utils.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/click/_bashcomplete.py create mode 100644 flex/lib/python3.6/site-packages/click/_compat.py create mode 100644 flex/lib/python3.6/site-packages/click/_termui_impl.py create mode 100644 flex/lib/python3.6/site-packages/click/_textwrap.py create mode 100644 flex/lib/python3.6/site-packages/click/_unicodefun.py create mode 100644 flex/lib/python3.6/site-packages/click/_winconsole.py create mode 100644 flex/lib/python3.6/site-packages/click/core.py create mode 100644 flex/lib/python3.6/site-packages/click/decorators.py create mode 100644 flex/lib/python3.6/site-packages/click/exceptions.py create mode 100644 flex/lib/python3.6/site-packages/click/formatting.py create mode 100644 flex/lib/python3.6/site-packages/click/globals.py create mode 100644 flex/lib/python3.6/site-packages/click/parser.py create mode 100644 flex/lib/python3.6/site-packages/click/termui.py create mode 100644 flex/lib/python3.6/site-packages/click/testing.py create mode 100644 flex/lib/python3.6/site-packages/click/types.py create mode 100644 flex/lib/python3.6/site-packages/click/utils.py create mode 100644 flex/lib/python3.6/site-packages/flask/__init__.py create mode 100644 flex/lib/python3.6/site-packages/flask/__main__.py create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/__main__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/_compat.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/app.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/blueprints.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/cli.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/config.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/ctx.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/debughelpers.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/exthook.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/globals.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/helpers.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/json.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/logging.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/sessions.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/signals.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/templating.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/testing.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/views.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/__pycache__/wrappers.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/_compat.py create mode 100644 flex/lib/python3.6/site-packages/flask/app.py create mode 100644 flex/lib/python3.6/site-packages/flask/blueprints.py create mode 100644 flex/lib/python3.6/site-packages/flask/cli.py create mode 100644 flex/lib/python3.6/site-packages/flask/config.py create mode 100644 flex/lib/python3.6/site-packages/flask/ctx.py create mode 100644 flex/lib/python3.6/site-packages/flask/debughelpers.py create mode 100644 flex/lib/python3.6/site-packages/flask/ext/__init__.py create mode 100644 flex/lib/python3.6/site-packages/flask/ext/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/flask/exthook.py create mode 100644 flex/lib/python3.6/site-packages/flask/globals.py create mode 100644 flex/lib/python3.6/site-packages/flask/helpers.py create mode 100644 flex/lib/python3.6/site-packages/flask/json.py create mode 100644 flex/lib/python3.6/site-packages/flask/logging.py create mode 100644 flex/lib/python3.6/site-packages/flask/sessions.py create mode 100644 flex/lib/python3.6/site-packages/flask/signals.py create mode 100644 flex/lib/python3.6/site-packages/flask/templating.py create mode 100644 flex/lib/python3.6/site-packages/flask/testing.py create mode 100644 flex/lib/python3.6/site-packages/flask/views.py create mode 100644 flex/lib/python3.6/site-packages/flask/wrappers.py create mode 100644 flex/lib/python3.6/site-packages/idna-2.6.dist-info/DESCRIPTION.rst create mode 100644 flex/lib/python3.6/site-packages/idna-2.6.dist-info/INSTALLER create mode 100644 flex/lib/python3.6/site-packages/idna-2.6.dist-info/METADATA create mode 100644 flex/lib/python3.6/site-packages/idna-2.6.dist-info/RECORD create mode 100644 flex/lib/python3.6/site-packages/idna-2.6.dist-info/WHEEL create mode 100644 flex/lib/python3.6/site-packages/idna-2.6.dist-info/metadata.json create mode 100644 flex/lib/python3.6/site-packages/idna-2.6.dist-info/top_level.txt create mode 100644 flex/lib/python3.6/site-packages/idna/__init__.py create mode 100644 flex/lib/python3.6/site-packages/idna/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/idna/__pycache__/codec.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/idna/__pycache__/compat.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/idna/__pycache__/core.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/idna/__pycache__/idnadata.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/idna/__pycache__/intranges.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/idna/__pycache__/package_data.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/idna/__pycache__/uts46data.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/idna/codec.py create mode 100644 flex/lib/python3.6/site-packages/idna/compat.py create mode 100644 flex/lib/python3.6/site-packages/idna/core.py create mode 100644 flex/lib/python3.6/site-packages/idna/idnadata.py create mode 100644 flex/lib/python3.6/site-packages/idna/intranges.py create mode 100644 flex/lib/python3.6/site-packages/idna/package_data.py create mode 100644 flex/lib/python3.6/site-packages/idna/uts46data.py create mode 100644 flex/lib/python3.6/site-packages/itsdangerous-0.24.dist-info/DESCRIPTION.rst create mode 100644 flex/lib/python3.6/site-packages/itsdangerous-0.24.dist-info/INSTALLER create mode 100644 flex/lib/python3.6/site-packages/itsdangerous-0.24.dist-info/METADATA create mode 100644 flex/lib/python3.6/site-packages/itsdangerous-0.24.dist-info/RECORD create mode 100644 flex/lib/python3.6/site-packages/itsdangerous-0.24.dist-info/WHEEL create mode 100644 flex/lib/python3.6/site-packages/itsdangerous-0.24.dist-info/metadata.json create mode 100644 flex/lib/python3.6/site-packages/itsdangerous-0.24.dist-info/top_level.txt create mode 100644 flex/lib/python3.6/site-packages/itsdangerous.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/__init__.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/_compat.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/_identifier.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/asyncfilters.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/asyncsupport.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/bccache.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/compiler.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/constants.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/debug.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/defaults.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/environment.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/exceptions.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/ext.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/filters.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/idtracking.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/lexer.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/loaders.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/meta.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/nativetypes.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/nodes.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/optimizer.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/parser.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/runtime.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/sandbox.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/tests.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/utils.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/__pycache__/visitor.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/jinja2/_compat.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/_identifier.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/asyncfilters.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/asyncsupport.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/bccache.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/compiler.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/constants.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/debug.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/defaults.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/environment.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/exceptions.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/ext.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/filters.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/idtracking.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/lexer.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/loaders.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/meta.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/nativetypes.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/nodes.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/optimizer.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/parser.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/runtime.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/sandbox.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/tests.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/utils.py create mode 100644 flex/lib/python3.6/site-packages/jinja2/visitor.py create mode 100644 flex/lib/python3.6/site-packages/markupsafe/__init__.py create mode 100644 flex/lib/python3.6/site-packages/markupsafe/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/markupsafe/__pycache__/_compat.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/markupsafe/__pycache__/_constants.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/markupsafe/__pycache__/_native.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/markupsafe/_compat.py create mode 100644 flex/lib/python3.6/site-packages/markupsafe/_constants.py create mode 100644 flex/lib/python3.6/site-packages/markupsafe/_native.py create mode 100644 flex/lib/python3.6/site-packages/markupsafe/_speedups.c create mode 100755 flex/lib/python3.6/site-packages/markupsafe/_speedups.cpython-36m-darwin.so create mode 100644 flex/lib/python3.6/site-packages/requests-2.18.4.dist-info/DESCRIPTION.rst create mode 100644 flex/lib/python3.6/site-packages/requests-2.18.4.dist-info/INSTALLER create mode 100644 flex/lib/python3.6/site-packages/requests-2.18.4.dist-info/METADATA create mode 100644 flex/lib/python3.6/site-packages/requests-2.18.4.dist-info/RECORD create mode 100644 flex/lib/python3.6/site-packages/requests-2.18.4.dist-info/WHEEL create mode 100644 flex/lib/python3.6/site-packages/requests-2.18.4.dist-info/metadata.json create mode 100644 flex/lib/python3.6/site-packages/requests-2.18.4.dist-info/top_level.txt create mode 100644 flex/lib/python3.6/site-packages/requests/__init__.py create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/__version__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/_internal_utils.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/adapters.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/api.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/auth.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/certs.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/compat.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/cookies.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/exceptions.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/help.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/hooks.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/models.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/packages.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/sessions.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/status_codes.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/structures.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__pycache__/utils.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/requests/__version__.py create mode 100644 flex/lib/python3.6/site-packages/requests/_internal_utils.py create mode 100644 flex/lib/python3.6/site-packages/requests/adapters.py create mode 100644 flex/lib/python3.6/site-packages/requests/api.py create mode 100644 flex/lib/python3.6/site-packages/requests/auth.py create mode 100644 flex/lib/python3.6/site-packages/requests/certs.py create mode 100644 flex/lib/python3.6/site-packages/requests/compat.py create mode 100644 flex/lib/python3.6/site-packages/requests/cookies.py create mode 100644 flex/lib/python3.6/site-packages/requests/exceptions.py create mode 100644 flex/lib/python3.6/site-packages/requests/help.py create mode 100644 flex/lib/python3.6/site-packages/requests/hooks.py create mode 100644 flex/lib/python3.6/site-packages/requests/models.py create mode 100644 flex/lib/python3.6/site-packages/requests/packages.py create mode 100644 flex/lib/python3.6/site-packages/requests/sessions.py create mode 100644 flex/lib/python3.6/site-packages/requests/status_codes.py create mode 100644 flex/lib/python3.6/site-packages/requests/structures.py create mode 100644 flex/lib/python3.6/site-packages/requests/utils.py create mode 100644 flex/lib/python3.6/site-packages/urllib3-1.22.dist-info/DESCRIPTION.rst create mode 100644 flex/lib/python3.6/site-packages/urllib3-1.22.dist-info/INSTALLER create mode 100644 flex/lib/python3.6/site-packages/urllib3-1.22.dist-info/METADATA create mode 100644 flex/lib/python3.6/site-packages/urllib3-1.22.dist-info/RECORD create mode 100644 flex/lib/python3.6/site-packages/urllib3-1.22.dist-info/WHEEL create mode 100644 flex/lib/python3.6/site-packages/urllib3-1.22.dist-info/metadata.json create mode 100644 flex/lib/python3.6/site-packages/urllib3-1.22.dist-info/top_level.txt create mode 100644 flex/lib/python3.6/site-packages/urllib3/__init__.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/__pycache__/_collections.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/__pycache__/connection.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/__pycache__/connectionpool.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/__pycache__/exceptions.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/__pycache__/fields.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/__pycache__/filepost.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/__pycache__/poolmanager.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/__pycache__/request.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/__pycache__/response.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/_collections.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/connection.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/connectionpool.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/__init__.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/__pycache__/appengine.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/__pycache__/ntlmpool.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/__pycache__/pyopenssl.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/__pycache__/securetransport.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/__pycache__/socks.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/_securetransport/__init__.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/_securetransport/bindings.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/_securetransport/low_level.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/appengine.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/ntlmpool.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/pyopenssl.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/securetransport.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/contrib/socks.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/exceptions.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/fields.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/filepost.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/packages/__init__.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/packages/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/packages/__pycache__/ordered_dict.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/packages/__pycache__/six.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/packages/backports/__init__.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/packages/backports/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/packages/backports/__pycache__/makefile.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/packages/backports/makefile.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/packages/ordered_dict.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/packages/six.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/packages/ssl_match_hostname/__init__.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/packages/ssl_match_hostname/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/packages/ssl_match_hostname/__pycache__/_implementation.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/packages/ssl_match_hostname/_implementation.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/poolmanager.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/request.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/response.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/__init__.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/__pycache__/connection.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/__pycache__/request.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/__pycache__/response.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/__pycache__/retry.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/__pycache__/selectors.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/__pycache__/ssl_.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/__pycache__/timeout.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/__pycache__/url.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/__pycache__/wait.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/connection.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/request.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/response.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/retry.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/selectors.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/ssl_.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/timeout.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/url.py create mode 100644 flex/lib/python3.6/site-packages/urllib3/util/wait.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__init__.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/_compat.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/_internal.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/_reloader.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/datastructures.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/exceptions.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/filesystem.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/formparser.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/http.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/local.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/posixemulation.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/routing.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/script.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/security.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/serving.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/test.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/testapp.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/urls.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/useragents.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/utils.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/websocket.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/wrappers.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/__pycache__/wsgi.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/_compat.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/_internal.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/_reloader.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/__init__.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/__pycache__/atom.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/__pycache__/cache.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/__pycache__/fixers.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/__pycache__/iterio.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/__pycache__/jsrouting.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/__pycache__/limiter.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/__pycache__/lint.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/__pycache__/profiler.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/__pycache__/securecookie.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/__pycache__/sessions.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/__pycache__/testtools.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/__pycache__/wrappers.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/atom.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/cache.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/fixers.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/iterio.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/jsrouting.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/limiter.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/lint.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/profiler.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/securecookie.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/sessions.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/testtools.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/contrib/wrappers.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/datastructures.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/__init__.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/__pycache__/__init__.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/__pycache__/console.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/__pycache__/repr.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/__pycache__/tbtools.cpython-36.pyc create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/console.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/repr.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/shared/FONT_LICENSE create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/shared/console.png create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/shared/debugger.js create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/shared/jquery.js create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/shared/less.png create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/shared/more.png create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/shared/source.png create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/shared/style.css create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/shared/ubuntu.ttf create mode 100644 flex/lib/python3.6/site-packages/werkzeug/debug/tbtools.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/exceptions.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/filesystem.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/formparser.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/http.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/local.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/posixemulation.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/routing.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/script.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/security.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/serving.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/test.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/testapp.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/urls.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/useragents.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/utils.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/websocket.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/wrappers.py create mode 100644 flex/lib/python3.6/site-packages/werkzeug/wsgi.py diff --git a/flex/bin/chardetect b/flex/bin/chardetect new file mode 100755 index 0000000..1b7f570 --- /dev/null +++ b/flex/bin/chardetect @@ -0,0 +1,11 @@ +#!/Users/karthikpullela/Desktop/hackdavis/Flex/flex/bin/python3 + +# -*- coding: utf-8 -*- +import re +import sys + +from chardet.cli.chardetect import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/flex/bin/flask b/flex/bin/flask new file mode 100755 index 0000000..870c9b8 --- /dev/null +++ b/flex/bin/flask @@ -0,0 +1,11 @@ +#!/Users/karthikpullela/Desktop/hackdavis/Flex/flex/bin/python3 + +# -*- coding: utf-8 -*- +import re +import sys + +from flask.cli import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/flex/flex/home/__pycache__/views.cpython-36.pyc b/flex/flex/home/__pycache__/views.cpython-36.pyc index 1e336cd6846e0f971d31573ab9af2f44ab050f08..6a55b083bc14674bd72c55519c0a57f19eabe532 100644 GIT binary patch literal 473 zcmYjNy-ve05cb7MTl#}4Au;de6u`%U3@Vz^Don#B zr!q<-9`fjoq%BVGN!(cVuJ@NcErhY-9DFsJ7mX0t z2y=pD$qYDb;T3GKL19ieFoms`2*>N=0!Ny2##XCUGEr(GMUty(eORbUFi%NgE9pST z)OECI)QqDOVYQdSt=hX&?PcGIK0x;~Vh=`W!^%wCVp`S_&=b_PD1;b~zO*lhiLR^l1y{nGlIU7jzGO+;&4g%jOf6m_lirFRW>{alPHKf0d?K is(qvOBbv@;xqsBf3)i`*6kkYj>HpC9+CB`SLw^CpEq18@ delta 266 zcmcb~{F$lVn3tE!ZBug80tN<#$3P4ROhA?c5ErWei4=wu#vF!R#wbQc5SuB7DVI5l z8OUZ%VQFEAVo6~QX3%7N2~^3T$#{#cC^au7wFt=K@hB-N2udw3$j>WIO=bki0|AI; z24ZIh21|xwE+DIfp$2F}GZWAhCci4ajQreGeGs9SQIeaZ$yfw(4A40CqSV6D)Z&tr z3`MMy1sVN?S%KokAV~(sB6c9@r^!0Ggi%W$#4Z9!A`xsr?kx_R-29Z%oK!oI8;V(g J1P>z*GXTMQF~a}= diff --git a/flex/flex/home/templates/home/home.html b/flex/flex/home/templates/home/home.html index 4cf2443..9e8a2de 100644 --- a/flex/flex/home/templates/home/home.html +++ b/flex/flex/home/templates/home/home.html @@ -6,6 +6,8 @@

FLEX - health

+

+ {{ r.text }} \ No newline at end of file diff --git a/flex/flex/home/views.py b/flex/flex/home/views.py index 064a33c..19e66fb 100644 --- a/flex/flex/home/views.py +++ b/flex/flex/home/views.py @@ -1,6 +1,8 @@ from django.shortcuts import render -from django.http import HttpResponse +from django.http import HttpResponse, HttpRequest +import requests # Create your views here. def home(request): - return render(request, 'home/home.html') \ No newline at end of file + r = requests.get('https://www.google.com') + return render(request, 'home/home.html', {'r':r}) \ No newline at end of file diff --git a/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/DESCRIPTION.rst b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..239dbda --- /dev/null +++ b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/DESCRIPTION.rst @@ -0,0 +1,46 @@ +Flask +----- + +Flask is a microframework for Python based on Werkzeug, Jinja 2 and good +intentions. And before you ask: It's BSD licensed! + +Flask is Fun +```````````` + +Save in a hello.py: + +.. code:: python + + from flask import Flask + app = Flask(__name__) + + @app.route("/") + def hello(): + return "Hello World!" + + if __name__ == "__main__": + app.run() + +And Easy to Setup +````````````````` + +And run it: + +.. code:: bash + + $ pip install Flask + $ python hello.py + * Running on http://localhost:5000/ + + Ready for production? `Read this first `. + +Links +````` + +* `website `_ +* `documentation `_ +* `development version + `_ + + + diff --git a/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/INSTALLER b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/LICENSE.txt b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/LICENSE.txt new file mode 100644 index 0000000..a7da10e --- /dev/null +++ b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/LICENSE.txt @@ -0,0 +1,33 @@ +Copyright (c) 2015 by Armin Ronacher and contributors. See AUTHORS +for more details. + +Some rights reserved. + +Redistribution and use in source and binary forms of the software as well +as documentation, with or without modification, are permitted provided +that the following conditions are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +* The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. diff --git a/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/METADATA b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/METADATA new file mode 100644 index 0000000..8c43205 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/METADATA @@ -0,0 +1,75 @@ +Metadata-Version: 2.0 +Name: Flask +Version: 0.12.2 +Summary: A microframework based on Werkzeug, Jinja2 and good intentions +Home-page: http://github.com/pallets/flask/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +License: BSD +Platform: any +Classifier: Development Status :: 4 - Beta +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Requires-Dist: Jinja2 (>=2.4) +Requires-Dist: Werkzeug (>=0.7) +Requires-Dist: click (>=2.0) +Requires-Dist: itsdangerous (>=0.21) + +Flask +----- + +Flask is a microframework for Python based on Werkzeug, Jinja 2 and good +intentions. And before you ask: It's BSD licensed! + +Flask is Fun +```````````` + +Save in a hello.py: + +.. code:: python + + from flask import Flask + app = Flask(__name__) + + @app.route("/") + def hello(): + return "Hello World!" + + if __name__ == "__main__": + app.run() + +And Easy to Setup +````````````````` + +And run it: + +.. code:: bash + + $ pip install Flask + $ python hello.py + * Running on http://localhost:5000/ + + Ready for production? `Read this first `. + +Links +````` + +* `website `_ +* `documentation `_ +* `development version + `_ + + + diff --git a/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/RECORD b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/RECORD new file mode 100644 index 0000000..70595d3 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/RECORD @@ -0,0 +1,52 @@ +Flask-0.12.2.dist-info/DESCRIPTION.rst,sha256=DmJm8IBlBjl3wkm0Ly23jYvWbvK_mCuE5oUseYCijbI,810 +Flask-0.12.2.dist-info/LICENSE.txt,sha256=hLgKluMRHSnxG-L0EmrqjmKgG5cHlff6pIh3rCNINeI,1582 +Flask-0.12.2.dist-info/METADATA,sha256=OgSkJQ_kmrz4qEkS-OzYtL75uZmXAThymkOcGR4kXRQ,1948 +Flask-0.12.2.dist-info/RECORD,, +Flask-0.12.2.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 +Flask-0.12.2.dist-info/entry_points.txt,sha256=jzk2Wy2h30uEcqqzd4CVnlzsMXB-vaD5GXjuPMXmTmI,60 +Flask-0.12.2.dist-info/metadata.json,sha256=By8kZ1vY9lLEAGnRiWNBhudqKvLPo0HkZVXTYECyPKk,1389 +Flask-0.12.2.dist-info/top_level.txt,sha256=dvi65F6AeGWVU0TBpYiC04yM60-FX1gJFkK31IKQr5c,6 +flask/__init__.py,sha256=sHdK1v6WRbVmCN0fEv990EE7rOT2UlamQkSof2d0Dt0,1673 +flask/__main__.py,sha256=cldbNi5zpjE68XzIWI8uYHNWwBHHVJmwtlXWk6P4CO4,291 +flask/_compat.py,sha256=VlfjUuLjufsTHJIjr_ZsnnOesSbAXIslBBgRe5tfOok,2802 +flask/app.py,sha256=6DPjtb5jUJWgL5fXksG5boA49EB3l-k9pWyftitbNNk,83169 +flask/blueprints.py,sha256=6HVasMcPcaq7tk36kCrgX4bnhTkky4G5WIWCyyJL8HY,16872 +flask/cli.py,sha256=2NXEdCOu5-4ymklxX4Lf6bjb-89I4VHYeP6xScR3i8E,18328 +flask/config.py,sha256=Ym5Jenyu6zAZ1fdVLeKekY9-EsKmq8183qnRgauwCMY,9905 +flask/ctx.py,sha256=UPA0YwoIlHP0txOGanC9lQLSGv6eCqV5Fmw2cVJRmgQ,14739 +flask/debughelpers.py,sha256=z-uQavKIymOZl0WQDLXsnacA00ERIlCx3S3Tnb_OYsE,6024 +flask/exthook.py,sha256=SvXs5jwpcOjogwJ7SNquiWTxowoN1-MHFoqAejWnk2o,5762 +flask/globals.py,sha256=I3m_4RssLhWW1R11zuEI8oFryHUHX3NQwjMkGXOZzg8,1645 +flask/helpers.py,sha256=KrsQ2Yo3lOVHvBTgQCLvpubgmTOpQdTTyiCOOYlwDuQ,38452 +flask/json.py,sha256=1zPM-NPLiWoOfGd0P14FxnEkeKtjtUZxMC9pyYyDBYI,9183 +flask/logging.py,sha256=UG-77jPkRClk9w1B-_ArjjXPuj9AmZz9mG0IRGvptW0,2751 +flask/sessions.py,sha256=QBKXVYKJ-HKbx9m6Yb5yan_EPq84a5yevVLgAzNKFQY,14394 +flask/signals.py,sha256=MfZk5qTRj_R_O3aGYlTEnx2g3SvlZncz8Ii73eKK59g,2209 +flask/templating.py,sha256=u7FbN6j56H_q6CrdJJyJ6gZtqaMa0vh1_GP12gEHRQQ,4912 +flask/testing.py,sha256=II8EO_NjOT1LvL8Hh_SdIFL_BdlwVPcB9yot5pbltxE,5630 +flask/views.py,sha256=6OPv7gwu3h14JhqpeeMRWwrxoGHsUr4_nOGSyTRAxAI,5630 +flask/wrappers.py,sha256=1S_5mmuA1Tlx7D9lXV6xMblrg-PdAauNWahe-henMEE,7612 +flask/ext/__init__.py,sha256=UEezCApsG4ZJWqwUnX9YmWcNN4OVENgph_9L05n0eOM,842 +../../../bin/flask,sha256=Dvns7NRNbpv589oWzJyzp5zTknhHkVZDfPeYpq0Cyz4,257 +Flask-0.12.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +flask/ext/__pycache__/__init__.cpython-36.pyc,, +flask/__pycache__/blueprints.cpython-36.pyc,, +flask/__pycache__/logging.cpython-36.pyc,, +flask/__pycache__/sessions.cpython-36.pyc,, +flask/__pycache__/templating.cpython-36.pyc,, +flask/__pycache__/cli.cpython-36.pyc,, +flask/__pycache__/config.cpython-36.pyc,, +flask/__pycache__/signals.cpython-36.pyc,, +flask/__pycache__/testing.cpython-36.pyc,, +flask/__pycache__/views.cpython-36.pyc,, +flask/__pycache__/ctx.cpython-36.pyc,, +flask/__pycache__/app.cpython-36.pyc,, +flask/__pycache__/exthook.cpython-36.pyc,, +flask/__pycache__/__main__.cpython-36.pyc,, +flask/__pycache__/_compat.cpython-36.pyc,, +flask/__pycache__/helpers.cpython-36.pyc,, +flask/__pycache__/wrappers.cpython-36.pyc,, +flask/__pycache__/__init__.cpython-36.pyc,, +flask/__pycache__/debughelpers.cpython-36.pyc,, +flask/__pycache__/globals.cpython-36.pyc,, +flask/__pycache__/json.cpython-36.pyc,, diff --git a/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/WHEEL b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/WHEEL new file mode 100644 index 0000000..8b6dd1b --- /dev/null +++ b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.29.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/entry_points.txt b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/entry_points.txt new file mode 100644 index 0000000..14adf18 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/entry_points.txt @@ -0,0 +1,4 @@ + + [console_scripts] + flask=flask.cli:main + \ No newline at end of file diff --git a/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/metadata.json b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/metadata.json new file mode 100644 index 0000000..4d814b8 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/metadata.json @@ -0,0 +1 @@ +{"classifiers": ["Development Status :: 4 - Beta", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules"], "extensions": {"python.commands": {"wrap_console": {"flask": "flask.cli:main"}}, "python.details": {"contacts": [{"email": "armin.ronacher@active-4.com", "name": "Armin Ronacher", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst", "license": "LICENSE.txt"}, "project_urls": {"Home": "http://github.com/pallets/flask/"}}, "python.exports": {"console_scripts": {"flask": "flask.cli:main"}}}, "extras": [], "generator": "bdist_wheel (0.29.0)", "license": "BSD", "metadata_version": "2.0", "name": "Flask", "platform": "any", "run_requires": [{"requires": ["Jinja2 (>=2.4)", "Werkzeug (>=0.7)", "click (>=2.0)", "itsdangerous (>=0.21)"]}], "summary": "A microframework based on Werkzeug, Jinja2 and good intentions", "version": "0.12.2"} \ No newline at end of file diff --git a/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/top_level.txt b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/top_level.txt new file mode 100644 index 0000000..7e10602 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Flask-0.12.2.dist-info/top_level.txt @@ -0,0 +1 @@ +flask diff --git a/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/DESCRIPTION.rst b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..1594da5 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/DESCRIPTION.rst @@ -0,0 +1,37 @@ + +Jinja2 +~~~~~~ + +Jinja2 is a template engine written in pure Python. It provides a +`Django`_ inspired non-XML syntax but supports inline expressions and +an optional `sandboxed`_ environment. + +Nutshell +-------- + +Here a small example of a Jinja template:: + + {% extends 'base.html' %} + {% block title %}Memberlist{% endblock %} + {% block content %} + + {% endblock %} + +Philosophy +---------- + +Application logic is for the controller but don't try to make the life +for the template designer too hard by giving him too few functionality. + +For more informations visit the new `Jinja2 webpage`_ and `documentation`_. + +.. _sandboxed: https://en.wikipedia.org/wiki/Sandbox_(computer_security) +.. _Django: https://www.djangoproject.com/ +.. _Jinja2 webpage: http://jinja.pocoo.org/ +.. _documentation: http://jinja.pocoo.org/2/documentation/ + + diff --git a/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/INSTALLER b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/LICENSE.txt b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/LICENSE.txt new file mode 100644 index 0000000..10145a2 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/LICENSE.txt @@ -0,0 +1,31 @@ +Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/METADATA b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/METADATA new file mode 100644 index 0000000..40f2b46 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/METADATA @@ -0,0 +1,68 @@ +Metadata-Version: 2.0 +Name: Jinja2 +Version: 2.10 +Summary: A small but fast and easy to use stand-alone template engine written in pure python. +Home-page: http://jinja.pocoo.org/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +License: BSD +Description-Content-Type: UNKNOWN +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup :: HTML +Requires-Dist: MarkupSafe (>=0.23) +Provides-Extra: i18n +Requires-Dist: Babel (>=0.8); extra == 'i18n' + + +Jinja2 +~~~~~~ + +Jinja2 is a template engine written in pure Python. It provides a +`Django`_ inspired non-XML syntax but supports inline expressions and +an optional `sandboxed`_ environment. + +Nutshell +-------- + +Here a small example of a Jinja template:: + + {% extends 'base.html' %} + {% block title %}Memberlist{% endblock %} + {% block content %} + + {% endblock %} + +Philosophy +---------- + +Application logic is for the controller but don't try to make the life +for the template designer too hard by giving him too few functionality. + +For more informations visit the new `Jinja2 webpage`_ and `documentation`_. + +.. _sandboxed: https://en.wikipedia.org/wiki/Sandbox_(computer_security) +.. _Django: https://www.djangoproject.com/ +.. _Jinja2 webpage: http://jinja.pocoo.org/ +.. _documentation: http://jinja.pocoo.org/2/documentation/ + + diff --git a/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/RECORD b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/RECORD new file mode 100644 index 0000000..e4d7ce6 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/RECORD @@ -0,0 +1,63 @@ +Jinja2-2.10.dist-info/DESCRIPTION.rst,sha256=b5ckFDoM7vVtz_mAsJD4OPteFKCqE7beu353g4COoYI,978 +Jinja2-2.10.dist-info/LICENSE.txt,sha256=JvzUNv3Io51EiWrAPm8d_SXjhJnEjyDYvB3Tvwqqils,1554 +Jinja2-2.10.dist-info/METADATA,sha256=18EgU8zR6-av-0-5y_gXebzK4GnBB_76lALUsl-6QHM,2258 +Jinja2-2.10.dist-info/RECORD,, +Jinja2-2.10.dist-info/WHEEL,sha256=kdsN-5OJAZIiHN-iO4Rhl82KyS0bDWf4uBwMbkNafr8,110 +Jinja2-2.10.dist-info/entry_points.txt,sha256=NdzVcOrqyNyKDxD09aERj__3bFx2paZhizFDsKmVhiA,72 +Jinja2-2.10.dist-info/metadata.json,sha256=NPUJ9TMBxVQAv_kTJzvU8HwmP-4XZvbK9mz6_4YUVl4,1473 +Jinja2-2.10.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7 +jinja2/__init__.py,sha256=xJHjaMoy51_KXn1wf0cysH6tUUifUxZCwSOfcJGEYZw,2614 +jinja2/_compat.py,sha256=xP60CE5Qr8FTYcDE1f54tbZLKGvMwYml4-8T7Q4KG9k,2596 +jinja2/_identifier.py,sha256=W1QBSY-iJsyt6oR_nKSuNNCzV95vLIOYgUNPUI1d5gU,1726 +jinja2/asyncfilters.py,sha256=cTDPvrS8Hp_IkwsZ1m9af_lr5nHysw7uTa5gV0NmZVE,4144 +jinja2/asyncsupport.py,sha256=UErQ3YlTLaSjFb94P4MVn08-aVD9jJxty2JVfMRb-1M,7878 +jinja2/bccache.py,sha256=nQldx0ZRYANMyfvOihRoYFKSlUdd5vJkS7BjxNwlOZM,12794 +jinja2/compiler.py,sha256=BqC5U6JxObSRhblyT_a6Tp5GtEU5z3US1a4jLQaxxgo,65386 +jinja2/constants.py,sha256=uwwV8ZUhHhacAuz5PTwckfsbqBaqM7aKfyJL7kGX5YQ,1626 +jinja2/debug.py,sha256=WTVeUFGUa4v6ReCsYv-iVPa3pkNB75OinJt3PfxNdXs,12045 +jinja2/defaults.py,sha256=Em-95hmsJxIenDCZFB1YSvf9CNhe9rBmytN3yUrBcWA,1400 +jinja2/environment.py,sha256=VnkAkqw8JbjZct4tAyHlpBrka2vqB-Z58RAP-32P1ZY,50849 +jinja2/exceptions.py,sha256=_Rj-NVi98Q6AiEjYQOsP8dEIdu5AlmRHzcSNOPdWix4,4428 +jinja2/ext.py,sha256=atMQydEC86tN1zUsdQiHw5L5cF62nDbqGue25Yiu3N4,24500 +jinja2/filters.py,sha256=yOAJk0MsH-_gEC0i0U6NweVQhbtYaC-uE8xswHFLF4w,36528 +jinja2/idtracking.py,sha256=2GbDSzIvGArEBGLkovLkqEfmYxmWsEf8c3QZwM4uNsw,9197 +jinja2/lexer.py,sha256=ySEPoXd1g7wRjsuw23uimS6nkGN5aqrYwcOKxCaVMBQ,28559 +jinja2/loaders.py,sha256=xiTuURKAEObyym0nU8PCIXu_Qp8fn0AJ5oIADUUm-5Q,17382 +jinja2/meta.py,sha256=fmKHxkmZYAOm9QyWWy8EMd6eefAIh234rkBMW2X4ZR8,4340 +jinja2/nativetypes.py,sha256=_sJhS8f-8Q0QMIC0dm1YEdLyxEyoO-kch8qOL5xUDfE,7308 +jinja2/nodes.py,sha256=L10L_nQDfubLhO3XjpF9qz46FSh2clL-3e49ogVlMmA,30853 +jinja2/optimizer.py,sha256=MsdlFACJ0FRdPtjmCAdt7JQ9SGrXFaDNUaslsWQaG3M,1722 +jinja2/parser.py,sha256=lPzTEbcpTRBLw8ii6OYyExHeAhaZLMA05Hpv4ll3ULk,35875 +jinja2/runtime.py,sha256=DHdD38Pq8gj7uWQC5usJyWFoNWL317A9AvXOW_CLB34,27755 +jinja2/sandbox.py,sha256=TVyZHlNqqTzsv9fv2NvJNmSdWRHTguhyMHdxjWms32U,16708 +jinja2/tests.py,sha256=iJQLwbapZr-EKquTG_fVOVdwHUUKf3SX9eNkjQDF8oU,4237 +jinja2/utils.py,sha256=q24VupGZotQ-uOyrJxCaXtDWhZC1RgsQG7kcdmjck2Q,20629 +jinja2/visitor.py,sha256=JD1H1cANA29JcntFfN5fPyqQxB4bI4wC00BzZa-XHks,3316 +Jinja2-2.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +jinja2/__pycache__/lexer.cpython-36.pyc,, +jinja2/__pycache__/sandbox.cpython-36.pyc,, +jinja2/__pycache__/debug.cpython-36.pyc,, +jinja2/__pycache__/constants.cpython-36.pyc,, +jinja2/__pycache__/idtracking.cpython-36.pyc,, +jinja2/__pycache__/parser.cpython-36.pyc,, +jinja2/__pycache__/exceptions.cpython-36.pyc,, +jinja2/__pycache__/ext.cpython-36.pyc,, +jinja2/__pycache__/meta.cpython-36.pyc,, +jinja2/__pycache__/environment.cpython-36.pyc,, +jinja2/__pycache__/loaders.cpython-36.pyc,, +jinja2/__pycache__/asyncsupport.cpython-36.pyc,, +jinja2/__pycache__/asyncfilters.cpython-36.pyc,, +jinja2/__pycache__/tests.cpython-36.pyc,, +jinja2/__pycache__/optimizer.cpython-36.pyc,, +jinja2/__pycache__/compiler.cpython-36.pyc,, +jinja2/__pycache__/bccache.cpython-36.pyc,, +jinja2/__pycache__/_identifier.cpython-36.pyc,, +jinja2/__pycache__/_compat.cpython-36.pyc,, +jinja2/__pycache__/defaults.cpython-36.pyc,, +jinja2/__pycache__/utils.cpython-36.pyc,, +jinja2/__pycache__/nodes.cpython-36.pyc,, +jinja2/__pycache__/filters.cpython-36.pyc,, +jinja2/__pycache__/runtime.cpython-36.pyc,, +jinja2/__pycache__/__init__.cpython-36.pyc,, +jinja2/__pycache__/nativetypes.cpython-36.pyc,, +jinja2/__pycache__/visitor.cpython-36.pyc,, diff --git a/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/WHEEL b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/WHEEL new file mode 100644 index 0000000..7332a41 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.30.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/entry_points.txt b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/entry_points.txt new file mode 100644 index 0000000..32e6b75 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/entry_points.txt @@ -0,0 +1,4 @@ + + [babel.extractors] + jinja2 = jinja2.ext:babel_extract[i18n] + \ No newline at end of file diff --git a/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/metadata.json b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/metadata.json new file mode 100644 index 0000000..7f5dc38 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/metadata.json @@ -0,0 +1 @@ +{"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Text Processing :: Markup :: HTML"], "description_content_type": "UNKNOWN", "extensions": {"python.details": {"contacts": [{"email": "armin.ronacher@active-4.com", "name": "Armin Ronacher", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst", "license": "LICENSE.txt"}, "project_urls": {"Home": "http://jinja.pocoo.org/"}}, "python.exports": {"babel.extractors": {"jinja2": "jinja2.ext:babel_extract [i18n]"}}}, "extras": ["i18n"], "generator": "bdist_wheel (0.30.0)", "license": "BSD", "metadata_version": "2.0", "name": "Jinja2", "run_requires": [{"extra": "i18n", "requires": ["Babel (>=0.8)"]}, {"requires": ["MarkupSafe (>=0.23)"]}], "summary": "A small but fast and easy to use stand-alone template engine written in pure python.", "version": "2.10"} \ No newline at end of file diff --git a/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/top_level.txt b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/top_level.txt new file mode 100644 index 0000000..7f7afbf --- /dev/null +++ b/flex/lib/python3.6/site-packages/Jinja2-2.10.dist-info/top_level.txt @@ -0,0 +1 @@ +jinja2 diff --git a/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/DESCRIPTION.rst b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..495211b --- /dev/null +++ b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/DESCRIPTION.rst @@ -0,0 +1,115 @@ +MarkupSafe +========== + +Implements a unicode subclass that supports HTML strings: + +.. code-block:: python + + >>> from markupsafe import Markup, escape + >>> escape("") + Markup(u'<script>alert(document.cookie);</script>') + >>> tmpl = Markup("%s") + >>> tmpl % "Peter > Lustig" + Markup(u'Peter > Lustig') + +If you want to make an object unicode that is not yet unicode +but don't want to lose the taint information, you can use the +``soft_unicode`` function. (On Python 3 you can also use ``soft_str`` which +is a different name for the same function). + +.. code-block:: python + + >>> from markupsafe import soft_unicode + >>> soft_unicode(42) + u'42' + >>> soft_unicode(Markup('foo')) + Markup(u'foo') + +HTML Representations +-------------------- + +Objects can customize their HTML markup equivalent by overriding +the ``__html__`` function: + +.. code-block:: python + + >>> class Foo(object): + ... def __html__(self): + ... return 'Nice' + ... + >>> escape(Foo()) + Markup(u'Nice') + >>> Markup(Foo()) + Markup(u'Nice') + +Silent Escapes +-------------- + +Since MarkupSafe 0.10 there is now also a separate escape function +called ``escape_silent`` that returns an empty string for ``None`` for +consistency with other systems that return empty strings for ``None`` +when escaping (for instance Pylons' webhelpers). + +If you also want to use this for the escape method of the Markup +object, you can create your own subclass that does that: + +.. code-block:: python + + from markupsafe import Markup, escape_silent as escape + + class SilentMarkup(Markup): + __slots__ = () + + @classmethod + def escape(cls, s): + return cls(escape(s)) + +New-Style String Formatting +--------------------------- + +Starting with MarkupSafe 0.21 new style string formats from Python 2.6 and +3.x are now fully supported. Previously the escape behavior of those +functions was spotty at best. The new implementations operates under the +following algorithm: + +1. if an object has an ``__html_format__`` method it is called as + replacement for ``__format__`` with the format specifier. It either + has to return a string or markup object. +2. if an object has an ``__html__`` method it is called. +3. otherwise the default format system of Python kicks in and the result + is HTML escaped. + +Here is how you can implement your own formatting: + +.. code-block:: python + + class User(object): + + def __init__(self, id, username): + self.id = id + self.username = username + + def __html_format__(self, format_spec): + if format_spec == 'link': + return Markup('{1}').format( + self.id, + self.__html__(), + ) + elif format_spec: + raise ValueError('Invalid format spec') + return self.__html__() + + def __html__(self): + return Markup('{0}').format(self.username) + +And to format that user: + +.. code-block:: python + + >>> user = User(1, 'foo') + >>> Markup('

User: {0:link}').format(user) + Markup(u'

User: foo') + +Markupsafe supports Python 2.6, 2.7 and Python 3.3 and higher. + + diff --git a/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/INSTALLER b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/LICENSE.txt b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/LICENSE.txt new file mode 100644 index 0000000..5d26938 --- /dev/null +++ b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/LICENSE.txt @@ -0,0 +1,33 @@ +Copyright (c) 2010 by Armin Ronacher and contributors. See AUTHORS +for more details. + +Some rights reserved. + +Redistribution and use in source and binary forms of the software as well +as documentation, with or without modification, are permitted provided +that the following conditions are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +* The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. diff --git a/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/METADATA b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/METADATA new file mode 100644 index 0000000..725be08 --- /dev/null +++ b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/METADATA @@ -0,0 +1,135 @@ +Metadata-Version: 2.0 +Name: MarkupSafe +Version: 1.0 +Summary: Implements a XML/HTML/XHTML Markup safe string for Python +Home-page: http://github.com/pallets/markupsafe +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +License: BSD +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup :: HTML + +MarkupSafe +========== + +Implements a unicode subclass that supports HTML strings: + +.. code-block:: python + + >>> from markupsafe import Markup, escape + >>> escape("") + Markup(u'<script>alert(document.cookie);</script>') + >>> tmpl = Markup("%s") + >>> tmpl % "Peter > Lustig" + Markup(u'Peter > Lustig') + +If you want to make an object unicode that is not yet unicode +but don't want to lose the taint information, you can use the +``soft_unicode`` function. (On Python 3 you can also use ``soft_str`` which +is a different name for the same function). + +.. code-block:: python + + >>> from markupsafe import soft_unicode + >>> soft_unicode(42) + u'42' + >>> soft_unicode(Markup('foo')) + Markup(u'foo') + +HTML Representations +-------------------- + +Objects can customize their HTML markup equivalent by overriding +the ``__html__`` function: + +.. code-block:: python + + >>> class Foo(object): + ... def __html__(self): + ... return 'Nice' + ... + >>> escape(Foo()) + Markup(u'Nice') + >>> Markup(Foo()) + Markup(u'Nice') + +Silent Escapes +-------------- + +Since MarkupSafe 0.10 there is now also a separate escape function +called ``escape_silent`` that returns an empty string for ``None`` for +consistency with other systems that return empty strings for ``None`` +when escaping (for instance Pylons' webhelpers). + +If you also want to use this for the escape method of the Markup +object, you can create your own subclass that does that: + +.. code-block:: python + + from markupsafe import Markup, escape_silent as escape + + class SilentMarkup(Markup): + __slots__ = () + + @classmethod + def escape(cls, s): + return cls(escape(s)) + +New-Style String Formatting +--------------------------- + +Starting with MarkupSafe 0.21 new style string formats from Python 2.6 and +3.x are now fully supported. Previously the escape behavior of those +functions was spotty at best. The new implementations operates under the +following algorithm: + +1. if an object has an ``__html_format__`` method it is called as + replacement for ``__format__`` with the format specifier. It either + has to return a string or markup object. +2. if an object has an ``__html__`` method it is called. +3. otherwise the default format system of Python kicks in and the result + is HTML escaped. + +Here is how you can implement your own formatting: + +.. code-block:: python + + class User(object): + + def __init__(self, id, username): + self.id = id + self.username = username + + def __html_format__(self, format_spec): + if format_spec == 'link': + return Markup('{1}').format( + self.id, + self.__html__(), + ) + elif format_spec: + raise ValueError('Invalid format spec') + return self.__html__() + + def __html__(self): + return Markup('{0}').format(self.username) + +And to format that user: + +.. code-block:: python + + >>> user = User(1, 'foo') + >>> Markup('

User: {0:link}').format(user) + Markup(u'

User: foo') + +Markupsafe supports Python 2.6, 2.7 and Python 3.3 and higher. + + diff --git a/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/RECORD b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/RECORD new file mode 100644 index 0000000..e7fbf2b --- /dev/null +++ b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/RECORD @@ -0,0 +1,18 @@ +MarkupSafe-1.0.dist-info/DESCRIPTION.rst,sha256=3B3J0YLzzmJQVaWQ_XlVMhGeHA_DvBqysABvul_5fko,3397 +MarkupSafe-1.0.dist-info/LICENSE.txt,sha256=C76IIo_WPSDsCX9k5Y1aCkZRI64TkUChjUBsYLSIJLU,1582 +MarkupSafe-1.0.dist-info/METADATA,sha256=EUwvRzJbtRP3hBMc8Z2TDT44TBDeZdIurbGzIc7FOkg,4182 +MarkupSafe-1.0.dist-info/RECORD,, +MarkupSafe-1.0.dist-info/WHEEL,sha256=OFNdaJiI9g_GkizF_uxlV7QqkMhIg08EkykbDF40LSY,109 +MarkupSafe-1.0.dist-info/metadata.json,sha256=LPb3W7qq-SH_u1SFzjXQqT8sCGpE-b4NmYAxMcw91e8,924 +MarkupSafe-1.0.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 +markupsafe/__init__.py,sha256=xtkRdxhzJzgp65wUo1D4DjnazxHU88pPldaAuDekBeY,10697 +markupsafe/_compat.py,sha256=r1HE0CpcAZeb-AiTV9wITR91PeLHn0CzZ_XHkYoozpI,565 +markupsafe/_constants.py,sha256=U_xybFQsyXKCgHSfranJnFzo-z9nn9fuBeSk243sE5Q,4795 +markupsafe/_native.py,sha256=E2Un1ysOf-w45d18YCj8UelT5UP7Vt__IuFPYJ7YRIs,1187 +markupsafe/_speedups.c,sha256=B6Mf6Fn33WqkagfwY7q5ZBSm_vJoHDYxDB0Jp_DP7Jw,5936 +markupsafe/_speedups.cpython-36m-darwin.so,sha256=3TPPKm0bCg7eEE4RjnhAsEoEzykFtaXPEzhvbcxroVc,31080 +MarkupSafe-1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +markupsafe/__pycache__/_native.cpython-36.pyc,, +markupsafe/__pycache__/_constants.cpython-36.pyc,, +markupsafe/__pycache__/_compat.cpython-36.pyc,, +markupsafe/__pycache__/__init__.cpython-36.pyc,, diff --git a/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/WHEEL b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/WHEEL new file mode 100644 index 0000000..92d86eb --- /dev/null +++ b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.30.0) +Root-Is-Purelib: false +Tag: cp36-cp36m-macosx_10_6_intel + diff --git a/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/metadata.json b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/metadata.json new file mode 100644 index 0000000..7c29531 --- /dev/null +++ b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/metadata.json @@ -0,0 +1 @@ +{"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Text Processing :: Markup :: HTML"], "extensions": {"python.details": {"contacts": [{"email": "armin.ronacher@active-4.com", "name": "Armin Ronacher", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst", "license": "LICENSE.txt"}, "project_urls": {"Home": "http://github.com/pallets/markupsafe"}}}, "generator": "bdist_wheel (0.30.0)", "license": "BSD", "metadata_version": "2.0", "name": "MarkupSafe", "summary": "Implements a XML/HTML/XHTML Markup safe string for Python", "version": "1.0"} \ No newline at end of file diff --git a/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/top_level.txt b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/top_level.txt new file mode 100644 index 0000000..75bf729 --- /dev/null +++ b/flex/lib/python3.6/site-packages/MarkupSafe-1.0.dist-info/top_level.txt @@ -0,0 +1 @@ +markupsafe diff --git a/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/DESCRIPTION.rst b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..675f08d --- /dev/null +++ b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/DESCRIPTION.rst @@ -0,0 +1,80 @@ +Werkzeug +======== + +Werkzeug is a comprehensive `WSGI`_ web application library. It began as +a simple collection of various utilities for WSGI applications and has +become one of the most advanced WSGI utility libraries. + +It includes: + +* An interactive debugger that allows inspecting stack traces and source + code in the browser with an interactive interpreter for any frame in + the stack. +* A full-featured request object with objects to interact with headers, + query args, form data, files, and cookies. +* A response object that can wrap other WSGI applications and handle + streaming data. +* A routing system for matching URLs to endpoints and generating URLs + for endpoints, with an extensible system for capturing variables from + URLs. +* HTTP utilities to handle entity tags, cache control, dates, user + agents, cookies, files, and more. +* A threaded WSGI server for use while developing applications locally. +* A test client for simulating HTTP requests during testing without + requiring running a server. + +Werkzeug is Unicode aware and doesn't enforce any dependencies. It is up +to the developer to choose a template engine, database adapter, and even +how to handle requests. It can be used to build all sorts of end user +applications such as blogs, wikis, or bulletin boards. + +`Flask`_ wraps Werkzeug, using it to handle the details of WSGI while +providing more structure and patterns for defining powerful +applications. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + pip install -U Werkzeug + + +A Simple Example +---------------- + +.. code-block:: python + + from werkzeug.wrappers import Request, Response + + @Request.application + def application(request): + return Response('Hello, World!') + + if __name__ == '__main__': + from werkzeug.serving import run_simple + run_simple('localhost', 4000, application) + + +Links +----- + +* Website: https://www.palletsprojects.com/p/werkzeug/ +* Releases: https://pypi.org/project/Werkzeug/ +* Code: https://github.com/pallets/werkzeug +* Issue tracker: https://github.com/pallets/werkzeug/issues +* Test status: + + * Linux, Mac: https://travis-ci.org/pallets/werkzeug + * Windows: https://ci.appveyor.com/project/davidism/werkzeug + +* Test coverage: https://codecov.io/gh/pallets/werkzeug + +.. _WSGI: https://wsgi.readthedocs.io/en/latest/ +.. _Flask: https://www.palletsprojects.com/p/flask/ +.. _pip: https://pip.pypa.io/en/stable/quickstart/ + + diff --git a/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/INSTALLER b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/LICENSE.txt b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/LICENSE.txt new file mode 100644 index 0000000..1cc75bb --- /dev/null +++ b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/LICENSE.txt @@ -0,0 +1,31 @@ +Copyright © 2007 by the Pallets team. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/METADATA b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/METADATA new file mode 100644 index 0000000..bfc3c4e --- /dev/null +++ b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/METADATA @@ -0,0 +1,116 @@ +Metadata-Version: 2.0 +Name: Werkzeug +Version: 0.14.1 +Summary: The comprehensive WSGI web application library. +Home-page: https://www.palletsprojects.org/p/werkzeug/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +License: BSD +Description-Content-Type: UNKNOWN +Platform: any +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Provides-Extra: dev +Requires-Dist: coverage; extra == 'dev' +Requires-Dist: pytest; extra == 'dev' +Requires-Dist: sphinx; extra == 'dev' +Requires-Dist: tox; extra == 'dev' +Provides-Extra: termcolor +Requires-Dist: termcolor; extra == 'termcolor' +Provides-Extra: watchdog +Requires-Dist: watchdog; extra == 'watchdog' + +Werkzeug +======== + +Werkzeug is a comprehensive `WSGI`_ web application library. It began as +a simple collection of various utilities for WSGI applications and has +become one of the most advanced WSGI utility libraries. + +It includes: + +* An interactive debugger that allows inspecting stack traces and source + code in the browser with an interactive interpreter for any frame in + the stack. +* A full-featured request object with objects to interact with headers, + query args, form data, files, and cookies. +* A response object that can wrap other WSGI applications and handle + streaming data. +* A routing system for matching URLs to endpoints and generating URLs + for endpoints, with an extensible system for capturing variables from + URLs. +* HTTP utilities to handle entity tags, cache control, dates, user + agents, cookies, files, and more. +* A threaded WSGI server for use while developing applications locally. +* A test client for simulating HTTP requests during testing without + requiring running a server. + +Werkzeug is Unicode aware and doesn't enforce any dependencies. It is up +to the developer to choose a template engine, database adapter, and even +how to handle requests. It can be used to build all sorts of end user +applications such as blogs, wikis, or bulletin boards. + +`Flask`_ wraps Werkzeug, using it to handle the details of WSGI while +providing more structure and patterns for defining powerful +applications. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + pip install -U Werkzeug + + +A Simple Example +---------------- + +.. code-block:: python + + from werkzeug.wrappers import Request, Response + + @Request.application + def application(request): + return Response('Hello, World!') + + if __name__ == '__main__': + from werkzeug.serving import run_simple + run_simple('localhost', 4000, application) + + +Links +----- + +* Website: https://www.palletsprojects.com/p/werkzeug/ +* Releases: https://pypi.org/project/Werkzeug/ +* Code: https://github.com/pallets/werkzeug +* Issue tracker: https://github.com/pallets/werkzeug/issues +* Test status: + + * Linux, Mac: https://travis-ci.org/pallets/werkzeug + * Windows: https://ci.appveyor.com/project/davidism/werkzeug + +* Test coverage: https://codecov.io/gh/pallets/werkzeug + +.. _WSGI: https://wsgi.readthedocs.io/en/latest/ +.. _Flask: https://www.palletsprojects.com/p/flask/ +.. _pip: https://pip.pypa.io/en/stable/quickstart/ + + diff --git a/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/RECORD b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/RECORD new file mode 100644 index 0000000..51590a6 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/RECORD @@ -0,0 +1,97 @@ +Werkzeug-0.14.1.dist-info/DESCRIPTION.rst,sha256=rOCN36jwsWtWsTpqPG96z7FMilB5qI1CIARSKRuUmz8,2452 +Werkzeug-0.14.1.dist-info/LICENSE.txt,sha256=xndz_dD4m269AF9l_Xbl5V3tM1N3C1LoZC2PEPxWO-8,1534 +Werkzeug-0.14.1.dist-info/METADATA,sha256=FbfadrPdJNUWAxMOKxGUtHe5R3IDSBKYYmAz3FvI3uY,3872 +Werkzeug-0.14.1.dist-info/RECORD,, +Werkzeug-0.14.1.dist-info/WHEEL,sha256=GrqQvamwgBV4nLoJe0vhYRSWzWsx7xjlt74FT0SWYfE,110 +Werkzeug-0.14.1.dist-info/metadata.json,sha256=4489UTt6HBp2NQil95-pBkjU4Je93SMHvMxZ_rjOpqA,1452 +Werkzeug-0.14.1.dist-info/top_level.txt,sha256=QRyj2VjwJoQkrwjwFIOlB8Xg3r9un0NtqVHQF-15xaw,9 +werkzeug/__init__.py,sha256=NR0d4n_-U9BLVKlOISean3zUt2vBwhvK-AZE6M0sC0k,6842 +werkzeug/_compat.py,sha256=8c4U9o6A_TR9nKCcTbpZNxpqCXcXDVIbFawwKM2s92c,6311 +werkzeug/_internal.py,sha256=GhEyGMlsSz_tYjsDWO9TG35VN7304MM8gjKDrXLEdVc,13873 +werkzeug/_reloader.py,sha256=AyPphcOHPbu6qzW0UbrVvTDJdre5WgpxbhIJN_TqzUc,9264 +werkzeug/datastructures.py,sha256=3IgNKNqrz-ZjmAG7y3YgEYK-enDiMT_b652PsypWcYg,90080 +werkzeug/exceptions.py,sha256=3wp95Hqj9FqV8MdikV99JRcHse_fSMn27V8tgP5Hw2c,20505 +werkzeug/filesystem.py,sha256=hHWeWo_gqLMzTRfYt8-7n2wWcWUNTnDyudQDLOBEICE,2175 +werkzeug/formparser.py,sha256=mUuCwjzjb8_E4RzrAT2AioLuZSYpqR1KXTK6LScRYzA,21722 +werkzeug/http.py,sha256=RQg4MJuhRv2isNRiEh__Phh09ebpfT3Kuu_GfrZ54_c,40079 +werkzeug/local.py,sha256=QdQhWV5L8p1Y1CJ1CDStwxaUs24SuN5aebHwjVD08C8,14553 +werkzeug/posixemulation.py,sha256=xEF2Bxc-vUCPkiu4IbfWVd3LW7DROYAT-ExW6THqyzw,3519 +werkzeug/routing.py,sha256=2JVtdSgxKGeANy4Z_FP-dKESvKtkYGCZ1J2fARCLGCY,67214 +werkzeug/script.py,sha256=DwaVDcXdaOTffdNvlBdLitxWXjKaRVT32VbhDtljFPY,11365 +werkzeug/security.py,sha256=0m107exslz4QJLWQCpfQJ04z3re4eGHVggRvrQVAdWc,9193 +werkzeug/serving.py,sha256=A0flnIJHufdn2QJ9oeuHfrXwP3LzP8fn3rNW6hbxKUg,31926 +werkzeug/test.py,sha256=XmECSmnpASiYQTct4oMiWr0LT5jHWCtKqnpYKZd2ui8,36100 +werkzeug/testapp.py,sha256=3HQRW1sHZKXuAjCvFMet4KXtQG3loYTFnvn6LWt-4zI,9396 +werkzeug/urls.py,sha256=dUeLg2IeTm0WLmSvFeD4hBZWGdOs-uHudR5-t8n9zPo,36771 +werkzeug/useragents.py,sha256=BhYMf4cBTHyN4U0WsQedePIocmNlH_34C-UwqSThGCc,5865 +werkzeug/utils.py,sha256=BrY1j0DHQ8RTb0K1StIobKuMJhN9SQQkWEARbrh2qpk,22972 +werkzeug/websocket.py,sha256=PpSeDxXD_0UsPAa5hQhQNM6mxibeUgn8lA8eRqiS0vM,11344 +werkzeug/wrappers.py,sha256=kbyL_aFjxELwPgMwfNCYjKu-CR6kNkh-oO8wv3GXbk8,84511 +werkzeug/wsgi.py,sha256=1Nob-aeChWQf7MsiicO8RZt6J90iRzEcik44ev9Qu8s,49347 +werkzeug/contrib/__init__.py,sha256=f7PfttZhbrImqpr5Ezre8CXgwvcGUJK7zWNpO34WWrw,623 +werkzeug/contrib/atom.py,sha256=qqfJcfIn2RYY-3hO3Oz0aLq9YuNubcPQ_KZcNsDwVJo,15575 +werkzeug/contrib/cache.py,sha256=xBImHNj09BmX_7kC5NUCx8f_l4L8_O7zi0jCL21UZKE,32163 +werkzeug/contrib/fixers.py,sha256=gR06T-w71ur-tHQ_31kP_4jpOncPJ4Wc1dOqTvYusr8,10179 +werkzeug/contrib/iterio.py,sha256=RlqDvGhz0RneTpzE8dVc-yWCUv4nkPl1jEc_EDp2fH0,10814 +werkzeug/contrib/jsrouting.py,sha256=QTmgeDoKXvNK02KzXgx9lr3cAH6fAzpwF5bBdPNvJPs,8564 +werkzeug/contrib/limiter.py,sha256=iS8-ahPZ-JLRnmfIBzxpm7O_s3lPsiDMVWv7llAIDCI,1334 +werkzeug/contrib/lint.py,sha256=Mj9NeUN7s4zIUWeQOAVjrmtZIcl3Mm2yDe9BSIr9YGE,12558 +werkzeug/contrib/profiler.py,sha256=ISwCWvwVyGpDLRBRpLjo_qUWma6GXYBrTAco4PEQSHY,5151 +werkzeug/contrib/securecookie.py,sha256=uWMyHDHY3lkeBRiCSayGqWkAIy4a7xAbSE_Hln9ecqc,12196 +werkzeug/contrib/sessions.py,sha256=39LVNvLbm5JWpbxM79WC2l87MJFbqeISARjwYbkJatw,12577 +werkzeug/contrib/testtools.py,sha256=G9xN-qeihJlhExrIZMCahvQOIDxdL9NiX874jiiHFMs,2453 +werkzeug/contrib/wrappers.py,sha256=v7OYlz7wQtDlS9fey75UiRZ1IkUWqCpzbhsLy4k14Hw,10398 +werkzeug/debug/__init__.py,sha256=uSn9BqCZ5E3ySgpoZtundpROGsn-uYvZtSFiTfAX24M,17452 +werkzeug/debug/console.py,sha256=n3-dsKk1TsjnN-u4ZgmuWCU_HO0qw5IA7ttjhyyMM6I,5607 +werkzeug/debug/repr.py,sha256=bKqstDYGfECpeLerd48s_hxuqK4b6UWnjMu3d_DHO8I,9340 +werkzeug/debug/tbtools.py,sha256=rBudXCmkVdAKIcdhxANxgf09g6kQjJWW9_5bjSpr4OY,18451 +werkzeug/debug/shared/FONT_LICENSE,sha256=LwAVEI1oYnvXiNMT9SnCH_TaLCxCpeHziDrMg0gPkAI,4673 +werkzeug/debug/shared/console.png,sha256=bxax6RXXlvOij_KeqvSNX0ojJf83YbnZ7my-3Gx9w2A,507 +werkzeug/debug/shared/debugger.js,sha256=PKPVYuyO4SX1hkqLOwCLvmIEO5154WatFYaXE-zIfKI,6264 +werkzeug/debug/shared/jquery.js,sha256=7LkWEzqTdpEfELxcZZlS6wAx5Ff13zZ83lYO2_ujj7g,95957 +werkzeug/debug/shared/less.png,sha256=-4-kNRaXJSONVLahrQKUxMwXGm9R4OnZ9SxDGpHlIR4,191 +werkzeug/debug/shared/more.png,sha256=GngN7CioHQoV58rH6ojnkYi8c_qED2Aka5FO5UXrReY,200 +werkzeug/debug/shared/source.png,sha256=RoGcBTE4CyCB85GBuDGTFlAnUqxwTBiIfDqW15EpnUQ,818 +werkzeug/debug/shared/style.css,sha256=IEO0PC2pWmh2aEyGCaN--txuWsRCliuhlbEhPDFwh0A,6270 +werkzeug/debug/shared/ubuntu.ttf,sha256=1eaHFyepmy4FyDvjLVzpITrGEBu_CZYY94jE0nED1c0,70220 +Werkzeug-0.14.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +werkzeug/__pycache__/posixemulation.cpython-36.pyc,, +werkzeug/__pycache__/exceptions.cpython-36.pyc,, +werkzeug/__pycache__/websocket.cpython-36.pyc,, +werkzeug/__pycache__/datastructures.cpython-36.pyc,, +werkzeug/__pycache__/filesystem.cpython-36.pyc,, +werkzeug/__pycache__/useragents.cpython-36.pyc,, +werkzeug/__pycache__/serving.cpython-36.pyc,, +werkzeug/__pycache__/testapp.cpython-36.pyc,, +werkzeug/__pycache__/_compat.cpython-36.pyc,, +werkzeug/__pycache__/script.cpython-36.pyc,, +werkzeug/__pycache__/security.cpython-36.pyc,, +werkzeug/__pycache__/_internal.cpython-36.pyc,, +werkzeug/__pycache__/routing.cpython-36.pyc,, +werkzeug/__pycache__/_reloader.cpython-36.pyc,, +werkzeug/__pycache__/local.cpython-36.pyc,, +werkzeug/__pycache__/http.cpython-36.pyc,, +werkzeug/__pycache__/utils.cpython-36.pyc,, +werkzeug/__pycache__/wsgi.cpython-36.pyc,, +werkzeug/__pycache__/formparser.cpython-36.pyc,, +werkzeug/__pycache__/wrappers.cpython-36.pyc,, +werkzeug/__pycache__/__init__.cpython-36.pyc,, +werkzeug/__pycache__/test.cpython-36.pyc,, +werkzeug/__pycache__/urls.cpython-36.pyc,, +werkzeug/contrib/__pycache__/sessions.cpython-36.pyc,, +werkzeug/contrib/__pycache__/lint.cpython-36.pyc,, +werkzeug/contrib/__pycache__/jsrouting.cpython-36.pyc,, +werkzeug/contrib/__pycache__/iterio.cpython-36.pyc,, +werkzeug/contrib/__pycache__/testtools.cpython-36.pyc,, +werkzeug/contrib/__pycache__/securecookie.cpython-36.pyc,, +werkzeug/contrib/__pycache__/fixers.cpython-36.pyc,, +werkzeug/contrib/__pycache__/profiler.cpython-36.pyc,, +werkzeug/contrib/__pycache__/cache.cpython-36.pyc,, +werkzeug/contrib/__pycache__/limiter.cpython-36.pyc,, +werkzeug/contrib/__pycache__/wrappers.cpython-36.pyc,, +werkzeug/contrib/__pycache__/__init__.cpython-36.pyc,, +werkzeug/contrib/__pycache__/atom.cpython-36.pyc,, +werkzeug/debug/__pycache__/repr.cpython-36.pyc,, +werkzeug/debug/__pycache__/console.cpython-36.pyc,, +werkzeug/debug/__pycache__/tbtools.cpython-36.pyc,, +werkzeug/debug/__pycache__/__init__.cpython-36.pyc,, diff --git a/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/WHEEL b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/WHEEL new file mode 100644 index 0000000..0de529b --- /dev/null +++ b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.26.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/metadata.json b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/metadata.json new file mode 100644 index 0000000..bca8d12 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/metadata.json @@ -0,0 +1 @@ +{"generator": "bdist_wheel (0.26.0)", "summary": "The comprehensive WSGI web application library.", "classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules"], "description_content_type": "UNKNOWN", "extensions": {"python.details": {"project_urls": {"Home": "https://www.palletsprojects.org/p/werkzeug/"}, "contacts": [{"email": "armin.ronacher@active-4.com", "name": "Armin Ronacher", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst", "license": "LICENSE.txt"}}}, "license": "BSD", "metadata_version": "2.0", "name": "Werkzeug", "platform": "any", "extras": ["dev", "termcolor", "watchdog"], "run_requires": [{"requires": ["coverage", "pytest", "sphinx", "tox"], "extra": "dev"}, {"requires": ["termcolor"], "extra": "termcolor"}, {"requires": ["watchdog"], "extra": "watchdog"}], "version": "0.14.1"} \ No newline at end of file diff --git a/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/top_level.txt b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/top_level.txt new file mode 100644 index 0000000..6fe8da8 --- /dev/null +++ b/flex/lib/python3.6/site-packages/Werkzeug-0.14.1.dist-info/top_level.txt @@ -0,0 +1 @@ +werkzeug diff --git a/flex/lib/python3.6/site-packages/__pycache__/itsdangerous.cpython-36.pyc b/flex/lib/python3.6/site-packages/__pycache__/itsdangerous.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6f9a760b20fc41597168f38c0bef85d51f16e8eb GIT binary patch literal 29356 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

pXRFZr;ug5 zi8X?mkAIp8)~7$BhS`;9y?qQ|yAmudG?MVb4Kxr6J-}?j{sgmlnE;F*Y3_`)OxMAo z`l;s5XegO{JBBJpc(SBWYZ?qATjY{lf)wycY~md?Cis##wK)@7bgUy3DKhbIV5z+i z@R~Nc_gs1L>ZRAO-Dte{=BqEi_Tu%%%kyzf<64OInT$5o<_o{i-6-ZoZZMAKB#NZg zqbD}D1 zTF54EP~YMv9efWbX4u#fxQUBe)+2?igee$Uz#TH45}w92?)lDPxCw6CT||_4?w8k! z;j1WxDI2WDAV|goXp(@8UhYI!z!mgdXziNPn1nUV^xJe6LEwLYLoSRYHtmF74qpC1 zK&bu^OFV;JJjJ=kLi;kM=qFJE4s!(Q47DKm_aH@U!k)rdLJ2^2KCtU~YDM>Pf1$Ve5{l#y%ksNdsPM9&bNLevR%TH{6r4LRGz z2Y(;CKgajQsH;v;lc+Iqe_ypE&zg9i{?JzWg(q>y>knVC7}Ui~(Q3UY=ZrE{>!q*2 zQmXThsFdRaSOfApmUzreo>yA8TAkj%$3cs?B+PB5hUQ(l$pYP27MZJP(UR#Qn_CuQ zz(SNd{x2~JJuwZ>$x5h_%d!jz^djWn39zn2$UjX%8%ie?hyj&2&9qb&$&stetipr3 zDE1gT*C~7(ZDjw88Rc<(ORdTeu;qsUC4wycP3$mn44HI5cObSp0>j<$tuNV!G3U-N z?$|QTp4mB0;#lM~d#o*xB*cPx;P;x|Fgio`b>t z3%;B|j`hzIa;(D=2yqn<&hJW0$-6--?+iqgVn6FWz}-RaXh~*9R6LoCS`({fn~`H9 zOoN2S5d$u;ErdCj37^;_KxpDJ{ZU9?#3l{S^EOUPk{G!Y@4jPzd;ctF-k3Of#^SUI zBd(ov#tLl%FeqUfT9@ULxk=(@6BY*6DxnO zwKrD0MNE0j&HGqbINmtEuz&>*7LK37iPVGhS)6Nzb+^?Qe;1(8W~+>8wiAf{Ydrld zAxfPZ5G^R)`LW??WP-@O3~IeU90Am!GXK9q_TLbW1CZq%C=-WqQ1|itIUxcpe6=0w z<$Au)N7OT9(O>PRsCI!i{OekJV)_Jf*=V7{JOO`w0%hYdrkzH}rwjET)Ttz?!SY8^ zVyC&H)HT*g&59|F_+wM0CHQzEMb#@Flhi4BohC@^;BT;@O_7QxbaFUz-2+vxWwW{T zU-lY*d7Uv=aks~19p8~ZqooArIALB#d5*E#3e+$DH3ant?^Ey4!Jbn*BjcClI%M&9 zSzBCBVZFo$SGoH%cdv8z8SXyM-50o9<*v`&SGoH(cOP&^jY#uI;>> import certifi + + >>> certifi.where() + '/usr/local/lib/python2.7/site-packages/certifi/cacert.pem' + +Enjoy! + +1024-bit Root Certificates +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Browsers and certificate authorities have concluded that 1024-bit keys are +unacceptably weak for certificates, particularly root certificates. For this +reason, Mozilla has removed any weak (i.e. 1024-bit key) certificate from its +bundle, replacing it with an equivalent strong (i.e. 2048-bit or greater key) +certificate from the same CA. Because Mozilla removed these certificates from +its bundle, ``certifi`` removed them as well. + +In previous versions, ``certifi`` provided the ``certifi.old_where()`` function +to intentionally re-add the 1024-bit roots back into your bundle. This was not +recommended in production and therefore was removed. To assist in migrating old +code, the function ``certifi.old_where()`` continues to exist as an alias of +``certifi.where()``. Please update your code to use ``certifi.where()`` +instead. ``certifi.old_where()`` will be removed in 2018. + +.. _`Certifi`: http://certifi.io/en/latest/ +.. _`Requests`: http://docs.python-requests.org/en/latest/ + + diff --git a/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/INSTALLER b/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/LICENSE.txt b/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/LICENSE.txt new file mode 100644 index 0000000..802b53f --- /dev/null +++ b/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/LICENSE.txt @@ -0,0 +1,21 @@ +This packge contains a modified version of ca-bundle.crt: + +ca-bundle.crt -- Bundle of CA Root Certificates + +Certificate data from Mozilla as of: Thu Nov 3 19:04:19 2011# +This is a bundle of X.509 certificates of public Certificate Authorities +(CA). These were automatically extracted from Mozilla's root certificates +file (certdata.txt). This file can be found in the mozilla source tree: +http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1# +It contains the certificates in PEM format and therefore +can be directly used with curl / libcurl / php_curl, or with +an Apache+mod_ssl webserver for SSL client authentication. +Just configure this file as the SSLCACertificateFile.# + +***** BEGIN LICENSE BLOCK ***** +This Source Code Form is subject to the terms of the Mozilla Public License, +v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain +one at http://mozilla.org/MPL/2.0/. + +***** END LICENSE BLOCK ***** +@(#) $RCSfile: certdata.txt,v $ $Revision: 1.80 $ $Date: 2011/11/03 15:11:58 $ diff --git a/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/METADATA b/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/METADATA new file mode 100644 index 0000000..5ab7fa6 --- /dev/null +++ b/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/METADATA @@ -0,0 +1,71 @@ +Metadata-Version: 2.0 +Name: certifi +Version: 2018.1.18 +Summary: Python package for providing Mozilla's CA Bundle. +Home-page: http://certifi.io/ +Author: Kenneth Reitz +Author-email: me@kennethreitz.com +License: MPL-2.0 +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0) +Classifier: Natural Language :: English +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 + +Certifi: Python SSL Certificates +================================ + +`Certifi`_ is a carefully curated collection of Root Certificates for +validating the trustworthiness of SSL certificates while verifying the identity +of TLS hosts. It has been extracted from the `Requests`_ project. + +Installation +------------ + +``certifi`` is available on PyPI. Simply install it with ``pip``:: + + $ pip install certifi + +Usage +----- + +To reference the installed certificate authority (CA) bundle, you can use the +built-in function:: + + >>> import certifi + + >>> certifi.where() + '/usr/local/lib/python2.7/site-packages/certifi/cacert.pem' + +Enjoy! + +1024-bit Root Certificates +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Browsers and certificate authorities have concluded that 1024-bit keys are +unacceptably weak for certificates, particularly root certificates. For this +reason, Mozilla has removed any weak (i.e. 1024-bit key) certificate from its +bundle, replacing it with an equivalent strong (i.e. 2048-bit or greater key) +certificate from the same CA. Because Mozilla removed these certificates from +its bundle, ``certifi`` removed them as well. + +In previous versions, ``certifi`` provided the ``certifi.old_where()`` function +to intentionally re-add the 1024-bit roots back into your bundle. This was not +recommended in production and therefore was removed. To assist in migrating old +code, the function ``certifi.old_where()`` continues to exist as an alias of +``certifi.where()``. Please update your code to use ``certifi.where()`` +instead. ``certifi.old_where()`` will be removed in 2018. + +.. _`Certifi`: http://certifi.io/en/latest/ +.. _`Requests`: http://docs.python-requests.org/en/latest/ + + diff --git a/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/RECORD b/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/RECORD new file mode 100644 index 0000000..c611959 --- /dev/null +++ b/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/RECORD @@ -0,0 +1,15 @@ +certifi/__init__.py,sha256=QSRy1UztE-i09IuGIKKuc190k07lt6ktabbelPMIZoc,63 +certifi/__main__.py,sha256=FiOYt1Fltst7wk9DRa6GCoBr8qBUxlNQu_MKJf04E6s,41 +certifi/cacert.pem,sha256=7CEXfLHxDwvDpwVu0y_2lfJYk63cU-KUKI_DL1Lq8Uo,271088 +certifi/core.py,sha256=xPQDdG_siy5A7BfqGWa7RJhcA61xXEqPiSrw9GNyhHE,836 +certifi-2018.1.18.dist-info/DESCRIPTION.rst,sha256=jXrtxvB2mFIsHbuK8aP8RXrMx5yecyAIMZ2cn8Xb_ro,1679 +certifi-2018.1.18.dist-info/LICENSE.txt,sha256=anCkv2sBABbVmmS4rkrY3H9e8W8ftFPMLs13HFo0ETE,1048 +certifi-2018.1.18.dist-info/METADATA,sha256=mEn3NzwdDqk5m8P7xy4ThWe0f0fnWrgDPTiF_WsKMVw,2570 +certifi-2018.1.18.dist-info/RECORD,, +certifi-2018.1.18.dist-info/WHEEL,sha256=5wvfB7GvgZAbKBSE9uX9Zbi6LCL-_KgezgHblXhCRnM,113 +certifi-2018.1.18.dist-info/metadata.json,sha256=QJ0o4guOVYx7CMB_el5dN5f6EubxySvzsyNUnFcOBmE,1006 +certifi-2018.1.18.dist-info/top_level.txt,sha256=KMu4vUCfsjLrkPbSNdgdekS-pVJzBAJFO__nI8NF6-U,8 +certifi-2018.1.18.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +certifi/__pycache__/__main__.cpython-36.pyc,, +certifi/__pycache__/core.cpython-36.pyc,, +certifi/__pycache__/__init__.cpython-36.pyc,, diff --git a/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/WHEEL b/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/WHEEL new file mode 100644 index 0000000..7bf9daa --- /dev/null +++ b/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.30.0.a0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/metadata.json b/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/metadata.json new file mode 100644 index 0000000..cfd442e --- /dev/null +++ b/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/metadata.json @@ -0,0 +1 @@ +{"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)", "Natural Language :: English", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6"], "extensions": {"python.details": {"contacts": [{"email": "me@kennethreitz.com", "name": "Kenneth Reitz", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst", "license": "LICENSE.txt"}, "project_urls": {"Home": "http://certifi.io/"}}}, "generator": "bdist_wheel (0.30.0.a0)", "license": "MPL-2.0", "metadata_version": "2.0", "name": "certifi", "summary": "Python package for providing Mozilla's CA Bundle.", "version": "2018.1.18"} \ No newline at end of file diff --git a/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/top_level.txt b/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/top_level.txt new file mode 100644 index 0000000..963eac5 --- /dev/null +++ b/flex/lib/python3.6/site-packages/certifi-2018.1.18.dist-info/top_level.txt @@ -0,0 +1 @@ +certifi diff --git a/flex/lib/python3.6/site-packages/certifi/__init__.py b/flex/lib/python3.6/site-packages/certifi/__init__.py new file mode 100644 index 0000000..556193c --- /dev/null +++ b/flex/lib/python3.6/site-packages/certifi/__init__.py @@ -0,0 +1,3 @@ +from .core import where, old_where + +__version__ = "2018.01.18" diff --git a/flex/lib/python3.6/site-packages/certifi/__main__.py b/flex/lib/python3.6/site-packages/certifi/__main__.py new file mode 100644 index 0000000..5f1da0d --- /dev/null +++ b/flex/lib/python3.6/site-packages/certifi/__main__.py @@ -0,0 +1,2 @@ +from certifi import where +print(where()) diff --git a/flex/lib/python3.6/site-packages/certifi/__pycache__/__init__.cpython-36.pyc b/flex/lib/python3.6/site-packages/certifi/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7cd71acb0ac874e66f93fc124605eec150c84e9e GIT binary patch literal 271 zcmX|6OHRWu6ttayN>L@2Tp^3b2@O>up~4BefmJqE8$0FEe4Ljwh}?)Ha20P^aRpY` zEIQK68)=?K@2wV#`R1$09|hqe*oli;NboctcRMi_U4 z;^Pi^X$$QdFOjc~af4lwMRJl;)+gyP$?9yKL>7mJziNnHTY0L~#=X$H%Wl{ouct^y literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/certifi/__pycache__/__main__.cpython-36.pyc b/flex/lib/python3.6/site-packages/certifi/__pycache__/__main__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..48156f48cb00bc413ecca24dcc67e4688d750f36 GIT binary patch literal 242 zcmX|5K@P!C5S?EdB3!@?x~NZ-Xd>bSHmtg7%Kzol*6*~4ZhIO>aFuSYT*1l^@sjuE z%}g?HhMi7pcHejw06d6)806-}tV<$5un1!2F$U6*tb~%BFqUA|p0o#xRpw>sD^6(f5i5U-(4-bO`Q^)O#LKJT1Ob(74 zyJM$M*d~0%wbJ(bq#|LfRPV`$ zOM2x&cm$q+ckq=HufT~J=cg5-D|vRjJG=AEH{Txb?s{iG;^4w24eSbtT|T}LnHF%J;IE35C*o72Q<)AH-#iB6 z3R2HSG-gJ`g_ij>>s3(7H~B zVGL6L%FkqW&?{uZ59Bl(oyh46f8Dp+S!n@H)E1x2)p#F)k9)pPP$v2lt z0xu3yxhYZ~ literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/certifi/cacert.pem b/flex/lib/python3.6/site-packages/certifi/cacert.pem new file mode 100644 index 0000000..101ac98 --- /dev/null +++ b/flex/lib/python3.6/site-packages/certifi/cacert.pem @@ -0,0 +1,4433 @@ + +# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA +# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA +# Label: "GlobalSign Root CA" +# Serial: 4835703278459707669005204 +# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a +# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c +# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99 +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 +# Label: "GlobalSign Root CA - R2" +# Serial: 4835703278459682885658125 +# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30 +# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe +# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only +# Label: "Verisign Class 3 Public Primary Certification Authority - G3" +# Serial: 206684696279472310254277870180966723415 +# MD5 Fingerprint: cd:68:b6:a7:c7:c4:ce:75:e0:1d:4f:57:44:61:92:09 +# SHA1 Fingerprint: 13:2d:0d:45:53:4b:69:97:cd:b2:d5:c3:39:e2:55:76:60:9b:5c:c6 +# SHA256 Fingerprint: eb:04:cf:5e:b1:f3:9a:fa:76:2f:2b:b1:20:f2:96:cb:a5:20:c1:b9:7d:b1:58:95:65:b8:1c:b9:a1:7b:72:44 +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b +N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t +KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu +kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm +CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ +Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu +imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te +2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe +DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p +F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt +TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- + +# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Label: "Entrust.net Premium 2048 Secure Server CA" +# Serial: 946069240 +# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90 +# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31 +# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77 +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 +MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub +j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo +U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b +u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ +bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er +fF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- + +# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust +# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust +# Label: "Baltimore CyberTrust Root" +# Serial: 33554617 +# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4 +# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74 +# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +# Issuer: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network +# Subject: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network +# Label: "AddTrust External Root" +# Serial: 1 +# MD5 Fingerprint: 1d:35:54:04:85:78:b0:3f:42:42:4d:bf:20:73:0a:3f +# SHA1 Fingerprint: 02:fa:f3:e2:91:43:54:68:60:78:57:69:4d:f5:e4:5b:68:85:18:68 +# SHA256 Fingerprint: 68:7f:a4:51:38:22:78:ff:f0:c8:b1:1f:8d:43:d5:76:67:1c:6e:b2:bc:ea:b4:13:fb:83:d9:65:d0:6d:2f:f2 +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs +IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 +MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h +bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt +H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 +uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX +mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX +a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN +E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 +WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD +VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 +Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU +cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx +IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN +AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH +YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC +Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX +c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a +mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. +# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. +# Label: "Entrust Root Certification Authority" +# Serial: 1164660820 +# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4 +# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9 +# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 +Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW +KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw +NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw +NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy +ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV +BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo +Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 +4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 +KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI +rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi +94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB +sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi +gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo +kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE +vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t +O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua +AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP +9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ +eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m +0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Global CA O=GeoTrust Inc. +# Subject: CN=GeoTrust Global CA O=GeoTrust Inc. +# Label: "GeoTrust Global CA" +# Serial: 144470 +# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5 +# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12 +# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg +R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 +9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq +fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv +iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU +1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ +bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW +MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA +ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l +uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn +Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS +tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF +PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un +hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV +5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Universal CA O=GeoTrust Inc. +# Subject: CN=GeoTrust Universal CA O=GeoTrust Inc. +# Label: "GeoTrust Universal CA" +# Serial: 1 +# MD5 Fingerprint: 92:65:58:8b:a2:1a:31:72:73:68:5c:b4:a5:7a:07:48 +# SHA1 Fingerprint: e6:21:f3:35:43:79:05:9a:4b:68:30:9d:8a:2f:74:22:15:87:ec:79 +# SHA256 Fingerprint: a0:45:9b:9f:63:b2:25:59:f5:fa:5d:4c:6d:b3:f9:f7:2f:f1:93:42:03:35:78:f0:73:bf:1d:1b:46:cb:b9:12 +-----BEGIN CERTIFICATE----- +MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy +c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE +BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 +IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV +VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 +cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT +QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh +F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v +c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w +mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd +VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX +teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ +f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe +Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ +nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB +/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY +MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG +9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc +aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX +IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn +ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z +uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN +Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja +QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW +koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 +ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt +DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm +bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. +# Subject: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. +# Label: "GeoTrust Universal CA 2" +# Serial: 1 +# MD5 Fingerprint: 34:fc:b8:d0:36:db:9e:14:b3:c2:f2:db:8f:e4:94:c7 +# SHA1 Fingerprint: 37:9a:19:7b:41:85:45:35:0c:a6:03:69:f3:3c:2e:af:47:4f:20:79 +# SHA256 Fingerprint: a0:23:4f:3b:c8:52:7c:a5:62:8e:ec:81:ad:5d:69:89:5d:a5:68:0d:c9:1d:1c:b8:47:7f:33:f8:78:b9:5b:0b +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy +c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD +VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 +c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 +WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG +FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq +XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL +se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb +KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd +IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 +y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt +hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc +QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 +Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV +HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ +KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z +dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ +L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr +Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo +ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY +T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz +GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m +1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV +OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH +6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX +QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS +-----END CERTIFICATE----- + +# Issuer: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association +# Subject: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association +# Label: "Visa eCommerce Root" +# Serial: 25952180776285836048024890241505565794 +# MD5 Fingerprint: fc:11:b8:d8:08:93:30:00:6d:23:f9:7e:eb:52:1e:02 +# SHA1 Fingerprint: 70:17:9b:86:8c:00:a4:fa:60:91:52:22:3f:9f:3e:32:bd:e0:05:62 +# SHA256 Fingerprint: 69:fa:c9:bd:55:fb:0a:c7:8d:53:bb:ee:5c:f1:d5:97:98:9f:d0:aa:ab:20:a2:51:51:bd:f1:73:3e:e7:d1:22 +-----BEGIN CERTIFICATE----- +MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr +MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl +cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv +bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw +CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h +dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l +cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h +2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E +lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV +ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq +299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t +vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL +dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF +AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR +zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 +LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd +7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw +++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt +398znM/jra6O1I7mT1GvFpLgXPYHDw== +-----END CERTIFICATE----- + +# Issuer: CN=AAA Certificate Services O=Comodo CA Limited +# Subject: CN=AAA Certificate Services O=Comodo CA Limited +# Label: "Comodo AAA Services root" +# Serial: 1 +# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0 +# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49 +# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4 +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority +# Subject: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority +# Label: "QuoVadis Root CA" +# Serial: 985026699 +# MD5 Fingerprint: 27:de:36:fe:72:b7:00:03:00:9d:f4:f0:1e:6c:04:24 +# SHA1 Fingerprint: de:3f:40:bd:50:93:d3:9b:6c:60:f6:da:bc:07:62:01:00:89:76:c9 +# SHA256 Fingerprint: a4:5e:de:3b:bb:f0:9c:8a:e1:5c:72:ef:c0:72:68:d6:93:a2:1c:99:6f:d5:1e:67:ca:07:94:60:fd:6d:88:73 +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz +MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw +IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR +dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp +li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D +rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ +WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug +F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU +xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC +Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv +dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw +ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl +IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh +c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy +ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI +KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T +KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq +y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p +dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD +VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL +MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk +fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 +7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R +cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y +mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW +xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK +SnQ2+Q== +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 2 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 2 O=QuoVadis Limited +# Label: "QuoVadis Root CA 2" +# Serial: 1289 +# MD5 Fingerprint: 5e:39:7b:dd:f8:ba:ec:82:e9:ac:62:ba:0c:54:00:2b +# SHA1 Fingerprint: ca:3a:fb:cf:12:40:36:4b:44:b2:16:20:88:80:48:39:19:93:7c:f7 +# SHA256 Fingerprint: 85:a0:dd:7d:d7:20:ad:b7:ff:05:f8:3d:54:2b:20:9d:c7:ff:45:28:f7:d6:77:b1:83:89:fe:a5:e5:c4:9e:86 +-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa +GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg +Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J +WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB +rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp ++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 +ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i +Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz +PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og +/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH +oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI +yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud +EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 +A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL +MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f +BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn +g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl +fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K +WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha +B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc +hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR +TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD +mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z +ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y +4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza +8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 3" +# Serial: 1478 +# MD5 Fingerprint: 31:85:3c:62:94:97:63:b9:aa:fd:89:4e:af:6f:e0:cf +# SHA1 Fingerprint: 1f:49:14:f7:d8:74:95:1d:dd:ae:02:c0:be:fd:3a:2d:82:75:51:85 +# SHA256 Fingerprint: 18:f1:fc:7f:20:5d:f8:ad:dd:eb:7f:e0:07:dd:57:e3:af:37:5a:9c:4d:8d:73:54:6b:f4:f1:fe:d1:e1:8d:35 +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM +V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB +4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr +H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd +8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv +vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT +mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe +btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc +T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt +WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ +c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A +4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD +VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG +CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 +aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu +dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw +czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G +A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg +Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 +7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem +d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd ++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B +4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN +t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x +DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 +k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s +zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j +Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT +mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK +4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- + +# Issuer: O=SECOM Trust.net OU=Security Communication RootCA1 +# Subject: O=SECOM Trust.net OU=Security Communication RootCA1 +# Label: "Security Communication Root CA" +# Serial: 0 +# MD5 Fingerprint: f1:bc:63:6a:54:e0:b5:27:f5:cd:e7:1a:e3:4d:6e:4a +# SHA1 Fingerprint: 36:b1:2b:49:f9:81:9e:d7:4c:9e:bc:38:0f:c6:56:8f:5d:ac:b2:f7 +# SHA256 Fingerprint: e7:5e:72:ed:9f:56:0e:ec:6e:b4:80:00:73:a4:3f:c3:ad:19:19:5a:39:22:82:01:78:95:97:4a:99:02:6b:6c +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY +MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t +dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 +WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD +VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 +9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ +DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 +Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N +QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ +xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G +A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG +kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr +Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 +Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU +JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot +RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== +-----END CERTIFICATE----- + +# Issuer: CN=Sonera Class2 CA O=Sonera +# Subject: CN=Sonera Class2 CA O=Sonera +# Label: "Sonera Class 2 Root CA" +# Serial: 29 +# MD5 Fingerprint: a3:ec:75:0f:2e:88:df:fa:48:01:4e:0b:5c:48:6f:fb +# SHA1 Fingerprint: 37:f7:6d:e6:07:7c:90:c5:b1:3e:93:1a:b7:41:10:b4:f2:e4:9a:27 +# SHA256 Fingerprint: 79:08:b4:03:14:c1:38:10:0b:51:8d:07:35:80:7f:fb:fc:f8:51:8a:00:95:33:71:05:ba:38:6b:15:3d:d9:27 +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP +MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx +MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV +BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o +Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt +5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s +3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej +vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu +8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw +DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil +zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ +3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD +FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 +Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 +ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M +-----END CERTIFICATE----- + +# Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com +# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com +# Label: "XRamp Global CA Root" +# Serial: 107108908803651509692980124233745014957 +# MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1 +# SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6 +# SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2 +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB +gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk +MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY +UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx +NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 +dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy +dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 +38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP +KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q +DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 +qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa +JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi +PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs +jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 +eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR +vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa +IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy +i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ +O+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority +# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority +# Label: "Go Daddy Class 2 CA" +# Serial: 0 +# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67 +# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4 +# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4 +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh +MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE +YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 +MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo +ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg +MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN +ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA +PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w +wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi +EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY +avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ +YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE +sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h +/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 +IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy +OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P +TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER +dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf +ReYNnyicsbkqWletNw+vHX/bvZ8= +-----END CERTIFICATE----- + +# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority +# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority +# Label: "Starfield Class 2 CA" +# Serial: 0 +# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24 +# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a +# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58 +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw +NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE +ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp +ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 +DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf +8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN ++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 +X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa +K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA +1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G +A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR +zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 +YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD +bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 +L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D +eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp +VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY +WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +# Issuer: O=Government Root Certification Authority +# Subject: O=Government Root Certification Authority +# Label: "Taiwan GRCA" +# Serial: 42023070807708724159991140556527066870 +# MD5 Fingerprint: 37:85:44:53:32:45:1f:20:f0:f3:95:e1:25:c4:43:4e +# SHA1 Fingerprint: f4:8b:11:bf:de:ab:be:94:54:20:71:e6:41:de:6b:be:88:2b:40:b9 +# SHA256 Fingerprint: 76:00:29:5e:ef:e8:5b:9e:1f:d6:24:db:76:06:2a:aa:ae:59:81:8a:54:d2:77:4c:d4:c0:b2:c0:11:31:e1:b3 +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ +MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow +PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR +IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q +gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy +yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts +F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2 +jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx +ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC +VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK +YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH +EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN +Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud +DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE +MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK +UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ +TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf +qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK +ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE +JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7 +hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1 +EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm +nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX +udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz +ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe +LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl +pYYsfPQS +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root CA" +# Serial: 17154717934120587862167794914071425081 +# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72 +# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43 +# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c +JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP +mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ +wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 +VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ +AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB +AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun +pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC +dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf +fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm +NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx +H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root CA" +# Serial: 10944719598952040374951832963794454346 +# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e +# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36 +# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61 +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert High Assurance EV Root CA" +# Serial: 3553400076410547919724730734378100087 +# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a +# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25 +# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K +-----END CERTIFICATE----- + +# Issuer: CN=Class 2 Primary CA O=Certplus +# Subject: CN=Class 2 Primary CA O=Certplus +# Label: "Certplus Class 2 Primary CA" +# Serial: 177770208045934040241468760488327595043 +# MD5 Fingerprint: 88:2c:8c:52:b8:a2:3c:f3:f7:bb:03:ea:ae:ac:42:0b +# SHA1 Fingerprint: 74:20:74:41:72:9c:dd:92:ec:79:31:d8:23:10:8d:c2:81:92:e2:bb +# SHA256 Fingerprint: 0f:99:3c:8a:ef:97:ba:af:56:87:14:0e:d5:9a:d1:82:1b:b4:af:ac:f0:aa:9a:58:b5:d5:7a:33:8a:3a:fb:cb +-----BEGIN CERTIFICATE----- +MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw +PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz +cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 +MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz +IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ +ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR +VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL +kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd +EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas +H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 +HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud +DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 +QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu +Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ +AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 +yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR +FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA +ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB +kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 +l7+ijrRU +-----END CERTIFICATE----- + +# Issuer: CN=DST Root CA X3 O=Digital Signature Trust Co. +# Subject: CN=DST Root CA X3 O=Digital Signature Trust Co. +# Label: "DST Root CA X3" +# Serial: 91299735575339953335919266965803778155 +# MD5 Fingerprint: 41:03:52:dc:0f:f7:50:1b:16:f0:02:8e:ba:6f:45:c5 +# SHA1 Fingerprint: da:c9:02:4f:54:d8:f6:df:94:93:5f:b1:73:26:38:ca:6a:d7:7c:13 +# SHA256 Fingerprint: 06:87:26:03:31:a7:24:03:d9:09:f1:05:e6:9b:cf:0d:32:e1:bd:24:93:ff:c6:d9:20:6d:11:bc:d6:77:07:39 +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + +# Issuer: CN=SwissSign Gold CA - G2 O=SwissSign AG +# Subject: CN=SwissSign Gold CA - G2 O=SwissSign AG +# Label: "SwissSign Gold CA - G2" +# Serial: 13492815561806991280 +# MD5 Fingerprint: 24:77:d9:a8:91:d1:3b:fa:88:2d:c2:ff:f8:cd:33:93 +# SHA1 Fingerprint: d8:c5:38:8a:b7:30:1b:1b:6e:d4:7a:e6:45:25:3a:6f:9f:1a:27:61 +# SHA256 Fingerprint: 62:dd:0b:e9:b9:f5:0a:16:3e:a0:f8:e7:5c:05:3b:1e:ca:57:ea:55:c8:68:8f:64:7c:68:81:f2:c8:35:7b:95 +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=SwissSign Silver CA - G2 O=SwissSign AG +# Subject: CN=SwissSign Silver CA - G2 O=SwissSign AG +# Label: "SwissSign Silver CA - G2" +# Serial: 5700383053117599563 +# MD5 Fingerprint: e0:06:a1:c9:7d:cf:c9:fc:0d:c0:56:75:96:d8:62:13 +# SHA1 Fingerprint: 9b:aa:e5:9f:56:ee:21:cb:43:5a:be:25:93:df:a7:f0:40:d1:1d:cb +# SHA256 Fingerprint: be:6c:4d:a2:bb:b9:ba:59:b6:f3:93:97:68:37:42:46:c3:c0:05:99:3f:a9:8f:02:0d:1d:ed:be:d4:8a:81:d5 +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. +# Subject: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. +# Label: "GeoTrust Primary Certification Authority" +# Serial: 32798226551256963324313806436981982369 +# MD5 Fingerprint: 02:26:c3:01:5e:08:30:37:43:a9:d0:7d:cf:37:e6:bf +# SHA1 Fingerprint: 32:3c:11:8e:1b:f7:b8:b6:52:54:e2:e2:10:0d:d6:02:90:37:f0:96 +# SHA256 Fingerprint: 37:d5:10:06:c5:12:ea:ab:62:64:21:f1:ec:8c:92:01:3f:c5:f8:2a:e9:8e:e5:33:eb:46:19:b8:de:b4:d0:6c +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY +MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo +R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx +MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 +AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA +ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 +7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W +kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI +mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ +KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 +6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl +4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K +oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj +UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU +AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA" +# Serial: 69529181992039203566298953787712940909 +# MD5 Fingerprint: 8c:ca:dc:0b:22:ce:f5:be:72:ac:41:1a:11:a8:d8:12 +# SHA1 Fingerprint: 91:c6:d6:ee:3e:8a:c8:63:84:e5:48:c2:99:29:5c:75:6c:81:7b:81 +# SHA256 Fingerprint: 8d:72:2f:81:a9:c1:13:c0:79:1d:f1:36:a2:96:6d:b2:6c:95:0a:97:1d:b4:6b:41:99:f4:ea:54:b7:8b:fb:9f +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB +qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV +BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw +NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j +LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG +A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs +W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta +3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk +6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 +Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J +NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP +r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU +DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz +YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX +xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 +/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ +LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 +jVaMaA== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Class 3 Public Primary Certification Authority - G5" +# Serial: 33037644167568058970164719475676101450 +# MD5 Fingerprint: cb:17:e4:31:67:3e:e2:09:fe:45:57:93:f3:0a:fa:1c +# SHA1 Fingerprint: 4e:b6:d5:78:49:9b:1c:cf:5f:58:1e:ad:56:be:3d:9b:67:44:a5:e5 +# SHA256 Fingerprint: 9a:cf:ab:7e:43:c8:d8:80:d0:6b:26:2a:94:de:ee:e4:b4:65:99:89:c3:d0:ca:f1:9b:af:64:05:e4:1a:b7:df +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW +ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 +nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex +t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz +SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG +BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ +rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ +NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH +BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv +MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE +p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y +5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK +WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ +4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N +hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----END CERTIFICATE----- + +# Issuer: CN=SecureTrust CA O=SecureTrust Corporation +# Subject: CN=SecureTrust CA O=SecureTrust Corporation +# Label: "SecureTrust CA" +# Serial: 17199774589125277788362757014266862032 +# MD5 Fingerprint: dc:32:c3:a7:6d:25:57:c7:68:09:9d:ea:2d:a9:a2:d1 +# SHA1 Fingerprint: 87:82:c6:c3:04:35:3b:cf:d2:96:92:d2:59:3e:7d:44:d9:34:ff:11 +# SHA256 Fingerprint: f1:c1:b5:0a:e5:a2:0d:d8:03:0e:c9:f6:bc:24:82:3d:d3:67:b5:25:57:59:b4:e7:1b:61:fc:e9:f7:37:5d:73 +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz +MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv +cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz +Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO +0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao +wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj +7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS +8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT +BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg +JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 +6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ +3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm +D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS +CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +# Issuer: CN=Secure Global CA O=SecureTrust Corporation +# Subject: CN=Secure Global CA O=SecureTrust Corporation +# Label: "Secure Global CA" +# Serial: 9751836167731051554232119481456978597 +# MD5 Fingerprint: cf:f4:27:0d:d4:ed:dc:65:16:49:6d:3d:da:bf:6e:de +# SHA1 Fingerprint: 3a:44:73:5a:e5:81:90:1f:24:86:61:46:1e:3b:9c:c4:5f:f5:3a:1b +# SHA256 Fingerprint: 42:00:f5:04:3a:c8:59:0e:bb:52:7d:20:9e:d1:50:30:29:fb:cb:d4:1c:a1:b5:06:ec:27:f1:5a:de:7d:ac:69 +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx +MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg +Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ +iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa +/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ +jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI +HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 +sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w +gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw +KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG +AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L +URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO +H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm +I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY +iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO Certification Authority O=COMODO CA Limited +# Label: "COMODO Certification Authority" +# Serial: 104350513648249232941998508985834464573 +# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75 +# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b +# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66 +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl +YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P +RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 +UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI +2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 +Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp ++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ +DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O +nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW +/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g +PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u +QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY +SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv +IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 +zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd +BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB +ZQ== +-----END CERTIFICATE----- + +# Issuer: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. +# Subject: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. +# Label: "Network Solutions Certificate Authority" +# Serial: 116697915152937497490437556386812487904 +# MD5 Fingerprint: d3:f3:a6:16:c0:fa:6b:1d:59:b1:2d:96:4d:0e:11:2e +# SHA1 Fingerprint: 74:f8:a3:c3:ef:e7:b3:90:06:4b:83:90:3c:21:64:60:20:e5:df:ce +# SHA256 Fingerprint: 15:f0:ba:00:a3:ac:7a:f3:ac:88:4c:07:2b:10:11:a0:77:bd:77:c0:97:f4:01:64:b2:f8:59:8a:bd:83:86:0c +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi +MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV +UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO +ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz +c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP +OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl +mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF +BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 +qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw +gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu +bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp +dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 +6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ +h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH +/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN +pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- + +# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited +# Label: "COMODO ECC Certification Authority" +# Serial: 41578283867086692638256921589707938090 +# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23 +# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11 +# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7 +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT +IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw +MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy +ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N +T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR +FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J +cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW +BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm +fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv +GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +# Issuer: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GA CA" +# Serial: 86718877871133159090080555911823548314 +# MD5 Fingerprint: bc:6c:51:33:a7:e9:d3:66:63:54:15:72:1b:21:92:93 +# SHA1 Fingerprint: 59:22:a1:e1:5a:ea:16:35:21:f8:98:39:6a:46:46:b0:44:1b:0f:a9 +# SHA256 Fingerprint: 41:c9:23:86:6a:b4:ca:d6:b7:ad:57:80:81:58:2e:02:07:97:a6:cb:df:4f:ff:78:ce:83:96:b3:89:37:d7:f5 +-----BEGIN CERTIFICATE----- +MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB +ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly +aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w +NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G +A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX +SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR +VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 +w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF +mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg +4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 +4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw +EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx +SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 +ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 +vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa +hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi +Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ +/L7fCg0= +-----END CERTIFICATE----- + +# Issuer: CN=Certigna O=Dhimyotis +# Subject: CN=Certigna O=Dhimyotis +# Label: "Certigna" +# Serial: 18364802974209362175 +# MD5 Fingerprint: ab:57:a6:5b:7d:42:82:19:b5:d8:58:26:28:5e:fd:ff +# SHA1 Fingerprint: b1:2e:13:63:45:86:a4:6f:1a:b2:60:68:37:58:2d:c4:ac:fd:94:97 +# SHA256 Fingerprint: e3:b6:a2:db:2e:d7:ce:48:84:2f:7a:c5:32:41:c7:b7:1d:54:14:4b:fb:40:c1:1f:3f:1d:0b:42:f5:ee:a1:2d +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV +BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X +DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ +BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 +QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny +gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw +zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q +130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 +JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw +ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT +AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj +AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG +9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h +bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc +fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu +HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w +t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +# Issuer: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center +# Subject: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center +# Label: "Deutsche Telekom Root CA 2" +# Serial: 38 +# MD5 Fingerprint: 74:01:4a:91:b1:08:c4:58:ce:47:cd:f0:dd:11:53:08 +# SHA1 Fingerprint: 85:a4:08:c0:9c:19:3e:5d:51:58:7d:cd:d6:13:30:fd:8c:de:37:bf +# SHA256 Fingerprint: b6:19:1a:50:d0:c3:97:7f:7d:a9:9b:cd:aa:c8:6a:22:7d:ae:b9:67:9e:c7:0b:a3:b0:c9:d9:22:71:c1:70:d3 +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc +MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj +IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB +IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE +RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl +U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 +IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU +ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC +QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr +rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S +NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc +QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH +txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP +BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC +AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp +tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa +IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl +6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ +xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU +Cm26OWMohpLzGITY+9HPBVZkVw== +-----END CERTIFICATE----- + +# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc +# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc +# Label: "Cybertrust Global Root" +# Serial: 4835703278459682877484360 +# MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1 +# SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6 +# SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3 +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG +A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh +bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE +ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS +b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5 +7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS +J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y +HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP +t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz +FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY +XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ +MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw +hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js +MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA +A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj +Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx +XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o +omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc +A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----END CERTIFICATE----- + +# Issuer: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority +# Subject: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority +# Label: "ePKI Root Certification Authority" +# Serial: 28956088682735189655030529057352760477 +# MD5 Fingerprint: 1b:2e:00:ca:26:06:90:3d:ad:fe:6f:15:68:d3:6b:b3 +# SHA1 Fingerprint: 67:65:0d:f1:7e:8e:7e:5b:82:40:a4:f4:56:4b:cf:e2:3d:69:c6:f0 +# SHA256 Fingerprint: c0:a6:f4:dc:63:a2:4b:fd:cf:54:ef:2a:6a:08:2a:0a:72:de:35:80:3e:2f:f5:ff:52:7a:e5:d8:72:06:df:d5 +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe +MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 +ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw +IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL +SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH +SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh +ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X +DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 +TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ +fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA +sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU +WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS +nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH +dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip +NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC +AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF +MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB +uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl +PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP +JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ +gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 +j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 +5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB +o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS +/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z +Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE +W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D +hNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +# Issuer: O=certSIGN OU=certSIGN ROOT CA +# Subject: O=certSIGN OU=certSIGN ROOT CA +# Label: "certSIGN ROOT CA" +# Serial: 35210227249154 +# MD5 Fingerprint: 18:98:c0:d6:e9:3a:fc:f9:b0:f5:0c:f7:4b:01:44:17 +# SHA1 Fingerprint: fa:b7:ee:36:97:26:62:fb:2d:b0:2a:f6:bf:03:fd:e8:7c:4b:2f:9b +# SHA256 Fingerprint: ea:a9:62:c4:fa:4a:6b:af:eb:e4:15:19:6d:35:1c:cd:88:8d:4f:53:f3:fa:8a:e6:d7:c4:66:a9:4e:60:42:bb +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT +AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD +QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP +MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do +0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ +UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d +RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ +OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv +JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C +AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O +BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ +LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY +MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ +44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I +Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw +i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN +9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only +# Subject: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only +# Label: "GeoTrust Primary Certification Authority - G3" +# Serial: 28809105769928564313984085209975885599 +# MD5 Fingerprint: b5:e8:34:36:c9:10:44:58:48:70:6d:2e:83:d4:b8:05 +# SHA1 Fingerprint: 03:9e:ed:b8:0b:e7:a0:3c:69:53:89:3b:20:d2:d9:32:3a:4c:2a:fd +# SHA256 Fingerprint: b4:78:b8:12:25:0d:f8:78:63:5c:2a:a7:ec:7d:15:5e:aa:62:5e:e8:29:16:e2:cd:29:43:61:88:6c:d1:fb:d4 +-----BEGIN CERTIFICATE----- +MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB +mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT +MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ +BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg +MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 +BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz ++uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm +hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn +5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W +JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL +DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC +huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB +AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB +zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN +kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD +AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH +SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G +spki4cErx5z481+oghLrGREt +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA - G2" +# Serial: 71758320672825410020661621085256472406 +# MD5 Fingerprint: 74:9d:ea:60:24:c4:fd:22:53:3e:cc:3a:72:d9:29:4f +# SHA1 Fingerprint: aa:db:bc:22:23:8f:c4:01:a1:27:bb:38:dd:f4:1d:db:08:9e:f0:12 +# SHA256 Fingerprint: a4:31:0d:50:af:18:a6:44:71:90:37:2a:86:af:af:8b:95:1f:fb:43:1d:83:7f:1e:56:88:b4:59:71:ed:15:57 +-----BEGIN CERTIFICATE----- +MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp +IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi +BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw +MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh +d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig +YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v +dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ +BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 +papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K +DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 +KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox +XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA - G3" +# Serial: 127614157056681299805556476275995414779 +# MD5 Fingerprint: fb:1b:5d:43:8a:94:cd:44:c6:76:f2:43:4b:47:e7:31 +# SHA1 Fingerprint: f1:8b:53:8d:1b:e9:03:b6:a6:f0:56:43:5b:17:15:89:ca:f3:6b:f2 +# SHA256 Fingerprint: 4b:03:f4:58:07:ad:70:f2:1b:fc:2c:ae:71:c9:fd:e4:60:4c:06:4c:f5:ff:b6:86:ba:e5:db:aa:d7:fd:d3:4c +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB +rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV +BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa +Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl +LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u +MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl +ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm +gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 +YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf +b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 +9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S +zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk +OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV +HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA +2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW +oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu +t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c +KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM +m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu +MdRAGmI0Nj81Aa6sY6A= +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only +# Subject: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only +# Label: "GeoTrust Primary Certification Authority - G2" +# Serial: 80682863203381065782177908751794619243 +# MD5 Fingerprint: 01:5e:d8:6b:bd:6f:3d:8e:a1:31:f8:12:e0:98:73:6a +# SHA1 Fingerprint: 8d:17:84:d5:37:f3:03:7d:ec:70:fe:57:8b:51:9a:99:e6:10:d7:b0 +# SHA256 Fingerprint: 5e:db:7a:c4:3b:82:a0:6a:87:61:e8:d7:be:49:79:eb:f2:61:1f:7d:d7:9b:f9:1c:1c:6b:56:6a:21:9e:d7:66 +-----BEGIN CERTIFICATE----- +MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL +MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj +KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 +MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw +NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV +BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH +MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL +So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal +tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG +CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT +qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz +rD6ogRLQy7rQkgu2npaqBA+K +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Universal Root Certification Authority" +# Serial: 85209574734084581917763752644031726877 +# MD5 Fingerprint: 8e:ad:b5:01:aa:4d:81:e4:8c:1d:d1:e1:14:00:95:19 +# SHA1 Fingerprint: 36:79:ca:35:66:87:72:30:4d:30:a5:fb:87:3b:0f:a7:7b:b7:0d:54 +# SHA256 Fingerprint: 23:99:56:11:27:a5:71:25:de:8c:ef:ea:61:0d:df:2f:a0:78:b5:c8:06:7f:4e:82:82:90:bf:b8:60:e8:4b:3c +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB +vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W +ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX +MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 +IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y +IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh +bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF +9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH +H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H +LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN +/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT +rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw +WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs +exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud +DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 +sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ +seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz +4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ +BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR +lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 +7M2CYfE45k+XmCpajQ== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Class 3 Public Primary Certification Authority - G4" +# Serial: 63143484348153506665311985501458640051 +# MD5 Fingerprint: 3a:52:e1:e7:fd:6f:3a:e3:6f:f3:6f:99:1b:f9:22:41 +# SHA1 Fingerprint: 22:d5:d8:df:8f:02:31:d1:8d:f7:9d:b7:cf:8a:2d:64:c9:3f:6c:3a +# SHA256 Fingerprint: 69:dd:d7:ea:90:bb:57:c9:3e:13:5d:c8:5e:a6:fc:d5:48:0b:60:32:39:bd:c4:54:fc:75:8b:2a:26:cf:7f:79 +-----BEGIN CERTIFICATE----- +MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp +U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg +SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln +biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm +GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve +fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ +aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj +aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW +kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC +4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga +FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== +-----END CERTIFICATE----- + +# Issuer: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) +# Subject: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) +# Label: "NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny" +# Serial: 80544274841616 +# MD5 Fingerprint: c5:a1:b7:ff:73:dd:d6:d7:34:32:18:df:fc:3c:ad:88 +# SHA1 Fingerprint: 06:08:3f:59:3f:15:a1:04:a0:69:a4:6b:a9:03:d0:06:b7:97:09:91 +# SHA256 Fingerprint: 6c:61:da:c3:a2:de:f0:31:50:6b:e0:36:d2:a6:fe:40:19:94:fb:d1:3d:f9:c8:d4:66:59:92:74:c4:46:ec:98 +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG +EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 +MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl +cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR +dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB +pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM +b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm +aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz +IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT +lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz +AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 +VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG +ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 +BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG +AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M +U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh +bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C ++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F +uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 +XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +# Issuer: CN=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden +# Label: "Staat der Nederlanden Root CA - G2" +# Serial: 10000012 +# MD5 Fingerprint: 7c:a5:0f:f8:5b:9a:7d:6d:30:ae:54:5a:e3:42:a2:8a +# SHA1 Fingerprint: 59:af:82:79:91:86:c7:b4:75:07:cb:cf:03:57:46:eb:04:dd:b7:16 +# SHA256 Fingerprint: 66:8c:83:94:7d:a6:3b:72:4b:ec:e1:74:3c:31:a0:e6:ae:d0:db:8e:c5:b3:1b:e3:77:bb:78:4f:91:b6:71:6f +-----BEGIN CERTIFICATE----- +MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX +DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl +ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv +b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 +qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp +uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU +Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE +pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp +5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M +UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN +GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy +5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv +6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK +eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 +B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ +BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov +L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG +SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS +CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen +5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 +IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK +gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL ++63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL +vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm +bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk +N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC +Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z +ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== +-----END CERTIFICATE----- + +# Issuer: CN=Hongkong Post Root CA 1 O=Hongkong Post +# Subject: CN=Hongkong Post Root CA 1 O=Hongkong Post +# Label: "Hongkong Post Root CA 1" +# Serial: 1000 +# MD5 Fingerprint: a8:0d:6f:39:78:b9:43:6d:77:42:6d:98:5a:cc:23:ca +# SHA1 Fingerprint: d6:da:a8:20:8d:09:d2:15:4d:24:b5:2f:cb:34:6e:b2:58:b2:8a:58 +# SHA256 Fingerprint: f9:e6:7d:33:6c:51:00:2a:c0:54:c6:32:02:2d:66:dd:a2:e7:e3:ff:f1:0a:d0:61:ed:31:d8:bb:b4:10:cf:b2 +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx +FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg +Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG +A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr +b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ +jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn +PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh +ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 +nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h +q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED +MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC +mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 +7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB +oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs +EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO +fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi +AmvZWg== +-----END CERTIFICATE----- + +# Issuer: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. +# Subject: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. +# Label: "SecureSign RootCA11" +# Serial: 1 +# MD5 Fingerprint: b7:52:74:e2:92:b4:80:93:f2:75:e4:cc:d7:f2:ea:26 +# SHA1 Fingerprint: 3b:c4:9f:48:f8:f3:73:a0:9c:1e:bd:f8:5b:b1:c3:65:c7:d8:11:b3 +# SHA256 Fingerprint: bf:0f:ee:fb:9e:3a:58:1a:d5:f9:e9:db:75:89:98:57:43:d2:61:08:5c:4d:31:4f:6f:5d:72:59:aa:42:16:12 +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr +MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG +A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 +MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp +Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD +QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz +i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8 +h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV +MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9 +UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni +8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC +h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD +VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB +AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm +KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ +X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr +QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5 +pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN +QSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +# Issuer: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. +# Subject: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. +# Label: "Microsec e-Szigno Root CA 2009" +# Serial: 14014712776195784473 +# MD5 Fingerprint: f8:49:f4:03:bc:44:2d:83:be:48:69:7d:29:64:fc:b1 +# SHA1 Fingerprint: 89:df:74:fe:5c:f4:0f:4a:80:f9:e3:37:7d:54:da:91:e1:01:31:8e +# SHA256 Fingerprint: 3c:5f:81:fe:a5:fa:b8:2c:64:bf:a2:ea:ec:af:cd:e8:e0:77:fc:86:20:a7:ca:e5:37:16:3d:f3:6e:db:f3:78 +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD +VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 +ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G +CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y +OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx +FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp +Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP +kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc +cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U +fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 +N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC +xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 ++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM +Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG +SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h +mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk +ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c +2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t +HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 +# Label: "GlobalSign Root CA - R3" +# Serial: 4835703278459759426209954 +# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28 +# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad +# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f +-----END CERTIFICATE----- + +# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Label: "Autoridad de Certificacion Firmaprofesional CIF A62634068" +# Serial: 6047274297262753887 +# MD5 Fingerprint: 73:3a:74:7a:ec:bb:a3:96:a6:c2:e4:e2:c8:9b:c0:c3 +# SHA1 Fingerprint: ae:c5:fb:3f:c8:e1:bf:c4:e5:4f:03:07:5a:9a:e8:00:b7:f7:b6:fa +# SHA256 Fingerprint: 04:04:80:28:bf:1f:28:64:d4:8f:9a:d4:d8:32:94:36:6a:82:88:56:55:3f:3b:14:30:3f:90:14:7f:5d:40:ef +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE +BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h +cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy +MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg +Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 +thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM +cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG +L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i +NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h +X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b +m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy +Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja +EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T +KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF +6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh +OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD +VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv +ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl +AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF +661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9 +am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1 +ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481 +PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS +3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k +SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF +3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM +ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g +StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz +Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB +jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +# Issuer: CN=Izenpe.com O=IZENPE S.A. +# Subject: CN=Izenpe.com O=IZENPE S.A. +# Label: "Izenpe.com" +# Serial: 917563065490389241595536686991402621 +# MD5 Fingerprint: a6:b0:cd:85:80:da:5c:50:34:a3:39:90:2f:55:67:73 +# SHA1 Fingerprint: 2f:78:3d:25:52:18:a7:4a:65:39:71:b5:2c:a2:9c:45:15:6f:e9:19 +# SHA256 Fingerprint: 25:30:cc:8e:98:32:15:02:ba:d9:6f:9b:1f:ba:1b:09:9e:2d:29:9e:0f:45:48:bb:91:4f:36:3b:c0:d4:53:1f +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. +# Subject: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. +# Label: "Chambers of Commerce Root - 2008" +# Serial: 11806822484801597146 +# MD5 Fingerprint: 5e:80:9e:84:5a:0e:65:0b:17:02:f3:55:18:2a:3e:d7 +# SHA1 Fingerprint: 78:6a:74:ac:76:ab:14:7f:9c:6a:30:50:ba:9e:a8:7e:fe:9a:ce:3c +# SHA256 Fingerprint: 06:3e:4a:fa:c4:91:df:d3:32:f3:08:9b:85:42:e9:46:17:d8:93:d7:fe:94:4e:10:a7:93:7e:e2:9d:96:93:c0 +-----BEGIN CERTIFICATE----- +MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD +VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz +IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz +MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj +dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw +EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp +MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9 +28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq +VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q +DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR +5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL +ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a +Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl +UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s ++12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5 +Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj +ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx +hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV +HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1 ++HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN +YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t +L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy +ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt +IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV +HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w +DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW +PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF +5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1 +glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH +FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2 +pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD +xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG +tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq +jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De +fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg +OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ +d0jQ +-----END CERTIFICATE----- + +# Issuer: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. +# Subject: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. +# Label: "Global Chambersign Root - 2008" +# Serial: 14541511773111788494 +# MD5 Fingerprint: 9e:80:ff:78:01:0c:2e:c1:36:bd:fe:96:90:6e:08:f3 +# SHA1 Fingerprint: 4a:bd:ee:ec:95:0d:35:9c:89:ae:c7:52:a1:2c:5b:29:f6:d6:aa:0c +# SHA256 Fingerprint: 13:63:35:43:93:34:a7:69:80:16:a0:d3:24:de:72:28:4e:07:9d:7b:52:20:bb:8f:bd:74:78:16:ee:be:ba:ca +-----BEGIN CERTIFICATE----- +MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD +VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx +MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy +cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG +A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl +BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed +KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 +G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 +zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 +ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG +HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 +Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V +yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e +beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r +6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog +zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW +BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr +ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp +ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk +cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt +YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC +CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow +KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI +hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ +UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz +X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x +fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz +a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd +Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd +SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O +AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso +M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge +v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +-----END CERTIFICATE----- + +# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. +# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. +# Label: "Go Daddy Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01 +# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b +# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT +EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp +ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz +NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH +EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE +AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD +E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH +/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy +DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh +GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR +tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA +AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX +WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu +9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr +gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo +2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI +4uJEvlz36hz1 +-----END CERTIFICATE----- + +# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Label: "Starfield Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96 +# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e +# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5 +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs +ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw +MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj +aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp +Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg +nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 +HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N +Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN +dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 +HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G +CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU +sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 +4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg +8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 +mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Label: "Starfield Services Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2 +# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f +# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5 +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs +ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy +ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy +dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p +OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 +8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K +Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe +hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk +6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q +AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI +bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB +ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z +qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn +0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN +sSi6 +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Commercial O=AffirmTrust +# Subject: CN=AffirmTrust Commercial O=AffirmTrust +# Label: "AffirmTrust Commercial" +# Serial: 8608355977964138876 +# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7 +# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7 +# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7 +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP +Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr +ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL +MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 +yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr +VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ +nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG +XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj +vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt +Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g +N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC +nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Networking O=AffirmTrust +# Subject: CN=AffirmTrust Networking O=AffirmTrust +# Label: "AffirmTrust Networking" +# Serial: 8957382827206547757 +# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f +# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f +# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y +YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua +kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL +QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp +6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG +yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i +QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO +tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu +QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ +Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u +olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 +x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Premium O=AffirmTrust +# Subject: CN=AffirmTrust Premium O=AffirmTrust +# Label: "AffirmTrust Premium" +# Serial: 7893706540734352110 +# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57 +# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27 +# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz +dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG +A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U +cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf +qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ +JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ ++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS +s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 +HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 +70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG +V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S +qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S +5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia +C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX +OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE +FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 +KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B +8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ +MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc +0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ +u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF +u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH +YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 +GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO +RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e +KeC2uAloGRwYQw== +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust +# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust +# Label: "AffirmTrust Premium ECC" +# Serial: 8401224907861490260 +# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d +# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb +# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23 +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC +VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ +cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ +BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt +VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D +0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 +ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G +A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs +aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I +flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Network CA" +# Serial: 279744 +# MD5 Fingerprint: d5:e9:81:40:c5:18:69:fc:46:2c:89:75:62:0f:aa:78 +# SHA1 Fingerprint: 07:e0:32:e0:20:b7:2c:3f:19:2f:06:28:a2:59:3a:19:a7:0f:06:9e +# SHA256 Fingerprint: 5c:58:46:8d:55:f5:8e:49:7e:74:39:82:d2:b5:00:10:b6:d1:65:37:4a:cf:83:a7:d4:a3:2d:b7:68:c4:40:8e +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM +MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D +ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU +cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 +WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg +Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw +IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH +UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM +TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU +BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM +kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x +AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV +HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y +sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL +I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 +J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY +VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +# Issuer: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA +# Subject: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA +# Label: "TWCA Root Certification Authority" +# Serial: 1 +# MD5 Fingerprint: aa:08:8f:f6:f9:7b:b7:f2:b1:a7:1e:9b:ea:ea:bd:79 +# SHA1 Fingerprint: cf:9e:87:6d:d3:eb:fc:42:26:97:a3:b5:a3:7a:a0:76:a9:06:23:48 +# SHA256 Fingerprint: bf:d8:8f:e1:10:1c:41:ae:3e:80:1b:f8:be:56:35:0e:e9:ba:d1:a6:b9:bd:51:5e:dc:5c:6d:5b:87:11:ac:44 +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES +MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU +V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz +WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO +LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE +AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH +K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX +RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z +rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx +3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq +hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC +MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls +XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D +lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn +aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ +YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +# Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 +# Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 +# Label: "Security Communication RootCA2" +# Serial: 0 +# MD5 Fingerprint: 6c:39:7d:a4:0e:55:59:b2:3f:d6:41:b1:12:50:de:43 +# SHA1 Fingerprint: 5f:3b:8c:f2:f8:10:b3:7d:78:b4:ce:ec:19:19:c3:73:34:b9:c7:74 +# SHA256 Fingerprint: 51:3b:2c:ec:b8:10:d4:cd:e5:dd:85:39:1a:df:c6:c2:dd:60:d8:7b:b7:36:d2:b5:21:48:4a:a4:7a:0e:be:f6 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX +DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy +dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj +YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV +OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr +zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM +VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ +hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO +ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw +awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs +OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF +coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc +okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 +t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy +1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ +SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions RootCA 2011" +# Serial: 0 +# MD5 Fingerprint: 73:9f:4c:4b:73:5b:79:e9:fa:ba:1c:ef:6e:cb:d5:c9 +# SHA1 Fingerprint: fe:45:65:9b:79:03:5b:98:a1:61:b5:51:2e:ac:da:58:09:48:22:4d +# SHA256 Fingerprint: bc:10:4f:15:a4:8b:e7:09:dc:a5:42:a7:e1:d4:b9:df:6f:05:45:27:e8:02:ea:a9:2d:59:54:44:25:8a:fe:71 +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix +RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p +YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw +NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK +EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl +cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz +dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ +fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns +bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD +75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP +FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV +HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp +5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu +b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA +A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p +6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7 +dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys +Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI +l7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----END CERTIFICATE----- + +# Issuer: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 +# Subject: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 +# Label: "Actalis Authentication Root CA" +# Serial: 6271844772424770508 +# MD5 Fingerprint: 69:c1:0d:4f:07:a3:1b:c3:fe:56:3d:04:bc:11:f6:a6 +# SHA1 Fingerprint: f3:73:b3:87:06:5a:28:84:8a:f2:f3:4a:ce:19:2b:dd:c7:8e:9c:ac +# SHA256 Fingerprint: 55:92:60:84:ec:96:3a:64:b9:6e:2a:be:01:ce:0b:a8:6a:64:fb:fe:bc:c7:aa:b5:af:c1:55:b3:7f:d7:60:66 +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE +BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w +MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC +SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 +ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv +UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX +4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 +KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ +gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb +rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ +51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F +be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe +KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F +v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn +fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 +jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz +ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL +e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 +jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz +WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V +SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j +pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX +X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok +fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R +K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU +ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU +LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT +LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----END CERTIFICATE----- + +# Issuer: O=Trustis Limited OU=Trustis FPS Root CA +# Subject: O=Trustis Limited OU=Trustis FPS Root CA +# Label: "Trustis FPS Root CA" +# Serial: 36053640375399034304724988975563710553 +# MD5 Fingerprint: 30:c9:e7:1e:6b:e6:14:eb:65:b2:16:69:20:31:67:4d +# SHA1 Fingerprint: 3b:c0:38:0b:33:c3:f6:a6:0c:86:15:22:93:d9:df:f5:4b:81:c0:04 +# SHA256 Fingerprint: c1:b4:82:99:ab:a5:20:8f:e9:63:0a:ce:55:ca:68:a0:3e:da:5a:51:9c:88:02:a0:d3:a6:73:be:8f:8e:55:7d +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF +MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL +ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx +MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc +MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ +AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH +iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj +vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA +0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB +OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ +BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E +FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 +GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW +zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 +1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE +f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F +jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN +ZetX2fNXlrtIzYE= +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 +# Subject: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 +# Label: "Buypass Class 2 Root CA" +# Serial: 2 +# MD5 Fingerprint: 46:a7:d2:fe:45:fb:64:5a:a8:59:90:9b:78:44:9b:29 +# SHA1 Fingerprint: 49:0a:75:74:de:87:0a:47:fe:58:ee:f6:c7:6b:eb:c6:0b:12:40:99 +# SHA256 Fingerprint: 9a:11:40:25:19:7c:5b:b9:5d:94:e6:3d:55:cd:43:79:08:47:b6:46:b2:3c:df:11:ad:a4:a0:0e:ff:15:fb:48 +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr +6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV +L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 +1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx +MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ +QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB +arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr +Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi +FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS +P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN +9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz +uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h +9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t +OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo ++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 +KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 +DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us +H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ +I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 +5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h +3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz +Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 +# Subject: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 +# Label: "Buypass Class 3 Root CA" +# Serial: 2 +# MD5 Fingerprint: 3d:3b:18:9e:2c:64:5a:e8:d5:88:ce:0e:f9:37:c2:ec +# SHA1 Fingerprint: da:fa:f7:fa:66:84:ec:06:8f:14:50:bd:c7:c2:81:a5:bc:a9:64:57 +# SHA256 Fingerprint: ed:f7:eb:bc:a2:7a:2a:38:4d:38:7b:7d:40:10:c6:66:e2:ed:b4:84:3e:4c:29:b4:ae:1d:5b:93:32:e6:b2:4d +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y +ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E +N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 +tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX +0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c +/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X +KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY +zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS +O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D +34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP +K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv +Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj +QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS +IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 +HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa +O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv +033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u +dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE +kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 +3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD +u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq +4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= +-----END CERTIFICATE----- + +# Issuer: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Subject: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Label: "T-TeleSec GlobalRoot Class 3" +# Serial: 1 +# MD5 Fingerprint: ca:fb:40:a8:4e:39:92:8a:1d:fe:8e:2f:c4:27:ea:ef +# SHA1 Fingerprint: 55:a6:72:3e:cb:f2:ec:cd:c3:23:74:70:19:9d:2a:be:11:e3:81:d1 +# SHA256 Fingerprint: fd:73:da:d3:1c:64:4f:f1:b4:3b:ef:0c:cd:da:96:71:0b:9c:d9:87:5e:ca:7e:31:70:7a:f3:e9:6d:52:2b:bd +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN +8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ +RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 +hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 +ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM +EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 +A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy +WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ +1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 +6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT +91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p +TpPDpFQUWw== +-----END CERTIFICATE----- + +# Issuer: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus +# Subject: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus +# Label: "EE Certification Centre Root CA" +# Serial: 112324828676200291871926431888494945866 +# MD5 Fingerprint: 43:5e:88:d4:7d:1a:4a:7e:fd:84:2e:52:eb:01:d4:6f +# SHA1 Fingerprint: c9:a8:b9:e7:55:80:5e:58:e3:53:77:a7:25:eb:af:c3:7b:27:cc:d7 +# SHA256 Fingerprint: 3e:84:ba:43:42:90:85:16:e7:75:73:c0:99:2f:09:79:ca:08:4e:46:85:68:1f:f1:95:cc:ba:8a:22:9b:8a:76 +-----BEGIN CERTIFICATE----- +MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1 +MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1 +czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG +CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy +MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl +ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS +b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy +euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO +bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw +WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d +MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE +1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/ +zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB +BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF +BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV +v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG +E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u +uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW +iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v +GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0= +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH +# Subject: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH +# Label: "D-TRUST Root Class 3 CA 2 2009" +# Serial: 623603 +# MD5 Fingerprint: cd:e0:25:69:8d:47:ac:9c:89:35:90:f7:fd:51:3d:2f +# SHA1 Fingerprint: 58:e8:ab:b0:36:15:33:fb:80:f7:9b:1b:6d:29:d3:ff:8d:5f:00:f0 +# SHA256 Fingerprint: 49:e7:a4:42:ac:f0:ea:62:87:05:00:54:b5:25:64:b6:50:e4:f4:9e:42:e3:48:d6:aa:38:e0:39:e9:57:b1:c1 +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha +ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM +HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 +UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 +tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R +ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM +lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp +/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G +A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G +A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy +MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl +cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js +L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL +BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni +acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K +zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 +PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y +Johw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH +# Subject: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH +# Label: "D-TRUST Root Class 3 CA 2 EV 2009" +# Serial: 623604 +# MD5 Fingerprint: aa:c6:43:2c:5e:2d:cd:c4:34:c0:50:4f:11:02:4f:b6 +# SHA1 Fingerprint: 96:c9:1b:0b:95:b4:10:98:42:fa:d0:d8:22:79:fe:60:fa:b9:16:83 +# SHA256 Fingerprint: ee:c5:49:6b:98:8c:e9:86:25:b9:34:09:2e:ec:29:08:be:d0:b0:f3:16:c2:d4:73:0c:84:ea:f1:f3:d3:48:81 +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw +NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV +BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn +ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 +3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z +qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR +p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 +HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw +ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea +HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw +Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh +c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E +RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt +dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku +Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp +3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF +CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na +xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX +KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- + +# Issuer: CN=CA Disig Root R2 O=Disig a.s. +# Subject: CN=CA Disig Root R2 O=Disig a.s. +# Label: "CA Disig Root R2" +# Serial: 10572350602393338211 +# MD5 Fingerprint: 26:01:fb:d8:27:a7:17:9a:45:54:38:1a:43:01:3b:03 +# SHA1 Fingerprint: b5:61:eb:ea:a4:de:e4:25:4b:69:1a:98:a5:57:47:c2:34:c7:d9:71 +# SHA256 Fingerprint: e2:3d:4a:03:6d:7b:70:e9:f5:95:b1:42:20:79:d2:b9:1e:df:bb:1f:b6:51:a0:63:3e:aa:8a:9d:c5:f8:07:03 +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV +BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu +MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy +MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx +EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe +NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH +PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I +x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe +QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR +yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO +QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 +H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ +QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD +i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs +nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 +rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI +hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf +GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb +lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka ++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal +TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i +nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 +gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr +G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os +zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x +L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- + +# Issuer: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV +# Subject: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV +# Label: "ACCVRAIZ1" +# Serial: 6828503384748696800 +# MD5 Fingerprint: d0:a0:5a:ee:05:b6:09:94:21:a1:7d:f1:b2:29:82:02 +# SHA1 Fingerprint: 93:05:7a:88:15:c6:4f:ce:88:2f:fa:91:16:52:28:78:bc:53:64:17 +# SHA256 Fingerprint: 9a:6e:c0:12:e1:a7:da:9d:be:34:19:4d:47:8a:d7:c0:db:18:22:fb:07:1d:f1:29:81:49:6e:d1:04:38:41:13 +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE +AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw +CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ +BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND +VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb +qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY +HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo +G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA +lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr +IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ +0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH +k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 +4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO +m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa +cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl +uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI +KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls +ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG +AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT +VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG +CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA +cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA +QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA +7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA +cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA +QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA +czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu +aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt +aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud +DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF +BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp +D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU +JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m +AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD +vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms +tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH +7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA +h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF +d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H +pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- + +# Issuer: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA +# Subject: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA +# Label: "TWCA Global Root CA" +# Serial: 3262 +# MD5 Fingerprint: f9:03:7e:cf:e6:9e:3c:73:7a:2a:90:07:69:ff:2b:96 +# SHA1 Fingerprint: 9c:bb:48:53:f6:a4:f6:d3:52:a4:e8:32:52:55:60:13:f5:ad:af:65 +# SHA256 Fingerprint: 59:76:90:07:f7:68:5d:0f:cd:50:87:2f:9f:95:d5:75:5a:5b:2b:45:7d:81:f3:69:2b:61:0a:98:67:2f:0e:1b +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx +EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT +VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 +NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT +B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF +10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz +0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh +MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH +zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc +46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 +yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi +laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP +oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA +BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE +qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm +4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL +1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF +H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo +RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ +nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh +15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW +6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW +nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j +wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz +aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy +KwbQBM0= +-----END CERTIFICATE----- + +# Issuer: CN=TeliaSonera Root CA v1 O=TeliaSonera +# Subject: CN=TeliaSonera Root CA v1 O=TeliaSonera +# Label: "TeliaSonera Root CA v1" +# Serial: 199041966741090107964904287217786801558 +# MD5 Fingerprint: 37:41:49:1b:18:56:9a:26:f5:ad:c2:66:fb:40:a5:4c +# SHA1 Fingerprint: 43:13:bb:96:f1:d5:86:9b:c1:4e:6a:92:f6:cf:f6:34:69:87:82:37 +# SHA256 Fingerprint: dd:69:36:fe:21:f8:f0:77:c1:23:a1:a5:21:c1:22:24:f7:22:55:b7:3e:03:a7:26:06:93:e8:a2:4b:0f:a3:89 +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw +NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv +b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD +VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F +VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 +7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X +Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ +/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs +81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm +dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe +Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu +sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 +pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs +slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ +arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD +VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG +9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl +dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj +TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed +Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 +Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI +OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 +vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW +t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn +HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx +SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE----- + +# Issuer: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi +# Subject: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi +# Label: "E-Tugra Certification Authority" +# Serial: 7667447206703254355 +# MD5 Fingerprint: b8:a1:03:63:b0:bd:21:71:70:8a:6f:13:3a:bb:79:49 +# SHA1 Fingerprint: 51:c6:e7:08:49:06:6e:f3:92:d4:5c:a0:0d:6d:a3:62:8f:c3:52:39 +# SHA256 Fingerprint: b0:bf:d5:2b:b0:d7:d9:bd:92:bf:5d:4d:c1:3d:a2:55:c0:2c:54:2f:37:83:65:ea:89:39:11:f5:5e:55:f2:3c +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV +BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC +aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV +BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1 +Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz +MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+ +BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp +em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN +ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY +B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH +D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF +Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo +q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D +k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH +fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut +dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM +ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8 +zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn +rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX +U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6 +Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5 +XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF +Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR +HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY +GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c +77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3 ++GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK +vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6 +FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl +yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P +AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD +y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d +NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA== +-----END CERTIFICATE----- + +# Issuer: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Subject: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Label: "T-TeleSec GlobalRoot Class 2" +# Serial: 1 +# MD5 Fingerprint: 2b:9b:9e:e4:7b:6c:1f:00:72:1a:cc:c1:77:79:df:6a +# SHA1 Fingerprint: 59:0d:2d:7d:88:4f:40:2e:61:7e:a5:62:32:17:65:cf:17:d8:94:e9 +# SHA256 Fingerprint: 91:e2:f5:78:8d:58:10:eb:a7:ba:58:73:7d:e1:54:8a:8e:ca:cd:01:45:98:bc:0b:14:3e:04:1b:17:05:25:52 +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd +AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC +FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi +1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq +jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ +wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ +WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy +NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC +uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw +IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 +g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP +BSeOE6Fuwg== +-----END CERTIFICATE----- + +# Issuer: CN=Atos TrustedRoot 2011 O=Atos +# Subject: CN=Atos TrustedRoot 2011 O=Atos +# Label: "Atos TrustedRoot 2011" +# Serial: 6643877497813316402 +# MD5 Fingerprint: ae:b9:c4:32:4b:ac:7f:5d:66:cc:77:94:bb:2a:77:56 +# SHA1 Fingerprint: 2b:b1:f5:3e:55:0c:1d:c5:f1:d4:e6:b7:6a:46:4b:55:06:02:ac:21 +# SHA256 Fingerprint: f3:56:be:a2:44:b7:a9:1e:b3:5d:53:ca:9a:d7:86:4a:ce:01:8e:2d:35:d5:f8:f9:6d:df:68:a6:f4:1a:a4:74 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE +AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG +EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM +FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC +REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp +Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM +VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ +SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ +4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L +cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi +eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG +A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 +DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j +vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP +DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc +maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D +lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv +KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 1 G3" +# Serial: 687049649626669250736271037606554624078720034195 +# MD5 Fingerprint: a4:bc:5b:3f:fe:37:9a:fa:64:f0:e2:fa:05:3d:0b:ab +# SHA1 Fingerprint: 1b:8e:ea:57:96:29:1a:c9:39:ea:b8:0a:81:1a:73:73:c0:93:79:67 +# SHA256 Fingerprint: 8a:86:6f:d1:b2:76:b5:7e:57:8e:92:1c:65:82:8a:2b:ed:58:e9:f2:f2:88:05:41:34:b7:f1:f4:bf:c9:cc:74 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 +MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV +wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe +rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 +68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh +4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp +UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o +abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc +3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G +KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt +hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO +Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt +zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD +ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 +cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN +qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 +YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv +b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 +8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k +NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj +ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp +q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt +nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 2 G3" +# Serial: 390156079458959257446133169266079962026824725800 +# MD5 Fingerprint: af:0c:86:6e:bf:40:2d:7f:0b:3e:12:50:ba:12:3d:06 +# SHA1 Fingerprint: 09:3c:61:f3:8b:8b:dc:7d:55:df:75:38:02:05:00:e1:25:f5:c8:36 +# SHA256 Fingerprint: 8f:e4:fb:0a:f9:3a:4d:0d:67:db:0b:eb:b2:3e:37:c7:1b:f3:25:dc:bc:dd:24:0e:a0:4d:af:58:b4:7e:18:40 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 +MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf +qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW +n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym +c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ +O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 +o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j +IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq +IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz +8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh +vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l +7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG +cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD +ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC +roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga +W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n +lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE ++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV +csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd +dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg +KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM +HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 +WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 3 G3" +# Serial: 268090761170461462463995952157327242137089239581 +# MD5 Fingerprint: df:7d:b9:ad:54:6f:68:a1:df:89:57:03:97:43:b0:d7 +# SHA1 Fingerprint: 48:12:bd:92:3c:a8:c4:39:06:e7:30:6d:27:96:e6:a4:cf:22:2e:7d +# SHA256 Fingerprint: 88:ef:81:de:20:2e:b0:18:45:2e:43:f8:64:72:5c:ea:5f:bd:1f:c2:d9:d2:05:73:07:09:c5:d8:b8:69:0f:46 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 +MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR +/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu +FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR +U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c +ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR +FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k +A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw +eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl +sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp +VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q +A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ +ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD +ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI +FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv +oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg +u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP +0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf +3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl +8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ +DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN +PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ +ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root G2" +# Serial: 15385348160840213938643033620894905419 +# MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d +# SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f +# SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85 +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA +n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc +biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp +EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA +bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu +YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB +AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW +BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI +QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I +0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni +lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 +B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv +ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root G3" +# Serial: 15459312981008553731928384953135426796 +# MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb +# SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89 +# SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2 +-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg +RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf +Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q +RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD +AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY +JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv +6pZjamVFkpUBtA== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root G2" +# Serial: 4293743540046975378534879503202253541 +# MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44 +# SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4 +# SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH +MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI +2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx +1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ +q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz +tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ +vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV +5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY +1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 +NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG +Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 +8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe +pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root G3" +# Serial: 7089244469030293291760083333884364146 +# MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca +# SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e +# SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0 +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe +Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw +EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x +IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG +fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO +Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd +BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx +AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ +oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 +sycX +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Trusted Root G4" +# Serial: 7451500558977370777930084869016614236 +# MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49 +# SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4 +# SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88 +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg +RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y +ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If +xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV +ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO +DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ +jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ +CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi +EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM +fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY +uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK +chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t +9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 +SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd ++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc +fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa +sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N +cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N +0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie +4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI +r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 +/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm +gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ +-----END CERTIFICATE----- + +# Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited +# Label: "COMODO RSA Certification Authority" +# Serial: 101909084537582093308941363524873193117 +# MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18 +# SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4 +# SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34 +-----BEGIN CERTIFICATE----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB +hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV +BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT +EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR +6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X +pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC +9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV +/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf +Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z ++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w +qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah +SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC +u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf +Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq +crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl +wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM +4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV +2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna +FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ +CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK +boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke +jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL +S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb +QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl +0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB +NVOFBkpdn627G190 +-----END CERTIFICATE----- + +# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network +# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network +# Label: "USERTrust RSA Certification Authority" +# Serial: 2645093764781058787591871645665788717 +# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5 +# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e +# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2 +-----BEGIN CERTIFICATE----- +MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB +iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl +cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV +BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw +MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV +BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B +3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY +tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ +Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 +VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT +79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 +c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT +Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l +c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee +UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE +Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd +BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G +A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF +Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO +VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 +ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs +8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR +iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze +Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ +XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ +qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB +VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB +L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG +jjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE----- + +# Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network +# Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network +# Label: "USERTrust ECC Certification Authority" +# Serial: 123013823720199481456569720443997572134 +# MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1 +# SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0 +# SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a +-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl +eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT +JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT +Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg +VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo +I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng +o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G +A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB +zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW +RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 +# Label: "GlobalSign ECC Root CA - R4" +# Serial: 14367148294922964480859022125800977897474 +# MD5 Fingerprint: 20:f0:27:68:d1:7e:a0:9d:0e:e6:2a:ca:df:5c:89:8e +# SHA1 Fingerprint: 69:69:56:2e:40:80:f4:24:a1:e7:19:9f:14:ba:f3:ee:58:ab:6a:bb +# SHA256 Fingerprint: be:c9:49:11:c2:95:56:76:db:6c:0a:55:09:86:d7:6e:3b:a0:05:66:7c:44:2c:97:62:b4:fb:b7:73:de:22:8c +-----BEGIN CERTIFICATE----- +MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ +FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F +uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX +kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs +ewv4n4Q= +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 +# Label: "GlobalSign ECC Root CA - R5" +# Serial: 32785792099990507226680698011560947931244 +# MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08 +# SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa +# SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24 +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc +8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke +hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI +KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg +515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO +xwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE----- + +# Issuer: CN=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden +# Label: "Staat der Nederlanden Root CA - G3" +# Serial: 10003001 +# MD5 Fingerprint: 0b:46:67:07:db:10:2f:19:8c:35:50:60:d1:0b:f4:37 +# SHA1 Fingerprint: d8:eb:6b:41:51:92:59:e0:f3:e7:85:00:c0:3d:b6:88:97:c9:ee:fc +# SHA256 Fingerprint: 3c:4f:b0:b9:5a:b8:b3:00:32:f4:32:b8:6f:53:5f:e1:72:c1:85:d0:fd:39:86:58:37:cf:36:18:7f:a6:f4:28 +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX +DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl +ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv +b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP +cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW +IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX +xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy +KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR +9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az +5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8 +6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7 +Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP +bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt +BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt +XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd +INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD +U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp +LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8 +Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp +gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh +/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw +0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A +fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq +4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR +1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/ +QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM +94B7IWcnMFk= +-----END CERTIFICATE----- + +# Issuer: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden +# Label: "Staat der Nederlanden EV Root CA" +# Serial: 10000013 +# MD5 Fingerprint: fc:06:af:7b:e8:1a:f1:9a:b4:e8:d2:70:1f:c0:f5:ba +# SHA1 Fingerprint: 76:e2:7e:c1:4f:db:82:c1:c0:a6:75:b5:05:be:3d:29:b4:ed:db:bb +# SHA256 Fingerprint: 4d:24:91:41:4c:fe:95:67:46:ec:4c:ef:a6:cf:6f:72:e2:8a:13:29:43:2f:9d:8a:90:7a:c4:cb:5d:ad:c1:5a +-----BEGIN CERTIFICATE----- +MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y +MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg +TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS +b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS +M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC +UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d +Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p +rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l +pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb +j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC +KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS +/ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X +cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH +1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP +px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7 +MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI +eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u +2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS +v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC +wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy +CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e +vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6 +Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa +Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL +eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8 +FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc +7uzXLg== +-----END CERTIFICATE----- + +# Issuer: CN=IdenTrust Commercial Root CA 1 O=IdenTrust +# Subject: CN=IdenTrust Commercial Root CA 1 O=IdenTrust +# Label: "IdenTrust Commercial Root CA 1" +# Serial: 13298821034946342390520003877796839426 +# MD5 Fingerprint: b3:3e:77:73:75:ee:a0:d3:e3:7e:49:63:49:59:bb:c7 +# SHA1 Fingerprint: df:71:7e:aa:4a:d9:4e:c9:55:84:99:60:2d:48:de:5f:bc:f0:3a:25 +# SHA256 Fingerprint: 5d:56:49:9b:e4:d2:e0:8b:cf:ca:d0:8a:3e:38:72:3d:50:50:3b:de:70:69:48:e4:2f:55:60:30:19:e5:28:ae +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu +VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw +MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw +JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT +3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU ++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp +S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 +bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi +T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL +vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK +Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK +dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT +c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv +l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N +iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD +ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt +LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 +nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 ++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK +W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT +AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq +l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG +4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ +mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A +7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- + +# Issuer: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust +# Subject: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust +# Label: "IdenTrust Public Sector Root CA 1" +# Serial: 13298821034946342390521976156843933698 +# MD5 Fingerprint: 37:06:a5:b0:fc:89:9d:ba:f4:6b:8c:1a:64:cd:d5:ba +# SHA1 Fingerprint: ba:29:41:60:77:98:3f:f4:f3:ef:f2:31:05:3b:2e:ea:6d:4d:45:fd +# SHA256 Fingerprint: 30:d0:89:5a:9a:44:8a:26:20:91:63:55:22:d1:f5:20:10:b5:86:7a:ca:e1:2c:78:ef:95:8f:d4:f4:38:9f:2f +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu +VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN +MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 +MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 +ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy +RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS +bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF +/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R +3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw +EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy +9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V +GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ +2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV +WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD +W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN +AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV +DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 +TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G +lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW +mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df +WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 ++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ +tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA +GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv +8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - G2" +# Serial: 1246989352 +# MD5 Fingerprint: 4b:e2:c9:91:96:65:0c:f4:0e:5a:93:92:a0:0a:fe:b2 +# SHA1 Fingerprint: 8c:f4:27:fd:79:0c:3a:d1:66:06:8d:e8:1e:57:ef:bb:93:22:72:d4 +# SHA256 Fingerprint: 43:df:57:74:b0:3e:7f:ef:5f:e4:0d:93:1a:7b:ed:f1:bb:2e:6b:42:73:8c:4e:6d:38:41:10:3d:3a:a7:f3:39 +-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 +cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs +IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz +dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy +NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu +dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt +dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 +aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T +RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN +cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW +wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 +U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 +jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN +BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ +jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v +1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R +nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH +VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - EC1" +# Serial: 51543124481930649114116133369 +# MD5 Fingerprint: b6:7e:1d:f0:58:c5:49:6c:24:3b:3d:ed:98:18:ed:bc +# SHA1 Fingerprint: 20:d8:06:40:df:9b:25:f5:12:25:3a:11:ea:f7:59:8a:eb:14:b5:47 +# SHA256 Fingerprint: 02:ed:0e:b2:8c:14:da:45:16:5c:56:67:91:70:0d:64:51:d7:fb:56:f0:b2:ab:1d:3b:8e:b0:70:e5:6e:df:f5 +-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG +A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 +d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu +dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq +RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy +MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD +VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 +L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g +Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi +A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt +ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH +Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC +R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX +hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE----- + +# Issuer: CN=CFCA EV ROOT O=China Financial Certification Authority +# Subject: CN=CFCA EV ROOT O=China Financial Certification Authority +# Label: "CFCA EV ROOT" +# Serial: 407555286 +# MD5 Fingerprint: 74:e1:b6:ed:26:7a:7a:44:30:33:94:ab:7b:27:81:30 +# SHA1 Fingerprint: e2:b8:29:4b:55:84:ab:6b:58:c2:90:46:6c:ac:3f:b8:39:8f:84:83 +# SHA256 Fingerprint: 5c:c3:d7:8e:4e:1d:5e:45:54:7a:04:e6:87:3e:64:f9:0c:f9:53:6d:1c:cc:2e:f8:00:f3:55:c4:c5:fd:70:fd +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD +TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y +aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx +MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j +aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP +T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 +sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL +TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 +/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp +7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz +EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt +hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP +a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot +aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg +TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV +PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv +cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL +tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd +BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT +ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL +jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS +ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy +P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 +xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d +Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN +5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe +/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z +AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ +5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE----- + +# Issuer: CN=T\xdcRKTRUST Elektronik Sertifika Hizmet Sa\u011flay\u0131c\u0131s\u0131 H5 O=T\xdcRKTRUST Bilgi \u0130leti\u015fim ve Bili\u015fim G\xfcvenli\u011fi Hizmetleri A.\u015e. +# Subject: CN=T\xdcRKTRUST Elektronik Sertifika Hizmet Sa\u011flay\u0131c\u0131s\u0131 H5 O=T\xdcRKTRUST Bilgi \u0130leti\u015fim ve Bili\u015fim G\xfcvenli\u011fi Hizmetleri A.\u015e. +# Label: "T\xdcRKTRUST Elektronik Sertifika Hizmet Sa\u011flay\u0131c\u0131s\u0131 H5" +# Serial: 156233699172481 +# MD5 Fingerprint: da:70:8e:f0:22:df:93:26:f6:5f:9f:d3:15:06:52:4e +# SHA1 Fingerprint: c4:18:f6:4d:46:d1:df:00:3d:27:30:13:72:43:a9:12:11:c6:75:fb +# SHA256 Fingerprint: 49:35:1b:90:34:44:c1:85:cc:dc:5c:69:3d:24:d8:55:5c:b2:08:d6:a8:14:13:07:69:9f:4a:f0:63:19:9d:78 +-----BEGIN CERTIFICATE----- +MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UE +BhMCVFIxDzANBgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxn +aSDEsGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkg +QS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1QgRWxla3Ryb25payBTZXJ0aWZpa2Eg +SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAwODA3MDFaFw0yMzA0 +MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYD +VQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 +dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF +bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApCUZ4WWe60ghUEoI5RHwWrom +/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537jVJp45wnEFPzpALFp/kR +Gml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1mep5Fimh3 +4khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z +5UNP9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0 +hO8EuPbJbKoCPrZV4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QID +AQABo0IwQDAdBgNVHQ4EFgQUVpkHHtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/ +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ5FdnsX +SDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPoBP5yCccLqh0l +VX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq +URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nf +peYVhDfwwvJllpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CF +Yv4HAqGEVka+lgqaE9chTLd8B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW ++qtB4Uu2NQvAmxU= +-----END CERTIFICATE----- + +# Issuer: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903 +# Subject: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903 +# Label: "Certinomis - Root CA" +# Serial: 1 +# MD5 Fingerprint: 14:0a:fd:8d:a8:28:b5:38:69:db:56:7e:61:22:03:3f +# SHA1 Fingerprint: 9d:70:bb:01:a5:a4:a0:18:11:2e:f7:1c:01:b9:32:c5:34:e7:88:a8 +# SHA256 Fingerprint: 2a:99:f5:bc:11:74:b7:3c:bb:1d:62:08:84:e0:1c:34:e5:1c:cb:39:78:da:12:5f:0e:33:26:88:83:bf:41:58 +-----BEGIN CERTIFICATE----- +MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjET +MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAb +BgNVBAMTFENlcnRpbm9taXMgLSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMz +MTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMx +FzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRDZXJ0aW5vbWlzIC0g +Um9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQosP5L2 +fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJfl +LieY6pOod5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQV +WZUKxkd8aRi5pwP5ynapz8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDF +TKWrteoB4owuZH9kb/2jJZOLyKIOSY008B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb +5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09xRLWtwHkziOC/7aOgFLSc +CbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE6OXWk6Ri +wsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJ +wx3tFvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SG +m/lg0h9tkQPTYKbVPZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4 +F2iw4lNVYC2vPsKD2NkJK/DAZNuHi5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZng +WVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I6tNxIqSSaHh0 +2TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF +AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/ +0KGRHCwPT5iVWVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWw +F6YSjNRieOpWauwK0kDDPAUwPk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZS +g081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAXlCOotQqSD7J6wWAsOMwaplv/8gzj +qh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJy29SWwNyhlCVCNSN +h4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9Iff/ +ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8V +btaw5BngDwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwj +Y/M50n92Uaf0yKHxDHYiI0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ +8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nMcyrDflOR1m749fPH0FFNjkulW+YZFzvW +gQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVrhkIGuUE= +-----END CERTIFICATE----- + +# Issuer: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GB CA" +# Serial: 157768595616588414422159278966750757568 +# MD5 Fingerprint: a4:eb:b9:61:28:2e:b7:2f:98:b0:35:26:90:99:51:1d +# SHA1 Fingerprint: 0f:f9:40:76:18:d3:d7:6a:4b:98:f0:a8:35:9e:0c:fd:27:ac:cc:ed +# SHA256 Fingerprint: 6b:9c:08:e8:6e:b0:f7:67:cf:ad:65:cd:98:b6:21:49:e5:49:4a:67:f5:84:5e:7b:d1:ed:01:9f:27:b8:6b:d6 +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt +MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg +Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i +YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x +CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG +b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh +bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 +HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx +WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX +1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk +u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P +99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r +M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB +BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh +cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 +gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO +ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf +aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- + +# Issuer: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. +# Subject: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. +# Label: "SZAFIR ROOT CA2" +# Serial: 357043034767186914217277344587386743377558296292 +# MD5 Fingerprint: 11:64:c1:89:b0:24:b1:8c:b1:07:7e:89:9e:51:9e:99 +# SHA1 Fingerprint: e2:52:fa:95:3f:ed:db:24:60:bd:6e:28:f3:9c:cc:cf:5e:b3:3f:de +# SHA256 Fingerprint: a1:33:9d:33:28:1a:0b:56:e5:57:d3:d3:2b:1c:e7:f9:36:7e:b0:94:bd:5f:a7:2a:7e:50:04:c8:de:d7:ca:fe +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL +BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 +ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw +NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L +cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg +Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN +QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT +3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw +3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6 +3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5 +BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN +XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF +AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw +8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG +nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP +oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy +d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg +LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Network CA 2" +# Serial: 44979900017204383099463764357512596969 +# MD5 Fingerprint: 6d:46:9e:d9:25:6d:08:23:5b:5e:74:7d:1e:27:db:f2 +# SHA1 Fingerprint: d3:dd:48:3e:2b:bf:4c:05:e8:af:10:f5:fa:76:26:cf:d3:dc:30:92 +# SHA256 Fingerprint: b6:76:f2:ed:da:e8:77:5c:d3:6c:b0:f6:3c:d1:d4:60:39:61:f4:9e:62:65:ba:01:3a:2f:03:07:b6:d0:b8:04 +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB +gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu +QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG +A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz +OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ +VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 +b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA +DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn +0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB +OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE +fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E +Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m +o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i +sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW +OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez +Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS +adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n +3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ +F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf +CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 +XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm +djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ +WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb +AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq +P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko +b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj +XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P +5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi +DrW5viSP +-----END CERTIFICATE----- + +# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions RootCA 2015" +# Serial: 0 +# MD5 Fingerprint: ca:ff:e2:db:03:d9:cb:4b:e9:0f:ad:84:fd:7b:18:ce +# SHA1 Fingerprint: 01:0c:06:95:a6:98:19:14:ff:bf:5f:c6:b0:b6:95:ea:29:e9:12:a6 +# SHA256 Fingerprint: a0:40:92:9a:02:ce:53:b4:ac:f4:f2:ff:c6:98:1c:e4:49:6f:75:5e:6d:45:fe:0b:2a:69:2b:cd:52:52:3f:36 +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix +DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k +IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT +N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v +dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG +A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh +ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx +QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA +4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 +AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 +4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C +ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV +9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD +gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 +Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq +NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko +LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd +ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I +XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI +M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot +9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V +Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea +j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh +X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ +l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf +bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 +pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK +e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 +vm9qp/UsQu0yrbYhnr68 +-----END CERTIFICATE----- + +# Issuer: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions ECC RootCA 2015" +# Serial: 0 +# MD5 Fingerprint: 81:e5:b4:17:eb:c2:f5:e1:4b:0d:41:7b:49:92:fe:ef +# SHA1 Fingerprint: 9f:f1:71:8d:92:d5:9a:f3:7d:74:97:b4:bc:6f:84:68:0b:ba:b6:66 +# SHA256 Fingerprint: 44:b5:45:aa:8a:25:e6:5a:73:ca:15:dc:27:fc:36:d2:4c:1c:b9:95:3a:06:65:39:b1:15:82:dc:48:7b:48:33 +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN +BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl +bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv +b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ +BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj +YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 +MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 +dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg +QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa +jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi +C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep +lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof +TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- + +# Issuer: CN=Certplus Root CA G1 O=Certplus +# Subject: CN=Certplus Root CA G1 O=Certplus +# Label: "Certplus Root CA G1" +# Serial: 1491911565779898356709731176965615564637713 +# MD5 Fingerprint: 7f:09:9c:f7:d9:b9:5c:69:69:56:d5:37:3e:14:0d:42 +# SHA1 Fingerprint: 22:fd:d0:b7:fd:a2:4e:0d:ac:49:2c:a0:ac:a6:7b:6a:1f:e3:f7:66 +# SHA256 Fingerprint: 15:2a:40:2b:fc:df:2c:d5:48:05:4d:22:75:b3:9c:7f:ca:3e:c0:97:80:78:b0:f0:ea:76:e5:61:a6:c7:43:3e +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUA +MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy +dHBsdXMgUm9vdCBDQSBHMTAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBa +MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy +dHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +ANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHNr49a +iZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt +6kuJPKNxQv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP +0FG7Yn2ksYyy/yARujVjBYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f +6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTvLRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDE +EW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2z4QTd28n6v+WZxcIbekN +1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc4nBvCGrc +h2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCT +mehd4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV +4EJQeIQEQWGw9CEjjy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPO +WftwenMGE9nTdDckQQoRb5fc5+R+ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1Ud +DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSowcCbkahDFXxd +Bie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHYlwuBsTANBgkq +hkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh +66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7 +/SMNkPX0XtPGYX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BS +S7CTKtQ+FjPlnsZlFT5kOwQ/2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j +2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F6ALEUz65noe8zDUa3qHpimOHZR4R +Kttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilXCNQ314cnrUlZp5Gr +RHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWetUNy +6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEV +V/xuZDDCVRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5 +g4VCXA9DO2pJNdWY9BW/+mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl +++O/QmueD6i9a5jc2NvLi6Td11n0bt3+qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo= +-----END CERTIFICATE----- + +# Issuer: CN=Certplus Root CA G2 O=Certplus +# Subject: CN=Certplus Root CA G2 O=Certplus +# Label: "Certplus Root CA G2" +# Serial: 1492087096131536844209563509228951875861589 +# MD5 Fingerprint: a7:ee:c4:78:2d:1b:ee:2d:b9:29:ce:d6:a7:96:32:31 +# SHA1 Fingerprint: 4f:65:8e:1f:e9:06:d8:28:02:e9:54:47:41:c9:54:25:5d:69:cc:1a +# SHA256 Fingerprint: 6c:c0:50:41:e6:44:5e:74:69:6c:4c:fb:c9:f8:0f:54:3b:7e:ab:bb:44:b4:ce:6f:78:7c:6a:99:71:c4:2f:17 +-----BEGIN CERTIFICATE----- +MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4x +CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs +dXMgUm9vdCBDQSBHMjAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4x +CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs +dXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABM0PW1aC3/BFGtat +93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uNAm8x +Ik0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0P +AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwj +FNiPwyCrKGBZMB8GA1UdIwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqG +SM49BAMDA2gAMGUCMHD+sAvZ94OX7PNVHdTcswYO/jOYnYs5kGuUIe22113WTNch +p+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjlvPl5adytRSv3tjFzzAal +U5ORGpOucGpnutee5WEaXw== +-----END CERTIFICATE----- + +# Issuer: CN=OpenTrust Root CA G1 O=OpenTrust +# Subject: CN=OpenTrust Root CA G1 O=OpenTrust +# Label: "OpenTrust Root CA G1" +# Serial: 1492036577811947013770400127034825178844775 +# MD5 Fingerprint: 76:00:cc:81:29:cd:55:5e:88:6a:7a:2e:f7:4d:39:da +# SHA1 Fingerprint: 79:91:e8:34:f7:e2:ee:dd:08:95:01:52:e9:55:2d:14:e9:58:d5:7e +# SHA256 Fingerprint: 56:c7:71:28:d9:8c:18:d9:1b:4c:fd:ff:bc:25:ee:91:03:d4:75:8e:a2:ab:ad:82:6a:90:f3:45:7d:46:0e:b4 +-----BEGIN CERTIFICATE----- +MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUA +MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w +ZW5UcnVzdCBSb290IENBIEcxMB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAw +MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU +T3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7faYp6b +wiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX +/uMftk87ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR0 +77F9jAHiOH3BX2pfJLKOYheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGP +uY4zbGneWK2gDqdkVBFpRGZPTBKnjix9xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLx +p2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO9z0M+Yo0FMT7MzUj8czx +Kselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq3ywgsNw2 +TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+W +G+Oin6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPw +vFEVVJSmdz7QdFG9URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYY +EQRVzXR7z2FwefR7LFxckvzluFqrTJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUl0YhVyE1 +2jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/PxN3DlCPaTKbYw +DQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E +PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kf +gLMtMrpkZ2CvuVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbS +FXJfLkur1J1juONI5f6ELlgKn0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0 +V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLhX4SPgPL0DTatdrOjteFkdjpY3H1P +XlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80nR14SohWZ25g/4/I +i+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcmGS3t +TAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L91 +09S5zvE/bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/Ky +Pu1svf0OnWZzsD2097+o4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJ +AwSQiumPv+i2tCqjI40cHLI5kqiPAlxAOXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj +1oxx +-----END CERTIFICATE----- + +# Issuer: CN=OpenTrust Root CA G2 O=OpenTrust +# Subject: CN=OpenTrust Root CA G2 O=OpenTrust +# Label: "OpenTrust Root CA G2" +# Serial: 1492012448042702096986875987676935573415441 +# MD5 Fingerprint: 57:24:b6:59:24:6b:ae:c8:fe:1c:0c:20:f2:c0:4e:eb +# SHA1 Fingerprint: 79:5f:88:60:c5:ab:7c:3d:92:e6:cb:f4:8d:e1:45:cd:11:ef:60:0b +# SHA256 Fingerprint: 27:99:58:29:fe:6a:75:15:c1:bf:e8:48:f9:c4:76:1d:b1:6c:22:59:29:25:7b:f4:0d:08:94:f2:9e:a8:ba:f2 +-----BEGIN CERTIFICATE----- +MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUA +MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w +ZW5UcnVzdCBSb290IENBIEcyMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAw +MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU +T3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+Ntmh +/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78e +CbY2albz4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/6 +1UWY0jUJ9gNDlP7ZvyCVeYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fE +FY8ElggGQgT4hNYdvJGmQr5J1WqIP7wtUdGejeBSzFfdNTVY27SPJIjki9/ca1TS +gSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz3GIZ38i1MH/1PCZ1Eb3X +G7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj3CzMpSZy +YhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaH +vGOz9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4 +t/bQWVyJ98LVtZR00dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/ +gh7PU3+06yzbXfZqfUAkBXKJOAGTy3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUajn6QiL3 +5okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59M4PLuG53hq8w +DQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz +Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0 +nXGEL8pZ0keImUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qT +RmTFAHneIWv2V6CG1wZy7HBGS4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpT +wm+bREx50B1ws9efAvSyB7DH5fitIw6mVskpEndI2S9G/Tvw/HRwkqWOOAgfZDC2 +t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ6e18CL13zSdkzJTa +TkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97krgCf2 +o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU +3jg9CcCoSmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eA +iN1nE28daCSLT7d0geX0YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14f +WKGVyasvc0rQLW6aWQ9VGHgtPFGml4vmu7JwqkwR3v98KzfUetF3NI/n+UL3PIEM +S1IK +-----END CERTIFICATE----- + +# Issuer: CN=OpenTrust Root CA G3 O=OpenTrust +# Subject: CN=OpenTrust Root CA G3 O=OpenTrust +# Label: "OpenTrust Root CA G3" +# Serial: 1492104908271485653071219941864171170455615 +# MD5 Fingerprint: 21:37:b4:17:16:92:7b:67:46:70:a9:96:d7:a8:13:24 +# SHA1 Fingerprint: 6e:26:64:f3:56:bf:34:55:bf:d1:93:3f:7c:01:de:d8:13:da:8a:a6 +# SHA256 Fingerprint: b7:c3:62:31:70:6e:81:07:8c:36:7c:b8:96:19:8f:1e:32:08:dd:92:69:49:dd:8f:57:09:a4:10:f7:5b:62:92 +-----BEGIN CERTIFICATE----- +MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAx +CzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5U +cnVzdCBSb290IENBIEczMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFow +QDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwUT3Bl +blRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARK7liuTcpm +3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5Bta1d +oYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4G +A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5 +DMlv4VBN0BBY3JWIbTAfBgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAK +BggqhkjOPQQDAwNpADBmAjEAj6jcnboMBBf6Fek9LykBl7+BFjNAk2z8+e2AcG+q +j9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta3U1fJAuwACEl74+nBCZx +4nxp5V2a+EEfOzmTk51V6s2N8fvB +-----END CERTIFICATE----- + +# Issuer: CN=ISRG Root X1 O=Internet Security Research Group +# Subject: CN=ISRG Root X1 O=Internet Security Research Group +# Label: "ISRG Root X1" +# Serial: 172886928669790476064670243504169061120 +# MD5 Fingerprint: 0c:d2:f9:e0:da:17:73:e9:ed:86:4d:a5:e3:70:e7:4e +# SHA1 Fingerprint: ca:bd:2a:79:a1:07:6a:31:f2:1d:25:36:35:cb:03:9d:43:29:a5:e8 +# SHA256 Fingerprint: 96:bc:ec:06:26:49:76:f3:74:60:77:9a:cf:28:c5:a7:cf:e8:a3:c0:aa:e1:1a:8f:fc:ee:05:c0:bd:df:08:c6 +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- + +# Issuer: O=FNMT-RCM OU=AC RAIZ FNMT-RCM +# Subject: O=FNMT-RCM OU=AC RAIZ FNMT-RCM +# Label: "AC RAIZ FNMT-RCM" +# Serial: 485876308206448804701554682760554759 +# MD5 Fingerprint: e2:09:04:b4:d3:bd:d1:a0:14:fd:1a:d2:47:c4:57:1d +# SHA1 Fingerprint: ec:50:35:07:b2:15:c4:95:62:19:e2:a8:9a:5b:42:99:2c:4c:2c:20 +# SHA256 Fingerprint: eb:c5:57:0c:29:01:8c:4d:67:b1:aa:12:7b:af:12:f7:03:b4:61:1e:bc:17:b7:da:b5:57:38:94:17:9b:93:fa +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx +CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ +WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ +BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG +Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ +yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf +BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz +WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF +tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z +374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC +IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL +mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 +wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS +MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 +ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet +UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H +YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 +LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 +RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM +LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf +77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N +JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm +fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp +6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp +1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B +9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok +RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv +uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 1 O=Amazon +# Subject: CN=Amazon Root CA 1 O=Amazon +# Label: "Amazon Root CA 1" +# Serial: 143266978916655856878034712317230054538369994 +# MD5 Fingerprint: 43:c6:bf:ae:ec:fe:ad:2f:18:c6:88:68:30:fc:c8:e6 +# SHA1 Fingerprint: 8d:a7:f9:65:ec:5e:fc:37:91:0f:1c:6e:59:fd:c1:cc:6a:6e:de:16 +# SHA256 Fingerprint: 8e:cd:e6:88:4f:3d:87:b1:12:5b:a3:1a:c3:fc:b1:3d:70:16:de:7f:57:cc:90:4f:e1:cb:97:c6:ae:98:19:6e +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 2 O=Amazon +# Subject: CN=Amazon Root CA 2 O=Amazon +# Label: "Amazon Root CA 2" +# Serial: 143266982885963551818349160658925006970653239 +# MD5 Fingerprint: c8:e5:8d:ce:a8:42:e2:7a:c0:2a:5c:7c:9e:26:bf:66 +# SHA1 Fingerprint: 5a:8c:ef:45:d7:a6:98:59:76:7a:8c:8b:44:96:b5:78:cf:47:4b:1a +# SHA256 Fingerprint: 1b:a5:b2:aa:8c:65:40:1a:82:96:01:18:f8:0b:ec:4f:62:30:4d:83:ce:c4:71:3a:19:c3:9c:01:1e:a4:6d:b4 +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK +gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ +W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg +1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K +8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r +2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me +z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR +8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj +mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz +7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 ++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI +0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm +UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 +LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS +k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl +7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm +btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl +urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ +fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 +n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE +76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H +9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT +4PsJYGw= +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 3 O=Amazon +# Subject: CN=Amazon Root CA 3 O=Amazon +# Label: "Amazon Root CA 3" +# Serial: 143266986699090766294700635381230934788665930 +# MD5 Fingerprint: a0:d4:ef:0b:f7:b5:d8:49:95:2a:ec:f5:c4:fc:81:87 +# SHA1 Fingerprint: 0d:44:dd:8c:3c:8c:1a:1a:58:75:64:81:e9:0f:2e:2a:ff:b3:d2:6e +# SHA256 Fingerprint: 18:ce:6c:fe:7b:f1:4e:60:b2:e3:47:b8:df:e8:68:cb:31:d0:2e:bb:3a:da:27:15:69:f5:03:43:b4:6d:b3:a4 +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl +ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr +ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr +BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM +YyRIHN8wfdVoOw== +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 4 O=Amazon +# Subject: CN=Amazon Root CA 4 O=Amazon +# Label: "Amazon Root CA 4" +# Serial: 143266989758080763974105200630763877849284878 +# MD5 Fingerprint: 89:bc:27:d5:eb:17:8d:06:6a:69:d5:fd:89:47:b4:cd +# SHA1 Fingerprint: f6:10:84:07:d6:f8:bb:67:98:0c:c2:e2:44:c2:eb:ae:1c:ef:63:be +# SHA256 Fingerprint: e3:5d:28:41:9e:d0:20:25:cf:a6:90:38:cd:62:39:62:45:8d:a5:c6:95:fb:de:a3:c2:2b:0b:fb:25:89:70:92 +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi +9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk +M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB +MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw +CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW +1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- + +# Issuer: CN=LuxTrust Global Root 2 O=LuxTrust S.A. +# Subject: CN=LuxTrust Global Root 2 O=LuxTrust S.A. +# Label: "LuxTrust Global Root 2" +# Serial: 59914338225734147123941058376788110305822489521 +# MD5 Fingerprint: b2:e1:09:00:61:af:f7:f1:91:6f:c4:ad:8d:5e:3b:7c +# SHA1 Fingerprint: 1e:0e:56:19:0a:d1:8b:25:98:b2:04:44:ff:66:8a:04:17:99:5f:3f +# SHA256 Fingerprint: 54:45:5f:71:29:c2:0b:14:47:c4:18:f9:97:16:8f:24:c5:8f:c5:02:3b:f5:da:5b:e2:eb:6e:1d:d8:90:2e:d5 +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM +# Subject: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM +# Label: "TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1" +# Serial: 1 +# MD5 Fingerprint: dc:00:81:dc:69:2f:3e:2f:b0:3b:f6:3d:5a:91:8e:49 +# SHA1 Fingerprint: 31:43:64:9b:ec:ce:27:ec:ed:3a:3f:0b:8f:0d:e4:e8:91:dd:ee:ca +# SHA256 Fingerprint: 46:ed:c3:68:90:46:d5:3a:45:3f:b3:10:4a:b8:0d:ca:ec:65:8b:26:60:ea:16:29:dd:7e:86:79:90:64:87:16 +-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx +GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp +bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w +KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0 +BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy +dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG +EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll +IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU +QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT +TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg +LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7 +a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr +LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr +N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X +YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/ +iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f +AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH +V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh +AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf +IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4 +lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c +8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf +lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= +-----END CERTIFICATE----- + +# Issuer: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. +# Subject: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. +# Label: "GDCA TrustAUTH R5 ROOT" +# Serial: 9009899650740120186 +# MD5 Fingerprint: 63:cc:d9:3d:34:35:5c:6f:53:a3:e2:08:70:48:1f:b4 +# SHA1 Fingerprint: 0f:36:38:5b:81:1a:25:c3:9b:31:4e:83:ca:e9:34:66:70:cc:74:b4 +# SHA256 Fingerprint: bf:ff:8f:d0:44:33:48:7d:6a:8a:a6:0c:1a:29:76:7a:9f:c2:bb:b0:5e:42:0f:71:3a:13:b9:92:89:1d:38:93 +-----BEGIN CERTIFICATE----- +MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE +BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ +IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 +MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV +BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w +HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj +Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj +TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u +KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj +qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm +MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12 +ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP +zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk +L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC +jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA +HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC +AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg +p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm +DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5 +COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry +L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf +JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg +IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io +2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV +09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ +XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq +T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe +MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== +-----END CERTIFICATE----- + +# Issuer: CN=TrustCor RootCert CA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor RootCert CA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor RootCert CA-1" +# Serial: 15752444095811006489 +# MD5 Fingerprint: 6e:85:f1:dc:1a:00:d3:22:d5:b2:b2:ac:6b:37:05:45 +# SHA1 Fingerprint: ff:bd:cd:e7:82:c8:43:5e:3c:6f:26:86:5c:ca:a8:3a:45:5b:c3:0a +# SHA256 Fingerprint: d4:0e:9c:86:cd:8f:e4:68:c1:77:69:59:f4:9e:a7:74:fa:54:86:84:b6:c4:06:f3:90:92:61:f4:dc:e2:57:5c +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYD +VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk +MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29y +IFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkxMjMxMTcyMzE2WjCB +pDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFuYW1h +IENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUG +A1UECwweVHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZU +cnVzdENvciBSb290Q2VydCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAv463leLCJhJrMxnHQFgKq1mqjQCj/IDHUHuO1CAmujIS2CNUSSUQIpid +RtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4pQa81QBeCQryJ3pS/C3V +seq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0JEsq1pme +9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CV +EY4hgLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorW +hnAbJN7+KIor0Gqw/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/ +DeOxCbeKyKsZn3MzUOcwHwYDVR0jBBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD +ggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5mDo4Nvu7Zp5I +/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf +ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZ +yonnMlo2HD6CqFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djts +L1Ac59v2Z3kf9YKVmgenFK+P3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdN +zl/HHk484IkzlQsPpTLWPFp5LBk= +-----END CERTIFICATE----- + +# Issuer: CN=TrustCor RootCert CA-2 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor RootCert CA-2 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor RootCert CA-2" +# Serial: 2711694510199101698 +# MD5 Fingerprint: a2:e1:f8:18:0b:ba:45:d5:c7:41:2a:bb:37:52:45:64 +# SHA1 Fingerprint: b8:be:6d:cb:56:f1:55:b9:63:d4:12:ca:4e:06:34:c7:94:b2:1c:c0 +# SHA256 Fingerprint: 07:53:e9:40:37:8c:1b:d5:e3:83:6e:39:5d:ae:a5:cb:83:9e:50:46:f1:bd:0e:ae:19:51:cf:10:fe:c7:c9:65 +-----BEGIN CERTIFICATE----- +MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig +Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk +MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg +Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD +VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy +dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+ +QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq +1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp +2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK +DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape +az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF +3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88 +oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM +g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3 +mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh +8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd +BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U +nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw +DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX +dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+ +MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL +/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX +CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa +ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW +2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7 +N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3 +Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB +As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp +5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu +1uwJ +-----END CERTIFICATE----- + +# Issuer: CN=TrustCor ECA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor ECA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor ECA-1" +# Serial: 9548242946988625984 +# MD5 Fingerprint: 27:92:23:1d:0a:f5:40:7c:e9:e6:6b:9d:d8:f5:e7:6c +# SHA1 Fingerprint: 58:d1:df:95:95:67:6b:63:c0:f0:5b:1c:17:4d:8b:84:0b:c8:78:bd +# SHA256 Fingerprint: 5a:88:5d:b1:9c:01:d9:12:c5:75:93:88:93:8c:af:bb:df:03:1a:b2:d4:8e:91:ee:15:58:9b:42:97:1d:03:9c +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYD +VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk +MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29y +IEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3MjgwN1owgZwxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3Ig +RUNBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb +3w9U73NjKYKtR8aja+3+XzP4Q1HpGjORMRegdMTUpwHmspI+ap3tDvl0mEDTPwOA +BoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23xFUfJ3zSCNV2HykVh0A5 +3ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmcp0yJF4Ou +owReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/ +wZ0+fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZF +ZtS6mFjBAgMBAAGjYzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAf +BgNVHSMEGDAWgBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABT41XBVwm8nHc2Fv +civUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u/ukZMjgDfxT2 +AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F +hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50 +soIipX1TH0XsJ5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BI +WJZpTdwHjFGTot+fDz2LYLSCjaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1Wi +tJ/X5g== +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com Root Certification Authority RSA O=SSL Corporation +# Subject: CN=SSL.com Root Certification Authority RSA O=SSL Corporation +# Label: "SSL.com Root Certification Authority RSA" +# Serial: 8875640296558310041 +# MD5 Fingerprint: 86:69:12:c0:70:f1:ec:ac:ac:c2:d5:bc:a5:5b:a1:29 +# SHA1 Fingerprint: b7:ab:33:08:d1:ea:44:77:ba:14:80:12:5a:6f:bd:a9:36:49:0c:bb +# SHA256 Fingerprint: 85:66:6a:56:2e:e0:be:5c:e9:25:c1:d8:89:0a:6f:76:a8:7e:c1:6d:4d:7d:5f:29:ea:74:19:cf:20:12:3b:69 +-----BEGIN CERTIFICATE----- +MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE +BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK +DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz +OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv +bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R +xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX +qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC +C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3 +6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh +/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF +YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E +JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc +US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8 +ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm ++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi +M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G +A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV +cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc +Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs +PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/ +q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0 +cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr +a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I +H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y +K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu +nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf +oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY +Ic2wBlX7Jz9TkHCpBB5XJ7k= +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com Root Certification Authority ECC O=SSL Corporation +# Subject: CN=SSL.com Root Certification Authority ECC O=SSL Corporation +# Label: "SSL.com Root Certification Authority ECC" +# Serial: 8495723813297216424 +# MD5 Fingerprint: 2e:da:e4:39:7f:9c:8f:37:d1:70:9f:26:17:51:3a:8e +# SHA1 Fingerprint: c3:19:7c:39:24:e6:54:af:1b:c4:ab:20:95:7a:e2:c3:0e:13:02:6a +# SHA256 Fingerprint: 34:17:bb:06:cc:60:07:da:1b:96:1c:92:0b:8a:b4:ce:3f:ad:82:0e:4a:a3:0b:9a:cb:c4:a7:4e:bd:ce:bc:65 +-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz +WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 +b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS +b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI +7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg +CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud +EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD +VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T +kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ +gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation +# Subject: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation +# Label: "SSL.com EV Root Certification Authority RSA R2" +# Serial: 6248227494352943350 +# MD5 Fingerprint: e1:1e:31:58:1a:ae:54:53:02:f6:17:6a:11:7b:4d:95 +# SHA1 Fingerprint: 74:3a:f0:52:9b:d0:32:a0:f4:4a:83:cd:d4:ba:a9:7b:7c:2e:c4:9a +# SHA256 Fingerprint: 2e:7b:f1:6c:c2:24:85:a7:bb:e2:aa:86:96:75:07:61:b0:ae:39:be:3b:2f:e9:d0:cc:6d:4e:f7:34:91:42:5c +-----BEGIN CERTIFICATE----- +MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV +BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE +CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy +MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G +A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD +DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq +M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf +OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa +4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9 +HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR +aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA +b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ +Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV +PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO +pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu +UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY +MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV +HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4 +9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW +s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5 +Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg +cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM +79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz +/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt +ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm +Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK +QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ +w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi +S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 +mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation +# Subject: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation +# Label: "SSL.com EV Root Certification Authority ECC" +# Serial: 3182246526754555285 +# MD5 Fingerprint: 59:53:22:65:83:42:01:54:c0:ce:42:b9:5a:7c:f2:90 +# SHA1 Fingerprint: 4c:dd:51:a3:d1:f5:20:32:14:b0:c6:c5:32:23:03:91:c7:46:42:6d +# SHA256 Fingerprint: 22:a2:c1:f7:bd:ed:70:4c:c1:e7:01:b5:f4:08:c3:10:88:0f:e9:56:b5:de:2a:4a:44:f9:9c:87:3a:25:a7:c8 +-----BEGIN CERTIFICATE----- +MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx +NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv +bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49 +AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA +VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku +WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP +MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX +5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ +ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg +h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== +-----END CERTIFICATE----- diff --git a/flex/lib/python3.6/site-packages/certifi/core.py b/flex/lib/python3.6/site-packages/certifi/core.py new file mode 100644 index 0000000..eab9d1d --- /dev/null +++ b/flex/lib/python3.6/site-packages/certifi/core.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +certifi.py +~~~~~~~~~~ + +This module returns the installation location of cacert.pem. +""" +import os +import warnings + + +class DeprecatedBundleWarning(DeprecationWarning): + """ + The weak security bundle is being deprecated. Please bother your service + provider to get them to stop using cross-signed roots. + """ + + +def where(): + f = os.path.dirname(__file__) + + return os.path.join(f, 'cacert.pem') + + +def old_where(): + warnings.warn( + "The weak security bundle has been removed. certifi.old_where() is now an alias " + "of certifi.where(). Please update your code to use certifi.where() instead. " + "certifi.old_where() will be removed in 2018.", + DeprecatedBundleWarning + ) + return where() + +if __name__ == '__main__': + print(where()) diff --git a/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/DESCRIPTION.rst b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..c0f044d --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/DESCRIPTION.rst @@ -0,0 +1,70 @@ +Chardet: The Universal Character Encoding Detector +-------------------------------------------------- + +.. image:: https://img.shields.io/travis/chardet/chardet/stable.svg + :alt: Build status + :target: https://travis-ci.org/chardet/chardet + +.. image:: https://img.shields.io/coveralls/chardet/chardet/stable.svg + :target: https://coveralls.io/r/chardet/chardet + +.. image:: https://img.shields.io/pypi/v/chardet.svg + :target: https://warehouse.python.org/project/chardet/ + :alt: Latest version on PyPI + +.. image:: https://img.shields.io/pypi/l/chardet.svg + :alt: License + + +Detects + - ASCII, UTF-8, UTF-16 (2 variants), UTF-32 (4 variants) + - Big5, GB2312, EUC-TW, HZ-GB-2312, ISO-2022-CN (Traditional and Simplified Chinese) + - EUC-JP, SHIFT_JIS, CP932, ISO-2022-JP (Japanese) + - EUC-KR, ISO-2022-KR (Korean) + - KOI8-R, MacCyrillic, IBM855, IBM866, ISO-8859-5, windows-1251 (Cyrillic) + - ISO-8859-5, windows-1251 (Bulgarian) + - ISO-8859-1, windows-1252 (Western European languages) + - ISO-8859-7, windows-1253 (Greek) + - ISO-8859-8, windows-1255 (Visual and Logical Hebrew) + - TIS-620 (Thai) + +.. note:: + Our ISO-8859-2 and windows-1250 (Hungarian) probers have been temporarily + disabled until we can retrain the models. + +Requires Python 2.6, 2.7, or 3.3+. + +Installation +------------ + +Install from `PyPI `_:: + + pip install chardet + +Documentation +------------- + +For users, docs are now available at https://chardet.readthedocs.io/. + +Command-line Tool +----------------- + +chardet comes with a command-line script which reports on the encodings of one +or more files:: + + % chardetect somefile someotherfile + somefile: windows-1252 with confidence 0.5 + someotherfile: ascii with confidence 1.0 + +About +----- + +This is a continuation of Mark Pilgrim's excellent chardet. Previously, two +versions needed to be maintained: one that supported python 2.x and one that +supported python 3.x. We've recently merged with `Ian Cordasco `_'s +`charade `_ fork, so now we have one +coherent version that works for Python 2.6+. + +:maintainer: Dan Blanchard + + diff --git a/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/INSTALLER b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/METADATA b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/METADATA new file mode 100644 index 0000000..1427867 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/METADATA @@ -0,0 +1,96 @@ +Metadata-Version: 2.0 +Name: chardet +Version: 3.0.4 +Summary: Universal encoding detector for Python 2 and 3 +Home-page: https://github.com/chardet/chardet +Author: Daniel Blanchard +Author-email: dan.blanchard@gmail.com +License: LGPL +Keywords: encoding,i18n,xml +Platform: UNKNOWN +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Linguistic + +Chardet: The Universal Character Encoding Detector +-------------------------------------------------- + +.. image:: https://img.shields.io/travis/chardet/chardet/stable.svg + :alt: Build status + :target: https://travis-ci.org/chardet/chardet + +.. image:: https://img.shields.io/coveralls/chardet/chardet/stable.svg + :target: https://coveralls.io/r/chardet/chardet + +.. image:: https://img.shields.io/pypi/v/chardet.svg + :target: https://warehouse.python.org/project/chardet/ + :alt: Latest version on PyPI + +.. image:: https://img.shields.io/pypi/l/chardet.svg + :alt: License + + +Detects + - ASCII, UTF-8, UTF-16 (2 variants), UTF-32 (4 variants) + - Big5, GB2312, EUC-TW, HZ-GB-2312, ISO-2022-CN (Traditional and Simplified Chinese) + - EUC-JP, SHIFT_JIS, CP932, ISO-2022-JP (Japanese) + - EUC-KR, ISO-2022-KR (Korean) + - KOI8-R, MacCyrillic, IBM855, IBM866, ISO-8859-5, windows-1251 (Cyrillic) + - ISO-8859-5, windows-1251 (Bulgarian) + - ISO-8859-1, windows-1252 (Western European languages) + - ISO-8859-7, windows-1253 (Greek) + - ISO-8859-8, windows-1255 (Visual and Logical Hebrew) + - TIS-620 (Thai) + +.. note:: + Our ISO-8859-2 and windows-1250 (Hungarian) probers have been temporarily + disabled until we can retrain the models. + +Requires Python 2.6, 2.7, or 3.3+. + +Installation +------------ + +Install from `PyPI `_:: + + pip install chardet + +Documentation +------------- + +For users, docs are now available at https://chardet.readthedocs.io/. + +Command-line Tool +----------------- + +chardet comes with a command-line script which reports on the encodings of one +or more files:: + + % chardetect somefile someotherfile + somefile: windows-1252 with confidence 0.5 + someotherfile: ascii with confidence 1.0 + +About +----- + +This is a continuation of Mark Pilgrim's excellent chardet. Previously, two +versions needed to be maintained: one that supported python 2.x and one that +supported python 3.x. We've recently merged with `Ian Cordasco `_'s +`charade `_ fork, so now we have one +coherent version that works for Python 2.6+. + +:maintainer: Dan Blanchard + + diff --git a/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/RECORD b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/RECORD new file mode 100644 index 0000000..92a894f --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/RECORD @@ -0,0 +1,91 @@ +chardet/__init__.py,sha256=YsP5wQlsHJ2auF1RZJfypiSrCA7_bQiRm3ES_NI76-Y,1559 +chardet/big5freq.py,sha256=D_zK5GyzoVsRes0HkLJziltFQX0bKCLOrFe9_xDvO_8,31254 +chardet/big5prober.py,sha256=kBxHbdetBpPe7xrlb-e990iot64g_eGSLd32lB7_h3M,1757 +chardet/chardistribution.py,sha256=3woWS62KrGooKyqz4zQSnjFbJpa6V7g02daAibTwcl8,9411 +chardet/charsetgroupprober.py,sha256=6bDu8YIiRuScX4ca9Igb0U69TA2PGXXDej6Cc4_9kO4,3787 +chardet/charsetprober.py,sha256=KSmwJErjypyj0bRZmC5F5eM7c8YQgLYIjZXintZNstg,5110 +chardet/codingstatemachine.py,sha256=VYp_6cyyki5sHgXDSZnXW4q1oelHc3cu9AyQTX7uug8,3590 +chardet/compat.py,sha256=PKTzHkSbtbHDqS9PyujMbX74q1a8mMpeQTDVsQhZMRw,1134 +chardet/cp949prober.py,sha256=TZ434QX8zzBsnUvL_8wm4AQVTZ2ZkqEEQL_lNw9f9ow,1855 +chardet/enums.py,sha256=Aimwdb9as1dJKZaFNUH2OhWIVBVd6ZkJJ_WK5sNY8cU,1661 +chardet/escprober.py,sha256=kkyqVg1Yw3DIOAMJ2bdlyQgUFQhuHAW8dUGskToNWSc,3950 +chardet/escsm.py,sha256=RuXlgNvTIDarndvllNCk5WZBIpdCxQ0kcd9EAuxUh84,10510 +chardet/eucjpprober.py,sha256=iD8Jdp0ISRjgjiVN7f0e8xGeQJ5GM2oeZ1dA8nbSeUw,3749 +chardet/euckrfreq.py,sha256=-7GdmvgWez4-eO4SuXpa7tBiDi5vRXQ8WvdFAzVaSfo,13546 +chardet/euckrprober.py,sha256=MqFMTQXxW4HbzIpZ9lKDHB3GN8SP4yiHenTmf8g_PxY,1748 +chardet/euctwfreq.py,sha256=No1WyduFOgB5VITUA7PLyC5oJRNzRyMbBxaKI1l16MA,31621 +chardet/euctwprober.py,sha256=13p6EP4yRaxqnP4iHtxHOJ6R2zxHq1_m8hTRjzVZ95c,1747 +chardet/gb2312freq.py,sha256=JX8lsweKLmnCwmk8UHEQsLgkr_rP_kEbvivC4qPOrlc,20715 +chardet/gb2312prober.py,sha256=gGvIWi9WhDjE-xQXHvNIyrnLvEbMAYgyUSZ65HUfylw,1754 +chardet/hebrewprober.py,sha256=c3SZ-K7hvyzGY6JRAZxJgwJ_sUS9k0WYkvMY00YBYFo,13838 +chardet/jisfreq.py,sha256=vpmJv2Bu0J8gnMVRPHMFefTRvo_ha1mryLig8CBwgOg,25777 +chardet/jpcntx.py,sha256=PYlNqRUQT8LM3cT5FmHGP0iiscFlTWED92MALvBungo,19643 +chardet/langbulgarianmodel.py,sha256=1HqQS9Pbtnj1xQgxitJMvw8X6kKr5OockNCZWfEQrPE,12839 +chardet/langcyrillicmodel.py,sha256=LODajvsetH87yYDDQKA2CULXUH87tI223dhfjh9Zx9c,17948 +chardet/langgreekmodel.py,sha256=8YAW7bU8YwSJap0kIJSbPMw1BEqzGjWzqcqf0WgUKAA,12688 +chardet/langhebrewmodel.py,sha256=JSnqmE5E62tDLTPTvLpQsg5gOMO4PbdWRvV7Avkc0HA,11345 +chardet/langhungarianmodel.py,sha256=RhapYSG5l0ZaO-VV4Fan5sW0WRGQqhwBM61yx3yxyOA,12592 +chardet/langthaimodel.py,sha256=8l0173Gu_W6G8mxmQOTEF4ls2YdE7FxWf3QkSxEGXJQ,11290 +chardet/langturkishmodel.py,sha256=W22eRNJsqI6uWAfwXSKVWWnCerYqrI8dZQTm_M0lRFk,11102 +chardet/latin1prober.py,sha256=S2IoORhFk39FEFOlSFWtgVybRiP6h7BlLldHVclNkU8,5370 +chardet/mbcharsetprober.py,sha256=AR95eFH9vuqSfvLQZN-L5ijea25NOBCoXqw8s5O9xLQ,3413 +chardet/mbcsgroupprober.py,sha256=h6TRnnYq2OxG1WdD5JOyxcdVpn7dG0q-vB8nWr5mbh4,2012 +chardet/mbcssm.py,sha256=SY32wVIF3HzcjY3BaEspy9metbNSKxIIB0RKPn7tjpI,25481 +chardet/sbcharsetprober.py,sha256=LDSpCldDCFlYwUkGkwD2oFxLlPWIWXT09akH_2PiY74,5657 +chardet/sbcsgroupprober.py,sha256=1IprcCB_k1qfmnxGC6MBbxELlKqD3scW6S8YIwdeyXA,3546 +chardet/sjisprober.py,sha256=IIt-lZj0WJqK4rmUZzKZP4GJlE8KUEtFYVuY96ek5MQ,3774 +chardet/universaldetector.py,sha256=qL0174lSZE442eB21nnktT9_VcAye07laFWUeUrjttY,12485 +chardet/utf8prober.py,sha256=IdD8v3zWOsB8OLiyPi-y_fqwipRFxV9Nc1eKBLSuIEw,2766 +chardet/version.py,sha256=sp3B08mrDXB-pf3K9fqJ_zeDHOCLC8RrngQyDFap_7g,242 +chardet/cli/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 +chardet/cli/chardetect.py,sha256=YBO8L4mXo0WR6_-Fjh_8QxPBoEBNqB9oNxNrdc54AQs,2738 +chardet-3.0.4.dist-info/DESCRIPTION.rst,sha256=PQ4sBsMyKFZkjC6QpmbpLn0UtCNyeb-ZqvCGEgyZMGk,2174 +chardet-3.0.4.dist-info/METADATA,sha256=RV_2I4B1Z586DL8oVO5Kp7X5bUdQ5EuKAvNoAEF8wSw,3239 +chardet-3.0.4.dist-info/RECORD,, +chardet-3.0.4.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 +chardet-3.0.4.dist-info/entry_points.txt,sha256=fAMmhu5eJ-zAJ-smfqQwRClQ3-nozOCmvJ6-E8lgGJo,60 +chardet-3.0.4.dist-info/metadata.json,sha256=0htbRM18ujyGZDdfowgAqj6Hq2eQtwzwyhaEveKntgo,1375 +chardet-3.0.4.dist-info/top_level.txt,sha256=AowzBbZy4x8EirABDdJSLJZMkJ_53iIag8xfKR6D7kI,8 +../../../bin/chardetect,sha256=Tcc31EYTYwZWMWDIKmXEVfSv60Z9WUUKHkRyHUXRDEM,270 +chardet-3.0.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +chardet/__pycache__/langgreekmodel.cpython-36.pyc,, +chardet/__pycache__/sjisprober.cpython-36.pyc,, +chardet/__pycache__/mbcharsetprober.cpython-36.pyc,, +chardet/__pycache__/eucjpprober.cpython-36.pyc,, +chardet/__pycache__/cp949prober.cpython-36.pyc,, +chardet/__pycache__/euctwfreq.cpython-36.pyc,, +chardet/__pycache__/gb2312prober.cpython-36.pyc,, +chardet/__pycache__/sbcsgroupprober.cpython-36.pyc,, +chardet/__pycache__/langturkishmodel.cpython-36.pyc,, +chardet/__pycache__/langhebrewmodel.cpython-36.pyc,, +chardet/__pycache__/version.cpython-36.pyc,, +chardet/__pycache__/euckrprober.cpython-36.pyc,, +chardet/__pycache__/euckrfreq.cpython-36.pyc,, +chardet/__pycache__/chardistribution.cpython-36.pyc,, +chardet/__pycache__/escsm.cpython-36.pyc,, +chardet/__pycache__/euctwprober.cpython-36.pyc,, +chardet/__pycache__/big5freq.cpython-36.pyc,, +chardet/__pycache__/compat.cpython-36.pyc,, +chardet/__pycache__/hebrewprober.cpython-36.pyc,, +chardet/__pycache__/latin1prober.cpython-36.pyc,, +chardet/__pycache__/universaldetector.cpython-36.pyc,, +chardet/__pycache__/escprober.cpython-36.pyc,, +chardet/__pycache__/codingstatemachine.cpython-36.pyc,, +chardet/__pycache__/utf8prober.cpython-36.pyc,, +chardet/__pycache__/langhungarianmodel.cpython-36.pyc,, +chardet/__pycache__/gb2312freq.cpython-36.pyc,, +chardet/__pycache__/enums.cpython-36.pyc,, +chardet/__pycache__/langthaimodel.cpython-36.pyc,, +chardet/__pycache__/jpcntx.cpython-36.pyc,, +chardet/__pycache__/mbcssm.cpython-36.pyc,, +chardet/__pycache__/big5prober.cpython-36.pyc,, +chardet/__pycache__/sbcharsetprober.cpython-36.pyc,, +chardet/__pycache__/langcyrillicmodel.cpython-36.pyc,, +chardet/__pycache__/__init__.cpython-36.pyc,, +chardet/__pycache__/jisfreq.cpython-36.pyc,, +chardet/__pycache__/charsetgroupprober.cpython-36.pyc,, +chardet/__pycache__/langbulgarianmodel.cpython-36.pyc,, +chardet/__pycache__/mbcsgroupprober.cpython-36.pyc,, +chardet/__pycache__/charsetprober.cpython-36.pyc,, +chardet/cli/__pycache__/chardetect.cpython-36.pyc,, +chardet/cli/__pycache__/__init__.cpython-36.pyc,, diff --git a/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/WHEEL b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/WHEEL new file mode 100644 index 0000000..8b6dd1b --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.29.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/entry_points.txt b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/entry_points.txt new file mode 100644 index 0000000..a884269 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +chardetect = chardet.cli.chardetect:main + diff --git a/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/metadata.json b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/metadata.json new file mode 100644 index 0000000..8cdf025 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/metadata.json @@ -0,0 +1 @@ +{"classifiers": ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Text Processing :: Linguistic"], "extensions": {"python.commands": {"wrap_console": {"chardetect": "chardet.cli.chardetect:main"}}, "python.details": {"contacts": [{"email": "dan.blanchard@gmail.com", "name": "Daniel Blanchard", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/chardet/chardet"}}, "python.exports": {"console_scripts": {"chardetect": "chardet.cli.chardetect:main"}}}, "generator": "bdist_wheel (0.29.0)", "keywords": ["encoding", "i18n", "xml"], "license": "LGPL", "metadata_version": "2.0", "name": "chardet", "summary": "Universal encoding detector for Python 2 and 3", "test_requires": [{"requires": ["hypothesis", "pytest"]}], "version": "3.0.4"} \ No newline at end of file diff --git a/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/top_level.txt b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/top_level.txt new file mode 100644 index 0000000..79236f2 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet-3.0.4.dist-info/top_level.txt @@ -0,0 +1 @@ +chardet diff --git a/flex/lib/python3.6/site-packages/chardet/__init__.py b/flex/lib/python3.6/site-packages/chardet/__init__.py new file mode 100644 index 0000000..0f9f820 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/__init__.py @@ -0,0 +1,39 @@ +######################## BEGIN LICENSE BLOCK ######################## +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + + +from .compat import PY2, PY3 +from .universaldetector import UniversalDetector +from .version import __version__, VERSION + + +def detect(byte_str): + """ + Detect the encoding of the given byte string. + + :param byte_str: The byte sequence to examine. + :type byte_str: ``bytes`` or ``bytearray`` + """ + if not isinstance(byte_str, bytearray): + if not isinstance(byte_str, bytes): + raise TypeError('Expected object of type bytes or bytearray, got: ' + '{0}'.format(type(byte_str))) + else: + byte_str = bytearray(byte_str) + detector = UniversalDetector() + detector.feed(byte_str) + return detector.close() diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/__init__.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..10f1259ccdcb1a8244a2683dcfe3f9e34195b013 GIT binary patch literal 838 zcmYjQL2uJA6tN!q!2oYr+Wzq6g;AXr);pgHK4-E@ zvNuezR0#3OM96C=kuq5f1~q2c?O&E~RE!caoPbetyU9}-kiplGXJjnY5&7C)wYGG?D_&G8 z0U~PDK0inXlBHyA@%`}F$Wej?d~ z$iL&Tlzg5j7S0nHjzmV`D#MWsI~UIjIqmk^bV--Js(X0R?d83LZX0A=glA#N%iZCO zXLOfO%gF(s?uY4lBB8+TKaP39RUGe?3+-+yKQV1!DkCqz0e0~N%Lg4``4Hw#VBc;k z@-k7)`E>7Ch4*WIw+?9#h#JJ~Ry@C;C$q~6#awPSMlFLOa>89ROiUS(pN_&#ph F{{R30>7xJu literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/big5freq.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/big5freq.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..97821e645ac8bf61ca00815260e1f32343052789 GIT binary patch literal 54725 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 z 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 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/big5prober.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/big5prober.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60819ca1958499220a75fdbb94be997cabf12239 GIT binary patch literal 1114 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 HUKjrWiVWfm literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/charsetprober.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/charsetprober.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b496877ab4d17133c77bd2a68d187ad93c49985b GIT binary patch literal 3447 zcmai1TW=f36`sA2qG(EXt4vK>t9W3bZf%4g1)whMW#Dx3e?nHs?Dtys@@c z-Th0@`p;#?{>jc17vs-R)9Yvi6IR4pd2h8WVGAd+2Tsee*cVK=qV$r9l5|gGwXapu4&&~D_O%S?)4Vtse1@9FXe0w`*0P1wa>Nzk2=}Gc0&`J* z$yy~@7AvCilAT(u6|pL+pjAM-AZmuTD%Qk0XjOSZTojiKt%mViV#AErFup9_Hsf_+ zL&>Yz+Fs9B2U3%IQgu6~{Oi;Gz=k$dsHeJznr@;IY|1<~wa{AH?mOB&rEy6xFtqmT z<*e+bWMy_C^5d@82_r34wh|@XE*y}pcBOuZF=!Rfi~WK0ysS)LrK;PRo64x8$`JG? zrfTT^8#RV1dPD0JuZD2rwBamUH?9@4d$KH;bXS- zyC?OJ{!OmuK#Q$p=A@%Gj`%H*UU&AD9DH6c?Do9&SW7R7qwz1XG9`)3UbiOiFDrTO zjzU+8SgJNeWWbtYoFN9zna?j*ptssoT=4!rVcV?`49HHNLm)dY(>~K zJ8`FO-#ukDroNuK!aYJSN}$pnWE6`Xzw-^U3~aBAb^w7YpOtSU7qSz^lIxz5XvagD z@}$GbzVvpn&X0yYzb*A`F5_+#raeBVr2MhJHMzUhdQvP7W8|pV*I^R-(QUpo_aNVj>j7pA;3iUTr&W5-cS z?DF%3?Ge$yMfZHY5TXlSk@Qo|6ZrKF)^GE>U_$DJ-BB`1q2KX{Lf&|PrboffSCT6^ zjQl_f91WQR??jTPLy)+i24T4H>~^)-nA>444ek$z5xD?%kO66+!l6$2vtAhVxJY=M zXg-3w@6S$naZ=j_zw`ry>HNTd_V~rtcTYZAOlRjr)KB*nrCNin7wQUzuf9W3*D$J= zvQ>&NUnzgAu7Z-SAO;1r%F6P&ma)iI!qh}qy=1VMRdUx$k(G?+Gncy7Y6L%fr0MHu zy*9(%lK(xk_j5>0-$uhOmP@#f?5edIPfZgsJ zkTc6GIe^6Z0Gel-cA|T82o>TMP%@s#V;oSvd$9N5!5LdWMkdo7sV7%U!^g(afF_W`N*(BoBv7bR}INXF_%^!0~m z>gD|I`!U9?au|Es?`G~$$)}l1O0_BohI0Y;-VAWhLf!Lbw}cl-O{t#l{`4nkSgj0{ zx%P&A$*$lbSg~AZ!(K0q7z`wC z6rtWBIvJtr)X=N+OhXS%Mel(3QB8KK*sfhIRh*hTtEJipW(9n_LaQnB;eSXx8l>hm io0XGxUk2JNI>XvXG7s6xo!rV@Ix6#?u2>bj=KK$xa(V&) literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/codingstatemachine.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/codingstatemachine.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c06a97a5c96feede9ee824a50fd2575cfc25d029 GIT binary patch literal 2878 zcma)8-E!MR6kbWT<2a5fErn))ndOG5hc*t=(2@>QTH3-5O_?Oag>E#8c5SaKOU~}v zZ8GUq`V71SkHD+wmaD!3SA1t>$8lmh$g?YHf4+0h_nouyz4i6RqrZ}{)?(~$cHyev z`7xTgjZQG(r7UE^7eVR`{m}Q=FHBTK^&Jyc8Jq=SMR@zHU3-t!Z1=r~zU>vw7je>8 zncTOrl?hGFt^f~@(abY+l7*gNp)b5JAQSHx;2d~Z6*aMf_nN4SRoquZL#*Lmm#d;F z*59!+FKmbwOn+2df0_%G^_;P(;rI{4(crkAa6?Y;Vd)XKIiE3%#V#!qsV36g;mY#YDouG;O2KVE zw$s%)m#_+(iN!*PwdhtniB%dOrt%KYGgPY++l2B zIL~O9kF=bqd~BvWR%m#uBA5mX2+H zcSgy>h6CC^c(Qj;LOeta3YfY#>fmOq8bjRP*g84q$pP*t$7W@ zaPu-81vL|VO6&8zy_b74W=p{@5c?rcp;0>5{<0~)Sf-BRd3nyGSr*DwtPDAJDYlZd zIpnihZ99_Wn!zpLGWyIRzuA&MX^T2V6AIwJ8S zC^&nk)QeJ?6>H_ZOYLGM&3io@oW*KS+F$W3by1I^EFQ`zDrz)~kt%9j+O}U*j7+SdjS&Pa{!9*$Ki?y95F;J!Ngu0t*&ndWzQ^g2hUNB8FFnA}sDvQhMaNNb{FUTyko zdMBS>{Ss`>b|gdGn-4JWqp_$; zE8JLRgMEV0&)D0*y;m_$>ySIAtilErQG0+e9Rhu!S9Zg-B#n)UEPZBN;)JbPVw8hn zvs}@|>6zA*_zD0>`( zMI)1MY~-eX!l1d1js-2R2~Ds0E$Y3Nck<;DV&^*-lqGc?yW|xyQ)=p!4ldQPxPkn4 zg@KPmM3kUZe#7>eu3s-PzhujTALkj?nEF8~yP7R3RAERd;&ORr6}KF`D}j=oXj%mO z7u@>hzua1~@BjK%Pw}^69QQu#pWc8Qzn{C}FD<+o(r$ZAuVHP`i0G6Wr*yhBqv&WH zr_-}$C5l9zM3E-_U0Lay^zJ$|p9SRWyKWf0c!h0ga&H+=%!=X)`-w%D`<6%6+u-8yq+va!&#>z^iQWaH0 zAD^#UOwe?u>28%=R04REXBN^{>N$9GsjD?KVO~41@5CInp)J0EX(M-;1GdWyE2>gp zIx7sDtS*(=#K~Cf#Xhm|%_>gT$uu5gy(l(kTIx~0m8BTTjb2XW=9(>DGb6zL?P{$v eccJShx?NXdTf*!NpV|{dMEhQV9eEx9cYg!ba$S`G literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/cp949prober.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/cp949prober.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..104bf57854a9ee165414fcf5f646f4a9aaf59a1a GIT binary patch literal 1121 zcmah|&2AGh5VrR(+ca%a1qdWgaEhSaqK1k{sQjcAhmukexcFji)=s*qceAmbN{M<) zr9KOfz^m+)6R*IDvA3n^1-!ETdAyz(fAe{FZLPllBOz~V2>nD$%>(=nx;lV?A%+FY zFu~YhM>v^FT#H@dWj^sO_C%1?NDZTpi1{qIL@eO`!X+WA^-weXg~3%5myZv>b&kFq zq)N-QKh^0tf1k%g!;EV6I)DQD}A;0;l-6 zxl;OST5u@?I9!I5rg^F?ivi3l zlqMopiqh}s_b4i4dJarR=dp|iW5Kvo(LhGKXD@R(X|;FQoXy*+_4=&U&f0se9caTm z`Wh8!vDKfZf^DUfVzie|UPTEo&$zyw3n0F*b=WRuGK4IjL01MKypHQ`i0Aj0=-a-z z<{cglmmPD?D2`#^$2lgxJtiAqYGPT3$>M5QgJsz;>A=-#9%uYHSd^g&IrB%$5to1Z zf7IY;EP0&&D{Ls@d^nAVJX#8Q=aM%+G(%HYlO3gHoziT~ro!L`rITqasvS#P83K)< z20fGO;8t$HP_A7UGT}miG7J?riLDxJSg`VW3P2ehg}4zmJZl4mk$bjaORA}av{?yD znFp3t56sGrY-Igwx~if|QxFn>Re=bND6Q+;Oe$on5x%LexBtW>V-(Q9_H+LL;&uuq literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/enums.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/enums.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..070ffcf3aeb8d55c40ccb8693a519eee623ee67e GIT binary patch literal 2612 zcmbVOOK;mo5T;%fMLTKY07VZ4x`!61fJRCiH>lkpupYF{Sf&h#4w}7CGm9p&UeWb+H%$hSSSL+4B=x`zr3(3)xnbpCA#U`Ct{+sqXjs-gIN|xoz-$93{u~%r zXa>%nWf_`dS(;}#T3~sqvI5wuPINOIrAaq&6F%14&k6Gn z54ix5#Hbz4Z z9cLJ^G{E_?r~cYDeo;gT7MAP} zRviid6pX8$x}tg*1q`gK9*XMI<8MQ8vby$!joElDUj5;Cb#1uzZ1o9@ept1uBY*Vx zAoT2N(`Z03GA)yG3NONZiD?j~(&T>24f`o1$EF`7T#S$I8Y)N@`5ifwAI9VjmmzXT zqu`7r5pm^8z25#Jl+Af0d%al%MGnjtSW8pM@X*r-$i4t(m6t^U?gENW5k+LEKvx>u zre$;ur)%!+waiV^XwpZEXLhI7G;OnO)ml`0S=+0jCRKOZ9iwK^qSdyX#>*X=tF>CR zIRA*|;L$~>XEPo5TLShFC|&`kUkS{|)W`Ckhz|U)KdX?fySn|nLPqd8 zzg86jbK}CXP!%^ivD7qdqhXuY7S%S}`&QF2ZK_&r+u1d4bOnZm0A0;YeER<#usdT zu-i(LYfNRucgougEzL`DrOQuJ9(ugxAM?N;L=hYRbh}%Eb4~0DE5EVpk zAipHS0^FYZQ5usdgf4(!{GNlRXt;;@iv#aS4WJlnlVt!bvg7r2!IM;k@j8GxCjeWR zg0S-?J3Ii%ek6Q=aX*xsBfM3_GAtugtDKqSydb`mW>{>Kl|D}#&~z>q_z}0qgjRCn zudX|%a{UXdtlyaLnq_R&Z1a^twSB8)?ij7tRGr_oy>=Hcz~~o{fLK zJqa$_=Y{LYIXpujB@z5GV7Ao4 zvjl3jPXZpxe~yqe+LqmEw+QrfFA8HH8Y29FxS)|h{>^*zzi{s9Kgj+@_7}20fm!9! zjd3ag6d9X86p3h+U8qh2}>H@BzkK!Av ytjRVqQKN$+_^*)7RRXy{FcVnNGLBOFrVS?A^VzS(3+zsEmwfI)>A@#J!2biO`Ebzy literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/escprober.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/escprober.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e89389f93dd61457dcd7c1253bc38ec15c925421 GIT binary patch literal 2603 zcma)7-ESL35Z}E!pU?K$N!>K0h{7pINJg|NZKxWAN~^?a(>6{N2Z~NYi*viS&pDs% zy>m${M?!L>N=QhECm#FCOW%?BOYRNv#1rp4F|+6qC$7e+tMj=Rq)xfcjnj;4C>{;A+>|hR znp>x2MBOy-8J<%`k3t|vA2X2{9=F5?H&LxB2vJSNUrXM-y1WrE^ zkyCS)y$%;nVxIOYNX9;++V zl@^jz)b9!@b8!E}V$2Wyn6V@?b}ozB(guk{sJO-TM_ZM0waltp+q+MV$?Cg~vRAd%@lDQg0@VS7!nb+xuadL@`!zwuQAa^1W zC&jZVye{TRVzLNRC`m~OOI*?tBN9Pf-4D#lFy;ldC}Qjv@^^EkEB)u7yz;yzSL&UB z3mL7{<;v~Dk3-p8UAxH#e6SX+-aTAhYp>l|y$P)muI#UL{qFUHz8~=Gey`iQqWsSU1OIPi7N z|97r3`_1QCQ#fwDcIL&|f1p4f&Z%83MAZ)k(}F8JcS{;ZUxU?FxDg_pn_{XC=qv>#8jqwn#iz<+n5 z4|N*?J=9y&Ch~(Ga@tTE(Gz26#Cpp()MOJNsWX6|L0T!U-33fDgk*~AhgAL)o2@iJ z(}I~ymB0?TE(`05Ajv6--m*tn%<`~%0miwh?laOepP}DiWyz>)O2o~d(BYL)=#*~* z?`A`B6pu@VL_j5}^4{Lg-Wb(rq-$1o_Stq>E-0xgDz3S;Uxhi>+T8h~vcb0Y-KDXw z@QoSo#@ge@dz>2AVDUIVQVO81b#NR*QHy0lJ#`(|o)%FoTjQKL1F%sSf>&XaXc-8h zS;(9MWKI@76Syq3;6sYNpbf5E2qx};iDF~n#yo(+on@@u;r#%4o3UQM7EB~*#(2kL zOqDE^w}}OH42pkzEU|h?WzxIIy$>YGPb#V>f&iAy5^!1sRQ}_;f!YxkLMvrxg?T$? z8@6GYs>W1G1vfv*z;V@-n5b@X@_M6drhe5?kP>0P9jOOLVzg8YVK(yMEt)+r>RD0G e$+(iuE_YU%66>?EC+?wf5k5;c_;`UX8UFx5*=WK5 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/escsm.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/escsm.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eeb6d609e35f72137b6766857a6a32e59dc69d1d GIT binary patch literal 7360 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 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/euckrfreq.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/euckrfreq.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d09c5c6c131e2034edf1a26b269efb7a6e7c4371 GIT binary patch literal 24111 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 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/euctwprober.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/euctwprober.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bf9d162d031e15cc9a0f8731b27094a515fa052d GIT binary patch literal 1122 zcmah|PjAyO6u0xQS=Vl80t6BlI8li$n^q<&p$X_FE_5KZXp%2h8oOP(ByDYHQ>)!N zX`h9Uz~|tWD<{4JC!U>kbQf^s=U@Di=l6c^=ly!UdiXseKRkqfqLtwQeg{(?fnkW@ z1f`f@tg)3?sZDHy?Zio4;u`EEURog)j6NdfGVdBOkK=_+d{*hAhW`sgs0J<`ck)EV zA7+ZT&qC4V>Wdinxd6{rd(7f&*j1t8oiI9!GY-2?kH5Bir$@0=BJSrZ9%t{fFqz3% zf^)+-X}3c=pO20|MR3I3uy2uU0^o>XhKO~82AE-HUHio54zrnajTV@=fKASTy&L2p zqI0ek>n47gVWbPtL$5lxp7IqKg%rL*3u|O8z^QEIEa08G%3B~ZhS5V9rJ13NE<<9vsP&0jz73 zMoB0orQgu+Q7{ql1&|qBgd!M>6UK!M1|rx$-^;|b+1h1uHgC!1oAYKXZ5=dsVGOgN z7fj;Gc0Z33wjEC=ql0+*I*6cIjH|nq=aIUcnAYt~X2ORoU%-?aAiROA*vIpSEA;Iw z%e=><=CZB-(`7OY{8%S*4}RP3or)UlHL$3{VsL5d@LJS#K2ST&!j!*+9ch6<*8Iup zk*gp5_gLcf!uT@G{&lRMgxN3;hg`RPdE~t+mmf5I-B_I+rA3v}bji46!VHo+A2+fGJ2NkAH!ie+N!8fzAeex3u6T1Y;wc{RuEfyBsW+P^Ko z?2^y~k*!i#Qs1$(ykkao literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/gb2312freq.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/gb2312freq.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bae11bdd32eb5e239535f3429af4b1367bb31c9f GIT binary patch literal 38376 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 G2L1=O1%>+n literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/gb2312prober.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/gb2312prober.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54fe54a9c9bc2a8e657156a7511302ce8144d803 GIT binary patch literal 1130 zcmah|%Wl&^6rJ%aZb&JrR3s1^SP_ZVeT0fgsDh@b8&Z(MYBnRsGfCZ!on&TGDN%Q+ z)NkPv_!Vzi@e8cD*KSI>fw6q&c&>dP=N=!duh)-$B&-Ms`AJrm2lxZr<^+r&f+~_x zMk!)PIho7c61&RFeCC(fQ$bc^HA+s2@I`P#L?G$HWud6`NHhFJAyktVPrFlP)8mbF}qvLJffU(5VYqD@IoCP?oYrO?LbKeFF0(OSWtbZ8*tX7x(-{3E3*!dMFT5>?s*<(@->_o2MlrM&mQDlee3^u zYaJAxk^f2@syH7`&Vr8_UWbAx0uf5xoRpP)#9i1P!k|1D&yrtba#9H7Si8vCT?d x2LH9J`qxVBu_xt}SEN>{FMucpq=?ciL;tO$Lghfh_f>mGFR&PtL4%f;^9Nx=3zz@^ literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/hebrewprober.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/hebrewprober.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..baed71e6337589312d806b0c9a48228806a56328 GIT binary patch literal 2964 zcmZuz%WoS+7@ygPv)-)TJewzJTAqd`?js3_K!uRFsYT;daZ06;(8}?w9Y10_vv%4T zS3*jpa^#FSaNxqF2ZWHg^H=N*aSDis#N*HleBbQaiQVpMfAh_AfAhU&Zbl;Jtsk;1 zxY%=)>>EZ)x|++tB4VHbFm4Ll(^$}jMN6N3%%K|XXs*bpD)BTx?WQGOB1 z5kAJpp&aECd=kow&KRHK(2kFND7l{z3Q`K?lfxGV*ler{>9fO*5I^np<98T$x*LS`P~q zUVZ4!UB9uom_<$EgC*(+Klc_uoz!WI94kfT7&; zL(j5zog9qxYZp4xYtjR}s2xlS>bh`Trw)#xxlTC;W!Sc}<&5jv_BZ5NDP9wWL-3UN zVMfGr)iQU48_$XO&C>OXI9OP@#+$sk;w~(g7FPCGmKLtTldr^g;7z8DJfyx~KAT&xt=icV%d2`RVRn=u31*Wax0@DB- zY-9UKxdO5x5iA6{S5v1jggm3OF-;7CB!&@25JmxFR7{{e)d5^mj01cPpKAaRWT%B_ zbEu1%)MvIGOjvek;l5guRtpJ1fcb8qh>Or8#sFff{4t9JR`#-n|$F*LU!5fk?20DD5$R zdrTK|3}?w4jr2V8yw+x|d1h*Bdo!TjmXUW`M&jXM%)LZFR=f)9_R_V0N~K!yDSzLg z+;7t6M3>gjkL%Dz=Rhk-+TVcy>V=$AR7#2%!ZM95YKtDz$Mn(XExJxV{_L^Rf~*W9 zYG@3QRPiN9I((sHDt211WU-GcZ-YJUz60#Tyn}rpLti-P3sU#@z7 zG_CUOidX}Vg|SidE)d#M#Gau;NHAYYHP>dOt8^hp$u*IULn6{?;h11 zyILt9$w(8g;anMbG7jIuDh8t$UQg^K)^?JqjdoBNa;jSwo|bh!4gD>peEOjDXBc} z1)o^>EKzx5o5_^z2h`e~)opt{nci7VttGtSyIUK{HSp~_i4V3D5A4+HX2Ki#D4D+B z-6k^*i{>G7WUG~2fjgC~BQuaUgllhZttakwmhBio9!qXxml-nOfYfUR3$r}tm`Y~f z`44!@WK1-Rnvjbu8d43wK-LV%pgoatetyRy=v(;7NWqZd6g*E!v5;>?$>POH+cV0U zO1_cFJCm@2E0dkllTg|ty8hSkfH&ZOU=>J%b)~36v|K?Ooz<{4O#t!c1*dw*Pv>}P zlVKp{P{Qmk<^f(zQ{eC!WGK%TH7d`)p0h=UR%{w?3aDPVDVR29{ze&P%eD{TI^g$+ zS^VGY2$vCX6XFU&4B=&jHxXU|U{;XrWOf$Uv3&vICc+H_Je=kECoZ8RqgKZ1HK=+9 z96WH3sUL|&>|H{@4SA8^Hj#D8W!pY;7Er<@4wAztjQC{qE_~Q D(VCx) literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/jisfreq.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/jisfreq.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6d556f57bfa9d66a1c239737005514c251f494e5 GIT binary patch literal 44520 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 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/jpcntx.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/jpcntx.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a8a360e69cac8cf829fd3bdcf5023b045ce3259c GIT binary patch literal 38659 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 S7SrqB`hSKCcO1FnzW)JO0l=mJ literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/langbulgarianmodel.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/langbulgarianmodel.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa4c954149db4c11d9e03b49c8ec7ac3c75500a5 GIT binary patch literal 24874 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 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/langgreekmodel.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/langgreekmodel.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..98c50e7d9a3e354cc8008eb3ce018e8e20dd80b9 GIT binary patch literal 24552 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 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/langhebrewmodel.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/langhebrewmodel.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e84844eb4e7b87c8b057f068f12d8dc5db4ec525 GIT binary patch literal 23406 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 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/langhungarianmodel.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/langhungarianmodel.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..31af4b0659034554d4e5efb554689ca1f1c3b91b GIT binary patch literal 24848 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 z zg=&jGic?S#h^5Xz-P|oN$XYxv7Ery1^Bi*?Dh9fR-MPblrb7H?trGLJZ84)GR~lu!%;ac6{8|_ zvB0@>K?qhz32tut)H4)ngUcRn>IUIToB~L3D+Ie?OH?eU;HC!3T`(jEHE{hxqS^Op@L;B&>q3DFg>TGgb>SZ5b|)t7zkJ%*RHS56`_n2 zb|cv_QfT0&K@I29k7Qe+3o#m`ESIGOV!1~;g*`$AZa9MqX0~Mk6_-4k1~nznDzvxj zirg+%$)kM`QYnrFA-JJSXkYBI7G3;su?#7;c=TLB9t}7W6^rQ|OC^(nmCB<57I|3i z!UPs@ZKYCZkZW;nxHSg1h0D3bNI_+)a5zVXJ;-yv(8_A+$WTUJIEcJli}p@of>cFH z<>5kQ3|rh)YD?5G0sVYN@jzh@Clg~Jx};*LSgha}Q{jeW+?2(+p08W?$KhCP$v~*K zNU_UQ+j4f8R zl{+bUsT5Q$g1pp~I2MkyOEM|B0x6XFTwJW;F67ywOR5Z&WMZxekDgV-D#@Wi5SS_m zc8TEz%MDl|WpM_hk%!7@;~1HjUbRr3VBX8_ybUZ$^^MFQbGd+*Wwmi9`K?jc3 zaRp^oNwGyrZk}6F8!Tp_A1SDGA?7^Xl$Dzj&IoQeEw>AKxechr@?C}6FntZzNds!b z7`Q2mF|cTb#VlB;xoeSPD>VVJkP-$8XM{2iLZBjaPNfh_B{K_69YbIOte{d$imi~B zicyOdy4VdWLt03IE-97KQmSK4K}{VQQc?>tMzGwOSgy+iAtlsyUk%gy|Bl_%t*mke zLh2yL0A<7|BSzC;aX4i(MGa-7U~yWiRmh_sWg(V2oMfy}hLEyI#v(5jv+7yMBj$=) z;j&tjotJwDxm`FT)Ta75Mny=m5Rf{T1|hjvNF{GhF;-;{Vpz;fjJrn-U1|{AkFrz+ z2XT0=6%UZ69kts3mz?%LcdUf5Xx{#u@%lp^>b|ya{Gn$xEw?bi!*A7ad@%i zR;185SfubUI2Ia&SW2Z;NDcySm?gM$;k01ox}lal4llMsg`{lR|^d(+ZP@+X$*x2q~$xYDh_y<;Ft4;D)JigN5q`c5`E>h1U3fjbr9ke^a_` za?_@tr=C;&9qC2w3-rU(^Qyl~J*N8m(faA=Jbm~kVQ%#&r{}eoE3J(qpX|9wc``cc z)X>S{b*1bs{b-=@#L9+_tYvj`SEXTfbJnn=y|p?-XTy@LVaoDJZQ07HGbfhUmeEgkh|tZHd3*SDArM81DAExK3JbCchab#A+itt{;p>(R z?ed6$fgcUr_RsbM14nlJsogqgT{kq)x_)R*d!Rk1b!F?S*1Fc!t!pmXVraA0wWkm4 zd&ByFb&A&iQ}~DQci{@*0%3*F60Q`k64nWA;auTr;TmB~SSgGP6T-E^b;9++S;DX| zDXbE15I!w@M)<67q;RZooKS@0g(+cLSSp+t2|pLs3%?M4Df~*fhp?M)lW>3G*TM


CgA0%1?#AmKt` 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 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/mbcharsetprober.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/mbcharsetprober.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..51f0e6fe67a0fe5748c8f681ebe3a8f07c96c0a3 GIT binary patch literal 2226 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 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/sbcsgroupprober.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/sbcsgroupprober.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6e503f579eaeebcc16b59fcaec8c77ba2be4fd39 GIT binary patch literal 1607 zcmaJ>&2HO95Z)#ALrJ7X$+F`FEzqmbCbDBowSgiiY@lw?CMX~Q1@=NvzbMXT%DRkiW=-s|5U8 zxU=5?ViHq9BxRH$w}d5aW@~PXk}R{btgwo#vZ{2LBWtWC>#VNhCDD*BbEU^TZI{KC zY_g{GnXm1NXvsEfYhD%Gvco!>J7P!fvR%z<;)&d2dz74$xE?p&leod@%4SbvcSyS4 z-xRjkrA7PfGE_sJpR3to{*#)GxdQK#VUkV+KfTTQI=&87iq6kTdhoJ;aCWN_A(H6L zEasx9|1e9AmEqezhIx|qA1C;4!sxN5@p>$e2LtnrHu`;SbgjbIulV|0aeieIT4ve9 zk1j~-n3YZ!ViKw(Oik*}dWVnQP*rpEdN_EwKe`MPvk;VTa{J%&vEskndtGC0+R--a zj27xD$u4zP1nt{g_L^m%0pWzvm@w-Dxu7wPt@jSIKadh(CFr|dG>4~W!w21ta1eN* zctB7DUzYt2kdvG)$;z5qD?&+b=cN?|ENiT2tZH;L)-={NHZ-~#J&ju$n=3kTmn87> z){4Btx3y!s1X;YZG`BRjmvp+lw3hbDqGU;?{W zjOT$w(FN;ZQQ^PlJdKO8;t=eXic-eK1@kWTP}gZ}N6aQk6pG-nyK|Fdi%-2EmRb-* zBFwTN_=EhD_U0m`m%_vF`Rhk=Kj+VRXwlm^73;2#R`uEnEoXZV+5U158A(TzKo+BQ6At z@hR*l%g*l}VPMWGbUK|m9wh#SN}5Hz)c_@mV%-L3U)27&b;`0*t5*AG0^^3z>4*!LCeEUXV?5cgWC zm-^dY=OBoESY2+t*=lVBNveYVQ5p>57qJ(fBtZgui@3Kwh*SSKomnp9vS@9K?VXLy zw{@1eDC6Sl%sszc3+jMYm!EM?CA&cQgi}d4`$)P}QprvoZfM$&CeWsDNlV(NWJk?WR4I)9Hc@hyja<|R_thiMG`4| z{A@|iz$!e%bqwb%+^cqSSTC0|OZkbP0_tYshg}$pLUckeNrd>F{2ergDtHes*Ld%# zMt2ZOUnPyMYCJytE>=gYYmekuj@Odar-!R+(b|*MNAUIHM!PW#h7a~fK`0*tN5lS; z;OP5C2RuXi>E)R8gJh`PKJF-jJjF@WT3=Vg3@%U56RK zG;+W%;4~FpufbIFNJ0Dn&Z?RZw{U3zyG87f<6CG60*gA0t55V&K|#6Fe)lhC~I=(jW_gS zcwQ~yW^tJldU0>$^?Y>F3z@T+U+j0ZKEQ;IgpQ{TeG4XkqQ^|*PN(qOAiwXdviCrmO}`8^bzoYDCD8uPA^SwtOD*H>6p+&NGKPA8<n>Ou+B>{0VyP(=ALhMeP61w z7Oz#|#f{DO=6ZXp`HIi?2C4Al!Kim2q?dYGMc+AyyMgrMj?WibuXpy^>+jm4{d#W` zCT}}0M9Zlu?nkD7q}fZo}URzwCyq+@h!0F@c0S{cv#2-;I8QMOj9h?p)qB7 zb}%(Y>T6)mAu=NGxNhVIf=#*-3K+ZGJx}g>_Fud3f}f!!7@kDiFkYF_^E#?fTA-X@ zCK4hm2@wtCC`8&7;%MZB`Hs%ZIuT|LcqCM!^kl|YY9L4}o|Vt*M#m3Bs85%WL*CI@ zRVP#|V&6bZ&@&zC7F-j5&OM!xoAnBxkM_^AT<-r09h@)Z534;V%KwSb6_8hvdA8u` z8p!SbuoI`py6ABmu1ughA}ZYS<584oAJ@^4mx4=ebG=d5%z2h0@*L}mR@jBd&wo|p EU(@P4ng9R* literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/universaldetector.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/universaldetector.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..06866d0575113cbcd7dea1d6d5a69ea5fb99f629 GIT binary patch literal 5828 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 Wk-6XHAwT^bok2$P=rW{&XZ-_9xwKpW literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/__pycache__/version.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/__pycache__/version.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..543a4b9fc79deb6abd326bf5d4dca8e2f7db6d5d GIT binary patch literal 433 zcmX|7u};G<5KY>YqM)wKH`1YTQA0&4R3QWdOOa^B&?RzXr*WIusqF;Xm9JrD;#acr z2aHUZ5_;0TyVE`C-n&7ko7$@eX}sF=CTUKs zuCsf0X9-h~2~wmK=nGR?f#B&Dv;f7jJZ13~B-N79lJO_mOL_V z*u!^>a>+`pDJrovJwQe$Xd7vI~@dx%PuB82Wt^OO9qJXL)Z?u$1)J fCSMKN<^t884z-qGd{@U;e{UWCo>q +# +# 128 --> 0.42261 +# 256 --> 0.57851 +# 512 --> 0.74851 +# 1024 --> 0.89384 +# 2048 --> 0.97583 +# +# Ideal Distribution Ratio = 0.74851/(1-0.74851) =2.98 +# Random Distribution Ration = 512/(5401-512)=0.105 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR + +BIG5_TYPICAL_DISTRIBUTION_RATIO = 0.75 + +#Char to FreqOrder table +BIG5_TABLE_SIZE = 5376 + +BIG5_CHAR_TO_FREQ_ORDER = ( + 1,1801,1506, 255,1431, 198, 9, 82, 6,5008, 177, 202,3681,1256,2821, 110, # 16 +3814, 33,3274, 261, 76, 44,2114, 16,2946,2187,1176, 659,3971, 26,3451,2653, # 32 +1198,3972,3350,4202, 410,2215, 302, 590, 361,1964, 8, 204, 58,4510,5009,1932, # 48 + 63,5010,5011, 317,1614, 75, 222, 159,4203,2417,1480,5012,3555,3091, 224,2822, # 64 +3682, 3, 10,3973,1471, 29,2787,1135,2866,1940, 873, 130,3275,1123, 312,5013, # 80 +4511,2052, 507, 252, 682,5014, 142,1915, 124, 206,2947, 34,3556,3204, 64, 604, # 96 +5015,2501,1977,1978, 155,1991, 645, 641,1606,5016,3452, 337, 72, 406,5017, 80, # 112 + 630, 238,3205,1509, 263, 939,1092,2654, 756,1440,1094,3453, 449, 69,2987, 591, # 128 + 179,2096, 471, 115,2035,1844, 60, 50,2988, 134, 806,1869, 734,2036,3454, 180, # 144 + 995,1607, 156, 537,2907, 688,5018, 319,1305, 779,2145, 514,2379, 298,4512, 359, # 160 +2502, 90,2716,1338, 663, 11, 906,1099,2553, 20,2441, 182, 532,1716,5019, 732, # 176 +1376,4204,1311,1420,3206, 25,2317,1056, 113, 399, 382,1950, 242,3455,2474, 529, # 192 +3276, 475,1447,3683,5020, 117, 21, 656, 810,1297,2300,2334,3557,5021, 126,4205, # 208 + 706, 456, 150, 613,4513, 71,1118,2037,4206, 145,3092, 85, 835, 486,2115,1246, # 224 +1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,5022,2128,2359, 347,3815, 221, # 240 +3558,3135,5023,1956,1153,4207, 83, 296,1199,3093, 192, 624, 93,5024, 822,1898, # 256 +2823,3136, 795,2065, 991,1554,1542,1592, 27, 43,2867, 859, 139,1456, 860,4514, # 272 + 437, 712,3974, 164,2397,3137, 695, 211,3037,2097, 195,3975,1608,3559,3560,3684, # 288 +3976, 234, 811,2989,2098,3977,2233,1441,3561,1615,2380, 668,2077,1638, 305, 228, # 304 +1664,4515, 467, 415,5025, 262,2099,1593, 239, 108, 300, 200,1033, 512,1247,2078, # 320 +5026,5027,2176,3207,3685,2682, 593, 845,1062,3277, 88,1723,2038,3978,1951, 212, # 336 + 266, 152, 149, 468,1899,4208,4516, 77, 187,5028,3038, 37, 5,2990,5029,3979, # 352 +5030,5031, 39,2524,4517,2908,3208,2079, 55, 148, 74,4518, 545, 483,1474,1029, # 368 +1665, 217,1870,1531,3138,1104,2655,4209, 24, 172,3562, 900,3980,3563,3564,4519, # 384 + 32,1408,2824,1312, 329, 487,2360,2251,2717, 784,2683, 4,3039,3351,1427,1789, # 400 + 188, 109, 499,5032,3686,1717,1790, 888,1217,3040,4520,5033,3565,5034,3352,1520, # 416 +3687,3981, 196,1034, 775,5035,5036, 929,1816, 249, 439, 38,5037,1063,5038, 794, # 432 +3982,1435,2301, 46, 178,3278,2066,5039,2381,5040, 214,1709,4521, 804, 35, 707, # 448 + 324,3688,1601,2554, 140, 459,4210,5041,5042,1365, 839, 272, 978,2262,2580,3456, # 464 +2129,1363,3689,1423, 697, 100,3094, 48, 70,1231, 495,3139,2196,5043,1294,5044, # 480 +2080, 462, 586,1042,3279, 853, 256, 988, 185,2382,3457,1698, 434,1084,5045,3458, # 496 + 314,2625,2788,4522,2335,2336, 569,2285, 637,1817,2525, 757,1162,1879,1616,3459, # 512 + 287,1577,2116, 768,4523,1671,2868,3566,2526,1321,3816, 909,2418,5046,4211, 933, # 528 +3817,4212,2053,2361,1222,4524, 765,2419,1322, 786,4525,5047,1920,1462,1677,2909, # 544 +1699,5048,4526,1424,2442,3140,3690,2600,3353,1775,1941,3460,3983,4213, 309,1369, # 560 +1130,2825, 364,2234,1653,1299,3984,3567,3985,3986,2656, 525,1085,3041, 902,2001, # 576 +1475, 964,4527, 421,1845,1415,1057,2286, 940,1364,3141, 376,4528,4529,1381, 7, # 592 +2527, 983,2383, 336,1710,2684,1846, 321,3461, 559,1131,3042,2752,1809,1132,1313, # 608 + 265,1481,1858,5049, 352,1203,2826,3280, 167,1089, 420,2827, 776, 792,1724,3568, # 624 +4214,2443,3281,5050,4215,5051, 446, 229, 333,2753, 901,3818,1200,1557,4530,2657, # 640 +1921, 395,2754,2685,3819,4216,1836, 125, 916,3209,2626,4531,5052,5053,3820,5054, # 656 +5055,5056,4532,3142,3691,1133,2555,1757,3462,1510,2318,1409,3569,5057,2146, 438, # 672 +2601,2910,2384,3354,1068, 958,3043, 461, 311,2869,2686,4217,1916,3210,4218,1979, # 688 + 383, 750,2755,2627,4219, 274, 539, 385,1278,1442,5058,1154,1965, 384, 561, 210, # 704 + 98,1295,2556,3570,5059,1711,2420,1482,3463,3987,2911,1257, 129,5060,3821, 642, # 720 + 523,2789,2790,2658,5061, 141,2235,1333, 68, 176, 441, 876, 907,4220, 603,2602, # 736 + 710, 171,3464, 404, 549, 18,3143,2398,1410,3692,1666,5062,3571,4533,2912,4534, # 752 +5063,2991, 368,5064, 146, 366, 99, 871,3693,1543, 748, 807,1586,1185, 22,2263, # 768 + 379,3822,3211,5065,3212, 505,1942,2628,1992,1382,2319,5066, 380,2362, 218, 702, # 784 +1818,1248,3465,3044,3572,3355,3282,5067,2992,3694, 930,3283,3823,5068, 59,5069, # 800 + 585, 601,4221, 497,3466,1112,1314,4535,1802,5070,1223,1472,2177,5071, 749,1837, # 816 + 690,1900,3824,1773,3988,1476, 429,1043,1791,2236,2117, 917,4222, 447,1086,1629, # 832 +5072, 556,5073,5074,2021,1654, 844,1090, 105, 550, 966,1758,2828,1008,1783, 686, # 848 +1095,5075,2287, 793,1602,5076,3573,2603,4536,4223,2948,2302,4537,3825, 980,2503, # 864 + 544, 353, 527,4538, 908,2687,2913,5077, 381,2629,1943,1348,5078,1341,1252, 560, # 880 +3095,5079,3467,2870,5080,2054, 973, 886,2081, 143,4539,5081,5082, 157,3989, 496, # 896 +4224, 57, 840, 540,2039,4540,4541,3468,2118,1445, 970,2264,1748,1966,2082,4225, # 912 +3144,1234,1776,3284,2829,3695, 773,1206,2130,1066,2040,1326,3990,1738,1725,4226, # 928 + 279,3145, 51,1544,2604, 423,1578,2131,2067, 173,4542,1880,5083,5084,1583, 264, # 944 + 610,3696,4543,2444, 280, 154,5085,5086,5087,1739, 338,1282,3096, 693,2871,1411, # 960 +1074,3826,2445,5088,4544,5089,5090,1240, 952,2399,5091,2914,1538,2688, 685,1483, # 976 +4227,2475,1436, 953,4228,2055,4545, 671,2400, 79,4229,2446,3285, 608, 567,2689, # 992 +3469,4230,4231,1691, 393,1261,1792,2401,5092,4546,5093,5094,5095,5096,1383,1672, # 1008 +3827,3213,1464, 522,1119, 661,1150, 216, 675,4547,3991,1432,3574, 609,4548,2690, # 1024 +2402,5097,5098,5099,4232,3045, 0,5100,2476, 315, 231,2447, 301,3356,4549,2385, # 1040 +5101, 233,4233,3697,1819,4550,4551,5102, 96,1777,1315,2083,5103, 257,5104,1810, # 1056 +3698,2718,1139,1820,4234,2022,1124,2164,2791,1778,2659,5105,3097, 363,1655,3214, # 1072 +5106,2993,5107,5108,5109,3992,1567,3993, 718, 103,3215, 849,1443, 341,3357,2949, # 1088 +1484,5110,1712, 127, 67, 339,4235,2403, 679,1412, 821,5111,5112, 834, 738, 351, # 1104 +2994,2147, 846, 235,1497,1881, 418,1993,3828,2719, 186,1100,2148,2756,3575,1545, # 1120 +1355,2950,2872,1377, 583,3994,4236,2581,2995,5113,1298,3699,1078,2557,3700,2363, # 1136 + 78,3829,3830, 267,1289,2100,2002,1594,4237, 348, 369,1274,2197,2178,1838,4552, # 1152 +1821,2830,3701,2757,2288,2003,4553,2951,2758, 144,3358, 882,4554,3995,2759,3470, # 1168 +4555,2915,5114,4238,1726, 320,5115,3996,3046, 788,2996,5116,2831,1774,1327,2873, # 1184 +3997,2832,5117,1306,4556,2004,1700,3831,3576,2364,2660, 787,2023, 506, 824,3702, # 1200 + 534, 323,4557,1044,3359,2024,1901, 946,3471,5118,1779,1500,1678,5119,1882,4558, # 1216 + 165, 243,4559,3703,2528, 123, 683,4239, 764,4560, 36,3998,1793, 589,2916, 816, # 1232 + 626,1667,3047,2237,1639,1555,1622,3832,3999,5120,4000,2874,1370,1228,1933, 891, # 1248 +2084,2917, 304,4240,5121, 292,2997,2720,3577, 691,2101,4241,1115,4561, 118, 662, # 1264 +5122, 611,1156, 854,2386,1316,2875, 2, 386, 515,2918,5123,5124,3286, 868,2238, # 1280 +1486, 855,2661, 785,2216,3048,5125,1040,3216,3578,5126,3146, 448,5127,1525,5128, # 1296 +2165,4562,5129,3833,5130,4242,2833,3579,3147, 503, 818,4001,3148,1568, 814, 676, # 1312 +1444, 306,1749,5131,3834,1416,1030, 197,1428, 805,2834,1501,4563,5132,5133,5134, # 1328 +1994,5135,4564,5136,5137,2198, 13,2792,3704,2998,3149,1229,1917,5138,3835,2132, # 1344 +5139,4243,4565,2404,3580,5140,2217,1511,1727,1120,5141,5142, 646,3836,2448, 307, # 1360 +5143,5144,1595,3217,5145,5146,5147,3705,1113,1356,4002,1465,2529,2530,5148, 519, # 1376 +5149, 128,2133, 92,2289,1980,5150,4003,1512, 342,3150,2199,5151,2793,2218,1981, # 1392 +3360,4244, 290,1656,1317, 789, 827,2365,5152,3837,4566, 562, 581,4004,5153, 401, # 1408 +4567,2252, 94,4568,5154,1399,2794,5155,1463,2025,4569,3218,1944,5156, 828,1105, # 1424 +4245,1262,1394,5157,4246, 605,4570,5158,1784,2876,5159,2835, 819,2102, 578,2200, # 1440 +2952,5160,1502, 436,3287,4247,3288,2836,4005,2919,3472,3473,5161,2721,2320,5162, # 1456 +5163,2337,2068, 23,4571, 193, 826,3838,2103, 699,1630,4248,3098, 390,1794,1064, # 1472 +3581,5164,1579,3099,3100,1400,5165,4249,1839,1640,2877,5166,4572,4573, 137,4250, # 1488 + 598,3101,1967, 780, 104, 974,2953,5167, 278, 899, 253, 402, 572, 504, 493,1339, # 1504 +5168,4006,1275,4574,2582,2558,5169,3706,3049,3102,2253, 565,1334,2722, 863, 41, # 1520 +5170,5171,4575,5172,1657,2338, 19, 463,2760,4251, 606,5173,2999,3289,1087,2085, # 1536 +1323,2662,3000,5174,1631,1623,1750,4252,2691,5175,2878, 791,2723,2663,2339, 232, # 1552 +2421,5176,3001,1498,5177,2664,2630, 755,1366,3707,3290,3151,2026,1609, 119,1918, # 1568 +3474, 862,1026,4253,5178,4007,3839,4576,4008,4577,2265,1952,2477,5179,1125, 817, # 1584 +4254,4255,4009,1513,1766,2041,1487,4256,3050,3291,2837,3840,3152,5180,5181,1507, # 1600 +5182,2692, 733, 40,1632,1106,2879, 345,4257, 841,2531, 230,4578,3002,1847,3292, # 1616 +3475,5183,1263, 986,3476,5184, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562, # 1632 +4010,4011,2954, 967,2761,2665,1349, 592,2134,1692,3361,3003,1995,4258,1679,4012, # 1648 +1902,2188,5185, 739,3708,2724,1296,1290,5186,4259,2201,2202,1922,1563,2605,2559, # 1664 +1871,2762,3004,5187, 435,5188, 343,1108, 596, 17,1751,4579,2239,3477,3709,5189, # 1680 +4580, 294,3582,2955,1693, 477, 979, 281,2042,3583, 643,2043,3710,2631,2795,2266, # 1696 +1031,2340,2135,2303,3584,4581, 367,1249,2560,5190,3585,5191,4582,1283,3362,2005, # 1712 + 240,1762,3363,4583,4584, 836,1069,3153, 474,5192,2149,2532, 268,3586,5193,3219, # 1728 +1521,1284,5194,1658,1546,4260,5195,3587,3588,5196,4261,3364,2693,1685,4262, 961, # 1744 +1673,2632, 190,2006,2203,3841,4585,4586,5197, 570,2504,3711,1490,5198,4587,2633, # 1760 +3293,1957,4588, 584,1514, 396,1045,1945,5199,4589,1968,2449,5200,5201,4590,4013, # 1776 + 619,5202,3154,3294, 215,2007,2796,2561,3220,4591,3221,4592, 763,4263,3842,4593, # 1792 +5203,5204,1958,1767,2956,3365,3712,1174, 452,1477,4594,3366,3155,5205,2838,1253, # 1808 +2387,2189,1091,2290,4264, 492,5206, 638,1169,1825,2136,1752,4014, 648, 926,1021, # 1824 +1324,4595, 520,4596, 997, 847,1007, 892,4597,3843,2267,1872,3713,2405,1785,4598, # 1840 +1953,2957,3103,3222,1728,4265,2044,3714,4599,2008,1701,3156,1551, 30,2268,4266, # 1856 +5207,2027,4600,3589,5208, 501,5209,4267, 594,3478,2166,1822,3590,3479,3591,3223, # 1872 + 829,2839,4268,5210,1680,3157,1225,4269,5211,3295,4601,4270,3158,2341,5212,4602, # 1888 +4271,5213,4015,4016,5214,1848,2388,2606,3367,5215,4603, 374,4017, 652,4272,4273, # 1904 + 375,1140, 798,5216,5217,5218,2366,4604,2269, 546,1659, 138,3051,2450,4605,5219, # 1920 +2254, 612,1849, 910, 796,3844,1740,1371, 825,3845,3846,5220,2920,2562,5221, 692, # 1936 + 444,3052,2634, 801,4606,4274,5222,1491, 244,1053,3053,4275,4276, 340,5223,4018, # 1952 +1041,3005, 293,1168, 87,1357,5224,1539, 959,5225,2240, 721, 694,4277,3847, 219, # 1968 +1478, 644,1417,3368,2666,1413,1401,1335,1389,4019,5226,5227,3006,2367,3159,1826, # 1984 + 730,1515, 184,2840, 66,4607,5228,1660,2958, 246,3369, 378,1457, 226,3480, 975, # 2000 +4020,2959,1264,3592, 674, 696,5229, 163,5230,1141,2422,2167, 713,3593,3370,4608, # 2016 +4021,5231,5232,1186, 15,5233,1079,1070,5234,1522,3224,3594, 276,1050,2725, 758, # 2032 +1126, 653,2960,3296,5235,2342, 889,3595,4022,3104,3007, 903,1250,4609,4023,3481, # 2048 +3596,1342,1681,1718, 766,3297, 286, 89,2961,3715,5236,1713,5237,2607,3371,3008, # 2064 +5238,2962,2219,3225,2880,5239,4610,2505,2533, 181, 387,1075,4024, 731,2190,3372, # 2080 +5240,3298, 310, 313,3482,2304, 770,4278, 54,3054, 189,4611,3105,3848,4025,5241, # 2096 +1230,1617,1850, 355,3597,4279,4612,3373, 111,4280,3716,1350,3160,3483,3055,4281, # 2112 +2150,3299,3598,5242,2797,4026,4027,3009, 722,2009,5243,1071, 247,1207,2343,2478, # 2128 +1378,4613,2010, 864,1437,1214,4614, 373,3849,1142,2220, 667,4615, 442,2763,2563, # 2144 +3850,4028,1969,4282,3300,1840, 837, 170,1107, 934,1336,1883,5244,5245,2119,4283, # 2160 +2841, 743,1569,5246,4616,4284, 582,2389,1418,3484,5247,1803,5248, 357,1395,1729, # 2176 +3717,3301,2423,1564,2241,5249,3106,3851,1633,4617,1114,2086,4285,1532,5250, 482, # 2192 +2451,4618,5251,5252,1492, 833,1466,5253,2726,3599,1641,2842,5254,1526,1272,3718, # 2208 +4286,1686,1795, 416,2564,1903,1954,1804,5255,3852,2798,3853,1159,2321,5256,2881, # 2224 +4619,1610,1584,3056,2424,2764, 443,3302,1163,3161,5257,5258,4029,5259,4287,2506, # 2240 +3057,4620,4030,3162,2104,1647,3600,2011,1873,4288,5260,4289, 431,3485,5261, 250, # 2256 + 97, 81,4290,5262,1648,1851,1558, 160, 848,5263, 866, 740,1694,5264,2204,2843, # 2272 +3226,4291,4621,3719,1687, 950,2479, 426, 469,3227,3720,3721,4031,5265,5266,1188, # 2288 + 424,1996, 861,3601,4292,3854,2205,2694, 168,1235,3602,4293,5267,2087,1674,4622, # 2304 +3374,3303, 220,2565,1009,5268,3855, 670,3010, 332,1208, 717,5269,5270,3603,2452, # 2320 +4032,3375,5271, 513,5272,1209,2882,3376,3163,4623,1080,5273,5274,5275,5276,2534, # 2336 +3722,3604, 815,1587,4033,4034,5277,3605,3486,3856,1254,4624,1328,3058,1390,4035, # 2352 +1741,4036,3857,4037,5278, 236,3858,2453,3304,5279,5280,3723,3859,1273,3860,4625, # 2368 +5281, 308,5282,4626, 245,4627,1852,2480,1307,2583, 430, 715,2137,2454,5283, 270, # 2384 + 199,2883,4038,5284,3606,2727,1753, 761,1754, 725,1661,1841,4628,3487,3724,5285, # 2400 +5286, 587, 14,3305, 227,2608, 326, 480,2270, 943,2765,3607, 291, 650,1884,5287, # 2416 +1702,1226, 102,1547, 62,3488, 904,4629,3489,1164,4294,5288,5289,1224,1548,2766, # 2432 + 391, 498,1493,5290,1386,1419,5291,2056,1177,4630, 813, 880,1081,2368, 566,1145, # 2448 +4631,2291,1001,1035,2566,2609,2242, 394,1286,5292,5293,2069,5294, 86,1494,1730, # 2464 +4039, 491,1588, 745, 897,2963, 843,3377,4040,2767,2884,3306,1768, 998,2221,2070, # 2480 + 397,1827,1195,1970,3725,3011,3378, 284,5295,3861,2507,2138,2120,1904,5296,4041, # 2496 +2151,4042,4295,1036,3490,1905, 114,2567,4296, 209,1527,5297,5298,2964,2844,2635, # 2512 +2390,2728,3164, 812,2568,5299,3307,5300,1559, 737,1885,3726,1210, 885, 28,2695, # 2528 +3608,3862,5301,4297,1004,1780,4632,5302, 346,1982,2222,2696,4633,3863,1742, 797, # 2544 +1642,4043,1934,1072,1384,2152, 896,4044,3308,3727,3228,2885,3609,5303,2569,1959, # 2560 +4634,2455,1786,5304,5305,5306,4045,4298,1005,1308,3728,4299,2729,4635,4636,1528, # 2576 +2610, 161,1178,4300,1983, 987,4637,1101,4301, 631,4046,1157,3229,2425,1343,1241, # 2592 +1016,2243,2570, 372, 877,2344,2508,1160, 555,1935, 911,4047,5307, 466,1170, 169, # 2608 +1051,2921,2697,3729,2481,3012,1182,2012,2571,1251,2636,5308, 992,2345,3491,1540, # 2624 +2730,1201,2071,2406,1997,2482,5309,4638, 528,1923,2191,1503,1874,1570,2369,3379, # 2640 +3309,5310, 557,1073,5311,1828,3492,2088,2271,3165,3059,3107, 767,3108,2799,4639, # 2656 +1006,4302,4640,2346,1267,2179,3730,3230, 778,4048,3231,2731,1597,2667,5312,4641, # 2672 +5313,3493,5314,5315,5316,3310,2698,1433,3311, 131, 95,1504,4049, 723,4303,3166, # 2688 +1842,3610,2768,2192,4050,2028,2105,3731,5317,3013,4051,1218,5318,3380,3232,4052, # 2704 +4304,2584, 248,1634,3864, 912,5319,2845,3732,3060,3865, 654, 53,5320,3014,5321, # 2720 +1688,4642, 777,3494,1032,4053,1425,5322, 191, 820,2121,2846, 971,4643, 931,3233, # 2736 + 135, 664, 783,3866,1998, 772,2922,1936,4054,3867,4644,2923,3234, 282,2732, 640, # 2752 +1372,3495,1127, 922, 325,3381,5323,5324, 711,2045,5325,5326,4055,2223,2800,1937, # 2768 +4056,3382,2224,2255,3868,2305,5327,4645,3869,1258,3312,4057,3235,2139,2965,4058, # 2784 +4059,5328,2225, 258,3236,4646, 101,1227,5329,3313,1755,5330,1391,3314,5331,2924, # 2800 +2057, 893,5332,5333,5334,1402,4305,2347,5335,5336,3237,3611,5337,5338, 878,1325, # 2816 +1781,2801,4647, 259,1385,2585, 744,1183,2272,4648,5339,4060,2509,5340, 684,1024, # 2832 +4306,5341, 472,3612,3496,1165,3315,4061,4062, 322,2153, 881, 455,1695,1152,1340, # 2848 + 660, 554,2154,4649,1058,4650,4307, 830,1065,3383,4063,4651,1924,5342,1703,1919, # 2864 +5343, 932,2273, 122,5344,4652, 947, 677,5345,3870,2637, 297,1906,1925,2274,4653, # 2880 +2322,3316,5346,5347,4308,5348,4309, 84,4310, 112, 989,5349, 547,1059,4064, 701, # 2896 +3613,1019,5350,4311,5351,3497, 942, 639, 457,2306,2456, 993,2966, 407, 851, 494, # 2912 +4654,3384, 927,5352,1237,5353,2426,3385, 573,4312, 680, 921,2925,1279,1875, 285, # 2928 + 790,1448,1984, 719,2168,5354,5355,4655,4065,4066,1649,5356,1541, 563,5357,1077, # 2944 +5358,3386,3061,3498, 511,3015,4067,4068,3733,4069,1268,2572,3387,3238,4656,4657, # 2960 +5359, 535,1048,1276,1189,2926,2029,3167,1438,1373,2847,2967,1134,2013,5360,4313, # 2976 +1238,2586,3109,1259,5361, 700,5362,2968,3168,3734,4314,5363,4315,1146,1876,1907, # 2992 +4658,2611,4070, 781,2427, 132,1589, 203, 147, 273,2802,2407, 898,1787,2155,4071, # 3008 +4072,5364,3871,2803,5365,5366,4659,4660,5367,3239,5368,1635,3872, 965,5369,1805, # 3024 +2699,1516,3614,1121,1082,1329,3317,4073,1449,3873, 65,1128,2848,2927,2769,1590, # 3040 +3874,5370,5371, 12,2668, 45, 976,2587,3169,4661, 517,2535,1013,1037,3240,5372, # 3056 +3875,2849,5373,3876,5374,3499,5375,2612, 614,1999,2323,3877,3110,2733,2638,5376, # 3072 +2588,4316, 599,1269,5377,1811,3735,5378,2700,3111, 759,1060, 489,1806,3388,3318, # 3088 +1358,5379,5380,2391,1387,1215,2639,2256, 490,5381,5382,4317,1759,2392,2348,5383, # 3104 +4662,3878,1908,4074,2640,1807,3241,4663,3500,3319,2770,2349, 874,5384,5385,3501, # 3120 +3736,1859, 91,2928,3737,3062,3879,4664,5386,3170,4075,2669,5387,3502,1202,1403, # 3136 +3880,2969,2536,1517,2510,4665,3503,2511,5388,4666,5389,2701,1886,1495,1731,4076, # 3152 +2370,4667,5390,2030,5391,5392,4077,2702,1216, 237,2589,4318,2324,4078,3881,4668, # 3168 +4669,2703,3615,3504, 445,4670,5393,5394,5395,5396,2771, 61,4079,3738,1823,4080, # 3184 +5397, 687,2046, 935, 925, 405,2670, 703,1096,1860,2734,4671,4081,1877,1367,2704, # 3200 +3389, 918,2106,1782,2483, 334,3320,1611,1093,4672, 564,3171,3505,3739,3390, 945, # 3216 +2641,2058,4673,5398,1926, 872,4319,5399,3506,2705,3112, 349,4320,3740,4082,4674, # 3232 +3882,4321,3741,2156,4083,4675,4676,4322,4677,2408,2047, 782,4084, 400, 251,4323, # 3248 +1624,5400,5401, 277,3742, 299,1265, 476,1191,3883,2122,4324,4325,1109, 205,5402, # 3264 +2590,1000,2157,3616,1861,5403,5404,5405,4678,5406,4679,2573, 107,2484,2158,4085, # 3280 +3507,3172,5407,1533, 541,1301, 158, 753,4326,2886,3617,5408,1696, 370,1088,4327, # 3296 +4680,3618, 579, 327, 440, 162,2244, 269,1938,1374,3508, 968,3063, 56,1396,3113, # 3312 +2107,3321,3391,5409,1927,2159,4681,3016,5410,3619,5411,5412,3743,4682,2485,5413, # 3328 +2804,5414,1650,4683,5415,2613,5416,5417,4086,2671,3392,1149,3393,4087,3884,4088, # 3344 +5418,1076, 49,5419, 951,3242,3322,3323, 450,2850, 920,5420,1812,2805,2371,4328, # 3360 +1909,1138,2372,3885,3509,5421,3243,4684,1910,1147,1518,2428,4685,3886,5422,4686, # 3376 +2393,2614, 260,1796,3244,5423,5424,3887,3324, 708,5425,3620,1704,5426,3621,1351, # 3392 +1618,3394,3017,1887, 944,4329,3395,4330,3064,3396,4331,5427,3744, 422, 413,1714, # 3408 +3325, 500,2059,2350,4332,2486,5428,1344,1911, 954,5429,1668,5430,5431,4089,2409, # 3424 +4333,3622,3888,4334,5432,2307,1318,2512,3114, 133,3115,2887,4687, 629, 31,2851, # 3440 +2706,3889,4688, 850, 949,4689,4090,2970,1732,2089,4335,1496,1853,5433,4091, 620, # 3456 +3245, 981,1242,3745,3397,1619,3746,1643,3326,2140,2457,1971,1719,3510,2169,5434, # 3472 +3246,5435,5436,3398,1829,5437,1277,4690,1565,2048,5438,1636,3623,3116,5439, 869, # 3488 +2852, 655,3890,3891,3117,4092,3018,3892,1310,3624,4691,5440,5441,5442,1733, 558, # 3504 +4692,3747, 335,1549,3065,1756,4336,3748,1946,3511,1830,1291,1192, 470,2735,2108, # 3520 +2806, 913,1054,4093,5443,1027,5444,3066,4094,4693, 982,2672,3399,3173,3512,3247, # 3536 +3248,1947,2807,5445, 571,4694,5446,1831,5447,3625,2591,1523,2429,5448,2090, 984, # 3552 +4695,3749,1960,5449,3750, 852, 923,2808,3513,3751, 969,1519, 999,2049,2325,1705, # 3568 +5450,3118, 615,1662, 151, 597,4095,2410,2326,1049, 275,4696,3752,4337, 568,3753, # 3584 +3626,2487,4338,3754,5451,2430,2275, 409,3249,5452,1566,2888,3514,1002, 769,2853, # 3600 + 194,2091,3174,3755,2226,3327,4339, 628,1505,5453,5454,1763,2180,3019,4096, 521, # 3616 +1161,2592,1788,2206,2411,4697,4097,1625,4340,4341, 412, 42,3119, 464,5455,2642, # 3632 +4698,3400,1760,1571,2889,3515,2537,1219,2207,3893,2643,2141,2373,4699,4700,3328, # 3648 +1651,3401,3627,5456,5457,3628,2488,3516,5458,3756,5459,5460,2276,2092, 460,5461, # 3664 +4701,5462,3020, 962, 588,3629, 289,3250,2644,1116, 52,5463,3067,1797,5464,5465, # 3680 +5466,1467,5467,1598,1143,3757,4342,1985,1734,1067,4702,1280,3402, 465,4703,1572, # 3696 + 510,5468,1928,2245,1813,1644,3630,5469,4704,3758,5470,5471,2673,1573,1534,5472, # 3712 +5473, 536,1808,1761,3517,3894,3175,2645,5474,5475,5476,4705,3518,2929,1912,2809, # 3728 +5477,3329,1122, 377,3251,5478, 360,5479,5480,4343,1529, 551,5481,2060,3759,1769, # 3744 +2431,5482,2930,4344,3330,3120,2327,2109,2031,4706,1404, 136,1468,1479, 672,1171, # 3760 +3252,2308, 271,3176,5483,2772,5484,2050, 678,2736, 865,1948,4707,5485,2014,4098, # 3776 +2971,5486,2737,2227,1397,3068,3760,4708,4709,1735,2931,3403,3631,5487,3895, 509, # 3792 +2854,2458,2890,3896,5488,5489,3177,3178,4710,4345,2538,4711,2309,1166,1010, 552, # 3808 + 681,1888,5490,5491,2972,2973,4099,1287,1596,1862,3179, 358, 453, 736, 175, 478, # 3824 +1117, 905,1167,1097,5492,1854,1530,5493,1706,5494,2181,3519,2292,3761,3520,3632, # 3840 +4346,2093,4347,5495,3404,1193,2489,4348,1458,2193,2208,1863,1889,1421,3331,2932, # 3856 +3069,2182,3521, 595,2123,5496,4100,5497,5498,4349,1707,2646, 223,3762,1359, 751, # 3872 +3121, 183,3522,5499,2810,3021, 419,2374, 633, 704,3897,2394, 241,5500,5501,5502, # 3888 + 838,3022,3763,2277,2773,2459,3898,1939,2051,4101,1309,3122,2246,1181,5503,1136, # 3904 +2209,3899,2375,1446,4350,2310,4712,5504,5505,4351,1055,2615, 484,3764,5506,4102, # 3920 + 625,4352,2278,3405,1499,4353,4103,5507,4104,4354,3253,2279,2280,3523,5508,5509, # 3936 +2774, 808,2616,3765,3406,4105,4355,3123,2539, 526,3407,3900,4356, 955,5510,1620, # 3952 +4357,2647,2432,5511,1429,3766,1669,1832, 994, 928,5512,3633,1260,5513,5514,5515, # 3968 +1949,2293, 741,2933,1626,4358,2738,2460, 867,1184, 362,3408,1392,5516,5517,4106, # 3984 +4359,1770,1736,3254,2934,4713,4714,1929,2707,1459,1158,5518,3070,3409,2891,1292, # 4000 +1930,2513,2855,3767,1986,1187,2072,2015,2617,4360,5519,2574,2514,2170,3768,2490, # 4016 +3332,5520,3769,4715,5521,5522, 666,1003,3023,1022,3634,4361,5523,4716,1814,2257, # 4032 + 574,3901,1603, 295,1535, 705,3902,4362, 283, 858, 417,5524,5525,3255,4717,4718, # 4048 +3071,1220,1890,1046,2281,2461,4107,1393,1599, 689,2575, 388,4363,5526,2491, 802, # 4064 +5527,2811,3903,2061,1405,2258,5528,4719,3904,2110,1052,1345,3256,1585,5529, 809, # 4080 +5530,5531,5532, 575,2739,3524, 956,1552,1469,1144,2328,5533,2329,1560,2462,3635, # 4096 +3257,4108, 616,2210,4364,3180,2183,2294,5534,1833,5535,3525,4720,5536,1319,3770, # 4112 +3771,1211,3636,1023,3258,1293,2812,5537,5538,5539,3905, 607,2311,3906, 762,2892, # 4128 +1439,4365,1360,4721,1485,3072,5540,4722,1038,4366,1450,2062,2648,4367,1379,4723, # 4144 +2593,5541,5542,4368,1352,1414,2330,2935,1172,5543,5544,3907,3908,4724,1798,1451, # 4160 +5545,5546,5547,5548,2936,4109,4110,2492,2351, 411,4111,4112,3637,3333,3124,4725, # 4176 +1561,2674,1452,4113,1375,5549,5550, 47,2974, 316,5551,1406,1591,2937,3181,5552, # 4192 +1025,2142,3125,3182, 354,2740, 884,2228,4369,2412, 508,3772, 726,3638, 996,2433, # 4208 +3639, 729,5553, 392,2194,1453,4114,4726,3773,5554,5555,2463,3640,2618,1675,2813, # 4224 + 919,2352,2975,2353,1270,4727,4115, 73,5556,5557, 647,5558,3259,2856,2259,1550, # 4240 +1346,3024,5559,1332, 883,3526,5560,5561,5562,5563,3334,2775,5564,1212, 831,1347, # 4256 +4370,4728,2331,3909,1864,3073, 720,3910,4729,4730,3911,5565,4371,5566,5567,4731, # 4272 +5568,5569,1799,4732,3774,2619,4733,3641,1645,2376,4734,5570,2938, 669,2211,2675, # 4288 +2434,5571,2893,5572,5573,1028,3260,5574,4372,2413,5575,2260,1353,5576,5577,4735, # 4304 +3183, 518,5578,4116,5579,4373,1961,5580,2143,4374,5581,5582,3025,2354,2355,3912, # 4320 + 516,1834,1454,4117,2708,4375,4736,2229,2620,1972,1129,3642,5583,2776,5584,2976, # 4336 +1422, 577,1470,3026,1524,3410,5585,5586, 432,4376,3074,3527,5587,2594,1455,2515, # 4352 +2230,1973,1175,5588,1020,2741,4118,3528,4737,5589,2742,5590,1743,1361,3075,3529, # 4368 +2649,4119,4377,4738,2295, 895, 924,4378,2171, 331,2247,3076, 166,1627,3077,1098, # 4384 +5591,1232,2894,2231,3411,4739, 657, 403,1196,2377, 542,3775,3412,1600,4379,3530, # 4400 +5592,4740,2777,3261, 576, 530,1362,4741,4742,2540,2676,3776,4120,5593, 842,3913, # 4416 +5594,2814,2032,1014,4121, 213,2709,3413, 665, 621,4380,5595,3777,2939,2435,5596, # 4432 +2436,3335,3643,3414,4743,4381,2541,4382,4744,3644,1682,4383,3531,1380,5597, 724, # 4448 +2282, 600,1670,5598,1337,1233,4745,3126,2248,5599,1621,4746,5600, 651,4384,5601, # 4464 +1612,4385,2621,5602,2857,5603,2743,2312,3078,5604, 716,2464,3079, 174,1255,2710, # 4480 +4122,3645, 548,1320,1398, 728,4123,1574,5605,1891,1197,3080,4124,5606,3081,3082, # 4496 +3778,3646,3779, 747,5607, 635,4386,4747,5608,5609,5610,4387,5611,5612,4748,5613, # 4512 +3415,4749,2437, 451,5614,3780,2542,2073,4388,2744,4389,4125,5615,1764,4750,5616, # 4528 +4390, 350,4751,2283,2395,2493,5617,4391,4126,2249,1434,4127, 488,4752, 458,4392, # 4544 +4128,3781, 771,1330,2396,3914,2576,3184,2160,2414,1553,2677,3185,4393,5618,2494, # 4560 +2895,2622,1720,2711,4394,3416,4753,5619,2543,4395,5620,3262,4396,2778,5621,2016, # 4576 +2745,5622,1155,1017,3782,3915,5623,3336,2313, 201,1865,4397,1430,5624,4129,5625, # 4592 +5626,5627,5628,5629,4398,1604,5630, 414,1866, 371,2595,4754,4755,3532,2017,3127, # 4608 +4756,1708, 960,4399, 887, 389,2172,1536,1663,1721,5631,2232,4130,2356,2940,1580, # 4624 +5632,5633,1744,4757,2544,4758,4759,5634,4760,5635,2074,5636,4761,3647,3417,2896, # 4640 +4400,5637,4401,2650,3418,2815, 673,2712,2465, 709,3533,4131,3648,4402,5638,1148, # 4656 + 502, 634,5639,5640,1204,4762,3649,1575,4763,2623,3783,5641,3784,3128, 948,3263, # 4672 + 121,1745,3916,1110,5642,4403,3083,2516,3027,4132,3785,1151,1771,3917,1488,4133, # 4688 +1987,5643,2438,3534,5644,5645,2094,5646,4404,3918,1213,1407,2816, 531,2746,2545, # 4704 +3264,1011,1537,4764,2779,4405,3129,1061,5647,3786,3787,1867,2897,5648,2018, 120, # 4720 +4406,4407,2063,3650,3265,2314,3919,2678,3419,1955,4765,4134,5649,3535,1047,2713, # 4736 +1266,5650,1368,4766,2858, 649,3420,3920,2546,2747,1102,2859,2679,5651,5652,2000, # 4752 +5653,1111,3651,2977,5654,2495,3921,3652,2817,1855,3421,3788,5655,5656,3422,2415, # 4768 +2898,3337,3266,3653,5657,2577,5658,3654,2818,4135,1460, 856,5659,3655,5660,2899, # 4784 +2978,5661,2900,3922,5662,4408, 632,2517, 875,3923,1697,3924,2296,5663,5664,4767, # 4800 +3028,1239, 580,4768,4409,5665, 914, 936,2075,1190,4136,1039,2124,5666,5667,5668, # 4816 +5669,3423,1473,5670,1354,4410,3925,4769,2173,3084,4137, 915,3338,4411,4412,3339, # 4832 +1605,1835,5671,2748, 398,3656,4413,3926,4138, 328,1913,2860,4139,3927,1331,4414, # 4848 +3029, 937,4415,5672,3657,4140,4141,3424,2161,4770,3425, 524, 742, 538,3085,1012, # 4864 +5673,5674,3928,2466,5675, 658,1103, 225,3929,5676,5677,4771,5678,4772,5679,3267, # 4880 +1243,5680,4142, 963,2250,4773,5681,2714,3658,3186,5682,5683,2596,2332,5684,4774, # 4896 +5685,5686,5687,3536, 957,3426,2547,2033,1931,2941,2467, 870,2019,3659,1746,2780, # 4912 +2781,2439,2468,5688,3930,5689,3789,3130,3790,3537,3427,3791,5690,1179,3086,5691, # 4928 +3187,2378,4416,3792,2548,3188,3131,2749,4143,5692,3428,1556,2549,2297, 977,2901, # 4944 +2034,4144,1205,3429,5693,1765,3430,3189,2125,1271, 714,1689,4775,3538,5694,2333, # 4960 +3931, 533,4417,3660,2184, 617,5695,2469,3340,3539,2315,5696,5697,3190,5698,5699, # 4976 +3932,1988, 618, 427,2651,3540,3431,5700,5701,1244,1690,5702,2819,4418,4776,5703, # 4992 +3541,4777,5704,2284,1576, 473,3661,4419,3432, 972,5705,3662,5706,3087,5707,5708, # 5008 +4778,4779,5709,3793,4145,4146,5710, 153,4780, 356,5711,1892,2902,4420,2144, 408, # 5024 + 803,2357,5712,3933,5713,4421,1646,2578,2518,4781,4782,3934,5714,3935,4422,5715, # 5040 +2416,3433, 752,5716,5717,1962,3341,2979,5718, 746,3030,2470,4783,4423,3794, 698, # 5056 +4784,1893,4424,3663,2550,4785,3664,3936,5719,3191,3434,5720,1824,1302,4147,2715, # 5072 +3937,1974,4425,5721,4426,3192, 823,1303,1288,1236,2861,3542,4148,3435, 774,3938, # 5088 +5722,1581,4786,1304,2862,3939,4787,5723,2440,2162,1083,3268,4427,4149,4428, 344, # 5104 +1173, 288,2316, 454,1683,5724,5725,1461,4788,4150,2597,5726,5727,4789, 985, 894, # 5120 +5728,3436,3193,5729,1914,2942,3795,1989,5730,2111,1975,5731,4151,5732,2579,1194, # 5136 + 425,5733,4790,3194,1245,3796,4429,5734,5735,2863,5736, 636,4791,1856,3940, 760, # 5152 +1800,5737,4430,2212,1508,4792,4152,1894,1684,2298,5738,5739,4793,4431,4432,2213, # 5168 + 479,5740,5741, 832,5742,4153,2496,5743,2980,2497,3797, 990,3132, 627,1815,2652, # 5184 +4433,1582,4434,2126,2112,3543,4794,5744, 799,4435,3195,5745,4795,2113,1737,3031, # 5200 +1018, 543, 754,4436,3342,1676,4796,4797,4154,4798,1489,5746,3544,5747,2624,2903, # 5216 +4155,5748,5749,2981,5750,5751,5752,5753,3196,4799,4800,2185,1722,5754,3269,3270, # 5232 +1843,3665,1715, 481, 365,1976,1857,5755,5756,1963,2498,4801,5757,2127,3666,3271, # 5248 + 433,1895,2064,2076,5758, 602,2750,5759,5760,5761,5762,5763,3032,1628,3437,5764, # 5264 +3197,4802,4156,2904,4803,2519,5765,2551,2782,5766,5767,5768,3343,4804,2905,5769, # 5280 +4805,5770,2864,4806,4807,1221,2982,4157,2520,5771,5772,5773,1868,1990,5774,5775, # 5296 +5776,1896,5777,5778,4808,1897,4158, 318,5779,2095,4159,4437,5780,5781, 485,5782, # 5312 + 938,3941, 553,2680, 116,5783,3942,3667,5784,3545,2681,2783,3438,3344,2820,5785, # 5328 +3668,2943,4160,1747,2944,2983,5786,5787, 207,5788,4809,5789,4810,2521,5790,3033, # 5344 + 890,3669,3943,5791,1878,3798,3439,5792,2186,2358,3440,1652,5793,5794,5795, 941, # 5360 +2299, 208,3546,4161,2020, 330,4438,3944,2906,2499,3799,4439,4811,5796,5797,5798, # 5376 +) + diff --git a/flex/lib/python3.6/site-packages/chardet/big5prober.py b/flex/lib/python3.6/site-packages/chardet/big5prober.py new file mode 100644 index 0000000..98f9970 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/big5prober.py @@ -0,0 +1,47 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import Big5DistributionAnalysis +from .mbcssm import BIG5_SM_MODEL + + +class Big5Prober(MultiByteCharSetProber): + def __init__(self): + super(Big5Prober, self).__init__() + self.coding_sm = CodingStateMachine(BIG5_SM_MODEL) + self.distribution_analyzer = Big5DistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "Big5" + + @property + def language(self): + return "Chinese" diff --git a/flex/lib/python3.6/site-packages/chardet/chardistribution.py b/flex/lib/python3.6/site-packages/chardet/chardistribution.py new file mode 100644 index 0000000..c0395f4 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/chardistribution.py @@ -0,0 +1,233 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .euctwfreq import (EUCTW_CHAR_TO_FREQ_ORDER, EUCTW_TABLE_SIZE, + EUCTW_TYPICAL_DISTRIBUTION_RATIO) +from .euckrfreq import (EUCKR_CHAR_TO_FREQ_ORDER, EUCKR_TABLE_SIZE, + EUCKR_TYPICAL_DISTRIBUTION_RATIO) +from .gb2312freq import (GB2312_CHAR_TO_FREQ_ORDER, GB2312_TABLE_SIZE, + GB2312_TYPICAL_DISTRIBUTION_RATIO) +from .big5freq import (BIG5_CHAR_TO_FREQ_ORDER, BIG5_TABLE_SIZE, + BIG5_TYPICAL_DISTRIBUTION_RATIO) +from .jisfreq import (JIS_CHAR_TO_FREQ_ORDER, JIS_TABLE_SIZE, + JIS_TYPICAL_DISTRIBUTION_RATIO) + + +class CharDistributionAnalysis(object): + ENOUGH_DATA_THRESHOLD = 1024 + SURE_YES = 0.99 + SURE_NO = 0.01 + MINIMUM_DATA_THRESHOLD = 3 + + def __init__(self): + # Mapping table to get frequency order from char order (get from + # GetOrder()) + self._char_to_freq_order = None + self._table_size = None # Size of above table + # This is a constant value which varies from language to language, + # used in calculating confidence. See + # http://www.mozilla.org/projects/intl/UniversalCharsetDetection.html + # for further detail. + self.typical_distribution_ratio = None + self._done = None + self._total_chars = None + self._freq_chars = None + self.reset() + + def reset(self): + """reset analyser, clear any state""" + # If this flag is set to True, detection is done and conclusion has + # been made + self._done = False + self._total_chars = 0 # Total characters encountered + # The number of characters whose frequency order is less than 512 + self._freq_chars = 0 + + def feed(self, char, char_len): + """feed a character with known length""" + if char_len == 2: + # we only care about 2-bytes character in our distribution analysis + order = self.get_order(char) + else: + order = -1 + if order >= 0: + self._total_chars += 1 + # order is valid + if order < self._table_size: + if 512 > self._char_to_freq_order[order]: + self._freq_chars += 1 + + def get_confidence(self): + """return confidence based on existing data""" + # if we didn't receive any character in our consideration range, + # return negative answer + if self._total_chars <= 0 or self._freq_chars <= self.MINIMUM_DATA_THRESHOLD: + return self.SURE_NO + + if self._total_chars != self._freq_chars: + r = (self._freq_chars / ((self._total_chars - self._freq_chars) + * self.typical_distribution_ratio)) + if r < self.SURE_YES: + return r + + # normalize confidence (we don't want to be 100% sure) + return self.SURE_YES + + def got_enough_data(self): + # It is not necessary to receive all data to draw conclusion. + # For charset detection, certain amount of data is enough + return self._total_chars > self.ENOUGH_DATA_THRESHOLD + + def get_order(self, byte_str): + # We do not handle characters based on the original encoding string, + # but convert this encoding string to a number, here called order. + # This allows multiple encodings of a language to share one frequency + # table. + return -1 + + +class EUCTWDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCTWDistributionAnalysis, self).__init__() + self._char_to_freq_order = EUCTW_CHAR_TO_FREQ_ORDER + self._table_size = EUCTW_TABLE_SIZE + self.typical_distribution_ratio = EUCTW_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-TW encoding, we are interested + # first byte range: 0xc4 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char = byte_str[0] + if first_char >= 0xC4: + return 94 * (first_char - 0xC4) + byte_str[1] - 0xA1 + else: + return -1 + + +class EUCKRDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCKRDistributionAnalysis, self).__init__() + self._char_to_freq_order = EUCKR_CHAR_TO_FREQ_ORDER + self._table_size = EUCKR_TABLE_SIZE + self.typical_distribution_ratio = EUCKR_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-KR encoding, we are interested + # first byte range: 0xb0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char = byte_str[0] + if first_char >= 0xB0: + return 94 * (first_char - 0xB0) + byte_str[1] - 0xA1 + else: + return -1 + + +class GB2312DistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(GB2312DistributionAnalysis, self).__init__() + self._char_to_freq_order = GB2312_CHAR_TO_FREQ_ORDER + self._table_size = GB2312_TABLE_SIZE + self.typical_distribution_ratio = GB2312_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for GB2312 encoding, we are interested + # first byte range: 0xb0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if (first_char >= 0xB0) and (second_char >= 0xA1): + return 94 * (first_char - 0xB0) + second_char - 0xA1 + else: + return -1 + + +class Big5DistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(Big5DistributionAnalysis, self).__init__() + self._char_to_freq_order = BIG5_CHAR_TO_FREQ_ORDER + self._table_size = BIG5_TABLE_SIZE + self.typical_distribution_ratio = BIG5_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for big5 encoding, we are interested + # first byte range: 0xa4 -- 0xfe + # second byte range: 0x40 -- 0x7e , 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if first_char >= 0xA4: + if second_char >= 0xA1: + return 157 * (first_char - 0xA4) + second_char - 0xA1 + 63 + else: + return 157 * (first_char - 0xA4) + second_char - 0x40 + else: + return -1 + + +class SJISDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(SJISDistributionAnalysis, self).__init__() + self._char_to_freq_order = JIS_CHAR_TO_FREQ_ORDER + self._table_size = JIS_TABLE_SIZE + self.typical_distribution_ratio = JIS_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for sjis encoding, we are interested + # first byte range: 0x81 -- 0x9f , 0xe0 -- 0xfe + # second byte range: 0x40 -- 0x7e, 0x81 -- oxfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if (first_char >= 0x81) and (first_char <= 0x9F): + order = 188 * (first_char - 0x81) + elif (first_char >= 0xE0) and (first_char <= 0xEF): + order = 188 * (first_char - 0xE0 + 31) + else: + return -1 + order = order + second_char - 0x40 + if second_char > 0x7F: + order = -1 + return order + + +class EUCJPDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCJPDistributionAnalysis, self).__init__() + self._char_to_freq_order = JIS_CHAR_TO_FREQ_ORDER + self._table_size = JIS_TABLE_SIZE + self.typical_distribution_ratio = JIS_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-JP encoding, we are interested + # first byte range: 0xa0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + char = byte_str[0] + if char >= 0xA0: + return 94 * (char - 0xA1) + byte_str[1] - 0xa1 + else: + return -1 diff --git a/flex/lib/python3.6/site-packages/chardet/charsetgroupprober.py b/flex/lib/python3.6/site-packages/chardet/charsetgroupprober.py new file mode 100644 index 0000000..8b3738e --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/charsetgroupprober.py @@ -0,0 +1,106 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import ProbingState +from .charsetprober import CharSetProber + + +class CharSetGroupProber(CharSetProber): + def __init__(self, lang_filter=None): + super(CharSetGroupProber, self).__init__(lang_filter=lang_filter) + self._active_num = 0 + self.probers = [] + self._best_guess_prober = None + + def reset(self): + super(CharSetGroupProber, self).reset() + self._active_num = 0 + for prober in self.probers: + if prober: + prober.reset() + prober.active = True + self._active_num += 1 + self._best_guess_prober = None + + @property + def charset_name(self): + if not self._best_guess_prober: + self.get_confidence() + if not self._best_guess_prober: + return None + return self._best_guess_prober.charset_name + + @property + def language(self): + if not self._best_guess_prober: + self.get_confidence() + if not self._best_guess_prober: + return None + return self._best_guess_prober.language + + def feed(self, byte_str): + for prober in self.probers: + if not prober: + continue + if not prober.active: + continue + state = prober.feed(byte_str) + if not state: + continue + if state == ProbingState.FOUND_IT: + self._best_guess_prober = prober + return self.state + elif state == ProbingState.NOT_ME: + prober.active = False + self._active_num -= 1 + if self._active_num <= 0: + self._state = ProbingState.NOT_ME + return self.state + return self.state + + def get_confidence(self): + state = self.state + if state == ProbingState.FOUND_IT: + return 0.99 + elif state == ProbingState.NOT_ME: + return 0.01 + best_conf = 0.0 + self._best_guess_prober = None + for prober in self.probers: + if not prober: + continue + if not prober.active: + self.logger.debug('%s not active', prober.charset_name) + continue + conf = prober.get_confidence() + self.logger.debug('%s %s confidence = %s', prober.charset_name, prober.language, conf) + if best_conf < conf: + best_conf = conf + self._best_guess_prober = prober + if not self._best_guess_prober: + return 0.0 + return best_conf diff --git a/flex/lib/python3.6/site-packages/chardet/charsetprober.py b/flex/lib/python3.6/site-packages/chardet/charsetprober.py new file mode 100644 index 0000000..eac4e59 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/charsetprober.py @@ -0,0 +1,145 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import logging +import re + +from .enums import ProbingState + + +class CharSetProber(object): + + SHORTCUT_THRESHOLD = 0.95 + + def __init__(self, lang_filter=None): + self._state = None + self.lang_filter = lang_filter + self.logger = logging.getLogger(__name__) + + def reset(self): + self._state = ProbingState.DETECTING + + @property + def charset_name(self): + return None + + def feed(self, buf): + pass + + @property + def state(self): + return self._state + + def get_confidence(self): + return 0.0 + + @staticmethod + def filter_high_byte_only(buf): + buf = re.sub(b'([\x00-\x7F])+', b' ', buf) + return buf + + @staticmethod + def filter_international_words(buf): + """ + We define three types of bytes: + alphabet: english alphabets [a-zA-Z] + international: international characters [\x80-\xFF] + marker: everything else [^a-zA-Z\x80-\xFF] + + The input buffer can be thought to contain a series of words delimited + by markers. This function works to filter all words that contain at + least one international character. All contiguous sequences of markers + are replaced by a single space ascii character. + + This filter applies to all scripts which do not use English characters. + """ + filtered = bytearray() + + # This regex expression filters out only words that have at-least one + # international character. The word may include one marker character at + # the end. + words = re.findall(b'[a-zA-Z]*[\x80-\xFF]+[a-zA-Z]*[^a-zA-Z\x80-\xFF]?', + buf) + + for word in words: + filtered.extend(word[:-1]) + + # If the last character in the word is a marker, replace it with a + # space as markers shouldn't affect our analysis (they are used + # similarly across all languages and may thus have similar + # frequencies). + last_char = word[-1:] + if not last_char.isalpha() and last_char < b'\x80': + last_char = b' ' + filtered.extend(last_char) + + return filtered + + @staticmethod + def filter_with_english_letters(buf): + """ + Returns a copy of ``buf`` that retains only the sequences of English + alphabet and high byte characters that are not between <> characters. + Also retains English alphabet and high byte characters immediately + before occurrences of >. + + This filter can be applied to all scripts which contain both English + characters and extended ASCII characters, but is currently only used by + ``Latin1Prober``. + """ + filtered = bytearray() + in_tag = False + prev = 0 + + for curr in range(len(buf)): + # Slice here to get bytes instead of an int with Python 3 + buf_char = buf[curr:curr + 1] + # Check if we're coming out of or entering an HTML tag + if buf_char == b'>': + in_tag = False + elif buf_char == b'<': + in_tag = True + + # If current character is not extended-ASCII and not alphabetic... + if buf_char < b'\x80' and not buf_char.isalpha(): + # ...and we're not in a tag + if curr > prev and not in_tag: + # Keep everything after last non-extended-ASCII, + # non-alphabetic character + filtered.extend(buf[prev:curr]) + # Output a space to delimit stretch we kept + filtered.extend(b' ') + prev = curr + 1 + + # If we're not in a tag... + if not in_tag: + # Keep everything after last non-extended-ASCII, non-alphabetic + # character + filtered.extend(buf[prev:]) + + return filtered diff --git a/flex/lib/python3.6/site-packages/chardet/cli/__init__.py b/flex/lib/python3.6/site-packages/chardet/cli/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/cli/__init__.py @@ -0,0 +1 @@ + diff --git a/flex/lib/python3.6/site-packages/chardet/cli/__pycache__/__init__.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/cli/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c8863137b3463bc90efce007bf6903a71977efe8 GIT binary patch literal 190 zcmXr!<>j*5nHDsY2KczG$)ehu{VjyM! E0Mno`=Kufz literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/chardet/cli/__pycache__/chardetect.cpython-36.pyc b/flex/lib/python3.6/site-packages/chardet/cli/__pycache__/chardetect.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a015e77cfea5ef20f2bf0528df9c4014358fb7e6 GIT binary patch literal 2661 zcma)8-EJE<7M?$iXkS^mgy|Re0O0eT4-I^gA5MQIMOCVe*hXJmlf|&Uf_D)>ib%e~115 zM2_>Dv-bIrKgGY2Xt>jNxXZoF&Aq;t`+YwT`hiPxepc((Y#;VR^g&k78~uh|t7RK` z)Q_wjW}A7l--Nuy8+_wux4*?(JmQ;>T4I|w&pla)*1~~?|FzTJPVT#o6Ma3D=|r=u zvvhdIbaE~fD+|F&$?{SPHcB(WCW$^%EGamXVp2*?Dome=R5C8K7;3>IQ4C9-7N;tT z{`DfsCzanY|;N_L->>oTnz(Aj|VOfk) zjxz+?>ps3!zctWfi5jNqTgv<0y(s!(#ENp|1bmvv@)E}QBbMr=%PD+Hi^){8kt}nj zG+gOM(f<${r|p~VWT47yszsdU^Z=$ck!hjh(X<%qv@Fcdv`FEG+D)KCc|3Q=b=??mEP$tlcjL|j?%j1{ z!ToVGUyd*r+;tW}2CvcV!i5w9C-vFy_PxIndMXQ+;BnylDI%``odJmmBR%RM82~IR zAh2=-WgF{KS_@gKG|g596yBHM(VHYP$yt^bLiN}QOj(iXlAQ{~2NP>1yVV|jJz47Y z*cbHTbTUj2uC-9>W{V^jJ$8hamY25yoU#nCMPz8!p0{SV+Jjr#ITNO*1yaE@R@a!_ zd%1VhV=wn_-oo3}jpa5B{p!f~ z(fvQ)1$HkJEp{&xxjQN|4lwSHDmgdRICM}NZ=)IBs#6uObya3e2t zL-e5=xI5^Zn31G41UuO;KueEi)8Q8g+8Mh=I*hTeeY<}2UMMso+rVs8;ybTA*U?*gdro>g3y%`;;-~K%eh2CDm)UO?HlKqo5hp+`&xtuH4lI$U zQ$!79LsN*Q0=|hfkrRmojlP)^P`~W4FPCX^yZI5wj-|+>i5RA%RPZGoug>bwSyiG? zg57@L!6TsT5qtg|`00}MANG4cK7YDi4?%pVZN-r2 zZO?>>Wfl1WU^?6TzMLZDg2`!75KpevK~xX07L+eVcHL#i$auwOAAff8)t8-TOkbs_ zbVuXc9Wz>YIf7oEtUcL(jiUhPTO=x#YJ5t6SSqiI~ zyJRTHleBmON!>@|Yy=*d#Ph%`?}JNP;F2bK&x;_-1KQDuW7 self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + context_conf = self.context_analyzer.get_confidence() + distrib_conf = self.distribution_analyzer.get_confidence() + return max(context_conf, distrib_conf) diff --git a/flex/lib/python3.6/site-packages/chardet/euckrfreq.py b/flex/lib/python3.6/site-packages/chardet/euckrfreq.py new file mode 100644 index 0000000..b68078c --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/euckrfreq.py @@ -0,0 +1,195 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Sampling from about 20M text materials include literature and computer technology + +# 128 --> 0.79 +# 256 --> 0.92 +# 512 --> 0.986 +# 1024 --> 0.99944 +# 2048 --> 0.99999 +# +# Idea Distribution Ratio = 0.98653 / (1-0.98653) = 73.24 +# Random Distribution Ration = 512 / (2350-512) = 0.279. +# +# Typical Distribution Ratio + +EUCKR_TYPICAL_DISTRIBUTION_RATIO = 6.0 + +EUCKR_TABLE_SIZE = 2352 + +# Char to FreqOrder table , +EUCKR_CHAR_TO_FREQ_ORDER = ( + 13, 130, 120,1396, 481,1719,1720, 328, 609, 212,1721, 707, 400, 299,1722, 87, +1397,1723, 104, 536,1117,1203,1724,1267, 685,1268, 508,1725,1726,1727,1728,1398, +1399,1729,1730,1731, 141, 621, 326,1057, 368,1732, 267, 488, 20,1733,1269,1734, + 945,1400,1735, 47, 904,1270,1736,1737, 773, 248,1738, 409, 313, 786, 429,1739, + 116, 987, 813,1401, 683, 75,1204, 145,1740,1741,1742,1743, 16, 847, 667, 622, + 708,1744,1745,1746, 966, 787, 304, 129,1747, 60, 820, 123, 676,1748,1749,1750, +1751, 617,1752, 626,1753,1754,1755,1756, 653,1757,1758,1759,1760,1761,1762, 856, + 344,1763,1764,1765,1766, 89, 401, 418, 806, 905, 848,1767,1768,1769, 946,1205, + 709,1770,1118,1771, 241,1772,1773,1774,1271,1775, 569,1776, 999,1777,1778,1779, +1780, 337, 751,1058, 28, 628, 254,1781, 177, 906, 270, 349, 891,1079,1782, 19, +1783, 379,1784, 315,1785, 629, 754,1402, 559,1786, 636, 203,1206,1787, 710, 567, +1788, 935, 814,1789,1790,1207, 766, 528,1791,1792,1208,1793,1794,1795,1796,1797, +1403,1798,1799, 533,1059,1404,1405,1156,1406, 936, 884,1080,1800, 351,1801,1802, +1803,1804,1805, 801,1806,1807,1808,1119,1809,1157, 714, 474,1407,1810, 298, 899, + 885,1811,1120, 802,1158,1812, 892,1813,1814,1408, 659,1815,1816,1121,1817,1818, +1819,1820,1821,1822, 319,1823, 594, 545,1824, 815, 937,1209,1825,1826, 573,1409, +1022,1827,1210,1828,1829,1830,1831,1832,1833, 556, 722, 807,1122,1060,1834, 697, +1835, 900, 557, 715,1836,1410, 540,1411, 752,1159, 294, 597,1211, 976, 803, 770, +1412,1837,1838, 39, 794,1413, 358,1839, 371, 925,1840, 453, 661, 788, 531, 723, + 544,1023,1081, 869, 91,1841, 392, 430, 790, 602,1414, 677,1082, 457,1415,1416, +1842,1843, 475, 327,1024,1417, 795, 121,1844, 733, 403,1418,1845,1846,1847, 300, + 119, 711,1212, 627,1848,1272, 207,1849,1850, 796,1213, 382,1851, 519,1852,1083, + 893,1853,1854,1855, 367, 809, 487, 671,1856, 663,1857,1858, 956, 471, 306, 857, +1859,1860,1160,1084,1861,1862,1863,1864,1865,1061,1866,1867,1868,1869,1870,1871, + 282, 96, 574,1872, 502,1085,1873,1214,1874, 907,1875,1876, 827, 977,1419,1420, +1421, 268,1877,1422,1878,1879,1880, 308,1881, 2, 537,1882,1883,1215,1884,1885, + 127, 791,1886,1273,1423,1887, 34, 336, 404, 643,1888, 571, 654, 894, 840,1889, + 0, 886,1274, 122, 575, 260, 908, 938,1890,1275, 410, 316,1891,1892, 100,1893, +1894,1123, 48,1161,1124,1025,1895, 633, 901,1276,1896,1897, 115, 816,1898, 317, +1899, 694,1900, 909, 734,1424, 572, 866,1425, 691, 85, 524,1010, 543, 394, 841, +1901,1902,1903,1026,1904,1905,1906,1907,1908,1909, 30, 451, 651, 988, 310,1910, +1911,1426, 810,1216, 93,1912,1913,1277,1217,1914, 858, 759, 45, 58, 181, 610, + 269,1915,1916, 131,1062, 551, 443,1000, 821,1427, 957, 895,1086,1917,1918, 375, +1919, 359,1920, 687,1921, 822,1922, 293,1923,1924, 40, 662, 118, 692, 29, 939, + 887, 640, 482, 174,1925, 69,1162, 728,1428, 910,1926,1278,1218,1279, 386, 870, + 217, 854,1163, 823,1927,1928,1929,1930, 834,1931, 78,1932, 859,1933,1063,1934, +1935,1936,1937, 438,1164, 208, 595,1938,1939,1940,1941,1219,1125,1942, 280, 888, +1429,1430,1220,1431,1943,1944,1945,1946,1947,1280, 150, 510,1432,1948,1949,1950, +1951,1952,1953,1954,1011,1087,1955,1433,1043,1956, 881,1957, 614, 958,1064,1065, +1221,1958, 638,1001, 860, 967, 896,1434, 989, 492, 553,1281,1165,1959,1282,1002, +1283,1222,1960,1961,1962,1963, 36, 383, 228, 753, 247, 454,1964, 876, 678,1965, +1966,1284, 126, 464, 490, 835, 136, 672, 529, 940,1088,1435, 473,1967,1968, 467, + 50, 390, 227, 587, 279, 378, 598, 792, 968, 240, 151, 160, 849, 882,1126,1285, + 639,1044, 133, 140, 288, 360, 811, 563,1027, 561, 142, 523,1969,1970,1971, 7, + 103, 296, 439, 407, 506, 634, 990,1972,1973,1974,1975, 645,1976,1977,1978,1979, +1980,1981, 236,1982,1436,1983,1984,1089, 192, 828, 618, 518,1166, 333,1127,1985, + 818,1223,1986,1987,1988,1989,1990,1991,1992,1993, 342,1128,1286, 746, 842,1994, +1995, 560, 223,1287, 98, 8, 189, 650, 978,1288,1996,1437,1997, 17, 345, 250, + 423, 277, 234, 512, 226, 97, 289, 42, 167,1998, 201,1999,2000, 843, 836, 824, + 532, 338, 783,1090, 182, 576, 436,1438,1439, 527, 500,2001, 947, 889,2002,2003, +2004,2005, 262, 600, 314, 447,2006, 547,2007, 693, 738,1129,2008, 71,1440, 745, + 619, 688,2009, 829,2010,2011, 147,2012, 33, 948,2013,2014, 74, 224,2015, 61, + 191, 918, 399, 637,2016,1028,1130, 257, 902,2017,2018,2019,2020,2021,2022,2023, +2024,2025,2026, 837,2027,2028,2029,2030, 179, 874, 591, 52, 724, 246,2031,2032, +2033,2034,1167, 969,2035,1289, 630, 605, 911,1091,1168,2036,2037,2038,1441, 912, +2039, 623,2040,2041, 253,1169,1290,2042,1442, 146, 620, 611, 577, 433,2043,1224, + 719,1170, 959, 440, 437, 534, 84, 388, 480,1131, 159, 220, 198, 679,2044,1012, + 819,1066,1443, 113,1225, 194, 318,1003,1029,2045,2046,2047,2048,1067,2049,2050, +2051,2052,2053, 59, 913, 112,2054, 632,2055, 455, 144, 739,1291,2056, 273, 681, + 499,2057, 448,2058,2059, 760,2060,2061, 970, 384, 169, 245,1132,2062,2063, 414, +1444,2064,2065, 41, 235,2066, 157, 252, 877, 568, 919, 789, 580,2067, 725,2068, +2069,1292,2070,2071,1445,2072,1446,2073,2074, 55, 588, 66,1447, 271,1092,2075, +1226,2076, 960,1013, 372,2077,2078,2079,2080,2081,1293,2082,2083,2084,2085, 850, +2086,2087,2088,2089,2090, 186,2091,1068, 180,2092,2093,2094, 109,1227, 522, 606, +2095, 867,1448,1093, 991,1171, 926, 353,1133,2096, 581,2097,2098,2099,1294,1449, +1450,2100, 596,1172,1014,1228,2101,1451,1295,1173,1229,2102,2103,1296,1134,1452, + 949,1135,2104,2105,1094,1453,1454,1455,2106,1095,2107,2108,2109,2110,2111,2112, +2113,2114,2115,2116,2117, 804,2118,2119,1230,1231, 805,1456, 405,1136,2120,2121, +2122,2123,2124, 720, 701,1297, 992,1457, 927,1004,2125,2126,2127,2128,2129,2130, + 22, 417,2131, 303,2132, 385,2133, 971, 520, 513,2134,1174, 73,1096, 231, 274, + 962,1458, 673,2135,1459,2136, 152,1137,2137,2138,2139,2140,1005,1138,1460,1139, +2141,2142,2143,2144, 11, 374, 844,2145, 154,1232, 46,1461,2146, 838, 830, 721, +1233, 106,2147, 90, 428, 462, 578, 566,1175, 352,2148,2149, 538,1234, 124,1298, +2150,1462, 761, 565,2151, 686,2152, 649,2153, 72, 173,2154, 460, 415,2155,1463, +2156,1235, 305,2157,2158,2159,2160,2161,2162, 579,2163,2164,2165,2166,2167, 747, +2168,2169,2170,2171,1464, 669,2172,2173,2174,2175,2176,1465,2177, 23, 530, 285, +2178, 335, 729,2179, 397,2180,2181,2182,1030,2183,2184, 698,2185,2186, 325,2187, +2188, 369,2189, 799,1097,1015, 348,2190,1069, 680,2191, 851,1466,2192,2193, 10, +2194, 613, 424,2195, 979, 108, 449, 589, 27, 172, 81,1031, 80, 774, 281, 350, +1032, 525, 301, 582,1176,2196, 674,1045,2197,2198,1467, 730, 762,2199,2200,2201, +2202,1468,2203, 993,2204,2205, 266,1070, 963,1140,2206,2207,2208, 664,1098, 972, +2209,2210,2211,1177,1469,1470, 871,2212,2213,2214,2215,2216,1471,2217,2218,2219, +2220,2221,2222,2223,2224,2225,2226,2227,1472,1236,2228,2229,2230,2231,2232,2233, +2234,2235,1299,2236,2237, 200,2238, 477, 373,2239,2240, 731, 825, 777,2241,2242, +2243, 521, 486, 548,2244,2245,2246,1473,1300, 53, 549, 137, 875, 76, 158,2247, +1301,1474, 469, 396,1016, 278, 712,2248, 321, 442, 503, 767, 744, 941,1237,1178, +1475,2249, 82, 178,1141,1179, 973,2250,1302,2251, 297,2252,2253, 570,2254,2255, +2256, 18, 450, 206,2257, 290, 292,1142,2258, 511, 162, 99, 346, 164, 735,2259, +1476,1477, 4, 554, 343, 798,1099,2260,1100,2261, 43, 171,1303, 139, 215,2262, +2263, 717, 775,2264,1033, 322, 216,2265, 831,2266, 149,2267,1304,2268,2269, 702, +1238, 135, 845, 347, 309,2270, 484,2271, 878, 655, 238,1006,1478,2272, 67,2273, + 295,2274,2275, 461,2276, 478, 942, 412,2277,1034,2278,2279,2280, 265,2281, 541, +2282,2283,2284,2285,2286, 70, 852,1071,2287,2288,2289,2290, 21, 56, 509, 117, + 432,2291,2292, 331, 980, 552,1101, 148, 284, 105, 393,1180,1239, 755,2293, 187, +2294,1046,1479,2295, 340,2296, 63,1047, 230,2297,2298,1305, 763,1306, 101, 800, + 808, 494,2299,2300,2301, 903,2302, 37,1072, 14, 5,2303, 79, 675,2304, 312, +2305,2306,2307,2308,2309,1480, 6,1307,2310,2311,2312, 1, 470, 35, 24, 229, +2313, 695, 210, 86, 778, 15, 784, 592, 779, 32, 77, 855, 964,2314, 259,2315, + 501, 380,2316,2317, 83, 981, 153, 689,1308,1481,1482,1483,2318,2319, 716,1484, +2320,2321,2322,2323,2324,2325,1485,2326,2327, 128, 57, 68, 261,1048, 211, 170, +1240, 31,2328, 51, 435, 742,2329,2330,2331, 635,2332, 264, 456,2333,2334,2335, + 425,2336,1486, 143, 507, 263, 943,2337, 363, 920,1487, 256,1488,1102, 243, 601, +1489,2338,2339,2340,2341,2342,2343,2344, 861,2345,2346,2347,2348,2349,2350, 395, +2351,1490,1491, 62, 535, 166, 225,2352,2353, 668, 419,1241, 138, 604, 928,2354, +1181,2355,1492,1493,2356,2357,2358,1143,2359, 696,2360, 387, 307,1309, 682, 476, +2361,2362, 332, 12, 222, 156,2363, 232,2364, 641, 276, 656, 517,1494,1495,1035, + 416, 736,1496,2365,1017, 586,2366,2367,2368,1497,2369, 242,2370,2371,2372,1498, +2373, 965, 713,2374,2375,2376,2377, 740, 982,1499, 944,1500,1007,2378,2379,1310, +1501,2380,2381,2382, 785, 329,2383,2384,1502,2385,2386,2387, 932,2388,1503,2389, +2390,2391,2392,1242,2393,2394,2395,2396,2397, 994, 950,2398,2399,2400,2401,1504, +1311,2402,2403,2404,2405,1049, 749,2406,2407, 853, 718,1144,1312,2408,1182,1505, +2409,2410, 255, 516, 479, 564, 550, 214,1506,1507,1313, 413, 239, 444, 339,1145, +1036,1508,1509,1314,1037,1510,1315,2411,1511,2412,2413,2414, 176, 703, 497, 624, + 593, 921, 302,2415, 341, 165,1103,1512,2416,1513,2417,2418,2419, 376,2420, 700, +2421,2422,2423, 258, 768,1316,2424,1183,2425, 995, 608,2426,2427,2428,2429, 221, +2430,2431,2432,2433,2434,2435,2436,2437, 195, 323, 726, 188, 897, 983,1317, 377, + 644,1050, 879,2438, 452,2439,2440,2441,2442,2443,2444, 914,2445,2446,2447,2448, + 915, 489,2449,1514,1184,2450,2451, 515, 64, 427, 495,2452, 583,2453, 483, 485, +1038, 562, 213,1515, 748, 666,2454,2455,2456,2457, 334,2458, 780, 996,1008, 705, +1243,2459,2460,2461,2462,2463, 114,2464, 493,1146, 366, 163,1516, 961,1104,2465, + 291,2466,1318,1105,2467,1517, 365,2468, 355, 951,1244,2469,1319,2470, 631,2471, +2472, 218,1320, 364, 320, 756,1518,1519,1321,1520,1322,2473,2474,2475,2476, 997, +2477,2478,2479,2480, 665,1185,2481, 916,1521,2482,2483,2484, 584, 684,2485,2486, + 797,2487,1051,1186,2488,2489,2490,1522,2491,2492, 370,2493,1039,1187, 65,2494, + 434, 205, 463,1188,2495, 125, 812, 391, 402, 826, 699, 286, 398, 155, 781, 771, + 585,2496, 590, 505,1073,2497, 599, 244, 219, 917,1018, 952, 646,1523,2498,1323, +2499,2500, 49, 984, 354, 741,2501, 625,2502,1324,2503,1019, 190, 357, 757, 491, + 95, 782, 868,2504,2505,2506,2507,2508,2509, 134,1524,1074, 422,1525, 898,2510, + 161,2511,2512,2513,2514, 769,2515,1526,2516,2517, 411,1325,2518, 472,1527,2519, +2520,2521,2522,2523,2524, 985,2525,2526,2527,2528,2529,2530, 764,2531,1245,2532, +2533, 25, 204, 311,2534, 496,2535,1052,2536,2537,2538,2539,2540,2541,2542, 199, + 704, 504, 468, 758, 657,1528, 196, 44, 839,1246, 272, 750,2543, 765, 862,2544, +2545,1326,2546, 132, 615, 933,2547, 732,2548,2549,2550,1189,1529,2551, 283,1247, +1053, 607, 929,2552,2553,2554, 930, 183, 872, 616,1040,1147,2555,1148,1020, 441, + 249,1075,2556,2557,2558, 466, 743,2559,2560,2561, 92, 514, 426, 420, 526,2562, +2563,2564,2565,2566,2567,2568, 185,2569,2570,2571,2572, 776,1530, 658,2573, 362, +2574, 361, 922,1076, 793,2575,2576,2577,2578,2579,2580,1531, 251,2581,2582,2583, +2584,1532, 54, 612, 237,1327,2585,2586, 275, 408, 647, 111,2587,1533,1106, 465, + 3, 458, 9, 38,2588, 107, 110, 890, 209, 26, 737, 498,2589,1534,2590, 431, + 202, 88,1535, 356, 287,1107, 660,1149,2591, 381,1536, 986,1150, 445,1248,1151, + 974,2592,2593, 846,2594, 446, 953, 184,1249,1250, 727,2595, 923, 193, 883,2596, +2597,2598, 102, 324, 539, 817,2599, 421,1041,2600, 832,2601, 94, 175, 197, 406, +2602, 459,2603,2604,2605,2606,2607, 330, 555,2608,2609,2610, 706,1108, 389,2611, +2612,2613,2614, 233,2615, 833, 558, 931, 954,1251,2616,2617,1537, 546,2618,2619, +1009,2620,2621,2622,1538, 690,1328,2623, 955,2624,1539,2625,2626, 772,2627,2628, +2629,2630,2631, 924, 648, 863, 603,2632,2633, 934,1540, 864, 865,2634, 642,1042, + 670,1190,2635,2636,2637,2638, 168,2639, 652, 873, 542,1054,1541,2640,2641,2642, # 512, 256 +) + diff --git a/flex/lib/python3.6/site-packages/chardet/euckrprober.py b/flex/lib/python3.6/site-packages/chardet/euckrprober.py new file mode 100644 index 0000000..345a060 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/euckrprober.py @@ -0,0 +1,47 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCKRDistributionAnalysis +from .mbcssm import EUCKR_SM_MODEL + + +class EUCKRProber(MultiByteCharSetProber): + def __init__(self): + super(EUCKRProber, self).__init__() + self.coding_sm = CodingStateMachine(EUCKR_SM_MODEL) + self.distribution_analyzer = EUCKRDistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "EUC-KR" + + @property + def language(self): + return "Korean" diff --git a/flex/lib/python3.6/site-packages/chardet/euctwfreq.py b/flex/lib/python3.6/site-packages/chardet/euctwfreq.py new file mode 100644 index 0000000..ed7a995 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/euctwfreq.py @@ -0,0 +1,387 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# EUCTW frequency table +# Converted from big5 work +# by Taiwan's Mandarin Promotion Council +# + +# 128 --> 0.42261 +# 256 --> 0.57851 +# 512 --> 0.74851 +# 1024 --> 0.89384 +# 2048 --> 0.97583 +# +# Idea Distribution Ratio = 0.74851/(1-0.74851) =2.98 +# Random Distribution Ration = 512/(5401-512)=0.105 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR + +EUCTW_TYPICAL_DISTRIBUTION_RATIO = 0.75 + +# Char to FreqOrder table , +EUCTW_TABLE_SIZE = 5376 + +EUCTW_CHAR_TO_FREQ_ORDER = ( + 1,1800,1506, 255,1431, 198, 9, 82, 6,7310, 177, 202,3615,1256,2808, 110, # 2742 +3735, 33,3241, 261, 76, 44,2113, 16,2931,2184,1176, 659,3868, 26,3404,2643, # 2758 +1198,3869,3313,4060, 410,2211, 302, 590, 361,1963, 8, 204, 58,4296,7311,1931, # 2774 + 63,7312,7313, 317,1614, 75, 222, 159,4061,2412,1480,7314,3500,3068, 224,2809, # 2790 +3616, 3, 10,3870,1471, 29,2774,1135,2852,1939, 873, 130,3242,1123, 312,7315, # 2806 +4297,2051, 507, 252, 682,7316, 142,1914, 124, 206,2932, 34,3501,3173, 64, 604, # 2822 +7317,2494,1976,1977, 155,1990, 645, 641,1606,7318,3405, 337, 72, 406,7319, 80, # 2838 + 630, 238,3174,1509, 263, 939,1092,2644, 756,1440,1094,3406, 449, 69,2969, 591, # 2854 + 179,2095, 471, 115,2034,1843, 60, 50,2970, 134, 806,1868, 734,2035,3407, 180, # 2870 + 995,1607, 156, 537,2893, 688,7320, 319,1305, 779,2144, 514,2374, 298,4298, 359, # 2886 +2495, 90,2707,1338, 663, 11, 906,1099,2545, 20,2436, 182, 532,1716,7321, 732, # 2902 +1376,4062,1311,1420,3175, 25,2312,1056, 113, 399, 382,1949, 242,3408,2467, 529, # 2918 +3243, 475,1447,3617,7322, 117, 21, 656, 810,1297,2295,2329,3502,7323, 126,4063, # 2934 + 706, 456, 150, 613,4299, 71,1118,2036,4064, 145,3069, 85, 835, 486,2114,1246, # 2950 +1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,7324,2127,2354, 347,3736, 221, # 2966 +3503,3110,7325,1955,1153,4065, 83, 296,1199,3070, 192, 624, 93,7326, 822,1897, # 2982 +2810,3111, 795,2064, 991,1554,1542,1592, 27, 43,2853, 859, 139,1456, 860,4300, # 2998 + 437, 712,3871, 164,2392,3112, 695, 211,3017,2096, 195,3872,1608,3504,3505,3618, # 3014 +3873, 234, 811,2971,2097,3874,2229,1441,3506,1615,2375, 668,2076,1638, 305, 228, # 3030 +1664,4301, 467, 415,7327, 262,2098,1593, 239, 108, 300, 200,1033, 512,1247,2077, # 3046 +7328,7329,2173,3176,3619,2673, 593, 845,1062,3244, 88,1723,2037,3875,1950, 212, # 3062 + 266, 152, 149, 468,1898,4066,4302, 77, 187,7330,3018, 37, 5,2972,7331,3876, # 3078 +7332,7333, 39,2517,4303,2894,3177,2078, 55, 148, 74,4304, 545, 483,1474,1029, # 3094 +1665, 217,1869,1531,3113,1104,2645,4067, 24, 172,3507, 900,3877,3508,3509,4305, # 3110 + 32,1408,2811,1312, 329, 487,2355,2247,2708, 784,2674, 4,3019,3314,1427,1788, # 3126 + 188, 109, 499,7334,3620,1717,1789, 888,1217,3020,4306,7335,3510,7336,3315,1520, # 3142 +3621,3878, 196,1034, 775,7337,7338, 929,1815, 249, 439, 38,7339,1063,7340, 794, # 3158 +3879,1435,2296, 46, 178,3245,2065,7341,2376,7342, 214,1709,4307, 804, 35, 707, # 3174 + 324,3622,1601,2546, 140, 459,4068,7343,7344,1365, 839, 272, 978,2257,2572,3409, # 3190 +2128,1363,3623,1423, 697, 100,3071, 48, 70,1231, 495,3114,2193,7345,1294,7346, # 3206 +2079, 462, 586,1042,3246, 853, 256, 988, 185,2377,3410,1698, 434,1084,7347,3411, # 3222 + 314,2615,2775,4308,2330,2331, 569,2280, 637,1816,2518, 757,1162,1878,1616,3412, # 3238 + 287,1577,2115, 768,4309,1671,2854,3511,2519,1321,3737, 909,2413,7348,4069, 933, # 3254 +3738,7349,2052,2356,1222,4310, 765,2414,1322, 786,4311,7350,1919,1462,1677,2895, # 3270 +1699,7351,4312,1424,2437,3115,3624,2590,3316,1774,1940,3413,3880,4070, 309,1369, # 3286 +1130,2812, 364,2230,1653,1299,3881,3512,3882,3883,2646, 525,1085,3021, 902,2000, # 3302 +1475, 964,4313, 421,1844,1415,1057,2281, 940,1364,3116, 376,4314,4315,1381, 7, # 3318 +2520, 983,2378, 336,1710,2675,1845, 321,3414, 559,1131,3022,2742,1808,1132,1313, # 3334 + 265,1481,1857,7352, 352,1203,2813,3247, 167,1089, 420,2814, 776, 792,1724,3513, # 3350 +4071,2438,3248,7353,4072,7354, 446, 229, 333,2743, 901,3739,1200,1557,4316,2647, # 3366 +1920, 395,2744,2676,3740,4073,1835, 125, 916,3178,2616,4317,7355,7356,3741,7357, # 3382 +7358,7359,4318,3117,3625,1133,2547,1757,3415,1510,2313,1409,3514,7360,2145, 438, # 3398 +2591,2896,2379,3317,1068, 958,3023, 461, 311,2855,2677,4074,1915,3179,4075,1978, # 3414 + 383, 750,2745,2617,4076, 274, 539, 385,1278,1442,7361,1154,1964, 384, 561, 210, # 3430 + 98,1295,2548,3515,7362,1711,2415,1482,3416,3884,2897,1257, 129,7363,3742, 642, # 3446 + 523,2776,2777,2648,7364, 141,2231,1333, 68, 176, 441, 876, 907,4077, 603,2592, # 3462 + 710, 171,3417, 404, 549, 18,3118,2393,1410,3626,1666,7365,3516,4319,2898,4320, # 3478 +7366,2973, 368,7367, 146, 366, 99, 871,3627,1543, 748, 807,1586,1185, 22,2258, # 3494 + 379,3743,3180,7368,3181, 505,1941,2618,1991,1382,2314,7369, 380,2357, 218, 702, # 3510 +1817,1248,3418,3024,3517,3318,3249,7370,2974,3628, 930,3250,3744,7371, 59,7372, # 3526 + 585, 601,4078, 497,3419,1112,1314,4321,1801,7373,1223,1472,2174,7374, 749,1836, # 3542 + 690,1899,3745,1772,3885,1476, 429,1043,1790,2232,2116, 917,4079, 447,1086,1629, # 3558 +7375, 556,7376,7377,2020,1654, 844,1090, 105, 550, 966,1758,2815,1008,1782, 686, # 3574 +1095,7378,2282, 793,1602,7379,3518,2593,4322,4080,2933,2297,4323,3746, 980,2496, # 3590 + 544, 353, 527,4324, 908,2678,2899,7380, 381,2619,1942,1348,7381,1341,1252, 560, # 3606 +3072,7382,3420,2856,7383,2053, 973, 886,2080, 143,4325,7384,7385, 157,3886, 496, # 3622 +4081, 57, 840, 540,2038,4326,4327,3421,2117,1445, 970,2259,1748,1965,2081,4082, # 3638 +3119,1234,1775,3251,2816,3629, 773,1206,2129,1066,2039,1326,3887,1738,1725,4083, # 3654 + 279,3120, 51,1544,2594, 423,1578,2130,2066, 173,4328,1879,7386,7387,1583, 264, # 3670 + 610,3630,4329,2439, 280, 154,7388,7389,7390,1739, 338,1282,3073, 693,2857,1411, # 3686 +1074,3747,2440,7391,4330,7392,7393,1240, 952,2394,7394,2900,1538,2679, 685,1483, # 3702 +4084,2468,1436, 953,4085,2054,4331, 671,2395, 79,4086,2441,3252, 608, 567,2680, # 3718 +3422,4087,4088,1691, 393,1261,1791,2396,7395,4332,7396,7397,7398,7399,1383,1672, # 3734 +3748,3182,1464, 522,1119, 661,1150, 216, 675,4333,3888,1432,3519, 609,4334,2681, # 3750 +2397,7400,7401,7402,4089,3025, 0,7403,2469, 315, 231,2442, 301,3319,4335,2380, # 3766 +7404, 233,4090,3631,1818,4336,4337,7405, 96,1776,1315,2082,7406, 257,7407,1809, # 3782 +3632,2709,1139,1819,4091,2021,1124,2163,2778,1777,2649,7408,3074, 363,1655,3183, # 3798 +7409,2975,7410,7411,7412,3889,1567,3890, 718, 103,3184, 849,1443, 341,3320,2934, # 3814 +1484,7413,1712, 127, 67, 339,4092,2398, 679,1412, 821,7414,7415, 834, 738, 351, # 3830 +2976,2146, 846, 235,1497,1880, 418,1992,3749,2710, 186,1100,2147,2746,3520,1545, # 3846 +1355,2935,2858,1377, 583,3891,4093,2573,2977,7416,1298,3633,1078,2549,3634,2358, # 3862 + 78,3750,3751, 267,1289,2099,2001,1594,4094, 348, 369,1274,2194,2175,1837,4338, # 3878 +1820,2817,3635,2747,2283,2002,4339,2936,2748, 144,3321, 882,4340,3892,2749,3423, # 3894 +4341,2901,7417,4095,1726, 320,7418,3893,3026, 788,2978,7419,2818,1773,1327,2859, # 3910 +3894,2819,7420,1306,4342,2003,1700,3752,3521,2359,2650, 787,2022, 506, 824,3636, # 3926 + 534, 323,4343,1044,3322,2023,1900, 946,3424,7421,1778,1500,1678,7422,1881,4344, # 3942 + 165, 243,4345,3637,2521, 123, 683,4096, 764,4346, 36,3895,1792, 589,2902, 816, # 3958 + 626,1667,3027,2233,1639,1555,1622,3753,3896,7423,3897,2860,1370,1228,1932, 891, # 3974 +2083,2903, 304,4097,7424, 292,2979,2711,3522, 691,2100,4098,1115,4347, 118, 662, # 3990 +7425, 611,1156, 854,2381,1316,2861, 2, 386, 515,2904,7426,7427,3253, 868,2234, # 4006 +1486, 855,2651, 785,2212,3028,7428,1040,3185,3523,7429,3121, 448,7430,1525,7431, # 4022 +2164,4348,7432,3754,7433,4099,2820,3524,3122, 503, 818,3898,3123,1568, 814, 676, # 4038 +1444, 306,1749,7434,3755,1416,1030, 197,1428, 805,2821,1501,4349,7435,7436,7437, # 4054 +1993,7438,4350,7439,7440,2195, 13,2779,3638,2980,3124,1229,1916,7441,3756,2131, # 4070 +7442,4100,4351,2399,3525,7443,2213,1511,1727,1120,7444,7445, 646,3757,2443, 307, # 4086 +7446,7447,1595,3186,7448,7449,7450,3639,1113,1356,3899,1465,2522,2523,7451, 519, # 4102 +7452, 128,2132, 92,2284,1979,7453,3900,1512, 342,3125,2196,7454,2780,2214,1980, # 4118 +3323,7455, 290,1656,1317, 789, 827,2360,7456,3758,4352, 562, 581,3901,7457, 401, # 4134 +4353,2248, 94,4354,1399,2781,7458,1463,2024,4355,3187,1943,7459, 828,1105,4101, # 4150 +1262,1394,7460,4102, 605,4356,7461,1783,2862,7462,2822, 819,2101, 578,2197,2937, # 4166 +7463,1502, 436,3254,4103,3255,2823,3902,2905,3425,3426,7464,2712,2315,7465,7466, # 4182 +2332,2067, 23,4357, 193, 826,3759,2102, 699,1630,4104,3075, 390,1793,1064,3526, # 4198 +7467,1579,3076,3077,1400,7468,4105,1838,1640,2863,7469,4358,4359, 137,4106, 598, # 4214 +3078,1966, 780, 104, 974,2938,7470, 278, 899, 253, 402, 572, 504, 493,1339,7471, # 4230 +3903,1275,4360,2574,2550,7472,3640,3029,3079,2249, 565,1334,2713, 863, 41,7473, # 4246 +7474,4361,7475,1657,2333, 19, 463,2750,4107, 606,7476,2981,3256,1087,2084,1323, # 4262 +2652,2982,7477,1631,1623,1750,4108,2682,7478,2864, 791,2714,2653,2334, 232,2416, # 4278 +7479,2983,1498,7480,2654,2620, 755,1366,3641,3257,3126,2025,1609, 119,1917,3427, # 4294 + 862,1026,4109,7481,3904,3760,4362,3905,4363,2260,1951,2470,7482,1125, 817,4110, # 4310 +4111,3906,1513,1766,2040,1487,4112,3030,3258,2824,3761,3127,7483,7484,1507,7485, # 4326 +2683, 733, 40,1632,1106,2865, 345,4113, 841,2524, 230,4364,2984,1846,3259,3428, # 4342 +7486,1263, 986,3429,7487, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562,3907, # 4358 +3908,2939, 967,2751,2655,1349, 592,2133,1692,3324,2985,1994,4114,1679,3909,1901, # 4374 +2185,7488, 739,3642,2715,1296,1290,7489,4115,2198,2199,1921,1563,2595,2551,1870, # 4390 +2752,2986,7490, 435,7491, 343,1108, 596, 17,1751,4365,2235,3430,3643,7492,4366, # 4406 + 294,3527,2940,1693, 477, 979, 281,2041,3528, 643,2042,3644,2621,2782,2261,1031, # 4422 +2335,2134,2298,3529,4367, 367,1249,2552,7493,3530,7494,4368,1283,3325,2004, 240, # 4438 +1762,3326,4369,4370, 836,1069,3128, 474,7495,2148,2525, 268,3531,7496,3188,1521, # 4454 +1284,7497,1658,1546,4116,7498,3532,3533,7499,4117,3327,2684,1685,4118, 961,1673, # 4470 +2622, 190,2005,2200,3762,4371,4372,7500, 570,2497,3645,1490,7501,4373,2623,3260, # 4486 +1956,4374, 584,1514, 396,1045,1944,7502,4375,1967,2444,7503,7504,4376,3910, 619, # 4502 +7505,3129,3261, 215,2006,2783,2553,3189,4377,3190,4378, 763,4119,3763,4379,7506, # 4518 +7507,1957,1767,2941,3328,3646,1174, 452,1477,4380,3329,3130,7508,2825,1253,2382, # 4534 +2186,1091,2285,4120, 492,7509, 638,1169,1824,2135,1752,3911, 648, 926,1021,1324, # 4550 +4381, 520,4382, 997, 847,1007, 892,4383,3764,2262,1871,3647,7510,2400,1784,4384, # 4566 +1952,2942,3080,3191,1728,4121,2043,3648,4385,2007,1701,3131,1551, 30,2263,4122, # 4582 +7511,2026,4386,3534,7512, 501,7513,4123, 594,3431,2165,1821,3535,3432,3536,3192, # 4598 + 829,2826,4124,7514,1680,3132,1225,4125,7515,3262,4387,4126,3133,2336,7516,4388, # 4614 +4127,7517,3912,3913,7518,1847,2383,2596,3330,7519,4389, 374,3914, 652,4128,4129, # 4630 + 375,1140, 798,7520,7521,7522,2361,4390,2264, 546,1659, 138,3031,2445,4391,7523, # 4646 +2250, 612,1848, 910, 796,3765,1740,1371, 825,3766,3767,7524,2906,2554,7525, 692, # 4662 + 444,3032,2624, 801,4392,4130,7526,1491, 244,1053,3033,4131,4132, 340,7527,3915, # 4678 +1041,2987, 293,1168, 87,1357,7528,1539, 959,7529,2236, 721, 694,4133,3768, 219, # 4694 +1478, 644,1417,3331,2656,1413,1401,1335,1389,3916,7530,7531,2988,2362,3134,1825, # 4710 + 730,1515, 184,2827, 66,4393,7532,1660,2943, 246,3332, 378,1457, 226,3433, 975, # 4726 +3917,2944,1264,3537, 674, 696,7533, 163,7534,1141,2417,2166, 713,3538,3333,4394, # 4742 +3918,7535,7536,1186, 15,7537,1079,1070,7538,1522,3193,3539, 276,1050,2716, 758, # 4758 +1126, 653,2945,3263,7539,2337, 889,3540,3919,3081,2989, 903,1250,4395,3920,3434, # 4774 +3541,1342,1681,1718, 766,3264, 286, 89,2946,3649,7540,1713,7541,2597,3334,2990, # 4790 +7542,2947,2215,3194,2866,7543,4396,2498,2526, 181, 387,1075,3921, 731,2187,3335, # 4806 +7544,3265, 310, 313,3435,2299, 770,4134, 54,3034, 189,4397,3082,3769,3922,7545, # 4822 +1230,1617,1849, 355,3542,4135,4398,3336, 111,4136,3650,1350,3135,3436,3035,4137, # 4838 +2149,3266,3543,7546,2784,3923,3924,2991, 722,2008,7547,1071, 247,1207,2338,2471, # 4854 +1378,4399,2009, 864,1437,1214,4400, 373,3770,1142,2216, 667,4401, 442,2753,2555, # 4870 +3771,3925,1968,4138,3267,1839, 837, 170,1107, 934,1336,1882,7548,7549,2118,4139, # 4886 +2828, 743,1569,7550,4402,4140, 582,2384,1418,3437,7551,1802,7552, 357,1395,1729, # 4902 +3651,3268,2418,1564,2237,7553,3083,3772,1633,4403,1114,2085,4141,1532,7554, 482, # 4918 +2446,4404,7555,7556,1492, 833,1466,7557,2717,3544,1641,2829,7558,1526,1272,3652, # 4934 +4142,1686,1794, 416,2556,1902,1953,1803,7559,3773,2785,3774,1159,2316,7560,2867, # 4950 +4405,1610,1584,3036,2419,2754, 443,3269,1163,3136,7561,7562,3926,7563,4143,2499, # 4966 +3037,4406,3927,3137,2103,1647,3545,2010,1872,4144,7564,4145, 431,3438,7565, 250, # 4982 + 97, 81,4146,7566,1648,1850,1558, 160, 848,7567, 866, 740,1694,7568,2201,2830, # 4998 +3195,4147,4407,3653,1687, 950,2472, 426, 469,3196,3654,3655,3928,7569,7570,1188, # 5014 + 424,1995, 861,3546,4148,3775,2202,2685, 168,1235,3547,4149,7571,2086,1674,4408, # 5030 +3337,3270, 220,2557,1009,7572,3776, 670,2992, 332,1208, 717,7573,7574,3548,2447, # 5046 +3929,3338,7575, 513,7576,1209,2868,3339,3138,4409,1080,7577,7578,7579,7580,2527, # 5062 +3656,3549, 815,1587,3930,3931,7581,3550,3439,3777,1254,4410,1328,3038,1390,3932, # 5078 +1741,3933,3778,3934,7582, 236,3779,2448,3271,7583,7584,3657,3780,1273,3781,4411, # 5094 +7585, 308,7586,4412, 245,4413,1851,2473,1307,2575, 430, 715,2136,2449,7587, 270, # 5110 + 199,2869,3935,7588,3551,2718,1753, 761,1754, 725,1661,1840,4414,3440,3658,7589, # 5126 +7590, 587, 14,3272, 227,2598, 326, 480,2265, 943,2755,3552, 291, 650,1883,7591, # 5142 +1702,1226, 102,1547, 62,3441, 904,4415,3442,1164,4150,7592,7593,1224,1548,2756, # 5158 + 391, 498,1493,7594,1386,1419,7595,2055,1177,4416, 813, 880,1081,2363, 566,1145, # 5174 +4417,2286,1001,1035,2558,2599,2238, 394,1286,7596,7597,2068,7598, 86,1494,1730, # 5190 +3936, 491,1588, 745, 897,2948, 843,3340,3937,2757,2870,3273,1768, 998,2217,2069, # 5206 + 397,1826,1195,1969,3659,2993,3341, 284,7599,3782,2500,2137,2119,1903,7600,3938, # 5222 +2150,3939,4151,1036,3443,1904, 114,2559,4152, 209,1527,7601,7602,2949,2831,2625, # 5238 +2385,2719,3139, 812,2560,7603,3274,7604,1559, 737,1884,3660,1210, 885, 28,2686, # 5254 +3553,3783,7605,4153,1004,1779,4418,7606, 346,1981,2218,2687,4419,3784,1742, 797, # 5270 +1642,3940,1933,1072,1384,2151, 896,3941,3275,3661,3197,2871,3554,7607,2561,1958, # 5286 +4420,2450,1785,7608,7609,7610,3942,4154,1005,1308,3662,4155,2720,4421,4422,1528, # 5302 +2600, 161,1178,4156,1982, 987,4423,1101,4157, 631,3943,1157,3198,2420,1343,1241, # 5318 +1016,2239,2562, 372, 877,2339,2501,1160, 555,1934, 911,3944,7611, 466,1170, 169, # 5334 +1051,2907,2688,3663,2474,2994,1182,2011,2563,1251,2626,7612, 992,2340,3444,1540, # 5350 +2721,1201,2070,2401,1996,2475,7613,4424, 528,1922,2188,1503,1873,1570,2364,3342, # 5366 +3276,7614, 557,1073,7615,1827,3445,2087,2266,3140,3039,3084, 767,3085,2786,4425, # 5382 +1006,4158,4426,2341,1267,2176,3664,3199, 778,3945,3200,2722,1597,2657,7616,4427, # 5398 +7617,3446,7618,7619,7620,3277,2689,1433,3278, 131, 95,1504,3946, 723,4159,3141, # 5414 +1841,3555,2758,2189,3947,2027,2104,3665,7621,2995,3948,1218,7622,3343,3201,3949, # 5430 +4160,2576, 248,1634,3785, 912,7623,2832,3666,3040,3786, 654, 53,7624,2996,7625, # 5446 +1688,4428, 777,3447,1032,3950,1425,7626, 191, 820,2120,2833, 971,4429, 931,3202, # 5462 + 135, 664, 783,3787,1997, 772,2908,1935,3951,3788,4430,2909,3203, 282,2723, 640, # 5478 +1372,3448,1127, 922, 325,3344,7627,7628, 711,2044,7629,7630,3952,2219,2787,1936, # 5494 +3953,3345,2220,2251,3789,2300,7631,4431,3790,1258,3279,3954,3204,2138,2950,3955, # 5510 +3956,7632,2221, 258,3205,4432, 101,1227,7633,3280,1755,7634,1391,3281,7635,2910, # 5526 +2056, 893,7636,7637,7638,1402,4161,2342,7639,7640,3206,3556,7641,7642, 878,1325, # 5542 +1780,2788,4433, 259,1385,2577, 744,1183,2267,4434,7643,3957,2502,7644, 684,1024, # 5558 +4162,7645, 472,3557,3449,1165,3282,3958,3959, 322,2152, 881, 455,1695,1152,1340, # 5574 + 660, 554,2153,4435,1058,4436,4163, 830,1065,3346,3960,4437,1923,7646,1703,1918, # 5590 +7647, 932,2268, 122,7648,4438, 947, 677,7649,3791,2627, 297,1905,1924,2269,4439, # 5606 +2317,3283,7650,7651,4164,7652,4165, 84,4166, 112, 989,7653, 547,1059,3961, 701, # 5622 +3558,1019,7654,4167,7655,3450, 942, 639, 457,2301,2451, 993,2951, 407, 851, 494, # 5638 +4440,3347, 927,7656,1237,7657,2421,3348, 573,4168, 680, 921,2911,1279,1874, 285, # 5654 + 790,1448,1983, 719,2167,7658,7659,4441,3962,3963,1649,7660,1541, 563,7661,1077, # 5670 +7662,3349,3041,3451, 511,2997,3964,3965,3667,3966,1268,2564,3350,3207,4442,4443, # 5686 +7663, 535,1048,1276,1189,2912,2028,3142,1438,1373,2834,2952,1134,2012,7664,4169, # 5702 +1238,2578,3086,1259,7665, 700,7666,2953,3143,3668,4170,7667,4171,1146,1875,1906, # 5718 +4444,2601,3967, 781,2422, 132,1589, 203, 147, 273,2789,2402, 898,1786,2154,3968, # 5734 +3969,7668,3792,2790,7669,7670,4445,4446,7671,3208,7672,1635,3793, 965,7673,1804, # 5750 +2690,1516,3559,1121,1082,1329,3284,3970,1449,3794, 65,1128,2835,2913,2759,1590, # 5766 +3795,7674,7675, 12,2658, 45, 976,2579,3144,4447, 517,2528,1013,1037,3209,7676, # 5782 +3796,2836,7677,3797,7678,3452,7679,2602, 614,1998,2318,3798,3087,2724,2628,7680, # 5798 +2580,4172, 599,1269,7681,1810,3669,7682,2691,3088, 759,1060, 489,1805,3351,3285, # 5814 +1358,7683,7684,2386,1387,1215,2629,2252, 490,7685,7686,4173,1759,2387,2343,7687, # 5830 +4448,3799,1907,3971,2630,1806,3210,4449,3453,3286,2760,2344, 874,7688,7689,3454, # 5846 +3670,1858, 91,2914,3671,3042,3800,4450,7690,3145,3972,2659,7691,3455,1202,1403, # 5862 +3801,2954,2529,1517,2503,4451,3456,2504,7692,4452,7693,2692,1885,1495,1731,3973, # 5878 +2365,4453,7694,2029,7695,7696,3974,2693,1216, 237,2581,4174,2319,3975,3802,4454, # 5894 +4455,2694,3560,3457, 445,4456,7697,7698,7699,7700,2761, 61,3976,3672,1822,3977, # 5910 +7701, 687,2045, 935, 925, 405,2660, 703,1096,1859,2725,4457,3978,1876,1367,2695, # 5926 +3352, 918,2105,1781,2476, 334,3287,1611,1093,4458, 564,3146,3458,3673,3353, 945, # 5942 +2631,2057,4459,7702,1925, 872,4175,7703,3459,2696,3089, 349,4176,3674,3979,4460, # 5958 +3803,4177,3675,2155,3980,4461,4462,4178,4463,2403,2046, 782,3981, 400, 251,4179, # 5974 +1624,7704,7705, 277,3676, 299,1265, 476,1191,3804,2121,4180,4181,1109, 205,7706, # 5990 +2582,1000,2156,3561,1860,7707,7708,7709,4464,7710,4465,2565, 107,2477,2157,3982, # 6006 +3460,3147,7711,1533, 541,1301, 158, 753,4182,2872,3562,7712,1696, 370,1088,4183, # 6022 +4466,3563, 579, 327, 440, 162,2240, 269,1937,1374,3461, 968,3043, 56,1396,3090, # 6038 +2106,3288,3354,7713,1926,2158,4467,2998,7714,3564,7715,7716,3677,4468,2478,7717, # 6054 +2791,7718,1650,4469,7719,2603,7720,7721,3983,2661,3355,1149,3356,3984,3805,3985, # 6070 +7722,1076, 49,7723, 951,3211,3289,3290, 450,2837, 920,7724,1811,2792,2366,4184, # 6086 +1908,1138,2367,3806,3462,7725,3212,4470,1909,1147,1518,2423,4471,3807,7726,4472, # 6102 +2388,2604, 260,1795,3213,7727,7728,3808,3291, 708,7729,3565,1704,7730,3566,1351, # 6118 +1618,3357,2999,1886, 944,4185,3358,4186,3044,3359,4187,7731,3678, 422, 413,1714, # 6134 +3292, 500,2058,2345,4188,2479,7732,1344,1910, 954,7733,1668,7734,7735,3986,2404, # 6150 +4189,3567,3809,4190,7736,2302,1318,2505,3091, 133,3092,2873,4473, 629, 31,2838, # 6166 +2697,3810,4474, 850, 949,4475,3987,2955,1732,2088,4191,1496,1852,7737,3988, 620, # 6182 +3214, 981,1242,3679,3360,1619,3680,1643,3293,2139,2452,1970,1719,3463,2168,7738, # 6198 +3215,7739,7740,3361,1828,7741,1277,4476,1565,2047,7742,1636,3568,3093,7743, 869, # 6214 +2839, 655,3811,3812,3094,3989,3000,3813,1310,3569,4477,7744,7745,7746,1733, 558, # 6230 +4478,3681, 335,1549,3045,1756,4192,3682,1945,3464,1829,1291,1192, 470,2726,2107, # 6246 +2793, 913,1054,3990,7747,1027,7748,3046,3991,4479, 982,2662,3362,3148,3465,3216, # 6262 +3217,1946,2794,7749, 571,4480,7750,1830,7751,3570,2583,1523,2424,7752,2089, 984, # 6278 +4481,3683,1959,7753,3684, 852, 923,2795,3466,3685, 969,1519, 999,2048,2320,1705, # 6294 +7754,3095, 615,1662, 151, 597,3992,2405,2321,1049, 275,4482,3686,4193, 568,3687, # 6310 +3571,2480,4194,3688,7755,2425,2270, 409,3218,7756,1566,2874,3467,1002, 769,2840, # 6326 + 194,2090,3149,3689,2222,3294,4195, 628,1505,7757,7758,1763,2177,3001,3993, 521, # 6342 +1161,2584,1787,2203,2406,4483,3994,1625,4196,4197, 412, 42,3096, 464,7759,2632, # 6358 +4484,3363,1760,1571,2875,3468,2530,1219,2204,3814,2633,2140,2368,4485,4486,3295, # 6374 +1651,3364,3572,7760,7761,3573,2481,3469,7762,3690,7763,7764,2271,2091, 460,7765, # 6390 +4487,7766,3002, 962, 588,3574, 289,3219,2634,1116, 52,7767,3047,1796,7768,7769, # 6406 +7770,1467,7771,1598,1143,3691,4198,1984,1734,1067,4488,1280,3365, 465,4489,1572, # 6422 + 510,7772,1927,2241,1812,1644,3575,7773,4490,3692,7774,7775,2663,1573,1534,7776, # 6438 +7777,4199, 536,1807,1761,3470,3815,3150,2635,7778,7779,7780,4491,3471,2915,1911, # 6454 +2796,7781,3296,1122, 377,3220,7782, 360,7783,7784,4200,1529, 551,7785,2059,3693, # 6470 +1769,2426,7786,2916,4201,3297,3097,2322,2108,2030,4492,1404, 136,1468,1479, 672, # 6486 +1171,3221,2303, 271,3151,7787,2762,7788,2049, 678,2727, 865,1947,4493,7789,2013, # 6502 +3995,2956,7790,2728,2223,1397,3048,3694,4494,4495,1735,2917,3366,3576,7791,3816, # 6518 + 509,2841,2453,2876,3817,7792,7793,3152,3153,4496,4202,2531,4497,2304,1166,1010, # 6534 + 552, 681,1887,7794,7795,2957,2958,3996,1287,1596,1861,3154, 358, 453, 736, 175, # 6550 + 478,1117, 905,1167,1097,7796,1853,1530,7797,1706,7798,2178,3472,2287,3695,3473, # 6566 +3577,4203,2092,4204,7799,3367,1193,2482,4205,1458,2190,2205,1862,1888,1421,3298, # 6582 +2918,3049,2179,3474, 595,2122,7800,3997,7801,7802,4206,1707,2636, 223,3696,1359, # 6598 + 751,3098, 183,3475,7803,2797,3003, 419,2369, 633, 704,3818,2389, 241,7804,7805, # 6614 +7806, 838,3004,3697,2272,2763,2454,3819,1938,2050,3998,1309,3099,2242,1181,7807, # 6630 +1136,2206,3820,2370,1446,4207,2305,4498,7808,7809,4208,1055,2605, 484,3698,7810, # 6646 +3999, 625,4209,2273,3368,1499,4210,4000,7811,4001,4211,3222,2274,2275,3476,7812, # 6662 +7813,2764, 808,2606,3699,3369,4002,4212,3100,2532, 526,3370,3821,4213, 955,7814, # 6678 +1620,4214,2637,2427,7815,1429,3700,1669,1831, 994, 928,7816,3578,1260,7817,7818, # 6694 +7819,1948,2288, 741,2919,1626,4215,2729,2455, 867,1184, 362,3371,1392,7820,7821, # 6710 +4003,4216,1770,1736,3223,2920,4499,4500,1928,2698,1459,1158,7822,3050,3372,2877, # 6726 +1292,1929,2506,2842,3701,1985,1187,2071,2014,2607,4217,7823,2566,2507,2169,3702, # 6742 +2483,3299,7824,3703,4501,7825,7826, 666,1003,3005,1022,3579,4218,7827,4502,1813, # 6758 +2253, 574,3822,1603, 295,1535, 705,3823,4219, 283, 858, 417,7828,7829,3224,4503, # 6774 +4504,3051,1220,1889,1046,2276,2456,4004,1393,1599, 689,2567, 388,4220,7830,2484, # 6790 + 802,7831,2798,3824,2060,1405,2254,7832,4505,3825,2109,1052,1345,3225,1585,7833, # 6806 + 809,7834,7835,7836, 575,2730,3477, 956,1552,1469,1144,2323,7837,2324,1560,2457, # 6822 +3580,3226,4005, 616,2207,3155,2180,2289,7838,1832,7839,3478,4506,7840,1319,3704, # 6838 +3705,1211,3581,1023,3227,1293,2799,7841,7842,7843,3826, 607,2306,3827, 762,2878, # 6854 +1439,4221,1360,7844,1485,3052,7845,4507,1038,4222,1450,2061,2638,4223,1379,4508, # 6870 +2585,7846,7847,4224,1352,1414,2325,2921,1172,7848,7849,3828,3829,7850,1797,1451, # 6886 +7851,7852,7853,7854,2922,4006,4007,2485,2346, 411,4008,4009,3582,3300,3101,4509, # 6902 +1561,2664,1452,4010,1375,7855,7856, 47,2959, 316,7857,1406,1591,2923,3156,7858, # 6918 +1025,2141,3102,3157, 354,2731, 884,2224,4225,2407, 508,3706, 726,3583, 996,2428, # 6934 +3584, 729,7859, 392,2191,1453,4011,4510,3707,7860,7861,2458,3585,2608,1675,2800, # 6950 + 919,2347,2960,2348,1270,4511,4012, 73,7862,7863, 647,7864,3228,2843,2255,1550, # 6966 +1346,3006,7865,1332, 883,3479,7866,7867,7868,7869,3301,2765,7870,1212, 831,1347, # 6982 +4226,4512,2326,3830,1863,3053, 720,3831,4513,4514,3832,7871,4227,7872,7873,4515, # 6998 +7874,7875,1798,4516,3708,2609,4517,3586,1645,2371,7876,7877,2924, 669,2208,2665, # 7014 +2429,7878,2879,7879,7880,1028,3229,7881,4228,2408,7882,2256,1353,7883,7884,4518, # 7030 +3158, 518,7885,4013,7886,4229,1960,7887,2142,4230,7888,7889,3007,2349,2350,3833, # 7046 + 516,1833,1454,4014,2699,4231,4519,2225,2610,1971,1129,3587,7890,2766,7891,2961, # 7062 +1422, 577,1470,3008,1524,3373,7892,7893, 432,4232,3054,3480,7894,2586,1455,2508, # 7078 +2226,1972,1175,7895,1020,2732,4015,3481,4520,7896,2733,7897,1743,1361,3055,3482, # 7094 +2639,4016,4233,4521,2290, 895, 924,4234,2170, 331,2243,3056, 166,1627,3057,1098, # 7110 +7898,1232,2880,2227,3374,4522, 657, 403,1196,2372, 542,3709,3375,1600,4235,3483, # 7126 +7899,4523,2767,3230, 576, 530,1362,7900,4524,2533,2666,3710,4017,7901, 842,3834, # 7142 +7902,2801,2031,1014,4018, 213,2700,3376, 665, 621,4236,7903,3711,2925,2430,7904, # 7158 +2431,3302,3588,3377,7905,4237,2534,4238,4525,3589,1682,4239,3484,1380,7906, 724, # 7174 +2277, 600,1670,7907,1337,1233,4526,3103,2244,7908,1621,4527,7909, 651,4240,7910, # 7190 +1612,4241,2611,7911,2844,7912,2734,2307,3058,7913, 716,2459,3059, 174,1255,2701, # 7206 +4019,3590, 548,1320,1398, 728,4020,1574,7914,1890,1197,3060,4021,7915,3061,3062, # 7222 +3712,3591,3713, 747,7916, 635,4242,4528,7917,7918,7919,4243,7920,7921,4529,7922, # 7238 +3378,4530,2432, 451,7923,3714,2535,2072,4244,2735,4245,4022,7924,1764,4531,7925, # 7254 +4246, 350,7926,2278,2390,2486,7927,4247,4023,2245,1434,4024, 488,4532, 458,4248, # 7270 +4025,3715, 771,1330,2391,3835,2568,3159,2159,2409,1553,2667,3160,4249,7928,2487, # 7286 +2881,2612,1720,2702,4250,3379,4533,7929,2536,4251,7930,3231,4252,2768,7931,2015, # 7302 +2736,7932,1155,1017,3716,3836,7933,3303,2308, 201,1864,4253,1430,7934,4026,7935, # 7318 +7936,7937,7938,7939,4254,1604,7940, 414,1865, 371,2587,4534,4535,3485,2016,3104, # 7334 +4536,1708, 960,4255, 887, 389,2171,1536,1663,1721,7941,2228,4027,2351,2926,1580, # 7350 +7942,7943,7944,1744,7945,2537,4537,4538,7946,4539,7947,2073,7948,7949,3592,3380, # 7366 +2882,4256,7950,4257,2640,3381,2802, 673,2703,2460, 709,3486,4028,3593,4258,7951, # 7382 +1148, 502, 634,7952,7953,1204,4540,3594,1575,4541,2613,3717,7954,3718,3105, 948, # 7398 +3232, 121,1745,3837,1110,7955,4259,3063,2509,3009,4029,3719,1151,1771,3838,1488, # 7414 +4030,1986,7956,2433,3487,7957,7958,2093,7959,4260,3839,1213,1407,2803, 531,2737, # 7430 +2538,3233,1011,1537,7960,2769,4261,3106,1061,7961,3720,3721,1866,2883,7962,2017, # 7446 + 120,4262,4263,2062,3595,3234,2309,3840,2668,3382,1954,4542,7963,7964,3488,1047, # 7462 +2704,1266,7965,1368,4543,2845, 649,3383,3841,2539,2738,1102,2846,2669,7966,7967, # 7478 +1999,7968,1111,3596,2962,7969,2488,3842,3597,2804,1854,3384,3722,7970,7971,3385, # 7494 +2410,2884,3304,3235,3598,7972,2569,7973,3599,2805,4031,1460, 856,7974,3600,7975, # 7510 +2885,2963,7976,2886,3843,7977,4264, 632,2510, 875,3844,1697,3845,2291,7978,7979, # 7526 +4544,3010,1239, 580,4545,4265,7980, 914, 936,2074,1190,4032,1039,2123,7981,7982, # 7542 +7983,3386,1473,7984,1354,4266,3846,7985,2172,3064,4033, 915,3305,4267,4268,3306, # 7558 +1605,1834,7986,2739, 398,3601,4269,3847,4034, 328,1912,2847,4035,3848,1331,4270, # 7574 +3011, 937,4271,7987,3602,4036,4037,3387,2160,4546,3388, 524, 742, 538,3065,1012, # 7590 +7988,7989,3849,2461,7990, 658,1103, 225,3850,7991,7992,4547,7993,4548,7994,3236, # 7606 +1243,7995,4038, 963,2246,4549,7996,2705,3603,3161,7997,7998,2588,2327,7999,4550, # 7622 +8000,8001,8002,3489,3307, 957,3389,2540,2032,1930,2927,2462, 870,2018,3604,1746, # 7638 +2770,2771,2434,2463,8003,3851,8004,3723,3107,3724,3490,3390,3725,8005,1179,3066, # 7654 +8006,3162,2373,4272,3726,2541,3163,3108,2740,4039,8007,3391,1556,2542,2292, 977, # 7670 +2887,2033,4040,1205,3392,8008,1765,3393,3164,2124,1271,1689, 714,4551,3491,8009, # 7686 +2328,3852, 533,4273,3605,2181, 617,8010,2464,3308,3492,2310,8011,8012,3165,8013, # 7702 +8014,3853,1987, 618, 427,2641,3493,3394,8015,8016,1244,1690,8017,2806,4274,4552, # 7718 +8018,3494,8019,8020,2279,1576, 473,3606,4275,3395, 972,8021,3607,8022,3067,8023, # 7734 +8024,4553,4554,8025,3727,4041,4042,8026, 153,4555, 356,8027,1891,2888,4276,2143, # 7750 + 408, 803,2352,8028,3854,8029,4277,1646,2570,2511,4556,4557,3855,8030,3856,4278, # 7766 +8031,2411,3396, 752,8032,8033,1961,2964,8034, 746,3012,2465,8035,4279,3728, 698, # 7782 +4558,1892,4280,3608,2543,4559,3609,3857,8036,3166,3397,8037,1823,1302,4043,2706, # 7798 +3858,1973,4281,8038,4282,3167, 823,1303,1288,1236,2848,3495,4044,3398, 774,3859, # 7814 +8039,1581,4560,1304,2849,3860,4561,8040,2435,2161,1083,3237,4283,4045,4284, 344, # 7830 +1173, 288,2311, 454,1683,8041,8042,1461,4562,4046,2589,8043,8044,4563, 985, 894, # 7846 +8045,3399,3168,8046,1913,2928,3729,1988,8047,2110,1974,8048,4047,8049,2571,1194, # 7862 + 425,8050,4564,3169,1245,3730,4285,8051,8052,2850,8053, 636,4565,1855,3861, 760, # 7878 +1799,8054,4286,2209,1508,4566,4048,1893,1684,2293,8055,8056,8057,4287,4288,2210, # 7894 + 479,8058,8059, 832,8060,4049,2489,8061,2965,2490,3731, 990,3109, 627,1814,2642, # 7910 +4289,1582,4290,2125,2111,3496,4567,8062, 799,4291,3170,8063,4568,2112,1737,3013, # 7926 +1018, 543, 754,4292,3309,1676,4569,4570,4050,8064,1489,8065,3497,8066,2614,2889, # 7942 +4051,8067,8068,2966,8069,8070,8071,8072,3171,4571,4572,2182,1722,8073,3238,3239, # 7958 +1842,3610,1715, 481, 365,1975,1856,8074,8075,1962,2491,4573,8076,2126,3611,3240, # 7974 + 433,1894,2063,2075,8077, 602,2741,8078,8079,8080,8081,8082,3014,1628,3400,8083, # 7990 +3172,4574,4052,2890,4575,2512,8084,2544,2772,8085,8086,8087,3310,4576,2891,8088, # 8006 +4577,8089,2851,4578,4579,1221,2967,4053,2513,8090,8091,8092,1867,1989,8093,8094, # 8022 +8095,1895,8096,8097,4580,1896,4054, 318,8098,2094,4055,4293,8099,8100, 485,8101, # 8038 + 938,3862, 553,2670, 116,8102,3863,3612,8103,3498,2671,2773,3401,3311,2807,8104, # 8054 +3613,2929,4056,1747,2930,2968,8105,8106, 207,8107,8108,2672,4581,2514,8109,3015, # 8070 + 890,3614,3864,8110,1877,3732,3402,8111,2183,2353,3403,1652,8112,8113,8114, 941, # 8086 +2294, 208,3499,4057,2019, 330,4294,3865,2892,2492,3733,4295,8115,8116,8117,8118, # 8102 +) + diff --git a/flex/lib/python3.6/site-packages/chardet/euctwprober.py b/flex/lib/python3.6/site-packages/chardet/euctwprober.py new file mode 100644 index 0000000..35669cc --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/euctwprober.py @@ -0,0 +1,46 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCTWDistributionAnalysis +from .mbcssm import EUCTW_SM_MODEL + +class EUCTWProber(MultiByteCharSetProber): + def __init__(self): + super(EUCTWProber, self).__init__() + self.coding_sm = CodingStateMachine(EUCTW_SM_MODEL) + self.distribution_analyzer = EUCTWDistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "EUC-TW" + + @property + def language(self): + return "Taiwan" diff --git a/flex/lib/python3.6/site-packages/chardet/gb2312freq.py b/flex/lib/python3.6/site-packages/chardet/gb2312freq.py new file mode 100644 index 0000000..697837b --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/gb2312freq.py @@ -0,0 +1,283 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# GB2312 most frequently used character table +# +# Char to FreqOrder table , from hz6763 + +# 512 --> 0.79 -- 0.79 +# 1024 --> 0.92 -- 0.13 +# 2048 --> 0.98 -- 0.06 +# 6768 --> 1.00 -- 0.02 +# +# Ideal Distribution Ratio = 0.79135/(1-0.79135) = 3.79 +# Random Distribution Ration = 512 / (3755 - 512) = 0.157 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher that RDR + +GB2312_TYPICAL_DISTRIBUTION_RATIO = 0.9 + +GB2312_TABLE_SIZE = 3760 + +GB2312_CHAR_TO_FREQ_ORDER = ( +1671, 749,1443,2364,3924,3807,2330,3921,1704,3463,2691,1511,1515, 572,3191,2205, +2361, 224,2558, 479,1711, 963,3162, 440,4060,1905,2966,2947,3580,2647,3961,3842, +2204, 869,4207, 970,2678,5626,2944,2956,1479,4048, 514,3595, 588,1346,2820,3409, + 249,4088,1746,1873,2047,1774, 581,1813, 358,1174,3590,1014,1561,4844,2245, 670, +1636,3112, 889,1286, 953, 556,2327,3060,1290,3141, 613, 185,3477,1367, 850,3820, +1715,2428,2642,2303,2732,3041,2562,2648,3566,3946,1349, 388,3098,2091,1360,3585, + 152,1687,1539, 738,1559, 59,1232,2925,2267,1388,1249,1741,1679,2960, 151,1566, +1125,1352,4271, 924,4296, 385,3166,4459, 310,1245,2850, 70,3285,2729,3534,3575, +2398,3298,3466,1960,2265, 217,3647, 864,1909,2084,4401,2773,1010,3269,5152, 853, +3051,3121,1244,4251,1895, 364,1499,1540,2313,1180,3655,2268, 562, 715,2417,3061, + 544, 336,3768,2380,1752,4075, 950, 280,2425,4382, 183,2759,3272, 333,4297,2155, +1688,2356,1444,1039,4540, 736,1177,3349,2443,2368,2144,2225, 565, 196,1482,3406, + 927,1335,4147, 692, 878,1311,1653,3911,3622,1378,4200,1840,2969,3149,2126,1816, +2534,1546,2393,2760, 737,2494, 13, 447, 245,2747, 38,2765,2129,2589,1079, 606, + 360, 471,3755,2890, 404, 848, 699,1785,1236, 370,2221,1023,3746,2074,2026,2023, +2388,1581,2119, 812,1141,3091,2536,1519, 804,2053, 406,1596,1090, 784, 548,4414, +1806,2264,2936,1100, 343,4114,5096, 622,3358, 743,3668,1510,1626,5020,3567,2513, +3195,4115,5627,2489,2991, 24,2065,2697,1087,2719, 48,1634, 315, 68, 985,2052, + 198,2239,1347,1107,1439, 597,2366,2172, 871,3307, 919,2487,2790,1867, 236,2570, +1413,3794, 906,3365,3381,1701,1982,1818,1524,2924,1205, 616,2586,2072,2004, 575, + 253,3099, 32,1365,1182, 197,1714,2454,1201, 554,3388,3224,2748, 756,2587, 250, +2567,1507,1517,3529,1922,2761,2337,3416,1961,1677,2452,2238,3153, 615, 911,1506, +1474,2495,1265,1906,2749,3756,3280,2161, 898,2714,1759,3450,2243,2444, 563, 26, +3286,2266,3769,3344,2707,3677, 611,1402, 531,1028,2871,4548,1375, 261,2948, 835, +1190,4134, 353, 840,2684,1900,3082,1435,2109,1207,1674, 329,1872,2781,4055,2686, +2104, 608,3318,2423,2957,2768,1108,3739,3512,3271,3985,2203,1771,3520,1418,2054, +1681,1153, 225,1627,2929, 162,2050,2511,3687,1954, 124,1859,2431,1684,3032,2894, + 585,4805,3969,2869,2704,2088,2032,2095,3656,2635,4362,2209, 256, 518,2042,2105, +3777,3657, 643,2298,1148,1779, 190, 989,3544, 414, 11,2135,2063,2979,1471, 403, +3678, 126, 770,1563, 671,2499,3216,2877, 600,1179, 307,2805,4937,1268,1297,2694, + 252,4032,1448,1494,1331,1394, 127,2256, 222,1647,1035,1481,3056,1915,1048, 873, +3651, 210, 33,1608,2516, 200,1520, 415, 102, 0,3389,1287, 817, 91,3299,2940, + 836,1814, 549,2197,1396,1669,2987,3582,2297,2848,4528,1070, 687, 20,1819, 121, +1552,1364,1461,1968,2617,3540,2824,2083, 177, 948,4938,2291, 110,4549,2066, 648, +3359,1755,2110,2114,4642,4845,1693,3937,3308,1257,1869,2123, 208,1804,3159,2992, +2531,2549,3361,2418,1350,2347,2800,2568,1291,2036,2680, 72, 842,1990, 212,1233, +1154,1586, 75,2027,3410,4900,1823,1337,2710,2676, 728,2810,1522,3026,4995, 157, + 755,1050,4022, 710, 785,1936,2194,2085,1406,2777,2400, 150,1250,4049,1206, 807, +1910, 534, 529,3309,1721,1660, 274, 39,2827, 661,2670,1578, 925,3248,3815,1094, +4278,4901,4252, 41,1150,3747,2572,2227,4501,3658,4902,3813,3357,3617,2884,2258, + 887, 538,4187,3199,1294,2439,3042,2329,2343,2497,1255, 107, 543,1527, 521,3478, +3568, 194,5062, 15, 961,3870,1241,1192,2664, 66,5215,3260,2111,1295,1127,2152, +3805,4135, 901,1164,1976, 398,1278, 530,1460, 748, 904,1054,1966,1426, 53,2909, + 509, 523,2279,1534, 536,1019, 239,1685, 460,2353, 673,1065,2401,3600,4298,2272, +1272,2363, 284,1753,3679,4064,1695, 81, 815,2677,2757,2731,1386, 859, 500,4221, +2190,2566, 757,1006,2519,2068,1166,1455, 337,2654,3203,1863,1682,1914,3025,1252, +1409,1366, 847, 714,2834,2038,3209, 964,2970,1901, 885,2553,1078,1756,3049, 301, +1572,3326, 688,2130,1996,2429,1805,1648,2930,3421,2750,3652,3088, 262,1158,1254, + 389,1641,1812, 526,1719, 923,2073,1073,1902, 468, 489,4625,1140, 857,2375,3070, +3319,2863, 380, 116,1328,2693,1161,2244, 273,1212,1884,2769,3011,1775,1142, 461, +3066,1200,2147,2212, 790, 702,2695,4222,1601,1058, 434,2338,5153,3640, 67,2360, +4099,2502, 618,3472,1329, 416,1132, 830,2782,1807,2653,3211,3510,1662, 192,2124, + 296,3979,1739,1611,3684, 23, 118, 324, 446,1239,1225, 293,2520,3814,3795,2535, +3116, 17,1074, 467,2692,2201, 387,2922, 45,1326,3055,1645,3659,2817, 958, 243, +1903,2320,1339,2825,1784,3289, 356, 576, 865,2315,2381,3377,3916,1088,3122,1713, +1655, 935, 628,4689,1034,1327, 441, 800, 720, 894,1979,2183,1528,5289,2702,1071, +4046,3572,2399,1571,3281, 79, 761,1103, 327, 134, 758,1899,1371,1615, 879, 442, + 215,2605,2579, 173,2048,2485,1057,2975,3317,1097,2253,3801,4263,1403,1650,2946, + 814,4968,3487,1548,2644,1567,1285, 2, 295,2636, 97, 946,3576, 832, 141,4257, +3273, 760,3821,3521,3156,2607, 949,1024,1733,1516,1803,1920,2125,2283,2665,3180, +1501,2064,3560,2171,1592, 803,3518,1416, 732,3897,4258,1363,1362,2458, 119,1427, + 602,1525,2608,1605,1639,3175, 694,3064, 10, 465, 76,2000,4846,4208, 444,3781, +1619,3353,2206,1273,3796, 740,2483, 320,1723,2377,3660,2619,1359,1137,1762,1724, +2345,2842,1850,1862, 912, 821,1866, 612,2625,1735,2573,3369,1093, 844, 89, 937, + 930,1424,3564,2413,2972,1004,3046,3019,2011, 711,3171,1452,4178, 428, 801,1943, + 432, 445,2811, 206,4136,1472, 730, 349, 73, 397,2802,2547, 998,1637,1167, 789, + 396,3217, 154,1218, 716,1120,1780,2819,4826,1931,3334,3762,2139,1215,2627, 552, +3664,3628,3232,1405,2383,3111,1356,2652,3577,3320,3101,1703, 640,1045,1370,1246, +4996, 371,1575,2436,1621,2210, 984,4033,1734,2638, 16,4529, 663,2755,3255,1451, +3917,2257,1253,1955,2234,1263,2951, 214,1229, 617, 485, 359,1831,1969, 473,2310, + 750,2058, 165, 80,2864,2419, 361,4344,2416,2479,1134, 796,3726,1266,2943, 860, +2715, 938, 390,2734,1313,1384, 248, 202, 877,1064,2854, 522,3907, 279,1602, 297, +2357, 395,3740, 137,2075, 944,4089,2584,1267,3802, 62,1533,2285, 178, 176, 780, +2440, 201,3707, 590, 478,1560,4354,2117,1075, 30, 74,4643,4004,1635,1441,2745, + 776,2596, 238,1077,1692,1912,2844, 605, 499,1742,3947, 241,3053, 980,1749, 936, +2640,4511,2582, 515,1543,2162,5322,2892,2993, 890,2148,1924, 665,1827,3581,1032, + 968,3163, 339,1044,1896, 270, 583,1791,1720,4367,1194,3488,3669, 43,2523,1657, + 163,2167, 290,1209,1622,3378, 550, 634,2508,2510, 695,2634,2384,2512,1476,1414, + 220,1469,2341,2138,2852,3183,2900,4939,2865,3502,1211,3680, 854,3227,1299,2976, +3172, 186,2998,1459, 443,1067,3251,1495, 321,1932,3054, 909, 753,1410,1828, 436, +2441,1119,1587,3164,2186,1258, 227, 231,1425,1890,3200,3942, 247, 959, 725,5254, +2741, 577,2158,2079, 929, 120, 174, 838,2813, 591,1115, 417,2024, 40,3240,1536, +1037, 291,4151,2354, 632,1298,2406,2500,3535,1825,1846,3451, 205,1171, 345,4238, + 18,1163, 811, 685,2208,1217, 425,1312,1508,1175,4308,2552,1033, 587,1381,3059, +2984,3482, 340,1316,4023,3972, 792,3176, 519, 777,4690, 918, 933,4130,2981,3741, + 90,3360,2911,2200,5184,4550, 609,3079,2030, 272,3379,2736, 363,3881,1130,1447, + 286, 779, 357,1169,3350,3137,1630,1220,2687,2391, 747,1277,3688,2618,2682,2601, +1156,3196,5290,4034,3102,1689,3596,3128, 874, 219,2783, 798, 508,1843,2461, 269, +1658,1776,1392,1913,2983,3287,2866,2159,2372, 829,4076, 46,4253,2873,1889,1894, + 915,1834,1631,2181,2318, 298, 664,2818,3555,2735, 954,3228,3117, 527,3511,2173, + 681,2712,3033,2247,2346,3467,1652, 155,2164,3382, 113,1994, 450, 899, 494, 994, +1237,2958,1875,2336,1926,3727, 545,1577,1550, 633,3473, 204,1305,3072,2410,1956, +2471, 707,2134, 841,2195,2196,2663,3843,1026,4940, 990,3252,4997, 368,1092, 437, +3212,3258,1933,1829, 675,2977,2893, 412, 943,3723,4644,3294,3283,2230,2373,5154, +2389,2241,2661,2323,1404,2524, 593, 787, 677,3008,1275,2059, 438,2709,2609,2240, +2269,2246,1446, 36,1568,1373,3892,1574,2301,1456,3962, 693,2276,5216,2035,1143, +2720,1919,1797,1811,2763,4137,2597,1830,1699,1488,1198,2090, 424,1694, 312,3634, +3390,4179,3335,2252,1214, 561,1059,3243,2295,2561, 975,5155,2321,2751,3772, 472, +1537,3282,3398,1047,2077,2348,2878,1323,3340,3076, 690,2906, 51, 369, 170,3541, +1060,2187,2688,3670,2541,1083,1683, 928,3918, 459, 109,4427, 599,3744,4286, 143, +2101,2730,2490, 82,1588,3036,2121, 281,1860, 477,4035,1238,2812,3020,2716,3312, +1530,2188,2055,1317, 843, 636,1808,1173,3495, 649, 181,1002, 147,3641,1159,2414, +3750,2289,2795, 813,3123,2610,1136,4368, 5,3391,4541,2174, 420, 429,1728, 754, +1228,2115,2219, 347,2223,2733, 735,1518,3003,2355,3134,1764,3948,3329,1888,2424, +1001,1234,1972,3321,3363,1672,1021,1450,1584, 226, 765, 655,2526,3404,3244,2302, +3665, 731, 594,2184, 319,1576, 621, 658,2656,4299,2099,3864,1279,2071,2598,2739, + 795,3086,3699,3908,1707,2352,2402,1382,3136,2475,1465,4847,3496,3865,1085,3004, +2591,1084, 213,2287,1963,3565,2250, 822, 793,4574,3187,1772,1789,3050, 595,1484, +1959,2770,1080,2650, 456, 422,2996, 940,3322,4328,4345,3092,2742, 965,2784, 739, +4124, 952,1358,2498,2949,2565, 332,2698,2378, 660,2260,2473,4194,3856,2919, 535, +1260,2651,1208,1428,1300,1949,1303,2942, 433,2455,2450,1251,1946, 614,1269, 641, +1306,1810,2737,3078,2912, 564,2365,1419,1415,1497,4460,2367,2185,1379,3005,1307, +3218,2175,1897,3063, 682,1157,4040,4005,1712,1160,1941,1399, 394, 402,2952,1573, +1151,2986,2404, 862, 299,2033,1489,3006, 346, 171,2886,3401,1726,2932, 168,2533, + 47,2507,1030,3735,1145,3370,1395,1318,1579,3609,4560,2857,4116,1457,2529,1965, + 504,1036,2690,2988,2405, 745,5871, 849,2397,2056,3081, 863,2359,3857,2096, 99, +1397,1769,2300,4428,1643,3455,1978,1757,3718,1440, 35,4879,3742,1296,4228,2280, + 160,5063,1599,2013, 166, 520,3479,1646,3345,3012, 490,1937,1545,1264,2182,2505, +1096,1188,1369,1436,2421,1667,2792,2460,1270,2122, 727,3167,2143, 806,1706,1012, +1800,3037, 960,2218,1882, 805, 139,2456,1139,1521, 851,1052,3093,3089, 342,2039, + 744,5097,1468,1502,1585,2087, 223, 939, 326,2140,2577, 892,2481,1623,4077, 982, +3708, 135,2131, 87,2503,3114,2326,1106, 876,1616, 547,2997,2831,2093,3441,4530, +4314, 9,3256,4229,4148, 659,1462,1986,1710,2046,2913,2231,4090,4880,5255,3392, +3274,1368,3689,4645,1477, 705,3384,3635,1068,1529,2941,1458,3782,1509, 100,1656, +2548, 718,2339, 408,1590,2780,3548,1838,4117,3719,1345,3530, 717,3442,2778,3220, +2898,1892,4590,3614,3371,2043,1998,1224,3483, 891, 635, 584,2559,3355, 733,1766, +1729,1172,3789,1891,2307, 781,2982,2271,1957,1580,5773,2633,2005,4195,3097,1535, +3213,1189,1934,5693,3262, 586,3118,1324,1598, 517,1564,2217,1868,1893,4445,3728, +2703,3139,1526,1787,1992,3882,2875,1549,1199,1056,2224,1904,2711,5098,4287, 338, +1993,3129,3489,2689,1809,2815,1997, 957,1855,3898,2550,3275,3057,1105,1319, 627, +1505,1911,1883,3526, 698,3629,3456,1833,1431, 746, 77,1261,2017,2296,1977,1885, + 125,1334,1600, 525,1798,1109,2222,1470,1945, 559,2236,1186,3443,2476,1929,1411, +2411,3135,1777,3372,2621,1841,1613,3229, 668,1430,1839,2643,2916, 195,1989,2671, +2358,1387, 629,3205,2293,5256,4439, 123,1310, 888,1879,4300,3021,3605,1003,1162, +3192,2910,2010, 140,2395,2859, 55,1082,2012,2901, 662, 419,2081,1438, 680,2774, +4654,3912,1620,1731,1625,5035,4065,2328, 512,1344, 802,5443,2163,2311,2537, 524, +3399, 98,1155,2103,1918,2606,3925,2816,1393,2465,1504,3773,2177,3963,1478,4346, + 180,1113,4655,3461,2028,1698, 833,2696,1235,1322,1594,4408,3623,3013,3225,2040, +3022, 541,2881, 607,3632,2029,1665,1219, 639,1385,1686,1099,2803,3231,1938,3188, +2858, 427, 676,2772,1168,2025, 454,3253,2486,3556, 230,1950, 580, 791,1991,1280, +1086,1974,2034, 630, 257,3338,2788,4903,1017, 86,4790, 966,2789,1995,1696,1131, + 259,3095,4188,1308, 179,1463,5257, 289,4107,1248, 42,3413,1725,2288, 896,1947, + 774,4474,4254, 604,3430,4264, 392,2514,2588, 452, 237,1408,3018, 988,4531,1970, +3034,3310, 540,2370,1562,1288,2990, 502,4765,1147, 4,1853,2708, 207, 294,2814, +4078,2902,2509, 684, 34,3105,3532,2551, 644, 709,2801,2344, 573,1727,3573,3557, +2021,1081,3100,4315,2100,3681, 199,2263,1837,2385, 146,3484,1195,2776,3949, 997, +1939,3973,1008,1091,1202,1962,1847,1149,4209,5444,1076, 493, 117,5400,2521, 972, +1490,2934,1796,4542,2374,1512,2933,2657, 413,2888,1135,2762,2314,2156,1355,2369, + 766,2007,2527,2170,3124,2491,2593,2632,4757,2437, 234,3125,3591,1898,1750,1376, +1942,3468,3138, 570,2127,2145,3276,4131, 962, 132,1445,4196, 19, 941,3624,3480, +3366,1973,1374,4461,3431,2629, 283,2415,2275, 808,2887,3620,2112,2563,1353,3610, + 955,1089,3103,1053, 96, 88,4097, 823,3808,1583, 399, 292,4091,3313, 421,1128, + 642,4006, 903,2539,1877,2082, 596, 29,4066,1790, 722,2157, 130, 995,1569, 769, +1485, 464, 513,2213, 288,1923,1101,2453,4316, 133, 486,2445, 50, 625, 487,2207, + 57, 423, 481,2962, 159,3729,1558, 491, 303, 482, 501, 240,2837, 112,3648,2392, +1783, 362, 8,3433,3422, 610,2793,3277,1390,1284,1654, 21,3823, 734, 367, 623, + 193, 287, 374,1009,1483, 816, 476, 313,2255,2340,1262,2150,2899,1146,2581, 782, +2116,1659,2018,1880, 255,3586,3314,1110,2867,2137,2564, 986,2767,5185,2006, 650, + 158, 926, 762, 881,3157,2717,2362,3587, 306,3690,3245,1542,3077,2427,1691,2478, +2118,2985,3490,2438, 539,2305, 983, 129,1754, 355,4201,2386, 827,2923, 104,1773, +2838,2771, 411,2905,3919, 376, 767, 122,1114, 828,2422,1817,3506, 266,3460,1007, +1609,4998, 945,2612,4429,2274, 726,1247,1964,2914,2199,2070,4002,4108, 657,3323, +1422, 579, 455,2764,4737,1222,2895,1670, 824,1223,1487,2525, 558, 861,3080, 598, +2659,2515,1967, 752,2583,2376,2214,4180, 977, 704,2464,4999,2622,4109,1210,2961, + 819,1541, 142,2284, 44, 418, 457,1126,3730,4347,4626,1644,1876,3671,1864, 302, +1063,5694, 624, 723,1984,3745,1314,1676,2488,1610,1449,3558,3569,2166,2098, 409, +1011,2325,3704,2306, 818,1732,1383,1824,1844,3757, 999,2705,3497,1216,1423,2683, +2426,2954,2501,2726,2229,1475,2554,5064,1971,1794,1666,2014,1343, 783, 724, 191, +2434,1354,2220,5065,1763,2752,2472,4152, 131, 175,2885,3434, 92,1466,4920,2616, +3871,3872,3866, 128,1551,1632, 669,1854,3682,4691,4125,1230, 188,2973,3290,1302, +1213, 560,3266, 917, 763,3909,3249,1760, 868,1958, 764,1782,2097, 145,2277,3774, +4462, 64,1491,3062, 971,2132,3606,2442, 221,1226,1617, 218, 323,1185,3207,3147, + 571, 619,1473,1005,1744,2281, 449,1887,2396,3685, 275, 375,3816,1743,3844,3731, + 845,1983,2350,4210,1377, 773, 967,3499,3052,3743,2725,4007,1697,1022,3943,1464, +3264,2855,2722,1952,1029,2839,2467, 84,4383,2215, 820,1391,2015,2448,3672, 377, +1948,2168, 797,2545,3536,2578,2645, 94,2874,1678, 405,1259,3071, 771, 546,1315, + 470,1243,3083, 895,2468, 981, 969,2037, 846,4181, 653,1276,2928, 14,2594, 557, +3007,2474, 156, 902,1338,1740,2574, 537,2518, 973,2282,2216,2433,1928, 138,2903, +1293,2631,1612, 646,3457, 839,2935, 111, 496,2191,2847, 589,3186, 149,3994,2060, +4031,2641,4067,3145,1870, 37,3597,2136,1025,2051,3009,3383,3549,1121,1016,3261, +1301, 251,2446,2599,2153, 872,3246, 637, 334,3705, 831, 884, 921,3065,3140,4092, +2198,1944, 246,2964, 108,2045,1152,1921,2308,1031, 203,3173,4170,1907,3890, 810, +1401,2003,1690, 506, 647,1242,2828,1761,1649,3208,2249,1589,3709,2931,5156,1708, + 498, 666,2613, 834,3817,1231, 184,2851,1124, 883,3197,2261,3710,1765,1553,2658, +1178,2639,2351, 93,1193, 942,2538,2141,4402, 235,1821, 870,1591,2192,1709,1871, +3341,1618,4126,2595,2334, 603, 651, 69, 701, 268,2662,3411,2555,1380,1606, 503, + 448, 254,2371,2646, 574,1187,2309,1770, 322,2235,1292,1801, 305, 566,1133, 229, +2067,2057, 706, 167, 483,2002,2672,3295,1820,3561,3067, 316, 378,2746,3452,1112, + 136,1981, 507,1651,2917,1117, 285,4591, 182,2580,3522,1304, 335,3303,1835,2504, +1795,1792,2248, 674,1018,2106,2449,1857,2292,2845, 976,3047,1781,2600,2727,1389, +1281, 52,3152, 153, 265,3950, 672,3485,3951,4463, 430,1183, 365, 278,2169, 27, +1407,1336,2304, 209,1340,1730,2202,1852,2403,2883, 979,1737,1062, 631,2829,2542, +3876,2592, 825,2086,2226,3048,3625, 352,1417,3724, 542, 991, 431,1351,3938,1861, +2294, 826,1361,2927,3142,3503,1738, 463,2462,2723, 582,1916,1595,2808, 400,3845, +3891,2868,3621,2254, 58,2492,1123, 910,2160,2614,1372,1603,1196,1072,3385,1700, +3267,1980, 696, 480,2430, 920, 799,1570,2920,1951,2041,4047,2540,1321,4223,2469, +3562,2228,1271,2602, 401,2833,3351,2575,5157, 907,2312,1256, 410, 263,3507,1582, + 996, 678,1849,2316,1480, 908,3545,2237, 703,2322, 667,1826,2849,1531,2604,2999, +2407,3146,2151,2630,1786,3711, 469,3542, 497,3899,2409, 858, 837,4446,3393,1274, + 786, 620,1845,2001,3311, 484, 308,3367,1204,1815,3691,2332,1532,2557,1842,2020, +2724,1927,2333,4440, 567, 22,1673,2728,4475,1987,1858,1144,1597, 101,1832,3601, + 12, 974,3783,4391, 951,1412, 1,3720, 453,4608,4041, 528,1041,1027,3230,2628, +1129, 875,1051,3291,1203,2262,1069,2860,2799,2149,2615,3278, 144,1758,3040, 31, + 475,1680, 366,2685,3184, 311,1642,4008,2466,5036,1593,1493,2809, 216,1420,1668, + 233, 304,2128,3284, 232,1429,1768,1040,2008,3407,2740,2967,2543, 242,2133, 778, +1565,2022,2620, 505,2189,2756,1098,2273, 372,1614, 708, 553,2846,2094,2278, 169, +3626,2835,4161, 228,2674,3165, 809,1454,1309, 466,1705,1095, 900,3423, 880,2667, +3751,5258,2317,3109,2571,4317,2766,1503,1342, 866,4447,1118, 63,2076, 314,1881, +1348,1061, 172, 978,3515,1747, 532, 511,3970, 6, 601, 905,2699,3300,1751, 276, +1467,3725,2668, 65,4239,2544,2779,2556,1604, 578,2451,1802, 992,2331,2624,1320, +3446, 713,1513,1013, 103,2786,2447,1661, 886,1702, 916, 654,3574,2031,1556, 751, +2178,2821,2179,1498,1538,2176, 271, 914,2251,2080,1325, 638,1953,2937,3877,2432, +2754, 95,3265,1716, 260,1227,4083, 775, 106,1357,3254, 426,1607, 555,2480, 772, +1985, 244,2546, 474, 495,1046,2611,1851,2061, 71,2089,1675,2590, 742,3758,2843, +3222,1433, 267,2180,2576,2826,2233,2092,3913,2435, 956,1745,3075, 856,2113,1116, + 451, 3,1988,2896,1398, 993,2463,1878,2049,1341,2718,2721,2870,2108, 712,2904, +4363,2753,2324, 277,2872,2349,2649, 384, 987, 435, 691,3000, 922, 164,3939, 652, +1500,1184,4153,2482,3373,2165,4848,2335,3775,3508,3154,2806,2830,1554,2102,1664, +2530,1434,2408, 893,1547,2623,3447,2832,2242,2532,3169,2856,3223,2078, 49,3770, +3469, 462, 318, 656,2259,3250,3069, 679,1629,2758, 344,1138,1104,3120,1836,1283, +3115,2154,1437,4448, 934, 759,1999, 794,2862,1038, 533,2560,1722,2342, 855,2626, +1197,1663,4476,3127, 85,4240,2528, 25,1111,1181,3673, 407,3470,4561,2679,2713, + 768,1925,2841,3986,1544,1165, 932, 373,1240,2146,1930,2673, 721,4766, 354,4333, + 391,2963, 187, 61,3364,1442,1102, 330,1940,1767, 341,3809,4118, 393,2496,2062, +2211, 105, 331, 300, 439, 913,1332, 626, 379,3304,1557, 328, 689,3952, 309,1555, + 931, 317,2517,3027, 325, 569, 686,2107,3084, 60,1042,1333,2794, 264,3177,4014, +1628, 258,3712, 7,4464,1176,1043,1778, 683, 114,1975, 78,1492, 383,1886, 510, + 386, 645,5291,2891,2069,3305,4138,3867,2939,2603,2493,1935,1066,1848,3588,1015, +1282,1289,4609, 697,1453,3044,2666,3611,1856,2412, 54, 719,1330, 568,3778,2459, +1748, 788, 492, 551,1191,1000, 488,3394,3763, 282,1799, 348,2016,1523,3155,2390, +1049, 382,2019,1788,1170, 729,2968,3523, 897,3926,2785,2938,3292, 350,2319,3238, +1718,1717,2655,3453,3143,4465, 161,2889,2980,2009,1421, 56,1908,1640,2387,2232, +1917,1874,2477,4921, 148, 83,3438, 592,4245,2882,1822,1055, 741, 115,1496,1624, + 381,1638,4592,1020, 516,3214, 458, 947,4575,1432, 211,1514,2926,1865,2142, 189, + 852,1221,1400,1486, 882,2299,4036, 351, 28,1122, 700,6479,6480,6481,6482,6483, #last 512 +) + diff --git a/flex/lib/python3.6/site-packages/chardet/gb2312prober.py b/flex/lib/python3.6/site-packages/chardet/gb2312prober.py new file mode 100644 index 0000000..8446d2d --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/gb2312prober.py @@ -0,0 +1,46 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import GB2312DistributionAnalysis +from .mbcssm import GB2312_SM_MODEL + +class GB2312Prober(MultiByteCharSetProber): + def __init__(self): + super(GB2312Prober, self).__init__() + self.coding_sm = CodingStateMachine(GB2312_SM_MODEL) + self.distribution_analyzer = GB2312DistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "GB2312" + + @property + def language(self): + return "Chinese" diff --git a/flex/lib/python3.6/site-packages/chardet/hebrewprober.py b/flex/lib/python3.6/site-packages/chardet/hebrewprober.py new file mode 100644 index 0000000..b0e1bf4 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/hebrewprober.py @@ -0,0 +1,292 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Shy Shalom +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState + +# This prober doesn't actually recognize a language or a charset. +# It is a helper prober for the use of the Hebrew model probers + +### General ideas of the Hebrew charset recognition ### +# +# Four main charsets exist in Hebrew: +# "ISO-8859-8" - Visual Hebrew +# "windows-1255" - Logical Hebrew +# "ISO-8859-8-I" - Logical Hebrew +# "x-mac-hebrew" - ?? Logical Hebrew ?? +# +# Both "ISO" charsets use a completely identical set of code points, whereas +# "windows-1255" and "x-mac-hebrew" are two different proper supersets of +# these code points. windows-1255 defines additional characters in the range +# 0x80-0x9F as some misc punctuation marks as well as some Hebrew-specific +# diacritics and additional 'Yiddish' ligature letters in the range 0xc0-0xd6. +# x-mac-hebrew defines similar additional code points but with a different +# mapping. +# +# As far as an average Hebrew text with no diacritics is concerned, all four +# charsets are identical with respect to code points. Meaning that for the +# main Hebrew alphabet, all four map the same values to all 27 Hebrew letters +# (including final letters). +# +# The dominant difference between these charsets is their directionality. +# "Visual" directionality means that the text is ordered as if the renderer is +# not aware of a BIDI rendering algorithm. The renderer sees the text and +# draws it from left to right. The text itself when ordered naturally is read +# backwards. A buffer of Visual Hebrew generally looks like so: +# "[last word of first line spelled backwards] [whole line ordered backwards +# and spelled backwards] [first word of first line spelled backwards] +# [end of line] [last word of second line] ... etc' " +# adding punctuation marks, numbers and English text to visual text is +# naturally also "visual" and from left to right. +# +# "Logical" directionality means the text is ordered "naturally" according to +# the order it is read. It is the responsibility of the renderer to display +# the text from right to left. A BIDI algorithm is used to place general +# punctuation marks, numbers and English text in the text. +# +# Texts in x-mac-hebrew are almost impossible to find on the Internet. From +# what little evidence I could find, it seems that its general directionality +# is Logical. +# +# To sum up all of the above, the Hebrew probing mechanism knows about two +# charsets: +# Visual Hebrew - "ISO-8859-8" - backwards text - Words and sentences are +# backwards while line order is natural. For charset recognition purposes +# the line order is unimportant (In fact, for this implementation, even +# word order is unimportant). +# Logical Hebrew - "windows-1255" - normal, naturally ordered text. +# +# "ISO-8859-8-I" is a subset of windows-1255 and doesn't need to be +# specifically identified. +# "x-mac-hebrew" is also identified as windows-1255. A text in x-mac-hebrew +# that contain special punctuation marks or diacritics is displayed with +# some unconverted characters showing as question marks. This problem might +# be corrected using another model prober for x-mac-hebrew. Due to the fact +# that x-mac-hebrew texts are so rare, writing another model prober isn't +# worth the effort and performance hit. +# +#### The Prober #### +# +# The prober is divided between two SBCharSetProbers and a HebrewProber, +# all of which are managed, created, fed data, inquired and deleted by the +# SBCSGroupProber. The two SBCharSetProbers identify that the text is in +# fact some kind of Hebrew, Logical or Visual. The final decision about which +# one is it is made by the HebrewProber by combining final-letter scores +# with the scores of the two SBCharSetProbers to produce a final answer. +# +# The SBCSGroupProber is responsible for stripping the original text of HTML +# tags, English characters, numbers, low-ASCII punctuation characters, spaces +# and new lines. It reduces any sequence of such characters to a single space. +# The buffer fed to each prober in the SBCS group prober is pure text in +# high-ASCII. +# The two SBCharSetProbers (model probers) share the same language model: +# Win1255Model. +# The first SBCharSetProber uses the model normally as any other +# SBCharSetProber does, to recognize windows-1255, upon which this model was +# built. The second SBCharSetProber is told to make the pair-of-letter +# lookup in the language model backwards. This in practice exactly simulates +# a visual Hebrew model using the windows-1255 logical Hebrew model. +# +# The HebrewProber is not using any language model. All it does is look for +# final-letter evidence suggesting the text is either logical Hebrew or visual +# Hebrew. Disjointed from the model probers, the results of the HebrewProber +# alone are meaningless. HebrewProber always returns 0.00 as confidence +# since it never identifies a charset by itself. Instead, the pointer to the +# HebrewProber is passed to the model probers as a helper "Name Prober". +# When the Group prober receives a positive identification from any prober, +# it asks for the name of the charset identified. If the prober queried is a +# Hebrew model prober, the model prober forwards the call to the +# HebrewProber to make the final decision. In the HebrewProber, the +# decision is made according to the final-letters scores maintained and Both +# model probers scores. The answer is returned in the form of the name of the +# charset identified, either "windows-1255" or "ISO-8859-8". + +class HebrewProber(CharSetProber): + # windows-1255 / ISO-8859-8 code points of interest + FINAL_KAF = 0xea + NORMAL_KAF = 0xeb + FINAL_MEM = 0xed + NORMAL_MEM = 0xee + FINAL_NUN = 0xef + NORMAL_NUN = 0xf0 + FINAL_PE = 0xf3 + NORMAL_PE = 0xf4 + FINAL_TSADI = 0xf5 + NORMAL_TSADI = 0xf6 + + # Minimum Visual vs Logical final letter score difference. + # If the difference is below this, don't rely solely on the final letter score + # distance. + MIN_FINAL_CHAR_DISTANCE = 5 + + # Minimum Visual vs Logical model score difference. + # If the difference is below this, don't rely at all on the model score + # distance. + MIN_MODEL_DISTANCE = 0.01 + + VISUAL_HEBREW_NAME = "ISO-8859-8" + LOGICAL_HEBREW_NAME = "windows-1255" + + def __init__(self): + super(HebrewProber, self).__init__() + self._final_char_logical_score = None + self._final_char_visual_score = None + self._prev = None + self._before_prev = None + self._logical_prober = None + self._visual_prober = None + self.reset() + + def reset(self): + self._final_char_logical_score = 0 + self._final_char_visual_score = 0 + # The two last characters seen in the previous buffer, + # mPrev and mBeforePrev are initialized to space in order to simulate + # a word delimiter at the beginning of the data + self._prev = ' ' + self._before_prev = ' ' + # These probers are owned by the group prober. + + def set_model_probers(self, logicalProber, visualProber): + self._logical_prober = logicalProber + self._visual_prober = visualProber + + def is_final(self, c): + return c in [self.FINAL_KAF, self.FINAL_MEM, self.FINAL_NUN, + self.FINAL_PE, self.FINAL_TSADI] + + def is_non_final(self, c): + # The normal Tsadi is not a good Non-Final letter due to words like + # 'lechotet' (to chat) containing an apostrophe after the tsadi. This + # apostrophe is converted to a space in FilterWithoutEnglishLetters + # causing the Non-Final tsadi to appear at an end of a word even + # though this is not the case in the original text. + # The letters Pe and Kaf rarely display a related behavior of not being + # a good Non-Final letter. Words like 'Pop', 'Winamp' and 'Mubarak' + # for example legally end with a Non-Final Pe or Kaf. However, the + # benefit of these letters as Non-Final letters outweighs the damage + # since these words are quite rare. + return c in [self.NORMAL_KAF, self.NORMAL_MEM, + self.NORMAL_NUN, self.NORMAL_PE] + + def feed(self, byte_str): + # Final letter analysis for logical-visual decision. + # Look for evidence that the received buffer is either logical Hebrew + # or visual Hebrew. + # The following cases are checked: + # 1) A word longer than 1 letter, ending with a final letter. This is + # an indication that the text is laid out "naturally" since the + # final letter really appears at the end. +1 for logical score. + # 2) A word longer than 1 letter, ending with a Non-Final letter. In + # normal Hebrew, words ending with Kaf, Mem, Nun, Pe or Tsadi, + # should not end with the Non-Final form of that letter. Exceptions + # to this rule are mentioned above in isNonFinal(). This is an + # indication that the text is laid out backwards. +1 for visual + # score + # 3) A word longer than 1 letter, starting with a final letter. Final + # letters should not appear at the beginning of a word. This is an + # indication that the text is laid out backwards. +1 for visual + # score. + # + # The visual score and logical score are accumulated throughout the + # text and are finally checked against each other in GetCharSetName(). + # No checking for final letters in the middle of words is done since + # that case is not an indication for either Logical or Visual text. + # + # We automatically filter out all 7-bit characters (replace them with + # spaces) so the word boundary detection works properly. [MAP] + + if self.state == ProbingState.NOT_ME: + # Both model probers say it's not them. No reason to continue. + return ProbingState.NOT_ME + + byte_str = self.filter_high_byte_only(byte_str) + + for cur in byte_str: + if cur == ' ': + # We stand on a space - a word just ended + if self._before_prev != ' ': + # next-to-last char was not a space so self._prev is not a + # 1 letter word + if self.is_final(self._prev): + # case (1) [-2:not space][-1:final letter][cur:space] + self._final_char_logical_score += 1 + elif self.is_non_final(self._prev): + # case (2) [-2:not space][-1:Non-Final letter][ + # cur:space] + self._final_char_visual_score += 1 + else: + # Not standing on a space + if ((self._before_prev == ' ') and + (self.is_final(self._prev)) and (cur != ' ')): + # case (3) [-2:space][-1:final letter][cur:not space] + self._final_char_visual_score += 1 + self._before_prev = self._prev + self._prev = cur + + # Forever detecting, till the end or until both model probers return + # ProbingState.NOT_ME (handled above) + return ProbingState.DETECTING + + @property + def charset_name(self): + # Make the decision: is it Logical or Visual? + # If the final letter score distance is dominant enough, rely on it. + finalsub = self._final_char_logical_score - self._final_char_visual_score + if finalsub >= self.MIN_FINAL_CHAR_DISTANCE: + return self.LOGICAL_HEBREW_NAME + if finalsub <= -self.MIN_FINAL_CHAR_DISTANCE: + return self.VISUAL_HEBREW_NAME + + # It's not dominant enough, try to rely on the model scores instead. + modelsub = (self._logical_prober.get_confidence() + - self._visual_prober.get_confidence()) + if modelsub > self.MIN_MODEL_DISTANCE: + return self.LOGICAL_HEBREW_NAME + if modelsub < -self.MIN_MODEL_DISTANCE: + return self.VISUAL_HEBREW_NAME + + # Still no good, back to final letter distance, maybe it'll save the + # day. + if finalsub < 0.0: + return self.VISUAL_HEBREW_NAME + + # (finalsub > 0 - Logical) or (don't know what to do) default to + # Logical. + return self.LOGICAL_HEBREW_NAME + + @property + def language(self): + return 'Hebrew' + + @property + def state(self): + # Remain active as long as any of the model probers are active. + if (self._logical_prober.state == ProbingState.NOT_ME) and \ + (self._visual_prober.state == ProbingState.NOT_ME): + return ProbingState.NOT_ME + return ProbingState.DETECTING diff --git a/flex/lib/python3.6/site-packages/chardet/jisfreq.py b/flex/lib/python3.6/site-packages/chardet/jisfreq.py new file mode 100644 index 0000000..83fc082 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/jisfreq.py @@ -0,0 +1,325 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Sampling from about 20M text materials include literature and computer technology +# +# Japanese frequency table, applied to both S-JIS and EUC-JP +# They are sorted in order. + +# 128 --> 0.77094 +# 256 --> 0.85710 +# 512 --> 0.92635 +# 1024 --> 0.97130 +# 2048 --> 0.99431 +# +# Ideal Distribution Ratio = 0.92635 / (1-0.92635) = 12.58 +# Random Distribution Ration = 512 / (2965+62+83+86-512) = 0.191 +# +# Typical Distribution Ratio, 25% of IDR + +JIS_TYPICAL_DISTRIBUTION_RATIO = 3.0 + +# Char to FreqOrder table , +JIS_TABLE_SIZE = 4368 + +JIS_CHAR_TO_FREQ_ORDER = ( + 40, 1, 6, 182, 152, 180, 295,2127, 285, 381,3295,4304,3068,4606,3165,3510, # 16 +3511,1822,2785,4607,1193,2226,5070,4608, 171,2996,1247, 18, 179,5071, 856,1661, # 32 +1262,5072, 619, 127,3431,3512,3230,1899,1700, 232, 228,1294,1298, 284, 283,2041, # 48 +2042,1061,1062, 48, 49, 44, 45, 433, 434,1040,1041, 996, 787,2997,1255,4305, # 64 +2108,4609,1684,1648,5073,5074,5075,5076,5077,5078,3687,5079,4610,5080,3927,3928, # 80 +5081,3296,3432, 290,2285,1471,2187,5082,2580,2825,1303,2140,1739,1445,2691,3375, # 96 +1691,3297,4306,4307,4611, 452,3376,1182,2713,3688,3069,4308,5083,5084,5085,5086, # 112 +5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102, # 128 +5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,4097,5113,5114,5115,5116,5117, # 144 +5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133, # 160 +5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149, # 176 +5150,5151,5152,4612,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164, # 192 +5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,1472, 598, 618, 820,1205, # 208 +1309,1412,1858,1307,1692,5176,5177,5178,5179,5180,5181,5182,1142,1452,1234,1172, # 224 +1875,2043,2149,1793,1382,2973, 925,2404,1067,1241, 960,1377,2935,1491, 919,1217, # 240 +1865,2030,1406,1499,2749,4098,5183,5184,5185,5186,5187,5188,2561,4099,3117,1804, # 256 +2049,3689,4309,3513,1663,5189,3166,3118,3298,1587,1561,3433,5190,3119,1625,2998, # 272 +3299,4613,1766,3690,2786,4614,5191,5192,5193,5194,2161, 26,3377, 2,3929, 20, # 288 +3691, 47,4100, 50, 17, 16, 35, 268, 27, 243, 42, 155, 24, 154, 29, 184, # 304 + 4, 91, 14, 92, 53, 396, 33, 289, 9, 37, 64, 620, 21, 39, 321, 5, # 320 + 12, 11, 52, 13, 3, 208, 138, 0, 7, 60, 526, 141, 151,1069, 181, 275, # 336 +1591, 83, 132,1475, 126, 331, 829, 15, 69, 160, 59, 22, 157, 55,1079, 312, # 352 + 109, 38, 23, 25, 10, 19, 79,5195, 61, 382,1124, 8, 30,5196,5197,5198, # 368 +5199,5200,5201,5202,5203,5204,5205,5206, 89, 62, 74, 34,2416, 112, 139, 196, # 384 + 271, 149, 84, 607, 131, 765, 46, 88, 153, 683, 76, 874, 101, 258, 57, 80, # 400 + 32, 364, 121,1508, 169,1547, 68, 235, 145,2999, 41, 360,3027, 70, 63, 31, # 416 + 43, 259, 262,1383, 99, 533, 194, 66, 93, 846, 217, 192, 56, 106, 58, 565, # 432 + 280, 272, 311, 256, 146, 82, 308, 71, 100, 128, 214, 655, 110, 261, 104,1140, # 448 + 54, 51, 36, 87, 67,3070, 185,2618,2936,2020, 28,1066,2390,2059,5207,5208, # 464 +5209,5210,5211,5212,5213,5214,5215,5216,4615,5217,5218,5219,5220,5221,5222,5223, # 480 +5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,3514,5237,5238, # 496 +5239,5240,5241,5242,5243,5244,2297,2031,4616,4310,3692,5245,3071,5246,3598,5247, # 512 +4617,3231,3515,5248,4101,4311,4618,3808,4312,4102,5249,4103,4104,3599,5250,5251, # 528 +5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267, # 544 +5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283, # 560 +5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299, # 576 +5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315, # 592 +5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331, # 608 +5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347, # 624 +5348,5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363, # 640 +5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379, # 656 +5380,5381, 363, 642,2787,2878,2788,2789,2316,3232,2317,3434,2011, 165,1942,3930, # 672 +3931,3932,3933,5382,4619,5383,4620,5384,5385,5386,5387,5388,5389,5390,5391,5392, # 688 +5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408, # 704 +5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424, # 720 +5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440, # 736 +5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456, # 752 +5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472, # 768 +5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488, # 784 +5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504, # 800 +5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520, # 816 +5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536, # 832 +5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552, # 848 +5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568, # 864 +5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584, # 880 +5585,5586,5587,5588,5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600, # 896 +5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616, # 912 +5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632, # 928 +5633,5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648, # 944 +5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664, # 960 +5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680, # 976 +5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696, # 992 +5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712, # 1008 +5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728, # 1024 +5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,5744, # 1040 +5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,5759,5760, # 1056 +5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,5774,5775,5776, # 1072 +5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,5789,5790,5791,5792, # 1088 +5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,5804,5805,5806,5807,5808, # 1104 +5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824, # 1120 +5825,5826,5827,5828,5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840, # 1136 +5841,5842,5843,5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856, # 1152 +5857,5858,5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872, # 1168 +5873,5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888, # 1184 +5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904, # 1200 +5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920, # 1216 +5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936, # 1232 +5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952, # 1248 +5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968, # 1264 +5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,5984, # 1280 +5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,5999,6000, # 1296 +6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016, # 1312 +6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032, # 1328 +6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048, # 1344 +6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064, # 1360 +6065,6066,6067,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080, # 1376 +6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096, # 1392 +6097,6098,6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112, # 1408 +6113,6114,2044,2060,4621, 997,1235, 473,1186,4622, 920,3378,6115,6116, 379,1108, # 1424 +4313,2657,2735,3934,6117,3809, 636,3233, 573,1026,3693,3435,2974,3300,2298,4105, # 1440 + 854,2937,2463, 393,2581,2417, 539, 752,1280,2750,2480, 140,1161, 440, 708,1569, # 1456 + 665,2497,1746,1291,1523,3000, 164,1603, 847,1331, 537,1997, 486, 508,1693,2418, # 1472 +1970,2227, 878,1220, 299,1030, 969, 652,2751, 624,1137,3301,2619, 65,3302,2045, # 1488 +1761,1859,3120,1930,3694,3516, 663,1767, 852, 835,3695, 269, 767,2826,2339,1305, # 1504 + 896,1150, 770,1616,6118, 506,1502,2075,1012,2519, 775,2520,2975,2340,2938,4314, # 1520 +3028,2086,1224,1943,2286,6119,3072,4315,2240,1273,1987,3935,1557, 175, 597, 985, # 1536 +3517,2419,2521,1416,3029, 585, 938,1931,1007,1052,1932,1685,6120,3379,4316,4623, # 1552 + 804, 599,3121,1333,2128,2539,1159,1554,2032,3810, 687,2033,2904, 952, 675,1467, # 1568 +3436,6121,2241,1096,1786,2440,1543,1924, 980,1813,2228, 781,2692,1879, 728,1918, # 1584 +3696,4624, 548,1950,4625,1809,1088,1356,3303,2522,1944, 502, 972, 373, 513,2827, # 1600 + 586,2377,2391,1003,1976,1631,6122,2464,1084, 648,1776,4626,2141, 324, 962,2012, # 1616 +2177,2076,1384, 742,2178,1448,1173,1810, 222, 102, 301, 445, 125,2420, 662,2498, # 1632 + 277, 200,1476,1165,1068, 224,2562,1378,1446, 450,1880, 659, 791, 582,4627,2939, # 1648 +3936,1516,1274, 555,2099,3697,1020,1389,1526,3380,1762,1723,1787,2229, 412,2114, # 1664 +1900,2392,3518, 512,2597, 427,1925,2341,3122,1653,1686,2465,2499, 697, 330, 273, # 1680 + 380,2162, 951, 832, 780, 991,1301,3073, 965,2270,3519, 668,2523,2636,1286, 535, # 1696 +1407, 518, 671, 957,2658,2378, 267, 611,2197,3030,6123, 248,2299, 967,1799,2356, # 1712 + 850,1418,3437,1876,1256,1480,2828,1718,6124,6125,1755,1664,2405,6126,4628,2879, # 1728 +2829, 499,2179, 676,4629, 557,2329,2214,2090, 325,3234, 464, 811,3001, 992,2342, # 1744 +2481,1232,1469, 303,2242, 466,1070,2163, 603,1777,2091,4630,2752,4631,2714, 322, # 1760 +2659,1964,1768, 481,2188,1463,2330,2857,3600,2092,3031,2421,4632,2318,2070,1849, # 1776 +2598,4633,1302,2254,1668,1701,2422,3811,2905,3032,3123,2046,4106,1763,1694,4634, # 1792 +1604, 943,1724,1454, 917, 868,2215,1169,2940, 552,1145,1800,1228,1823,1955, 316, # 1808 +1080,2510, 361,1807,2830,4107,2660,3381,1346,1423,1134,4108,6127, 541,1263,1229, # 1824 +1148,2540, 545, 465,1833,2880,3438,1901,3074,2482, 816,3937, 713,1788,2500, 122, # 1840 +1575, 195,1451,2501,1111,6128, 859, 374,1225,2243,2483,4317, 390,1033,3439,3075, # 1856 +2524,1687, 266, 793,1440,2599, 946, 779, 802, 507, 897,1081, 528,2189,1292, 711, # 1872 +1866,1725,1167,1640, 753, 398,2661,1053, 246, 348,4318, 137,1024,3440,1600,2077, # 1888 +2129, 825,4319, 698, 238, 521, 187,2300,1157,2423,1641,1605,1464,1610,1097,2541, # 1904 +1260,1436, 759,2255,1814,2150, 705,3235, 409,2563,3304, 561,3033,2005,2564, 726, # 1920 +1956,2343,3698,4109, 949,3812,3813,3520,1669, 653,1379,2525, 881,2198, 632,2256, # 1936 +1027, 778,1074, 733,1957, 514,1481,2466, 554,2180, 702,3938,1606,1017,1398,6129, # 1952 +1380,3521, 921, 993,1313, 594, 449,1489,1617,1166, 768,1426,1360, 495,1794,3601, # 1968 +1177,3602,1170,4320,2344, 476, 425,3167,4635,3168,1424, 401,2662,1171,3382,1998, # 1984 +1089,4110, 477,3169, 474,6130,1909, 596,2831,1842, 494, 693,1051,1028,1207,3076, # 2000 + 606,2115, 727,2790,1473,1115, 743,3522, 630, 805,1532,4321,2021, 366,1057, 838, # 2016 + 684,1114,2142,4322,2050,1492,1892,1808,2271,3814,2424,1971,1447,1373,3305,1090, # 2032 +1536,3939,3523,3306,1455,2199, 336, 369,2331,1035, 584,2393, 902, 718,2600,6131, # 2048 +2753, 463,2151,1149,1611,2467, 715,1308,3124,1268, 343,1413,3236,1517,1347,2663, # 2064 +2093,3940,2022,1131,1553,2100,2941,1427,3441,2942,1323,2484,6132,1980, 872,2368, # 2080 +2441,2943, 320,2369,2116,1082, 679,1933,3941,2791,3815, 625,1143,2023, 422,2200, # 2096 +3816,6133, 730,1695, 356,2257,1626,2301,2858,2637,1627,1778, 937, 883,2906,2693, # 2112 +3002,1769,1086, 400,1063,1325,3307,2792,4111,3077, 456,2345,1046, 747,6134,1524, # 2128 + 884,1094,3383,1474,2164,1059, 974,1688,2181,2258,1047, 345,1665,1187, 358, 875, # 2144 +3170, 305, 660,3524,2190,1334,1135,3171,1540,1649,2542,1527, 927, 968,2793, 885, # 2160 +1972,1850, 482, 500,2638,1218,1109,1085,2543,1654,2034, 876, 78,2287,1482,1277, # 2176 + 861,1675,1083,1779, 724,2754, 454, 397,1132,1612,2332, 893, 672,1237, 257,2259, # 2192 +2370, 135,3384, 337,2244, 547, 352, 340, 709,2485,1400, 788,1138,2511, 540, 772, # 2208 +1682,2260,2272,2544,2013,1843,1902,4636,1999,1562,2288,4637,2201,1403,1533, 407, # 2224 + 576,3308,1254,2071, 978,3385, 170, 136,1201,3125,2664,3172,2394, 213, 912, 873, # 2240 +3603,1713,2202, 699,3604,3699, 813,3442, 493, 531,1054, 468,2907,1483, 304, 281, # 2256 +4112,1726,1252,2094, 339,2319,2130,2639, 756,1563,2944, 748, 571,2976,1588,2425, # 2272 +2715,1851,1460,2426,1528,1392,1973,3237, 288,3309, 685,3386, 296, 892,2716,2216, # 2288 +1570,2245, 722,1747,2217, 905,3238,1103,6135,1893,1441,1965, 251,1805,2371,3700, # 2304 +2601,1919,1078, 75,2182,1509,1592,1270,2640,4638,2152,6136,3310,3817, 524, 706, # 2320 +1075, 292,3818,1756,2602, 317, 98,3173,3605,3525,1844,2218,3819,2502, 814, 567, # 2336 + 385,2908,1534,6137, 534,1642,3239, 797,6138,1670,1529, 953,4323, 188,1071, 538, # 2352 + 178, 729,3240,2109,1226,1374,2000,2357,2977, 731,2468,1116,2014,2051,6139,1261, # 2368 +1593, 803,2859,2736,3443, 556, 682, 823,1541,6140,1369,2289,1706,2794, 845, 462, # 2384 +2603,2665,1361, 387, 162,2358,1740, 739,1770,1720,1304,1401,3241,1049, 627,1571, # 2400 +2427,3526,1877,3942,1852,1500, 431,1910,1503, 677, 297,2795, 286,1433,1038,1198, # 2416 +2290,1133,1596,4113,4639,2469,1510,1484,3943,6141,2442, 108, 712,4640,2372, 866, # 2432 +3701,2755,3242,1348, 834,1945,1408,3527,2395,3243,1811, 824, 994,1179,2110,1548, # 2448 +1453, 790,3003, 690,4324,4325,2832,2909,3820,1860,3821, 225,1748, 310, 346,1780, # 2464 +2470, 821,1993,2717,2796, 828, 877,3528,2860,2471,1702,2165,2910,2486,1789, 453, # 2480 + 359,2291,1676, 73,1164,1461,1127,3311, 421, 604, 314,1037, 589, 116,2487, 737, # 2496 + 837,1180, 111, 244, 735,6142,2261,1861,1362, 986, 523, 418, 581,2666,3822, 103, # 2512 + 855, 503,1414,1867,2488,1091, 657,1597, 979, 605,1316,4641,1021,2443,2078,2001, # 2528 +1209, 96, 587,2166,1032, 260,1072,2153, 173, 94, 226,3244, 819,2006,4642,4114, # 2544 +2203, 231,1744, 782, 97,2667, 786,3387, 887, 391, 442,2219,4326,1425,6143,2694, # 2560 + 633,1544,1202, 483,2015, 592,2052,1958,2472,1655, 419, 129,4327,3444,3312,1714, # 2576 +1257,3078,4328,1518,1098, 865,1310,1019,1885,1512,1734, 469,2444, 148, 773, 436, # 2592 +1815,1868,1128,1055,4329,1245,2756,3445,2154,1934,1039,4643, 579,1238, 932,2320, # 2608 + 353, 205, 801, 115,2428, 944,2321,1881, 399,2565,1211, 678, 766,3944, 335,2101, # 2624 +1459,1781,1402,3945,2737,2131,1010, 844, 981,1326,1013, 550,1816,1545,2620,1335, # 2640 +1008, 371,2881, 936,1419,1613,3529,1456,1395,2273,1834,2604,1317,2738,2503, 416, # 2656 +1643,4330, 806,1126, 229, 591,3946,1314,1981,1576,1837,1666, 347,1790, 977,3313, # 2672 + 764,2861,1853, 688,2429,1920,1462, 77, 595, 415,2002,3034, 798,1192,4115,6144, # 2688 +2978,4331,3035,2695,2582,2072,2566, 430,2430,1727, 842,1396,3947,3702, 613, 377, # 2704 + 278, 236,1417,3388,3314,3174, 757,1869, 107,3530,6145,1194, 623,2262, 207,1253, # 2720 +2167,3446,3948, 492,1117,1935, 536,1838,2757,1246,4332, 696,2095,2406,1393,1572, # 2736 +3175,1782, 583, 190, 253,1390,2230, 830,3126,3389, 934,3245,1703,1749,2979,1870, # 2752 +2545,1656,2204, 869,2346,4116,3176,1817, 496,1764,4644, 942,1504, 404,1903,1122, # 2768 +1580,3606,2945,1022, 515, 372,1735, 955,2431,3036,6146,2797,1110,2302,2798, 617, # 2784 +6147, 441, 762,1771,3447,3607,3608,1904, 840,3037, 86, 939,1385, 572,1370,2445, # 2800 +1336, 114,3703, 898, 294, 203,3315, 703,1583,2274, 429, 961,4333,1854,1951,3390, # 2816 +2373,3704,4334,1318,1381, 966,1911,2322,1006,1155, 309, 989, 458,2718,1795,1372, # 2832 +1203, 252,1689,1363,3177, 517,1936, 168,1490, 562, 193,3823,1042,4117,1835, 551, # 2848 + 470,4645, 395, 489,3448,1871,1465,2583,2641, 417,1493, 279,1295, 511,1236,1119, # 2864 + 72,1231,1982,1812,3004, 871,1564, 984,3449,1667,2696,2096,4646,2347,2833,1673, # 2880 +3609, 695,3246,2668, 807,1183,4647, 890, 388,2333,1801,1457,2911,1765,1477,1031, # 2896 +3316,3317,1278,3391,2799,2292,2526, 163,3450,4335,2669,1404,1802,6148,2323,2407, # 2912 +1584,1728,1494,1824,1269, 298, 909,3318,1034,1632, 375, 776,1683,2061, 291, 210, # 2928 +1123, 809,1249,1002,2642,3038, 206,1011,2132, 144, 975, 882,1565, 342, 667, 754, # 2944 +1442,2143,1299,2303,2062, 447, 626,2205,1221,2739,2912,1144,1214,2206,2584, 760, # 2960 +1715, 614, 950,1281,2670,2621, 810, 577,1287,2546,4648, 242,2168, 250,2643, 691, # 2976 + 123,2644, 647, 313,1029, 689,1357,2946,1650, 216, 771,1339,1306, 808,2063, 549, # 2992 + 913,1371,2913,2914,6149,1466,1092,1174,1196,1311,2605,2396,1783,1796,3079, 406, # 3008 +2671,2117,3949,4649, 487,1825,2220,6150,2915, 448,2348,1073,6151,2397,1707, 130, # 3024 + 900,1598, 329, 176,1959,2527,1620,6152,2275,4336,3319,1983,2191,3705,3610,2155, # 3040 +3706,1912,1513,1614,6153,1988, 646, 392,2304,1589,3320,3039,1826,1239,1352,1340, # 3056 +2916, 505,2567,1709,1437,2408,2547, 906,6154,2672, 384,1458,1594,1100,1329, 710, # 3072 + 423,3531,2064,2231,2622,1989,2673,1087,1882, 333, 841,3005,1296,2882,2379, 580, # 3088 +1937,1827,1293,2585, 601, 574, 249,1772,4118,2079,1120, 645, 901,1176,1690, 795, # 3104 +2207, 478,1434, 516,1190,1530, 761,2080, 930,1264, 355, 435,1552, 644,1791, 987, # 3120 + 220,1364,1163,1121,1538, 306,2169,1327,1222, 546,2645, 218, 241, 610,1704,3321, # 3136 +1984,1839,1966,2528, 451,6155,2586,3707,2568, 907,3178, 254,2947, 186,1845,4650, # 3152 + 745, 432,1757, 428,1633, 888,2246,2221,2489,3611,2118,1258,1265, 956,3127,1784, # 3168 +4337,2490, 319, 510, 119, 457,3612, 274,2035,2007,4651,1409,3128, 970,2758, 590, # 3184 +2800, 661,2247,4652,2008,3950,1420,1549,3080,3322,3951,1651,1375,2111, 485,2491, # 3200 +1429,1156,6156,2548,2183,1495, 831,1840,2529,2446, 501,1657, 307,1894,3247,1341, # 3216 + 666, 899,2156,1539,2549,1559, 886, 349,2208,3081,2305,1736,3824,2170,2759,1014, # 3232 +1913,1386, 542,1397,2948, 490, 368, 716, 362, 159, 282,2569,1129,1658,1288,1750, # 3248 +2674, 276, 649,2016, 751,1496, 658,1818,1284,1862,2209,2087,2512,3451, 622,2834, # 3264 + 376, 117,1060,2053,1208,1721,1101,1443, 247,1250,3179,1792,3952,2760,2398,3953, # 3280 +6157,2144,3708, 446,2432,1151,2570,3452,2447,2761,2835,1210,2448,3082, 424,2222, # 3296 +1251,2449,2119,2836, 504,1581,4338, 602, 817, 857,3825,2349,2306, 357,3826,1470, # 3312 +1883,2883, 255, 958, 929,2917,3248, 302,4653,1050,1271,1751,2307,1952,1430,2697, # 3328 +2719,2359, 354,3180, 777, 158,2036,4339,1659,4340,4654,2308,2949,2248,1146,2232, # 3344 +3532,2720,1696,2623,3827,6158,3129,1550,2698,1485,1297,1428, 637, 931,2721,2145, # 3360 + 914,2550,2587, 81,2450, 612, 827,2646,1242,4655,1118,2884, 472,1855,3181,3533, # 3376 +3534, 569,1353,2699,1244,1758,2588,4119,2009,2762,2171,3709,1312,1531,6159,1152, # 3392 +1938, 134,1830, 471,3710,2276,1112,1535,3323,3453,3535, 982,1337,2950, 488, 826, # 3408 + 674,1058,1628,4120,2017, 522,2399, 211, 568,1367,3454, 350, 293,1872,1139,3249, # 3424 +1399,1946,3006,1300,2360,3324, 588, 736,6160,2606, 744, 669,3536,3828,6161,1358, # 3440 + 199, 723, 848, 933, 851,1939,1505,1514,1338,1618,1831,4656,1634,3613, 443,2740, # 3456 +3829, 717,1947, 491,1914,6162,2551,1542,4121,1025,6163,1099,1223, 198,3040,2722, # 3472 + 370, 410,1905,2589, 998,1248,3182,2380, 519,1449,4122,1710, 947, 928,1153,4341, # 3488 +2277, 344,2624,1511, 615, 105, 161,1212,1076,1960,3130,2054,1926,1175,1906,2473, # 3504 + 414,1873,2801,6164,2309, 315,1319,3325, 318,2018,2146,2157, 963, 631, 223,4342, # 3520 +4343,2675, 479,3711,1197,2625,3712,2676,2361,6165,4344,4123,6166,2451,3183,1886, # 3536 +2184,1674,1330,1711,1635,1506, 799, 219,3250,3083,3954,1677,3713,3326,2081,3614, # 3552 +1652,2073,4657,1147,3041,1752, 643,1961, 147,1974,3955,6167,1716,2037, 918,3007, # 3568 +1994, 120,1537, 118, 609,3184,4345, 740,3455,1219, 332,1615,3830,6168,1621,2980, # 3584 +1582, 783, 212, 553,2350,3714,1349,2433,2082,4124, 889,6169,2310,1275,1410, 973, # 3600 + 166,1320,3456,1797,1215,3185,2885,1846,2590,2763,4658, 629, 822,3008, 763, 940, # 3616 +1990,2862, 439,2409,1566,1240,1622, 926,1282,1907,2764, 654,2210,1607, 327,1130, # 3632 +3956,1678,1623,6170,2434,2192, 686, 608,3831,3715, 903,3957,3042,6171,2741,1522, # 3648 +1915,1105,1555,2552,1359, 323,3251,4346,3457, 738,1354,2553,2311,2334,1828,2003, # 3664 +3832,1753,2351,1227,6172,1887,4125,1478,6173,2410,1874,1712,1847, 520,1204,2607, # 3680 + 264,4659, 836,2677,2102, 600,4660,3833,2278,3084,6174,4347,3615,1342, 640, 532, # 3696 + 543,2608,1888,2400,2591,1009,4348,1497, 341,1737,3616,2723,1394, 529,3252,1321, # 3712 + 983,4661,1515,2120, 971,2592, 924, 287,1662,3186,4349,2700,4350,1519, 908,1948, # 3728 +2452, 156, 796,1629,1486,2223,2055, 694,4126,1259,1036,3392,1213,2249,2742,1889, # 3744 +1230,3958,1015, 910, 408, 559,3617,4662, 746, 725, 935,4663,3959,3009,1289, 563, # 3760 + 867,4664,3960,1567,2981,2038,2626, 988,2263,2381,4351, 143,2374, 704,1895,6175, # 3776 +1188,3716,2088, 673,3085,2362,4352, 484,1608,1921,2765,2918, 215, 904,3618,3537, # 3792 + 894, 509, 976,3043,2701,3961,4353,2837,2982, 498,6176,6177,1102,3538,1332,3393, # 3808 +1487,1636,1637, 233, 245,3962, 383, 650, 995,3044, 460,1520,1206,2352, 749,3327, # 3824 + 530, 700, 389,1438,1560,1773,3963,2264, 719,2951,2724,3834, 870,1832,1644,1000, # 3840 + 839,2474,3717, 197,1630,3394, 365,2886,3964,1285,2133, 734, 922, 818,1106, 732, # 3856 + 480,2083,1774,3458, 923,2279,1350, 221,3086, 85,2233,2234,3835,1585,3010,2147, # 3872 +1387,1705,2382,1619,2475, 133, 239,2802,1991,1016,2084,2383, 411,2838,1113, 651, # 3888 +1985,1160,3328, 990,1863,3087,1048,1276,2647, 265,2627,1599,3253,2056, 150, 638, # 3904 +2019, 656, 853, 326,1479, 680,1439,4354,1001,1759, 413,3459,3395,2492,1431, 459, # 3920 +4355,1125,3329,2265,1953,1450,2065,2863, 849, 351,2678,3131,3254,3255,1104,1577, # 3936 + 227,1351,1645,2453,2193,1421,2887, 812,2121, 634, 95,2435, 201,2312,4665,1646, # 3952 +1671,2743,1601,2554,2702,2648,2280,1315,1366,2089,3132,1573,3718,3965,1729,1189, # 3968 + 328,2679,1077,1940,1136, 558,1283, 964,1195, 621,2074,1199,1743,3460,3619,1896, # 3984 +1916,1890,3836,2952,1154,2112,1064, 862, 378,3011,2066,2113,2803,1568,2839,6178, # 4000 +3088,2919,1941,1660,2004,1992,2194, 142, 707,1590,1708,1624,1922,1023,1836,1233, # 4016 +1004,2313, 789, 741,3620,6179,1609,2411,1200,4127,3719,3720,4666,2057,3721, 593, # 4032 +2840, 367,2920,1878,6180,3461,1521, 628,1168, 692,2211,2649, 300, 720,2067,2571, # 4048 +2953,3396, 959,2504,3966,3539,3462,1977, 701,6181, 954,1043, 800, 681, 183,3722, # 4064 +1803,1730,3540,4128,2103, 815,2314, 174, 467, 230,2454,1093,2134, 755,3541,3397, # 4080 +1141,1162,6182,1738,2039, 270,3256,2513,1005,1647,2185,3837, 858,1679,1897,1719, # 4096 +2954,2324,1806, 402, 670, 167,4129,1498,2158,2104, 750,6183, 915, 189,1680,1551, # 4112 + 455,4356,1501,2455, 405,1095,2955, 338,1586,1266,1819, 570, 641,1324, 237,1556, # 4128 +2650,1388,3723,6184,1368,2384,1343,1978,3089,2436, 879,3724, 792,1191, 758,3012, # 4144 +1411,2135,1322,4357, 240,4667,1848,3725,1574,6185, 420,3045,1546,1391, 714,4358, # 4160 +1967, 941,1864, 863, 664, 426, 560,1731,2680,1785,2864,1949,2363, 403,3330,1415, # 4176 +1279,2136,1697,2335, 204, 721,2097,3838, 90,6186,2085,2505, 191,3967, 124,2148, # 4192 +1376,1798,1178,1107,1898,1405, 860,4359,1243,1272,2375,2983,1558,2456,1638, 113, # 4208 +3621, 578,1923,2609, 880, 386,4130, 784,2186,2266,1422,2956,2172,1722, 497, 263, # 4224 +2514,1267,2412,2610, 177,2703,3542, 774,1927,1344, 616,1432,1595,1018, 172,4360, # 4240 +2325, 911,4361, 438,1468,3622, 794,3968,2024,2173,1681,1829,2957, 945, 895,3090, # 4256 + 575,2212,2476, 475,2401,2681, 785,2744,1745,2293,2555,1975,3133,2865, 394,4668, # 4272 +3839, 635,4131, 639, 202,1507,2195,2766,1345,1435,2572,3726,1908,1184,1181,2457, # 4288 +3727,3134,4362, 843,2611, 437, 916,4669, 234, 769,1884,3046,3047,3623, 833,6187, # 4304 +1639,2250,2402,1355,1185,2010,2047, 999, 525,1732,1290,1488,2612, 948,1578,3728, # 4320 +2413,2477,1216,2725,2159, 334,3840,1328,3624,2921,1525,4132, 564,1056, 891,4363, # 4336 +1444,1698,2385,2251,3729,1365,2281,2235,1717,6188, 864,3841,2515, 444, 527,2767, # 4352 +2922,3625, 544, 461,6189, 566, 209,2437,3398,2098,1065,2068,3331,3626,3257,2137, # 4368 #last 512 +) + + diff --git a/flex/lib/python3.6/site-packages/chardet/jpcntx.py b/flex/lib/python3.6/site-packages/chardet/jpcntx.py new file mode 100644 index 0000000..20044e4 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/jpcntx.py @@ -0,0 +1,233 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + + +# This is hiragana 2-char sequence table, the number in each cell represents its frequency category +jp2CharContext = ( +(0,0,0,2,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,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,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1), +(2,4,0,4,0,3,0,4,0,3,4,4,4,2,4,3,3,4,3,2,3,3,4,2,3,3,3,2,4,1,4,3,3,1,5,4,3,4,3,4,3,5,3,0,3,5,4,2,0,3,1,0,3,3,0,3,3,0,1,1,0,4,3,0,3,3,0,4,0,2,0,3,5,5,5,5,4,0,4,1,0,3,4), +(0,0,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2), +(0,4,0,5,0,5,0,4,0,4,5,4,4,3,5,3,5,1,5,3,4,3,4,4,3,4,3,3,4,3,5,4,4,3,5,5,3,5,5,5,3,5,5,3,4,5,5,3,1,3,2,0,3,4,0,4,2,0,4,2,1,5,3,2,3,5,0,4,0,2,0,5,4,4,5,4,5,0,4,0,0,4,4), +(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,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,3,0,4,0,3,0,3,0,4,5,4,3,3,3,3,4,3,5,4,4,3,5,4,4,3,4,3,4,4,4,4,5,3,4,4,3,4,5,5,4,5,5,1,4,5,4,3,0,3,3,1,3,3,0,4,4,0,3,3,1,5,3,3,3,5,0,4,0,3,0,4,4,3,4,3,3,0,4,1,1,3,4), +(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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,4,0,3,0,3,0,4,0,3,4,4,3,2,2,1,2,1,3,1,3,3,3,3,3,4,3,1,3,3,5,3,3,0,4,3,0,5,4,3,3,5,4,4,3,4,4,5,0,1,2,0,1,2,0,2,2,0,1,0,0,5,2,2,1,4,0,3,0,1,0,4,4,3,5,4,3,0,2,1,0,4,3), +(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,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,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,5,0,4,0,2,1,4,4,2,4,1,4,2,4,2,4,3,3,3,4,3,3,3,3,1,4,2,3,3,3,1,4,4,1,1,1,4,3,3,2,0,2,4,3,2,0,3,3,0,3,1,1,0,0,0,3,3,0,4,2,2,3,4,0,4,0,3,0,4,4,5,3,4,4,0,3,0,0,1,4), +(1,4,0,4,0,4,0,4,0,3,5,4,4,3,4,3,5,4,3,3,4,3,5,4,4,4,4,3,4,2,4,3,3,1,5,4,3,2,4,5,4,5,5,4,4,5,4,4,0,3,2,2,3,3,0,4,3,1,3,2,1,4,3,3,4,5,0,3,0,2,0,4,5,5,4,5,4,0,4,0,0,5,4), +(0,5,0,5,0,4,0,3,0,4,4,3,4,3,3,3,4,0,4,4,4,3,4,3,4,3,3,1,4,2,4,3,4,0,5,4,1,4,5,4,4,5,3,2,4,3,4,3,2,4,1,3,3,3,2,3,2,0,4,3,3,4,3,3,3,4,0,4,0,3,0,4,5,4,4,4,3,0,4,1,0,1,3), +(0,3,1,4,0,3,0,2,0,3,4,4,3,1,4,2,3,3,4,3,4,3,4,3,4,4,3,2,3,1,5,4,4,1,4,4,3,5,4,4,3,5,5,4,3,4,4,3,1,2,3,1,2,2,0,3,2,0,3,1,0,5,3,3,3,4,3,3,3,3,4,4,4,4,5,4,2,0,3,3,2,4,3), +(0,2,0,3,0,1,0,1,0,0,3,2,0,0,2,0,1,0,2,1,3,3,3,1,2,3,1,0,1,0,4,2,1,1,3,3,0,4,3,3,1,4,3,3,0,3,3,2,0,0,0,0,1,0,0,2,0,0,0,0,0,4,1,0,2,3,2,2,2,1,3,3,3,4,4,3,2,0,3,1,0,3,3), +(0,4,0,4,0,3,0,3,0,4,4,4,3,3,3,3,3,3,4,3,4,2,4,3,4,3,3,2,4,3,4,5,4,1,4,5,3,5,4,5,3,5,4,0,3,5,5,3,1,3,3,2,2,3,0,3,4,1,3,3,2,4,3,3,3,4,0,4,0,3,0,4,5,4,4,5,3,0,4,1,0,3,4), +(0,2,0,3,0,3,0,0,0,2,2,2,1,0,1,0,0,0,3,0,3,0,3,0,1,3,1,0,3,1,3,3,3,1,3,3,3,0,1,3,1,3,4,0,0,3,1,1,0,3,2,0,0,0,0,1,3,0,1,0,0,3,3,2,0,3,0,0,0,0,0,3,4,3,4,3,3,0,3,0,0,2,3), +(2,3,0,3,0,2,0,1,0,3,3,4,3,1,3,1,1,1,3,1,4,3,4,3,3,3,0,0,3,1,5,4,3,1,4,3,2,5,5,4,4,4,4,3,3,4,4,4,0,2,1,1,3,2,0,1,2,0,0,1,0,4,1,3,3,3,0,3,0,1,0,4,4,4,5,5,3,0,2,0,0,4,4), +(0,2,0,1,0,3,1,3,0,2,3,3,3,0,3,1,0,0,3,0,3,2,3,1,3,2,1,1,0,0,4,2,1,0,2,3,1,4,3,2,0,4,4,3,1,3,1,3,0,1,0,0,1,0,0,0,1,0,0,0,0,4,1,1,1,2,0,3,0,0,0,3,4,2,4,3,2,0,1,0,0,3,3), +(0,1,0,4,0,5,0,4,0,2,4,4,2,3,3,2,3,3,5,3,3,3,4,3,4,2,3,0,4,3,3,3,4,1,4,3,2,1,5,5,3,4,5,1,3,5,4,2,0,3,3,0,1,3,0,4,2,0,1,3,1,4,3,3,3,3,0,3,0,1,0,3,4,4,4,5,5,0,3,0,1,4,5), +(0,2,0,3,0,3,0,0,0,2,3,1,3,0,4,0,1,1,3,0,3,4,3,2,3,1,0,3,3,2,3,1,3,0,2,3,0,2,1,4,1,2,2,0,0,3,3,0,0,2,0,0,0,1,0,0,0,0,2,2,0,3,2,1,3,3,0,2,0,2,0,0,3,3,1,2,4,0,3,0,2,2,3), +(2,4,0,5,0,4,0,4,0,2,4,4,4,3,4,3,3,3,1,2,4,3,4,3,4,4,5,0,3,3,3,3,2,0,4,3,1,4,3,4,1,4,4,3,3,4,4,3,1,2,3,0,4,2,0,4,1,0,3,3,0,4,3,3,3,4,0,4,0,2,0,3,5,3,4,5,2,0,3,0,0,4,5), +(0,3,0,4,0,1,0,1,0,1,3,2,2,1,3,0,3,0,2,0,2,0,3,0,2,0,0,0,1,0,1,1,0,0,3,1,0,0,0,4,0,3,1,0,2,1,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,4,2,2,3,1,0,3,0,0,0,1,4,4,4,3,0,0,4,0,0,1,4), +(1,4,1,5,0,3,0,3,0,4,5,4,4,3,5,3,3,4,4,3,4,1,3,3,3,3,2,1,4,1,5,4,3,1,4,4,3,5,4,4,3,5,4,3,3,4,4,4,0,3,3,1,2,3,0,3,1,0,3,3,0,5,4,4,4,4,4,4,3,3,5,4,4,3,3,5,4,0,3,2,0,4,4), +(0,2,0,3,0,1,0,0,0,1,3,3,3,2,4,1,3,0,3,1,3,0,2,2,1,1,0,0,2,0,4,3,1,0,4,3,0,4,4,4,1,4,3,1,1,3,3,1,0,2,0,0,1,3,0,0,0,0,2,0,0,4,3,2,4,3,5,4,3,3,3,4,3,3,4,3,3,0,2,1,0,3,3), +(0,2,0,4,0,3,0,2,0,2,5,5,3,4,4,4,4,1,4,3,3,0,4,3,4,3,1,3,3,2,4,3,0,3,4,3,0,3,4,4,2,4,4,0,4,5,3,3,2,2,1,1,1,2,0,1,5,0,3,3,2,4,3,3,3,4,0,3,0,2,0,4,4,3,5,5,0,0,3,0,2,3,3), +(0,3,0,4,0,3,0,1,0,3,4,3,3,1,3,3,3,0,3,1,3,0,4,3,3,1,1,0,3,0,3,3,0,0,4,4,0,1,5,4,3,3,5,0,3,3,4,3,0,2,0,1,1,1,0,1,3,0,1,2,1,3,3,2,3,3,0,3,0,1,0,1,3,3,4,4,1,0,1,2,2,1,3), +(0,1,0,4,0,4,0,3,0,1,3,3,3,2,3,1,1,0,3,0,3,3,4,3,2,4,2,0,1,0,4,3,2,0,4,3,0,5,3,3,2,4,4,4,3,3,3,4,0,1,3,0,0,1,0,0,1,0,0,0,0,4,2,3,3,3,0,3,0,0,0,4,4,4,5,3,2,0,3,3,0,3,5), +(0,2,0,3,0,0,0,3,0,1,3,0,2,0,0,0,1,0,3,1,1,3,3,0,0,3,0,0,3,0,2,3,1,0,3,1,0,3,3,2,0,4,2,2,0,2,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,2,1,2,0,1,0,1,0,0,0,1,3,1,2,0,0,0,1,0,0,1,4), +(0,3,0,3,0,5,0,1,0,2,4,3,1,3,3,2,1,1,5,2,1,0,5,1,2,0,0,0,3,3,2,2,3,2,4,3,0,0,3,3,1,3,3,0,2,5,3,4,0,3,3,0,1,2,0,2,2,0,3,2,0,2,2,3,3,3,0,2,0,1,0,3,4,4,2,5,4,0,3,0,0,3,5), +(0,3,0,3,0,3,0,1,0,3,3,3,3,0,3,0,2,0,2,1,1,0,2,0,1,0,0,0,2,1,0,0,1,0,3,2,0,0,3,3,1,2,3,1,0,3,3,0,0,1,0,0,0,0,0,2,0,0,0,0,0,2,3,1,2,3,0,3,0,1,0,3,2,1,0,4,3,0,1,1,0,3,3), +(0,4,0,5,0,3,0,3,0,4,5,5,4,3,5,3,4,3,5,3,3,2,5,3,4,4,4,3,4,3,4,5,5,3,4,4,3,4,4,5,4,4,4,3,4,5,5,4,2,3,4,2,3,4,0,3,3,1,4,3,2,4,3,3,5,5,0,3,0,3,0,5,5,5,5,4,4,0,4,0,1,4,4), +(0,4,0,4,0,3,0,3,0,3,5,4,4,2,3,2,5,1,3,2,5,1,4,2,3,2,3,3,4,3,3,3,3,2,5,4,1,3,3,5,3,4,4,0,4,4,3,1,1,3,1,0,2,3,0,2,3,0,3,0,0,4,3,1,3,4,0,3,0,2,0,4,4,4,3,4,5,0,4,0,0,3,4), +(0,3,0,3,0,3,1,2,0,3,4,4,3,3,3,0,2,2,4,3,3,1,3,3,3,1,1,0,3,1,4,3,2,3,4,4,2,4,4,4,3,4,4,3,2,4,4,3,1,3,3,1,3,3,0,4,1,0,2,2,1,4,3,2,3,3,5,4,3,3,5,4,4,3,3,0,4,0,3,2,2,4,4), +(0,2,0,1,0,0,0,0,0,1,2,1,3,0,0,0,0,0,2,0,1,2,1,0,0,1,0,0,0,0,3,0,0,1,0,1,1,3,1,0,0,0,1,1,0,1,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,1,2,2,0,3,4,0,0,0,1,1,0,0,1,0,0,0,0,0,1,1), +(0,1,0,0,0,1,0,0,0,0,4,0,4,1,4,0,3,0,4,0,3,0,4,0,3,0,3,0,4,1,5,1,4,0,0,3,0,5,0,5,2,0,1,0,0,0,2,1,4,0,1,3,0,0,3,0,0,3,1,1,4,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0), +(1,4,0,5,0,3,0,2,0,3,5,4,4,3,4,3,5,3,4,3,3,0,4,3,3,3,3,3,3,2,4,4,3,1,3,4,4,5,4,4,3,4,4,1,3,5,4,3,3,3,1,2,2,3,3,1,3,1,3,3,3,5,3,3,4,5,0,3,0,3,0,3,4,3,4,4,3,0,3,0,2,4,3), +(0,1,0,4,0,0,0,0,0,1,4,0,4,1,4,2,4,0,3,0,1,0,1,0,0,0,0,0,2,0,3,1,1,1,0,3,0,0,0,1,2,1,0,0,1,1,1,1,0,1,0,0,0,1,0,0,3,0,0,0,0,3,2,0,2,2,0,1,0,0,0,2,3,2,3,3,0,0,0,0,2,1,0), +(0,5,1,5,0,3,0,3,0,5,4,4,5,1,5,3,3,0,4,3,4,3,5,3,4,3,3,2,4,3,4,3,3,0,3,3,1,4,4,3,4,4,4,3,4,5,5,3,2,3,1,1,3,3,1,3,1,1,3,3,2,4,5,3,3,5,0,4,0,3,0,4,4,3,5,3,3,0,3,4,0,4,3), +(0,5,0,5,0,3,0,2,0,4,4,3,5,2,4,3,3,3,4,4,4,3,5,3,5,3,3,1,4,0,4,3,3,0,3,3,0,4,4,4,4,5,4,3,3,5,5,3,2,3,1,2,3,2,0,1,0,0,3,2,2,4,4,3,1,5,0,4,0,3,0,4,3,1,3,2,1,0,3,3,0,3,3), +(0,4,0,5,0,5,0,4,0,4,5,5,5,3,4,3,3,2,5,4,4,3,5,3,5,3,4,0,4,3,4,4,3,2,4,4,3,4,5,4,4,5,5,0,3,5,5,4,1,3,3,2,3,3,1,3,1,0,4,3,1,4,4,3,4,5,0,4,0,2,0,4,3,4,4,3,3,0,4,0,0,5,5), +(0,4,0,4,0,5,0,1,1,3,3,4,4,3,4,1,3,0,5,1,3,0,3,1,3,1,1,0,3,0,3,3,4,0,4,3,0,4,4,4,3,4,4,0,3,5,4,1,0,3,0,0,2,3,0,3,1,0,3,1,0,3,2,1,3,5,0,3,0,1,0,3,2,3,3,4,4,0,2,2,0,4,4), +(2,4,0,5,0,4,0,3,0,4,5,5,4,3,5,3,5,3,5,3,5,2,5,3,4,3,3,4,3,4,5,3,2,1,5,4,3,2,3,4,5,3,4,1,2,5,4,3,0,3,3,0,3,2,0,2,3,0,4,1,0,3,4,3,3,5,0,3,0,1,0,4,5,5,5,4,3,0,4,2,0,3,5), +(0,5,0,4,0,4,0,2,0,5,4,3,4,3,4,3,3,3,4,3,4,2,5,3,5,3,4,1,4,3,4,4,4,0,3,5,0,4,4,4,4,5,3,1,3,4,5,3,3,3,3,3,3,3,0,2,2,0,3,3,2,4,3,3,3,5,3,4,1,3,3,5,3,2,0,0,0,0,4,3,1,3,3), +(0,1,0,3,0,3,0,1,0,1,3,3,3,2,3,3,3,0,3,0,0,0,3,1,3,0,0,0,2,2,2,3,0,0,3,2,0,1,2,4,1,3,3,0,0,3,3,3,0,1,0,0,2,1,0,0,3,0,3,1,0,3,0,0,1,3,0,2,0,1,0,3,3,1,3,3,0,0,1,1,0,3,3), +(0,2,0,3,0,2,1,4,0,2,2,3,1,1,3,1,1,0,2,0,3,1,2,3,1,3,0,0,1,0,4,3,2,3,3,3,1,4,2,3,3,3,3,1,0,3,1,4,0,1,1,0,1,2,0,1,1,0,1,1,0,3,1,3,2,2,0,1,0,0,0,2,3,3,3,1,0,0,0,0,0,2,3), +(0,5,0,4,0,5,0,2,0,4,5,5,3,3,4,3,3,1,5,4,4,2,4,4,4,3,4,2,4,3,5,5,4,3,3,4,3,3,5,5,4,5,5,1,3,4,5,3,1,4,3,1,3,3,0,3,3,1,4,3,1,4,5,3,3,5,0,4,0,3,0,5,3,3,1,4,3,0,4,0,1,5,3), +(0,5,0,5,0,4,0,2,0,4,4,3,4,3,3,3,3,3,5,4,4,4,4,4,4,5,3,3,5,2,4,4,4,3,4,4,3,3,4,4,5,5,3,3,4,3,4,3,3,4,3,3,3,3,1,2,2,1,4,3,3,5,4,4,3,4,0,4,0,3,0,4,4,4,4,4,1,0,4,2,0,2,4), +(0,4,0,4,0,3,0,1,0,3,5,2,3,0,3,0,2,1,4,2,3,3,4,1,4,3,3,2,4,1,3,3,3,0,3,3,0,0,3,3,3,5,3,3,3,3,3,2,0,2,0,0,2,0,0,2,0,0,1,0,0,3,1,2,2,3,0,3,0,2,0,4,4,3,3,4,1,0,3,0,0,2,4), +(0,0,0,4,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,1,0,2,0,1,0,0,0,0,0,3,1,3,0,3,2,0,0,0,1,0,3,2,0,0,2,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,3,4,0,2,0,0,0,0,0,0,2), +(0,2,1,3,0,2,0,2,0,3,3,3,3,1,3,1,3,3,3,3,3,3,4,2,2,1,2,1,4,0,4,3,1,3,3,3,2,4,3,5,4,3,3,3,3,3,3,3,0,1,3,0,2,0,0,1,0,0,1,0,0,4,2,0,2,3,0,3,3,0,3,3,4,2,3,1,4,0,1,2,0,2,3), +(0,3,0,3,0,1,0,3,0,2,3,3,3,0,3,1,2,0,3,3,2,3,3,2,3,2,3,1,3,0,4,3,2,0,3,3,1,4,3,3,2,3,4,3,1,3,3,1,1,0,1,1,0,1,0,1,0,1,0,0,0,4,1,1,0,3,0,3,1,0,2,3,3,3,3,3,1,0,0,2,0,3,3), +(0,0,0,0,0,0,0,0,0,0,3,0,2,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,3,0,3,1,0,1,0,1,0,0,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,3,0,2,0,2,3,0,0,0,0,0,0,0,0,3), +(0,2,0,3,1,3,0,3,0,2,3,3,3,1,3,1,3,1,3,1,3,3,3,1,3,0,2,3,1,1,4,3,3,2,3,3,1,2,2,4,1,3,3,0,1,4,2,3,0,1,3,0,3,0,0,1,3,0,2,0,0,3,3,2,1,3,0,3,0,2,0,3,4,4,4,3,1,0,3,0,0,3,3), +(0,2,0,1,0,2,0,0,0,1,3,2,2,1,3,0,1,1,3,0,3,2,3,1,2,0,2,0,1,1,3,3,3,0,3,3,1,1,2,3,2,3,3,1,2,3,2,0,0,1,0,0,0,0,0,0,3,0,1,0,0,2,1,2,1,3,0,3,0,0,0,3,4,4,4,3,2,0,2,0,0,2,4), +(0,0,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,2,0,0,0,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,1,0,0,0,0,1,3,1,0,0,0,0,0,0,0,3), +(0,3,0,3,0,2,0,3,0,3,3,3,2,3,2,2,2,0,3,1,3,3,3,2,3,3,0,0,3,0,3,2,2,0,2,3,1,4,3,4,3,3,2,3,1,5,4,4,0,3,1,2,1,3,0,3,1,1,2,0,2,3,1,3,1,3,0,3,0,1,0,3,3,4,4,2,1,0,2,1,0,2,4), +(0,1,0,3,0,1,0,2,0,1,4,2,5,1,4,0,2,0,2,1,3,1,4,0,2,1,0,0,2,1,4,1,1,0,3,3,0,5,1,3,2,3,3,1,0,3,2,3,0,1,0,0,0,0,0,0,1,0,0,0,0,4,0,1,0,3,0,2,0,1,0,3,3,3,4,3,3,0,0,0,0,2,3), +(0,0,0,1,0,0,0,0,0,0,2,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,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,0,0,0,2,1,0,0,1,0,0,0,0,0,3), +(0,1,0,3,0,4,0,3,0,2,4,3,1,0,3,2,2,1,3,1,2,2,3,1,1,1,2,1,3,0,1,2,0,1,3,2,1,3,0,5,5,1,0,0,1,3,2,1,0,3,0,0,1,0,0,0,0,0,3,4,0,1,1,1,3,2,0,2,0,1,0,2,3,3,1,2,3,0,1,0,1,0,4), +(0,0,0,1,0,3,0,3,0,2,2,1,0,0,4,0,3,0,3,1,3,0,3,0,3,0,1,0,3,0,3,1,3,0,3,3,0,0,1,2,1,1,1,0,1,2,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,2,2,1,2,0,0,2,0,0,0,0,2,3,3,3,3,0,0,0,0,1,4), +(0,0,0,3,0,3,0,0,0,0,3,1,1,0,3,0,1,0,2,0,1,0,0,0,0,0,0,0,1,0,3,0,2,0,2,3,0,0,2,2,3,1,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,2,3), +(2,4,0,5,0,5,0,4,0,3,4,3,3,3,4,3,3,3,4,3,4,4,5,4,5,5,5,2,3,0,5,5,4,1,5,4,3,1,5,4,3,4,4,3,3,4,3,3,0,3,2,0,2,3,0,3,0,0,3,3,0,5,3,2,3,3,0,3,0,3,0,3,4,5,4,5,3,0,4,3,0,3,4), +(0,3,0,3,0,3,0,3,0,3,3,4,3,2,3,2,3,0,4,3,3,3,3,3,3,3,3,0,3,2,4,3,3,1,3,4,3,4,4,4,3,4,4,3,2,4,4,1,0,2,0,0,1,1,0,2,0,0,3,1,0,5,3,2,1,3,0,3,0,1,2,4,3,2,4,3,3,0,3,2,0,4,4), +(0,3,0,3,0,1,0,0,0,1,4,3,3,2,3,1,3,1,4,2,3,2,4,2,3,4,3,0,2,2,3,3,3,0,3,3,3,0,3,4,1,3,3,0,3,4,3,3,0,1,1,0,1,0,0,0,4,0,3,0,0,3,1,2,1,3,0,4,0,1,0,4,3,3,4,3,3,0,2,0,0,3,3), +(0,3,0,4,0,1,0,3,0,3,4,3,3,0,3,3,3,1,3,1,3,3,4,3,3,3,0,0,3,1,5,3,3,1,3,3,2,5,4,3,3,4,5,3,2,5,3,4,0,1,0,0,0,0,0,2,0,0,1,1,0,4,2,2,1,3,0,3,0,2,0,4,4,3,5,3,2,0,1,1,0,3,4), +(0,5,0,4,0,5,0,2,0,4,4,3,3,2,3,3,3,1,4,3,4,1,5,3,4,3,4,0,4,2,4,3,4,1,5,4,0,4,4,4,4,5,4,1,3,5,4,2,1,4,1,1,3,2,0,3,1,0,3,2,1,4,3,3,3,4,0,4,0,3,0,4,4,4,3,3,3,0,4,2,0,3,4), +(1,4,0,4,0,3,0,1,0,3,3,3,1,1,3,3,2,2,3,3,1,0,3,2,2,1,2,0,3,1,2,1,2,0,3,2,0,2,2,3,3,4,3,0,3,3,1,2,0,1,1,3,1,2,0,0,3,0,1,1,0,3,2,2,3,3,0,3,0,0,0,2,3,3,4,3,3,0,1,0,0,1,4), +(0,4,0,4,0,4,0,0,0,3,4,4,3,1,4,2,3,2,3,3,3,1,4,3,4,0,3,0,4,2,3,3,2,2,5,4,2,1,3,4,3,4,3,1,3,3,4,2,0,2,1,0,3,3,0,0,2,0,3,1,0,4,4,3,4,3,0,4,0,1,0,2,4,4,4,4,4,0,3,2,0,3,3), +(0,0,0,1,0,4,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,3,2,0,0,1,0,0,0,1,0,0,0,0,0,0,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,1,0,0,0,0,0,2), +(0,2,0,3,0,4,0,4,0,1,3,3,3,0,4,0,2,1,2,1,1,1,2,0,3,1,1,0,1,0,3,1,0,0,3,3,2,0,1,1,0,0,0,0,0,1,0,2,0,2,2,0,3,1,0,0,1,0,1,1,0,1,2,0,3,0,0,0,0,1,0,0,3,3,4,3,1,0,1,0,3,0,2), +(0,0,0,3,0,5,0,0,0,0,1,0,2,0,3,1,0,1,3,0,0,0,2,0,0,0,1,0,0,0,1,1,0,0,4,0,0,0,2,3,0,1,4,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,3,0,0,0,0,0,3), +(0,2,0,5,0,5,0,1,0,2,4,3,3,2,5,1,3,2,3,3,3,0,4,1,2,0,3,0,4,0,2,2,1,1,5,3,0,0,1,4,2,3,2,0,3,3,3,2,0,2,4,1,1,2,0,1,1,0,3,1,0,1,3,1,2,3,0,2,0,0,0,1,3,5,4,4,4,0,3,0,0,1,3), +(0,4,0,5,0,4,0,4,0,4,5,4,3,3,4,3,3,3,4,3,4,4,5,3,4,5,4,2,4,2,3,4,3,1,4,4,1,3,5,4,4,5,5,4,4,5,5,5,2,3,3,1,4,3,1,3,3,0,3,3,1,4,3,4,4,4,0,3,0,4,0,3,3,4,4,5,0,0,4,3,0,4,5), +(0,4,0,4,0,3,0,3,0,3,4,4,4,3,3,2,4,3,4,3,4,3,5,3,4,3,2,1,4,2,4,4,3,1,3,4,2,4,5,5,3,4,5,4,1,5,4,3,0,3,2,2,3,2,1,3,1,0,3,3,3,5,3,3,3,5,4,4,2,3,3,4,3,3,3,2,1,0,3,2,1,4,3), +(0,4,0,5,0,4,0,3,0,3,5,5,3,2,4,3,4,0,5,4,4,1,4,4,4,3,3,3,4,3,5,5,2,3,3,4,1,2,5,5,3,5,5,2,3,5,5,4,0,3,2,0,3,3,1,1,5,1,4,1,0,4,3,2,3,5,0,4,0,3,0,5,4,3,4,3,0,0,4,1,0,4,4), +(1,3,0,4,0,2,0,2,0,2,5,5,3,3,3,3,3,0,4,2,3,4,4,4,3,4,0,0,3,4,5,4,3,3,3,3,2,5,5,4,5,5,5,4,3,5,5,5,1,3,1,0,1,0,0,3,2,0,4,2,0,5,2,3,2,4,1,3,0,3,0,4,5,4,5,4,3,0,4,2,0,5,4), +(0,3,0,4,0,5,0,3,0,3,4,4,3,2,3,2,3,3,3,3,3,2,4,3,3,2,2,0,3,3,3,3,3,1,3,3,3,0,4,4,3,4,4,1,1,4,4,2,0,3,1,0,1,1,0,4,1,0,2,3,1,3,3,1,3,4,0,3,0,1,0,3,1,3,0,0,1,0,2,0,0,4,4), +(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,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,3,0,3,0,2,0,3,0,1,5,4,3,3,3,1,4,2,1,2,3,4,4,2,4,4,5,0,3,1,4,3,4,0,4,3,3,3,2,3,2,5,3,4,3,2,2,3,0,0,3,0,2,1,0,1,2,0,0,0,0,2,1,1,3,1,0,2,0,4,0,3,4,4,4,5,2,0,2,0,0,1,3), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,1,0,0,0,4,2,1,1,0,1,0,3,2,0,0,3,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,1,0,0,0,2,0,0,0,1,4,0,4,2,1,0,0,0,0,0,1), +(0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0,3,1,0,0,0,2,0,2,1,0,0,1,2,1,0,1,1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,1,3,1,0,0,0,0,0,1,0,0,2,1,0,0,0,0,0,0,0,0,2), +(0,4,0,4,0,4,0,3,0,4,4,3,4,2,4,3,2,0,4,4,4,3,5,3,5,3,3,2,4,2,4,3,4,3,1,4,0,2,3,4,4,4,3,3,3,4,4,4,3,4,1,3,4,3,2,1,2,1,3,3,3,4,4,3,3,5,0,4,0,3,0,4,3,3,3,2,1,0,3,0,0,3,3), +(0,4,0,3,0,3,0,3,0,3,5,5,3,3,3,3,4,3,4,3,3,3,4,4,4,3,3,3,3,4,3,5,3,3,1,3,2,4,5,5,5,5,4,3,4,5,5,3,2,2,3,3,3,3,2,3,3,1,2,3,2,4,3,3,3,4,0,4,0,2,0,4,3,2,2,1,2,0,3,0,0,4,1), +) + +class JapaneseContextAnalysis(object): + NUM_OF_CATEGORY = 6 + DONT_KNOW = -1 + ENOUGH_REL_THRESHOLD = 100 + MAX_REL_THRESHOLD = 1000 + MINIMUM_DATA_THRESHOLD = 4 + + def __init__(self): + self._total_rel = None + self._rel_sample = None + self._need_to_skip_char_num = None + self._last_char_order = None + self._done = None + self.reset() + + def reset(self): + self._total_rel = 0 # total sequence received + # category counters, each integer counts sequence in its category + self._rel_sample = [0] * self.NUM_OF_CATEGORY + # if last byte in current buffer is not the last byte of a character, + # we need to know how many bytes to skip in next buffer + self._need_to_skip_char_num = 0 + self._last_char_order = -1 # The order of previous char + # If this flag is set to True, detection is done and conclusion has + # been made + self._done = False + + def feed(self, byte_str, num_bytes): + if self._done: + return + + # The buffer we got is byte oriented, and a character may span in more than one + # buffers. In case the last one or two byte in last buffer is not + # complete, we record how many byte needed to complete that character + # and skip these bytes here. We can choose to record those bytes as + # well and analyse the character once it is complete, but since a + # character will not make much difference, by simply skipping + # this character will simply our logic and improve performance. + i = self._need_to_skip_char_num + while i < num_bytes: + order, char_len = self.get_order(byte_str[i:i + 2]) + i += char_len + if i > num_bytes: + self._need_to_skip_char_num = i - num_bytes + self._last_char_order = -1 + else: + if (order != -1) and (self._last_char_order != -1): + self._total_rel += 1 + if self._total_rel > self.MAX_REL_THRESHOLD: + self._done = True + break + self._rel_sample[jp2CharContext[self._last_char_order][order]] += 1 + self._last_char_order = order + + def got_enough_data(self): + return self._total_rel > self.ENOUGH_REL_THRESHOLD + + def get_confidence(self): + # This is just one way to calculate confidence. It works well for me. + if self._total_rel > self.MINIMUM_DATA_THRESHOLD: + return (self._total_rel - self._rel_sample[0]) / self._total_rel + else: + return self.DONT_KNOW + + def get_order(self, byte_str): + return -1, 1 + +class SJISContextAnalysis(JapaneseContextAnalysis): + def __init__(self): + super(SJISContextAnalysis, self).__init__() + self._charset_name = "SHIFT_JIS" + + @property + def charset_name(self): + return self._charset_name + + def get_order(self, byte_str): + if not byte_str: + return -1, 1 + # find out current char's byte length + first_char = byte_str[0] + if (0x81 <= first_char <= 0x9F) or (0xE0 <= first_char <= 0xFC): + char_len = 2 + if (first_char == 0x87) or (0xFA <= first_char <= 0xFC): + self._charset_name = "CP932" + else: + char_len = 1 + + # return its order if it is hiragana + if len(byte_str) > 1: + second_char = byte_str[1] + if (first_char == 202) and (0x9F <= second_char <= 0xF1): + return second_char - 0x9F, char_len + + return -1, char_len + +class EUCJPContextAnalysis(JapaneseContextAnalysis): + def get_order(self, byte_str): + if not byte_str: + return -1, 1 + # find out current char's byte length + first_char = byte_str[0] + if (first_char == 0x8E) or (0xA1 <= first_char <= 0xFE): + char_len = 2 + elif first_char == 0x8F: + char_len = 3 + else: + char_len = 1 + + # return its order if it is hiragana + if len(byte_str) > 1: + second_char = byte_str[1] + if (first_char == 0xA4) and (0xA1 <= second_char <= 0xF3): + return second_char - 0xA1, char_len + + return -1, char_len + + diff --git a/flex/lib/python3.6/site-packages/chardet/langbulgarianmodel.py b/flex/lib/python3.6/site-packages/chardet/langbulgarianmodel.py new file mode 100644 index 0000000..2aa4fb2 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/langbulgarianmodel.py @@ -0,0 +1,228 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +# this table is modified base on win1251BulgarianCharToOrderMap, so +# only number <64 is sure valid + +Latin5_BulgarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 +110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 +253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 +116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 +194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209, # 80 +210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225, # 90 + 81,226,227,228,229,230,105,231,232,233,234,235,236, 45,237,238, # a0 + 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # b0 + 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,239, 67,240, 60, 56, # c0 + 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # d0 + 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,241, 42, 16, # e0 + 62,242,243,244, 58,245, 98,246,247,248,249,250,251, 91,252,253, # f0 +) + +win1251BulgarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 +110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 +253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 +116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 +206,207,208,209,210,211,212,213,120,214,215,216,217,218,219,220, # 80 +221, 78, 64, 83,121, 98,117,105,222,223,224,225,226,227,228,229, # 90 + 88,230,231,232,233,122, 89,106,234,235,236,237,238, 45,239,240, # a0 + 73, 80,118,114,241,242,243,244,245, 62, 58,246,247,248,249,250, # b0 + 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # c0 + 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,251, 67,252, 60, 56, # d0 + 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # e0 + 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,253, 42, 16, # f0 +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 96.9392% +# first 1024 sequences:3.0618% +# rest sequences: 0.2992% +# negative sequences: 0.0020% +BulgarianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,2,2,1,2,2, +3,1,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,0,1, +0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,3,3,0,3,1,0, +0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,2,2,1,3,3,3,3,2,2,2,1,1,2,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,2,3,2,2,3,3,1,1,2,3,3,2,3,3,3,3,2,1,2,0,2,0,3,0,0, +0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,1,3,3,3,3,3,2,3,2,3,3,3,3,3,2,3,3,1,3,0,3,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,1,3,3,2,3,3,3,1,3,3,2,3,2,2,2,0,0,2,0,2,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,3,3,1,2,2,3,2,1,1,2,0,2,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,2,3,3,1,2,3,2,2,2,3,3,3,3,3,2,2,3,1,2,0,2,1,2,0,0, +0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,1,3,3,3,3,3,2,3,3,3,2,3,3,2,3,2,2,2,3,1,2,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,1,1,1,2,2,1,3,1,3,2,2,3,0,0,1,0,1,0,1,0,0, +0,0,0,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,2,2,3,2,2,3,1,2,1,1,1,2,3,1,3,1,2,2,0,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,1,3,2,2,3,3,1,2,3,1,1,3,3,3,3,1,2,2,1,1,1,0,2,0,2,0,1, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,2,2,3,3,3,2,2,1,1,2,0,2,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,0,1,2,1,3,3,2,3,3,3,3,3,2,3,2,1,0,3,1,2,1,2,1,2,3,2,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,2,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,1,3,3,2,3,3,2,2,2,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,0,3,3,3,3,3,2,1,1,2,1,3,3,0,3,1,1,1,1,3,2,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,1,1,3,1,3,3,2,3,2,2,2,3,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,3,2,2,3,2,1,1,1,1,1,3,1,3,1,1,0,0,0,1,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,2,0,3,2,0,3,0,2,0,0,2,1,3,1,0,0,1,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,2,1,1,1,1,2,1,1,2,1,1,1,2,2,1,2,1,1,1,0,1,1,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,2,1,3,1,1,2,1,3,2,1,1,0,1,2,3,2,1,1,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,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,2,2,1,0,1,0,0,1,0,0,0,2,1,0,3,0,0,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,0,0,0,0,0,0,0,0,0,1, +3,3,3,2,3,2,3,3,1,3,2,1,1,1,2,1,1,2,1,3,0,1,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,2,2,3,3,2,3,2,2,2,3,1,2,2,1,1,2,1,1,2,2,0,1,1,0,1,0,2,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, +3,3,3,3,2,1,3,1,0,2,2,1,3,2,1,0,0,2,0,2,0,1,0,0,0,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,1,2,0,2,3,1,2,3,2,0,1,3,1,2,1,1,1,0,0,1,0,0,2,2,2,3, +2,2,2,2,1,2,1,1,2,2,1,1,2,0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,1, +3,3,3,3,3,2,1,2,2,1,2,0,2,0,1,0,1,2,1,2,1,1,0,0,0,1,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,2,3,3,1,1,3,1,0,3,2,1,0,0,0,1,2,0,2,0,1,0,0,0,1,0,1,2,1,2,2, +1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,0,1,2,1,1,1,0,0,0,0,0,1,1,0,0, +3,1,0,1,0,2,3,2,2,2,3,2,2,2,2,2,1,0,2,1,2,1,1,1,0,1,2,1,2,2,2,1, +1,1,2,2,2,2,1,2,1,1,0,1,2,1,2,2,2,1,1,1,0,1,1,1,1,2,0,1,0,0,0,0, +2,3,2,3,3,0,0,2,1,0,2,1,0,0,0,0,2,3,0,2,0,0,0,0,0,1,0,0,2,0,1,2, +2,1,2,1,2,2,1,1,1,2,1,1,1,0,1,2,2,1,1,1,1,1,0,1,1,1,0,0,1,2,0,0, +3,3,2,2,3,0,2,3,1,1,2,0,0,0,1,0,0,2,0,2,0,0,0,1,0,1,0,1,2,0,2,2, +1,1,1,1,2,1,0,1,2,2,2,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,1,0,0, +2,3,2,3,3,0,0,3,0,1,1,0,1,0,0,0,2,2,1,2,0,0,0,0,0,0,0,0,2,0,1,2, +2,2,1,1,1,1,1,2,2,2,1,0,2,0,1,0,1,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0, +3,3,3,3,2,2,2,2,2,0,2,1,1,1,1,2,1,2,1,1,0,2,0,1,0,1,0,0,2,0,1,2, +1,1,1,1,1,1,1,2,2,1,1,0,2,0,1,0,2,0,0,1,1,1,0,0,2,0,0,0,1,1,0,0, +2,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0,0,0,0,1,2,0,1,2, +2,2,2,1,1,2,1,1,2,2,2,1,2,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,1,1,0,0, +2,3,3,3,3,0,2,2,0,2,1,0,0,0,1,1,1,2,0,2,0,0,0,3,0,0,0,0,2,0,2,2, +1,1,1,2,1,2,1,1,2,2,2,1,2,0,1,1,1,0,1,1,1,1,0,2,1,0,0,0,1,1,0,0, +2,3,3,3,3,0,2,1,0,0,2,0,0,0,0,0,1,2,0,2,0,0,0,0,0,0,0,0,2,0,1,2, +1,1,1,2,1,1,1,1,2,2,2,0,1,0,1,1,1,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0, +3,3,2,2,3,0,1,0,1,0,0,0,0,0,0,0,1,1,0,3,0,0,0,0,0,0,0,0,1,0,2,2, +1,1,1,1,1,2,1,1,2,2,1,2,2,1,0,1,1,1,1,1,0,1,0,0,1,0,0,0,1,1,0,0, +3,1,0,1,0,2,2,2,2,3,2,1,1,1,2,3,0,0,1,0,2,1,1,0,1,1,1,1,2,1,1,1, +1,2,2,1,2,1,2,2,1,1,0,1,2,1,2,2,1,1,1,0,0,1,1,1,2,1,0,1,0,0,0,0, +2,1,0,1,0,3,1,2,2,2,2,1,2,2,1,1,1,0,2,1,2,2,1,1,2,1,1,0,2,1,1,1, +1,2,2,2,2,2,2,2,1,2,0,1,1,0,2,1,1,1,1,1,0,0,1,1,1,1,0,1,0,0,0,0, +2,1,1,1,1,2,2,2,2,1,2,2,2,1,2,2,1,1,2,1,2,3,2,2,1,1,1,1,0,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,0,0,0, +2,2,2,3,2,0,1,2,0,1,2,1,1,0,1,0,1,2,1,2,0,0,0,1,1,0,0,0,1,0,0,2, +1,1,0,0,1,1,0,1,1,1,1,0,2,0,1,1,1,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0, +2,0,0,0,0,1,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,2,1,1,1, +1,2,2,2,2,1,1,2,1,2,1,1,1,0,2,1,2,1,1,1,0,2,1,1,1,1,0,1,0,0,0,0, +3,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,1,0,1,0, +1,1,0,1,0,1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,3,2,0,0,0,0,1,0,0,0,0,0,0,1,1,0,2,0,0,0,0,0,0,0,0,1,0,1,2, +1,1,1,1,1,1,0,0,2,2,2,2,2,0,1,1,0,1,1,1,1,1,0,0,1,0,0,0,1,1,0,1, +2,3,1,2,1,0,1,1,0,2,2,2,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,1,2, +1,1,1,1,2,1,1,1,1,1,1,1,1,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0, +2,2,2,2,2,0,0,2,0,0,2,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,0,2,2, +1,1,1,1,1,0,0,1,2,1,1,0,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,2,0,1,1,0,0,0,1,0,0,2,0,2,0,0,0,0,0,0,0,0,0,0,1,1, +0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,3,2,0,0,1,0,0,1,0,0,0,0,0,0,1,0,2,0,0,0,1,0,0,0,0,0,0,0,2, +1,1,0,0,1,0,0,0,1,1,0,0,1,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,1,2,2,2,1,2,1,2,2,1,1,2,1,1,1,0,1,1,1,1,2,0,1,0,1,1,1,1,0,1,1, +1,1,2,1,1,1,1,1,1,0,0,1,2,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0, +1,0,0,1,3,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,1,0,0,1,0,2,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,2,0,0,1, +0,2,0,1,0,0,1,1,2,0,1,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,1,1,0,2,1,0,1,1,1,0,0,1,0,2,0,1,0,0,0,0,0,0,0,0,0,1, +0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,2,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, +0,1,0,1,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,0,1,2,1,1,1,1,1,1,2,2,1,0,0,1,0,1,0,0,0,0,1,1,1,1,0,0,0, +1,1,2,1,1,1,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,1,2,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,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,0,0,0,0,0,0, +1,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +0,1,1,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, +1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,2,0,0,2,0,1,0,0,1,0,0,1, +1,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, +1,1,1,1,1,1,1,2,0,0,0,0,0,0,2,1,0,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0, +2,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,0,0,0,0,0,0, +1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,1,1,0,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,0,0,1, +) + +Latin5BulgarianModel = { + 'char_to_order_map': Latin5_BulgarianCharToOrderMap, + 'precedence_matrix': BulgarianLangModel, + 'typical_positive_ratio': 0.969392, + 'keep_english_letter': False, + 'charset_name': "ISO-8859-5", + 'language': 'Bulgairan', +} + +Win1251BulgarianModel = { + 'char_to_order_map': win1251BulgarianCharToOrderMap, + 'precedence_matrix': BulgarianLangModel, + 'typical_positive_ratio': 0.969392, + 'keep_english_letter': False, + 'charset_name': "windows-1251", + 'language': 'Bulgarian', +} diff --git a/flex/lib/python3.6/site-packages/chardet/langcyrillicmodel.py b/flex/lib/python3.6/site-packages/chardet/langcyrillicmodel.py new file mode 100644 index 0000000..e5f9a1f --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/langcyrillicmodel.py @@ -0,0 +1,333 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# KOI8-R language model +# Character Mapping Table: +KOI8R_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, # 80 +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, # 90 +223,224,225, 68,226,227,228,229,230,231,232,233,234,235,236,237, # a0 +238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, # b0 + 27, 3, 21, 28, 13, 2, 39, 19, 26, 4, 23, 11, 8, 12, 5, 1, # c0 + 15, 16, 9, 7, 6, 14, 24, 10, 17, 18, 20, 25, 30, 29, 22, 54, # d0 + 59, 37, 44, 58, 41, 48, 53, 46, 55, 42, 60, 36, 49, 38, 31, 34, # e0 + 35, 43, 45, 32, 40, 52, 56, 33, 61, 62, 51, 57, 47, 63, 50, 70, # f0 +) + +win1251_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, +239,240,241,242,243,244,245,246, 68,247,248,249,250,251,252,253, + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +) + +latin5_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, +) + +macCyrillic_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, +239,240,241,242,243,244,245,246,247,248,249,250,251,252, 68, 16, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27,255, +) + +IBM855_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194, 68,195,196,197,198,199,200,201,202,203,204,205, +206,207,208,209,210,211,212,213,214,215,216,217, 27, 59, 54, 70, + 3, 37, 21, 44, 28, 58, 13, 41, 2, 48, 39, 53, 19, 46,218,219, +220,221,222,223,224, 26, 55, 4, 42,225,226,227,228, 23, 60,229, +230,231,232,233,234,235, 11, 36,236,237,238,239,240,241,242,243, + 8, 49, 12, 38, 5, 31, 1, 34, 15,244,245,246,247, 35, 16,248, + 43, 9, 45, 7, 32, 6, 40, 14, 52, 24, 56, 10, 33, 17, 61,249, +250, 18, 62, 20, 51, 25, 57, 30, 47, 29, 63, 22, 50,251,252,255, +) + +IBM866_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 97.6601% +# first 1024 sequences: 2.3389% +# rest sequences: 0.1237% +# negative sequences: 0.0009% +RussianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,3,3,3,3,1,3,3,3,2,3,2,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,2,2,2,2,2,0,0,2, +3,3,3,2,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,2,3,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,2,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,2,3,3,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, +0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, +0,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,2,2,2,3,1,3,3,1,3,3,3,3,2,2,3,0,2,2,2,3,3,2,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,3,3,2,2,3,2,3,3,3,2,1,2,2,0,1,2,2,2,2,2,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,3,0,2,2,3,3,2,1,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,1,2,3,2,2,3,2,3,3,3,3,2,2,3,0,3,2,2,3,1,1,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,3,3,3,3,2,2,2,0,3,3,3,2,2,2,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,2,3,2,2,0,1,3,2,1,2,2,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,2,1,1,3,0,1,1,1,1,2,1,1,0,2,2,2,1,2,0,1,0, +0,0,0,0,0,0,0,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, +3,3,3,3,3,3,2,3,3,2,2,2,2,1,3,2,3,2,3,2,1,2,2,0,1,1,2,1,2,1,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,2,3,3,3,2,2,2,2,0,2,2,2,2,3,1,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,2,3,2,2,3,3,3,3,3,3,3,3,3,1,3,2,0,0,3,3,3,3,2,3,3,3,3,2,3,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,3,2,2,3,3,0,2,1,0,3,2,3,2,3,0,0,1,2,0,0,1,0,1,2,1,1,0, +0,0,0,0,0,0,0,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, +3,0,3,0,2,3,3,3,3,2,3,3,3,3,1,2,2,0,0,2,3,2,2,2,3,2,3,2,2,3,0,0, +0,0,0,0,0,0,0,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, +3,2,3,0,2,3,2,3,0,1,2,3,3,2,0,2,3,0,0,2,3,2,2,0,1,3,1,3,2,2,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,3,0,2,3,3,3,3,3,3,3,3,2,1,3,2,0,0,2,2,3,3,3,2,3,3,0,2,2,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, +3,3,3,3,3,3,2,2,3,3,2,2,2,3,3,0,0,1,1,1,1,1,2,0,0,1,1,1,1,0,1,0, +0,0,0,0,0,0,0,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, +3,3,3,3,3,3,2,2,3,3,3,3,3,3,3,0,3,2,3,3,2,3,2,0,2,1,0,1,1,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,2,2,2,2,3,1,3,2,3,1,1,2,1,0,2,2,2,2,1,3,1,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +2,2,3,3,3,3,3,1,2,2,1,3,1,0,3,0,0,3,0,0,0,1,1,0,1,2,1,0,0,0,0,0, +0,0,0,0,0,0,0,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, +3,2,2,1,1,3,3,3,2,2,1,2,2,3,1,1,2,0,0,2,2,1,3,0,0,2,1,1,2,1,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,3,3,3,1,2,2,2,1,2,1,3,3,1,1,2,1,2,1,2,2,0,2,0,0,1,1,0,1,0, +0,0,0,0,0,0,0,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, +2,3,3,3,3,3,2,1,3,2,2,3,2,0,3,2,0,3,0,1,0,1,1,0,0,1,1,1,1,0,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,3,3,3,2,2,2,3,3,1,2,1,2,1,0,1,0,1,1,0,1,0,0,2,1,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,1,1,2,1,2,3,3,2,2,1,2,2,3,0,2,1,0,0,2,2,3,2,1,2,2,2,2,2,3,1,0, +0,0,0,0,0,0,0,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, +3,3,3,3,3,1,1,0,1,1,2,2,1,1,3,0,0,1,3,1,1,1,0,0,0,1,0,1,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,0,0,0,0, +2,1,3,3,3,2,0,0,0,2,1,0,1,0,2,0,0,2,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, +2,0,1,0,0,2,3,2,2,2,1,2,2,2,1,2,1,0,0,1,1,1,0,2,0,1,1,1,0,0,1,1, +1,0,0,0,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,0,0,0,0,1,0,0,0,0,3,0,1,2,1,0,0,0,0,0,0,0,1,1,0,0,1,1, +1,0,1,0,1,2,0,0,1,1,2,1,0,1,1,1,1,0,1,1,1,1,0,1,0,0,1,0,0,1,1,0, +2,2,3,2,2,2,3,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,0,1,0,1,1,1,0,2,1, +1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,0,1,1,0, +3,3,3,2,2,2,2,3,2,2,1,1,2,2,2,2,1,1,3,1,2,1,2,0,0,1,1,0,1,0,2,1, +1,1,1,1,1,2,1,0,1,1,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,1,0, +2,0,0,1,0,3,2,2,2,2,1,2,1,2,1,2,0,0,0,2,1,2,2,1,1,2,2,0,1,1,0,2, +1,1,1,1,1,0,1,1,1,2,1,1,1,2,1,0,1,2,1,1,1,1,0,1,1,1,0,0,1,0,0,1, +1,3,2,2,2,1,1,1,2,3,0,0,0,0,2,0,2,2,1,0,0,0,0,0,0,1,0,0,0,0,1,1, +1,0,1,1,0,1,0,1,1,0,1,1,0,2,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, +2,3,2,3,2,1,2,2,2,2,1,0,0,0,2,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,2,1, +1,1,2,1,0,2,0,0,1,0,1,0,0,1,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,0, +3,0,0,1,0,2,2,2,3,2,2,2,2,2,2,2,0,0,0,2,1,2,1,1,1,2,2,0,0,0,1,2, +1,1,1,1,1,0,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,1, +2,3,2,3,3,2,0,1,1,1,0,0,1,0,2,0,1,1,3,1,0,0,0,0,0,0,0,1,0,0,2,1, +1,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,0,0,1,1,0,1,0,0,0,0,0,0,1,0, +2,3,3,3,3,1,2,2,2,2,0,1,1,0,2,1,1,1,2,1,0,1,1,0,0,1,0,1,0,0,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,2,0,0,1,1,2,2,1,0,0,2,0,1,1,3,0,0,1,0,0,0,0,0,1,0,1,2,1, +1,1,2,0,1,1,1,0,1,0,1,1,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,1,0,1,1,0, +1,3,2,3,2,1,0,0,2,2,2,0,1,0,2,0,1,1,1,0,1,0,0,0,3,0,1,1,0,0,2,1, +1,1,1,0,1,1,0,0,0,0,1,1,0,1,0,0,2,1,1,0,1,0,0,0,1,0,1,0,0,1,1,0, +3,1,2,1,1,2,2,2,2,2,2,1,2,2,1,1,0,0,0,2,2,2,0,0,0,1,2,1,0,1,0,1, +2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,1,1,1,0,1,0,1,1,0,1,1,1,0,0,1, +3,0,0,0,0,2,0,1,1,1,1,1,1,1,0,1,0,0,0,1,1,1,0,1,0,1,1,0,0,1,0,1, +1,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1, +1,3,3,2,2,0,0,0,2,2,0,0,0,1,2,0,1,1,2,0,0,0,0,0,0,0,0,1,0,0,2,1, +0,1,1,0,0,1,1,0,0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +2,3,2,3,2,0,0,0,0,1,1,0,0,0,2,0,2,0,2,0,0,0,0,0,1,0,0,1,0,0,1,1, +1,1,2,0,1,2,1,0,1,1,2,1,1,1,1,1,2,1,1,0,1,0,0,1,1,1,1,1,0,1,1,0, +1,3,2,2,2,1,0,0,2,2,1,0,1,2,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1, +0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,0,2,3,1,2,2,2,2,2,2,1,1,0,0,0,1,0,1,0,2,1,1,1,0,0,0,0,1, +1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +2,0,2,0,0,1,0,3,2,1,2,1,2,2,0,1,0,0,0,2,1,0,0,2,1,1,1,1,0,2,0,2, +2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,0,0,0,1,1,1,1,0,1,0,0,1, +1,2,2,2,2,1,0,0,1,0,0,0,0,0,2,0,1,1,1,1,0,0,0,0,1,0,1,2,0,0,2,0, +1,0,1,1,1,2,1,0,1,0,1,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0, +2,1,2,2,2,0,3,0,1,1,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0, +1,2,2,3,2,2,0,0,1,1,2,0,1,2,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1, +0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, +2,2,1,1,2,1,2,2,2,2,2,1,2,2,0,1,0,0,0,1,2,2,2,1,2,1,1,1,1,1,2,1, +1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,0,1, +1,2,2,2,2,0,1,0,2,2,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +0,0,1,0,0,1,0,0,0,0,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,0, +1,2,2,2,2,0,0,0,2,2,2,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1, +0,1,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,0,0,1,0,0,1,1,2,0,0,0,0,1,0,1,0,0,1,0,0,2,0,0,0,1, +0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,1,1,2,0,2,1,1,1,1,0,2,2,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1, +0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,0,2,1,2,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0, +0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +1,0,0,0,0,2,0,1,2,1,0,1,1,1,0,1,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1, +0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1, +2,2,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,1, +1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0, +2,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,1, +1,1,1,0,1,0,1,0,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0, +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,1, +1,1,0,1,1,0,1,0,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0, +0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, +) + +Koi8rModel = { + 'char_to_order_map': KOI8R_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "KOI8-R", + 'language': 'Russian', +} + +Win1251CyrillicModel = { + 'char_to_order_map': win1251_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "windows-1251", + 'language': 'Russian', +} + +Latin5CyrillicModel = { + 'char_to_order_map': latin5_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "ISO-8859-5", + 'language': 'Russian', +} + +MacCyrillicModel = { + 'char_to_order_map': macCyrillic_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "MacCyrillic", + 'language': 'Russian', +} + +Ibm866Model = { + 'char_to_order_map': IBM866_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "IBM866", + 'language': 'Russian', +} + +Ibm855Model = { + 'char_to_order_map': IBM855_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "IBM855", + 'language': 'Russian', +} diff --git a/flex/lib/python3.6/site-packages/chardet/langgreekmodel.py b/flex/lib/python3.6/site-packages/chardet/langgreekmodel.py new file mode 100644 index 0000000..5332221 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/langgreekmodel.py @@ -0,0 +1,225 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin7_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 + 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 +253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 + 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 +253,233, 90,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 +253,253,253,253,247,248, 61, 36, 46, 71, 73,253, 54,253,108,123, # b0 +110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 + 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 +124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 + 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 +) + +win1253_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 + 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 +253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 + 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 +253,233, 61,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 +253,253,253,253,247,253,253, 36, 46, 71, 73,253, 54,253,108,123, # b0 +110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 + 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 +124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 + 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 98.2851% +# first 1024 sequences:1.7001% +# rest sequences: 0.0359% +# negative sequences: 0.0148% +GreekLangModel = ( +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,0,0,0,0,0,0,0, +0,0,3,2,2,3,3,3,3,3,3,3,3,1,3,3,3,0,2,2,3,3,0,3,0,3,2,0,3,3,3,0, +3,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,0,3,3,0,3,2,3,3,0,3,2,3,3,3,0,0,3,0,3,0,3,3,2,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,2,3,2,2,3,3,3,3,3,3,3,3,0,3,3,3,3,0,2,3,3,0,3,3,3,3,2,3,3,3,0, +2,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,2,1,3,3,3,3,2,3,3,2,3,3,2,0, +0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,2,3,3,0, +2,0,1,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,3,0,0,0,0,3,3,0,3,1,3,3,3,0,3,3,0,3,3,3,3,0,0,0,0, +2,0,0,0,2,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,3,3,3,3,3,0,3,0,3,3,3,3,3,0,3,2,2,2,3,0,2,3,3,3,3,3,2,3,3,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,3,3,3,3,3,3,2,2,2,3,3,3,3,0,3,1,3,3,3,3,2,3,3,3,3,3,3,3,2,2,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,3,3,3,3,3,2,0,3,0,0,0,3,3,2,3,3,3,3,3,0,0,3,2,3,0,2,3,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,3,0,3,3,3,3,0,0,3,3,0,2,3,0,3,0,3,3,3,0,0,3,0,3,0,2,2,3,3,0,0, +0,0,1,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,3,2,3,3,3,3,0,3,3,3,3,3,0,3,3,2,3,2,3,3,2,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,3,3,2,3,2,3,3,3,3,3,3,0,2,3,2,3,2,2,2,3,2,3,3,2,3,0,2,2,2,3,0, +2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,0,3,3,3,2,3,3,0,0,3,0,3,0,0,0,3,2,0,3,0,3,0,0,2,0,2,0, +0,0,0,0,2,0,0,0,0,0,2,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,2,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,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,0,0,0,3,3,0,3,3,3,0,0,1,2,3,0, +3,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,0,3,2,2,3,3,0,3,3,3,3,3,2,1,3,0,3,2,3,3,2,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,0,0,0, +0,0,3,3,0,2,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,3,0,3,2,3,0,0,3,3,3,0, +3,0,0,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,2,0,3,2,3,0,0,3,2,3,0, +2,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,1,2,2,3,3,3,3,3,3,0,2,3,0,3,0,0,0,3,3,0,3,0,2,0,0,2,3,1,0, +2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,3,0,3,0,3,3,2,3,0,3,3,3,3,3,3,0,3,3,3,0,2,3,0,0,3,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,3,0,3,3,3,0,0,3,0,0,0,3,3,0,3,0,2,3,3,0,0,3,0,3,0,3,3,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,3,0,0,0,3,3,3,3,3,3,0,0,3,0,2,0,0,0,3,3,0,3,0,3,0,0,2,0,2,0, +0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,3,0,3,0,2,0,3,2,0,3,2,3,2,3,0,0,3,2,3,2,3,3,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,3,0,0,2,3,3,3,3,3,0,0,0,3,0,2,1,0,0,3,2,2,2,0,3,0,0,2,2,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,3,0,3,3,3,2,0,3,0,3,0,3,3,0,2,1,2,3,3,0,0,3,0,3,0,3,3,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,2,3,3,3,0,3,3,3,3,3,3,0,2,3,0,3,0,0,0,2,1,0,2,2,3,0,0,2,2,2,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,2,3,3,3,2,3,0,0,1,3,0,2,0,0,0,0,3,0,1,0,2,0,0,1,1,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,0,0, +0,3,3,3,3,3,1,0,3,0,0,0,3,2,0,3,2,3,3,3,0,0,3,0,3,2,2,2,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,0,0,0,0, +0,3,0,3,3,3,0,0,3,0,0,0,0,2,0,2,3,3,2,2,2,2,3,0,2,0,2,2,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,3,3,3,3,2,0,0,0,0,0,0,2,3,0,2,0,2,3,2,0,0,3,0,3,0,3,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,0,0,0,0,0, +0,0,0,0,0,0,3,2,3,3,2,2,3,0,2,0,3,0,0,0,2,0,0,0,0,1,2,0,2,0,2,0, +0,2,0,2,0,2,2,0,0,1,0,2,2,2,0,2,2,2,0,2,2,2,0,0,2,0,0,1,0,0,0,0, +0,2,0,3,3,2,0,0,0,0,0,0,1,3,0,2,0,2,2,2,0,0,2,0,3,0,0,2,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,3,0,2,3,2,0,2,2,0,2,0,2,2,0,2,0,2,2,2,0,0,0,0,0,0,2,3,0,0,0,2, +0,1,2,0,0,0,0,2,2,0,0,0,2,1,0,2,2,0,0,0,0,0,0,1,0,2,0,0,0,0,0,0, +0,0,2,1,0,2,3,2,2,3,2,3,2,0,0,3,3,3,0,0,3,2,0,0,0,1,1,0,2,0,2,2, +0,2,0,2,0,2,2,0,0,2,0,2,2,2,0,2,2,2,2,0,0,2,0,0,0,2,0,1,0,0,0,0, +0,3,0,3,3,2,2,0,3,0,0,0,2,2,0,2,2,2,1,2,0,0,1,2,2,0,0,3,0,0,0,2, +0,1,2,0,0,0,1,2,0,0,0,0,0,0,0,2,2,0,1,0,0,2,0,0,0,2,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,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,2,2,0,0,0,2,0,2,3,3,0,2,0,0,0,0,0,0,2,2,2,0,2,2,0,2,0,2, +0,2,2,0,0,2,2,2,2,1,0,0,2,2,0,2,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0, +0,2,0,3,2,3,0,0,0,3,0,0,2,2,0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,0,2, +0,0,2,2,0,0,2,2,2,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,3,2,0,2,2,2,2,2,0,0,0,2,0,0,0,0,2,0,1,0,0,2,0,1,0,0,0, +0,2,2,2,0,2,2,0,1,2,0,2,2,2,0,2,2,2,2,1,2,2,0,0,2,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,2,0,2,0,2,2,0,0,0,0,1,2,1,0,0,2,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,3,2,3,0,0,2,0,0,0,2,2,0,2,0,0,0,1,0,0,2,0,2,0,2,2,0,0,0,0, +0,0,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0, +0,2,2,3,2,2,0,0,0,0,0,0,1,3,0,2,0,2,2,0,0,0,1,0,2,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,2,0,2,0,3,2,0,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,2,0,0,0,0,1,1,0,0,2,1,2,0,2,2,0,1,0,0,1,0,0,0,2,0,0,0,0,0,0, +0,3,0,2,2,2,0,0,2,0,0,0,2,0,0,0,2,3,0,2,0,0,0,0,0,0,2,2,0,0,0,2, +0,1,2,0,0,0,1,2,2,1,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,1,2,0,2,2,0,2,0,0,2,0,0,0,0,1,2,1,0,2,1,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,3,1,2,2,0,2,0,0,0,0,2,0,0,0,2,0,0,3,0,0,0,0,2,2,2,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,2,1,0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,2, +0,2,2,0,0,2,2,2,2,2,0,1,2,0,0,0,2,2,0,1,0,2,0,0,2,2,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,0,0,0,0,2,0,2,0,0,0,0,2, +0,1,2,0,0,0,0,2,2,1,0,1,0,1,0,2,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,2,0,0,2,2,0,0,0,0,1,0,0,0,0,0,0,2, +0,2,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0, +0,2,2,2,2,0,0,0,3,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,1, +0,0,2,0,0,0,0,1,2,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,2,2,2,0,0,0,2,0,0,0,0,0,0,0,0,2, +0,0,1,0,0,0,0,2,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,3,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,2, +0,0,2,0,0,0,0,2,2,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,0,2,2,1,0,0,0,0,0,0,2,0,0,2,0,2,2,2,0,0,0,0,0,0,2,0,0,0,0,2, +0,0,2,0,0,2,0,2,2,0,0,0,0,2,0,2,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0, +0,0,3,0,0,0,2,2,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,2,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,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0, +0,2,2,2,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1, +0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,2,0,0,0,2,0,0,0,0,0,1,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,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,1,0,0,1,0,2,0,0,0, +0,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,1,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,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,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,2,0,2,0,0,0, +0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,1,2,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,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,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, +) + +Latin7GreekModel = { + 'char_to_order_map': Latin7_char_to_order_map, + 'precedence_matrix': GreekLangModel, + 'typical_positive_ratio': 0.982851, + 'keep_english_letter': False, + 'charset_name': "ISO-8859-7", + 'language': 'Greek', +} + +Win1253GreekModel = { + 'char_to_order_map': win1253_char_to_order_map, + 'precedence_matrix': GreekLangModel, + 'typical_positive_ratio': 0.982851, + 'keep_english_letter': False, + 'charset_name': "windows-1253", + 'language': 'Greek', +} diff --git a/flex/lib/python3.6/site-packages/chardet/langhebrewmodel.py b/flex/lib/python3.6/site-packages/chardet/langhebrewmodel.py new file mode 100644 index 0000000..58f4c87 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/langhebrewmodel.py @@ -0,0 +1,200 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Simon Montagu +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Shoshannah Forbes - original C code (?) +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Windows-1255 language model +# Character Mapping Table: +WIN1255_CHAR_TO_ORDER_MAP = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 69, 91, 79, 80, 92, 89, 97, 90, 68,111,112, 82, 73, 95, 85, # 40 + 78,121, 86, 71, 67,102,107, 84,114,103,115,253,253,253,253,253, # 50 +253, 50, 74, 60, 61, 42, 76, 70, 64, 53,105, 93, 56, 65, 54, 49, # 60 + 66,110, 51, 43, 44, 63, 81, 77, 98, 75,108,253,253,253,253,253, # 70 +124,202,203,204,205, 40, 58,206,207,208,209,210,211,212,213,214, +215, 83, 52, 47, 46, 72, 32, 94,216,113,217,109,218,219,220,221, + 34,116,222,118,100,223,224,117,119,104,125,225,226, 87, 99,227, +106,122,123,228, 55,229,230,101,231,232,120,233, 48, 39, 57,234, + 30, 59, 41, 88, 33, 37, 36, 31, 29, 35,235, 62, 28,236,126,237, +238, 38, 45,239,240,241,242,243,127,244,245,246,247,248,249,250, + 9, 8, 20, 16, 3, 2, 24, 14, 22, 1, 25, 15, 4, 11, 6, 23, + 12, 19, 13, 26, 18, 27, 21, 17, 7, 10, 5,251,252,128, 96,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 98.4004% +# first 1024 sequences: 1.5981% +# rest sequences: 0.087% +# negative sequences: 0.0015% +HEBREW_LANG_MODEL = ( +0,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,3,2,1,2,0,1,0,0, +3,0,3,1,0,0,1,3,2,0,1,1,2,0,2,2,2,1,1,1,1,2,1,1,1,2,0,0,2,2,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2, +1,2,1,2,1,2,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2, +1,2,1,3,1,1,0,0,2,0,0,0,1,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,1,2,2,1,3, +1,2,1,1,2,2,0,0,2,2,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,1,0,1,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,2,2,2,3,2, +1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,3,2,2,3,2,2,2,1,2,2,2,2, +1,2,1,1,2,2,0,1,2,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,0,2,2,2,2,2, +0,2,0,2,2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,0,2,2,2, +0,2,1,2,2,2,0,0,2,1,0,0,0,0,1,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,2,1,2,3,2,2,2, +1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,2,0,2, +0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,2,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,2,2,3,2,1,2,1,1,1, +0,1,1,1,1,1,3,0,1,0,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,0,1,0,0,1,0,0,0,0, +0,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,2,1,2,3,3,2,3,3,3,3,2,3,2,1,2,0,2,1,2, +0,2,0,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,1,2,2,3,3,2,3,2,3,2,2,3,1,2,2,0,2,2,2, +0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,2,2,3,3,3,3,1,3,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,2,3,2,2,2,1,2,2,0,2,2,2,2, +0,2,0,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,1,3,2,3,3,2,3,3,2,2,1,2,2,2,2,2,2, +0,2,1,2,1,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,2,3,3,2,3,3,3,3,2,3,2,3,3,3,3,3,2,2,2,2,2,2,2,1, +0,2,0,1,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,1,2,3,3,3,3,3,3,3,2,3,2,3,2,1,2,3,0,2,1,2,2, +0,2,1,1,2,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,2,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,3,2,1,3,1,2,2,2,1,2,3,3,1,2,1,2,2,2,2, +0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,0,2,3,3,3,1,3,3,3,1,2,2,2,2,1,1,2,2,2,2,2,2, +0,2,0,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,2,2,3,3,3,2,1,2,3,2,3,2,2,2,2,1,2,1,1,1,2,2, +0,2,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0, +1,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,3,2,3,1,2,2,2,2,3,2,3,1,1,2,2,1,2,2,1,1,0,2,2,2,2, +0,1,0,1,2,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,0,0,1,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,0,1,0,1,1,0,1,1,0,0,0,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +3,2,2,1,2,2,2,2,2,2,2,1,2,2,1,2,2,1,1,1,1,1,1,1,1,2,1,1,0,3,3,3, +0,3,0,2,2,2,2,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,1,2,2,2,1,1,1,2,0,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,0, +2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,0,0,0,0, +0,0,0,1,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, +2,3,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,0,2,1,0, +0,0,0,0,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, +3,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,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,0,1,0,0,0,0,0,0,0,0,0, +0,3,1,1,2,2,2,2,2,1,2,2,2,1,1,2,2,2,2,2,2,2,1,2,2,1,0,1,1,1,1,0, +0,1,0,0,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, +3,2,1,1,1,1,2,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, +0,0,2,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,0,0, +2,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,2,1,2,1,1,1,1,0,0,0,0, +0,0,0,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, +1,2,1,2,2,2,2,2,2,2,2,2,2,1,2,1,2,1,1,2,1,1,1,2,1,2,1,2,0,1,0,1, +0,0,0,0,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,3,1,2,2,2,1,2,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,2,1,2,1,1,0,1,0,1, +0,0,0,0,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, +2,1,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0, +2,1,1,1,1,1,1,1,0,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,1,1,1,0,1,0,0,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0, +0,1,1,1,2,1,2,2,2,0,2,0,2,0,1,1,2,1,1,1,1,2,1,0,1,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,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,1,0,0,0,0,0,1,0,1,2,2,0,1,0,0,1,1,2,2,1,2,0,2,0,0,0,1,2,0,1, +2,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,2,0,2,1,2,0,2,0,0,1,1,1,1,1,1,0,1,0,0,0,1,0,0,1, +2,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,1,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,1,2,2,0,0,1,0,0,0,1,0,0,1, +1,1,2,1,0,1,1,1,0,1,0,1,1,1,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,2,1, +0,2,0,1,2,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, +2,1,0,0,1,0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,1,0,0,0,1,1,0,1, +2,0,1,0,1,0,1,0,0,1,0,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +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, +0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,0,1,1,2,1,1,2,0,1,0,0,0,1,1,0,1, +1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,0,0,2,1,1,2,0,2,0,0,0,1,1,0,1, +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, +0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,2,2,1,2,1,1,0,1,0,0,0,1,1,0,1, +2,0,1,0,0,1,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,0,0,0,0,1,2,2,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,1,0,1, +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, +0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,2,1,1,1,0,2,1,1,0,0,0,2,1,0,1, +1,0,0,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,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,0,2,1,1,0,1,0,0,0,1,1,0,1, +2,2,1,1,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,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,1,0,2,1,1,0,1,0,0,1,1,0,1,2,1,0,2,0,0,0,1,1,0,1, +2,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,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,0,0,0,0,0,0,0,2,0,0,0,0,0, +0,1,0,0,2,0,2,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,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,0,0, +1,0,0,1,0,0,1,0,0,1,0,0,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,1,0,1,1,2,0,1,0,0,1,1,1,0,1,0,0,1,0,0,0,1,0,0,1, +1,0,0,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, +1,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,0,2,1,1,1,1,1,0,1,0,0,0,0,1,0,1, +0,1,1,1,2,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,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,0,0,0,0,0,0,0,0, +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, +0,0,0,0,0,0,0,0,0,0,1,2,1,0,0,0,0,0,1,1,1,1,1,0,1,0,0,0,1,1,0,0, +) + +Win1255HebrewModel = { + 'char_to_order_map': WIN1255_CHAR_TO_ORDER_MAP, + 'precedence_matrix': HEBREW_LANG_MODEL, + 'typical_positive_ratio': 0.984004, + 'keep_english_letter': False, + 'charset_name': "windows-1255", + 'language': 'Hebrew', +} diff --git a/flex/lib/python3.6/site-packages/chardet/langhungarianmodel.py b/flex/lib/python3.6/site-packages/chardet/langhungarianmodel.py new file mode 100644 index 0000000..bb7c095 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/langhungarianmodel.py @@ -0,0 +1,225 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin2_HungarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, + 46, 71, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, +253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, + 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, +159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174, +175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190, +191,192,193,194,195,196,197, 75,198,199,200,201,202,203,204,205, + 79,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, +221, 51, 81,222, 78,223,224,225,226, 44,227,228,229, 61,230,231, +232,233,234, 58,235, 66, 59,236,237,238, 60, 69, 63,239,240,241, + 82, 14, 74,242, 70, 80,243, 72,244, 15, 83, 77, 84, 30, 76, 85, +245,246,247, 25, 73, 42, 24,248,249,250, 31, 56, 29,251,252,253, +) + +win1250HungarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, + 46, 72, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, +253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, + 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, +161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176, +177,178,179,180, 78,181, 69,182,183,184,185,186,187,188,189,190, +191,192,193,194,195,196,197, 76,198,199,200,201,202,203,204,205, + 81,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, +221, 51, 83,222, 80,223,224,225,226, 44,227,228,229, 61,230,231, +232,233,234, 58,235, 66, 59,236,237,238, 60, 70, 63,239,240,241, + 84, 14, 75,242, 71, 82,243, 73,244, 15, 85, 79, 86, 30, 77, 87, +245,246,247, 25, 74, 42, 24,248,249,250, 31, 56, 29,251,252,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 94.7368% +# first 1024 sequences:5.2623% +# rest sequences: 0.8894% +# negative sequences: 0.0009% +HungarianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,2,3,3,1,1,2,2,2,2,2,1,2, +3,2,2,3,3,3,3,3,2,3,3,3,3,3,3,1,2,3,3,3,3,2,3,3,1,1,3,3,0,1,1,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,2,0, +3,2,1,3,3,3,3,3,2,3,3,3,3,3,1,1,2,3,3,3,3,3,3,3,1,1,3,2,0,1,1,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,1,0, +3,3,3,3,3,3,3,3,3,3,3,1,1,2,3,3,3,1,3,3,3,3,3,1,3,3,2,2,0,3,2,3, +0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,3,3,2,3,3,2,2,3,2,3,2,0,3,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,1,2,3,2,2,3,1,2,3,3,2,2,0,3,3,3, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,3,2,3,3,3,3,2,3,3,3,3,0,2,3,2, +0,0,0,1,1,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,1,1,1,3,3,2,1,3,2,2,3,2,1,3,2,2,1,0,3,3,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,2,2,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,3,2,2,3,1,1,3,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,1,3,3,3,3,3,2,2,1,3,3,3,0,1,1,2, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,2,0,3,2,3, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,1,3,2,2,2,3,1,1,3,3,1,1,0,3,3,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,2,3,3,3,3,3,1,2,3,2,2,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,1,3,3,2,2,1,3,3,3,1,1,3,1,2,3,2,3,2,2,2,1,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,2,2,3,2,1,0,3,2,0,1,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,0,0, +3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,1,0,3,3,3,3,0,2,3,0,0,2,1,0,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,0,0,0, +3,3,3,3,3,3,2,2,3,3,2,2,2,2,3,3,0,1,2,3,2,3,2,2,3,2,1,2,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,3,3,3,3,3,1,2,3,3,3,2,1,2,3,3,2,2,2,3,2,3,3,1,3,3,1,1,0,2,3,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,1,2,2,2,2,3,3,3,1,1,1,3,3,1,1,3,1,1,3,2,1,2,3,1,1,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,1,2,1,1,3,3,1,1,1,1,3,3,1,1,2,2,1,2,1,1,2,2,1,1,0,2,2,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,1,1,2,1,1,3,3,1,0,1,1,3,3,2,0,1,1,2,3,1,0,2,2,1,0,0,1,3,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,2,1,3,3,3,3,3,1,2,3,2,3,3,2,1,1,3,2,3,2,1,2,2,0,1,2,1,0,0,1,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,1,0, +3,3,3,3,2,2,2,2,3,1,2,2,1,1,3,3,0,3,2,1,2,3,2,1,3,3,1,1,0,2,1,3, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,2,3,3,3,2,1,1,3,3,1,1,1,2,2,3,2,3,2,2,2,1,0,2,2,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +1,0,0,3,3,3,3,3,0,0,3,3,2,3,0,0,0,2,3,3,1,0,1,2,0,0,1,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,0,0,0,0,0, +3,1,2,3,3,3,3,3,1,2,3,3,2,2,1,1,0,3,3,2,2,1,2,2,1,0,2,2,0,1,1,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,0, +3,3,2,2,1,3,1,2,3,3,2,2,1,1,2,2,1,1,1,1,3,2,1,1,1,1,2,1,0,1,2,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +2,3,3,1,1,1,1,1,3,3,3,0,1,1,3,3,1,1,1,1,1,2,2,0,3,1,1,2,0,2,1,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,1,0,1,2,1,2,2,0,1,2,3,1,2,0,0,0,2,1,1,1,1,1,2,0,0,1,1,0,0,0,0, +1,2,1,2,2,2,1,2,1,2,0,2,0,2,2,1,1,2,1,1,2,1,1,1,0,1,0,0,0,1,1,0, +1,1,1,2,3,2,3,3,0,1,2,2,3,1,0,1,0,2,1,2,2,0,1,1,0,0,1,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,0,0,0,0,0, +1,0,0,3,3,2,2,1,0,0,3,2,3,2,0,0,0,1,1,3,0,0,1,1,0,0,2,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,0,0,0,0,0, +3,1,1,2,2,3,3,1,0,1,3,2,3,1,1,1,0,1,1,1,1,1,3,1,0,0,2,2,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, +3,1,1,1,2,2,2,1,0,1,2,3,3,2,0,0,0,2,1,1,1,2,1,1,1,0,1,1,1,0,0,0, +1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,2,1,1,1,1,1,1,0,1,1,1,0,0,1,1, +3,2,2,1,0,0,1,1,2,2,0,3,0,1,2,1,1,0,0,1,1,1,0,1,1,1,1,0,2,1,1,1, +2,2,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,2,3,1,1,1,1,1,1,1,1,1,0,1, +2,3,3,0,1,0,0,0,3,3,1,0,0,1,2,2,1,0,0,0,0,2,0,0,1,1,1,0,2,1,1,1, +2,1,1,1,1,1,1,2,1,1,0,1,1,0,1,1,1,0,1,2,1,1,0,1,1,1,1,1,1,1,0,1, +2,3,3,0,1,0,0,0,2,2,0,0,0,0,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,1,0, +2,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, +3,2,2,0,1,0,1,0,2,3,2,0,0,1,2,2,1,0,0,1,1,1,0,0,2,1,0,1,2,2,1,1, +2,1,1,1,1,1,1,2,1,1,1,1,1,1,0,2,1,0,1,1,0,1,1,1,0,1,1,2,1,1,0,1, +2,2,2,0,0,1,0,0,2,2,1,1,0,0,2,1,1,0,0,0,1,2,0,0,2,1,0,0,2,1,1,1, +2,1,1,1,1,2,1,2,1,1,1,2,2,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1, +1,2,3,0,0,0,1,0,3,2,1,0,0,1,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,2,1, +1,1,0,0,0,1,0,1,1,1,1,1,2,0,0,1,0,0,0,2,0,0,1,1,1,1,1,1,1,1,0,1, +3,0,0,2,1,2,2,1,0,0,2,1,2,2,0,0,0,2,1,1,1,0,1,1,0,0,1,1,2,0,0,0, +1,2,1,2,2,1,1,2,1,2,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,0,0,1, +1,3,2,0,0,0,1,0,2,2,2,0,0,0,2,2,1,0,0,0,0,3,1,1,1,1,0,0,2,1,1,1, +2,1,0,1,1,1,0,1,1,1,1,1,1,1,0,2,1,0,0,1,0,1,1,0,1,1,1,1,1,1,0,1, +2,3,2,0,0,0,1,0,2,2,0,0,0,0,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,1,0, +2,1,1,1,1,2,1,2,1,2,0,1,1,1,0,2,1,1,1,2,1,1,1,1,0,1,1,1,1,1,0,1, +3,1,1,2,2,2,3,2,1,1,2,2,1,1,0,1,0,2,2,1,1,1,1,1,0,0,1,1,0,1,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,0,0, +2,2,2,0,0,0,0,0,2,2,0,0,0,0,2,2,1,0,0,0,1,1,0,0,1,2,0,0,2,1,1,1, +2,2,1,1,1,2,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,1,1,0,1,2,1,1,1,0,1, +1,0,0,1,2,3,2,1,0,0,2,0,1,1,0,0,0,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0, +1,2,1,2,1,2,1,1,1,2,0,2,1,1,1,0,1,2,0,0,1,1,1,0,0,0,0,0,0,0,0,0, +2,3,2,0,0,0,0,0,1,1,2,1,0,0,1,1,1,0,0,0,0,2,0,0,1,1,0,0,2,1,1,1, +2,1,1,1,1,1,1,2,1,0,1,1,1,1,0,2,1,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1, +1,2,2,0,1,1,1,0,2,2,2,0,0,0,3,2,1,0,0,0,1,1,0,0,1,1,0,1,1,1,0,0, +1,1,0,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,0,0,1,1,1,0,1,0,1, +2,1,0,2,1,1,2,2,1,1,2,1,1,1,0,0,0,1,1,0,1,1,1,1,0,0,1,1,1,0,0,0, +1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,1,0, +1,2,3,0,0,0,1,0,2,2,0,0,0,0,2,2,0,0,0,0,0,1,0,0,1,0,0,0,2,0,1,0, +2,1,1,1,1,1,0,2,0,0,0,1,2,1,1,1,1,0,1,2,0,1,0,1,0,1,1,1,0,1,0,1, +2,2,2,0,0,0,1,0,2,1,2,0,0,0,1,1,2,0,0,0,0,1,0,0,1,1,0,0,2,1,0,1, +2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, +1,2,2,0,0,0,1,0,2,2,2,0,0,0,1,1,0,0,0,0,0,1,1,0,2,0,0,1,1,1,0,1, +1,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,0,0,1,1,0,1,0,1,1,1,1,1,0,0,0,1, +1,0,0,1,0,1,2,1,0,0,1,1,1,2,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,0,0,0, +0,2,1,2,1,1,1,1,1,2,0,2,0,1,1,0,1,2,1,0,1,1,1,0,0,0,0,0,0,1,0,0, +2,1,1,0,1,2,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,2,1,0,1, +2,2,1,1,1,1,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,0,1,0,1,1,1,1,1,0,1, +1,2,2,0,0,0,0,0,1,1,0,0,0,0,2,1,0,0,0,0,0,2,0,0,2,2,0,0,2,0,0,1, +2,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,1, +1,1,2,0,0,3,1,0,2,1,1,1,0,0,1,1,1,0,0,0,1,1,0,0,0,1,0,0,1,0,1,0, +1,2,1,0,1,1,1,2,1,1,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,0,0, +2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,2,0,0,0, +2,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,1,0,1, +2,1,1,1,2,1,1,1,0,1,1,2,1,0,0,0,0,1,1,1,1,0,1,0,0,0,0,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,0,0,0,0,0, +1,1,0,1,1,1,1,1,0,0,1,1,2,1,0,0,0,1,1,0,0,0,1,1,0,0,1,0,1,0,0,0, +1,2,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0, +2,0,0,0,1,1,1,1,0,0,1,1,0,0,0,0,0,1,1,1,2,0,0,1,0,0,1,0,1,0,0,0, +0,1,1,1,1,1,1,1,1,2,0,1,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,1,0,0,2,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0, +0,1,1,1,1,1,1,0,1,1,0,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +0,1,1,1,1,1,0,0,1,1,0,1,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +0,0,0,1,0,0,0,0,0,0,1,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,1,1,0,1,0,0,1,1,0,1,0,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +2,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,0,1,0,0,1,0,1,0,1,1,1,0,0,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,0,0, +1,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,1,1,1,1,1,0,1,1,0,1,0,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +) + +Latin2HungarianModel = { + 'char_to_order_map': Latin2_HungarianCharToOrderMap, + 'precedence_matrix': HungarianLangModel, + 'typical_positive_ratio': 0.947368, + 'keep_english_letter': True, + 'charset_name': "ISO-8859-2", + 'language': 'Hungarian', +} + +Win1250HungarianModel = { + 'char_to_order_map': win1250HungarianCharToOrderMap, + 'precedence_matrix': HungarianLangModel, + 'typical_positive_ratio': 0.947368, + 'keep_english_letter': True, + 'charset_name': "windows-1250", + 'language': 'Hungarian', +} diff --git a/flex/lib/python3.6/site-packages/chardet/langthaimodel.py b/flex/lib/python3.6/site-packages/chardet/langthaimodel.py new file mode 100644 index 0000000..15f94c2 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/langthaimodel.py @@ -0,0 +1,199 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# The following result for thai was collected from a limited sample (1M). + +# Character Mapping Table: +TIS620CharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,182,106,107,100,183,184,185,101, 94,186,187,108,109,110,111, # 40 +188,189,190, 89, 95,112,113,191,192,193,194,253,253,253,253,253, # 50 +253, 64, 72, 73,114, 74,115,116,102, 81,201,117, 90,103, 78, 82, # 60 + 96,202, 91, 79, 84,104,105, 97, 98, 92,203,253,253,253,253,253, # 70 +209,210,211,212,213, 88,214,215,216,217,218,219,220,118,221,222, +223,224, 99, 85, 83,225,226,227,228,229,230,231,232,233,234,235, +236, 5, 30,237, 24,238, 75, 8, 26, 52, 34, 51,119, 47, 58, 57, + 49, 53, 55, 43, 20, 19, 44, 14, 48, 3, 17, 25, 39, 62, 31, 54, + 45, 9, 16, 2, 61, 15,239, 12, 42, 46, 18, 21, 76, 4, 66, 63, + 22, 10, 1, 36, 23, 13, 40, 27, 32, 35, 86,240,241,242,243,244, + 11, 28, 41, 29, 33,245, 50, 37, 6, 7, 67, 77, 38, 93,246,247, + 68, 56, 59, 65, 69, 60, 70, 80, 71, 87,248,249,250,251,252,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 92.6386% +# first 1024 sequences:7.3177% +# rest sequences: 1.0230% +# negative sequences: 0.0436% +ThaiLangModel = ( +0,1,3,3,3,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,0,0,3,3,3,0,3,3,3,3, +0,3,3,0,0,0,1,3,0,3,3,2,3,3,0,1,2,3,3,3,3,0,2,0,2,0,0,3,2,1,2,2, +3,0,3,3,2,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,0,3,2,3,0,2,2,2,3, +0,2,3,0,0,0,0,1,0,1,2,3,1,1,3,2,2,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1, +3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,3,3,2,3,2,3,3,2,2,2, +3,1,2,3,0,3,3,2,2,1,2,3,3,1,2,0,1,3,0,1,0,0,1,0,0,0,0,0,0,0,1,1, +3,3,2,2,3,3,3,3,1,2,3,3,3,3,3,2,2,2,2,3,3,2,2,3,3,2,2,3,2,3,2,2, +3,3,1,2,3,1,2,2,3,3,1,0,2,1,0,0,3,1,2,1,0,0,1,0,0,0,0,0,0,1,0,1, +3,3,3,3,3,3,2,2,3,3,3,3,2,3,2,2,3,3,2,2,3,2,2,2,2,1,1,3,1,2,1,1, +3,2,1,0,2,1,0,1,0,1,1,0,1,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,3,2,3,2,3,3,2,2,3,2,3,3,2,3,1,1,2,3,2,2,2,3,2,2,2,2,2,1,2,1, +2,2,1,1,3,3,2,1,0,1,2,2,0,1,3,0,0,0,1,1,0,0,0,0,0,2,3,0,0,2,1,1, +3,3,2,3,3,2,0,0,3,3,0,3,3,0,2,2,3,1,2,2,1,1,1,0,2,2,2,0,2,2,1,1, +0,2,1,0,2,0,0,2,0,1,0,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,2,3,3,2,0,0,3,3,0,2,3,0,2,1,2,2,2,2,1,2,0,0,2,2,2,0,2,2,1,1, +0,2,1,0,2,0,0,2,0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,2,3,2,3,2,0,2,2,1,3,2,1,3,2,1,2,3,2,2,3,0,2,3,2,2,1,2,2,2,2, +1,2,2,0,0,0,0,2,0,1,2,0,1,1,1,0,1,0,3,1,1,0,0,0,0,0,0,0,0,0,1,0, +3,3,2,3,3,2,3,2,2,2,3,2,2,3,2,2,1,2,3,2,2,3,1,3,2,2,2,3,2,2,2,3, +3,2,1,3,0,1,1,1,0,2,1,1,1,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,2,0,0, +1,0,0,3,0,3,3,3,3,3,0,0,3,0,2,2,3,3,3,3,3,0,0,0,1,1,3,0,0,0,0,2, +0,0,1,0,0,0,0,0,0,0,2,3,0,0,0,3,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +2,0,3,3,3,3,0,0,2,3,0,0,3,0,3,3,2,3,3,3,3,3,0,0,3,3,3,0,0,0,3,3, +0,0,3,0,0,0,0,2,0,0,2,1,1,3,0,0,1,0,0,2,3,0,1,0,0,0,0,0,0,0,1,0, +3,3,3,3,2,3,3,3,3,3,3,3,1,2,1,3,3,2,2,1,2,2,2,3,1,1,2,0,2,1,2,1, +2,2,1,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0, +3,0,2,1,2,3,3,3,0,2,0,2,2,0,2,1,3,2,2,1,2,1,0,0,2,2,1,0,2,1,2,2, +0,1,1,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,3,3,1,1,3,0,2,3,1,1,3,2,1,1,2,0,2,2,3,2,1,1,1,1,1,2, +3,0,0,1,3,1,2,1,2,0,3,0,0,0,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, +3,3,1,1,3,2,3,3,3,1,3,2,1,3,2,1,3,2,2,2,2,1,3,3,1,2,1,3,1,2,3,0, +2,1,1,3,2,2,2,1,2,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, +3,3,2,3,2,3,3,2,3,2,3,2,3,3,2,1,0,3,2,2,2,1,2,2,2,1,2,2,1,2,1,1, +2,2,2,3,0,1,3,1,1,1,1,0,1,1,0,2,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,3,2,2,1,1,3,2,3,2,3,2,0,3,2,2,1,2,0,2,2,2,1,2,2,2,2,1, +3,2,1,2,2,1,0,2,0,1,0,0,1,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,2,3,1,2,3,3,2,2,3,0,1,1,2,0,3,3,2,2,3,0,1,1,3,0,0,0,0, +3,1,0,3,3,0,2,0,2,1,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,3,2,3,3,0,1,3,1,1,2,1,2,1,1,3,1,1,0,2,3,1,1,1,1,1,1,1,1, +3,1,1,2,2,2,2,1,1,1,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,2,2,1,1,2,1,3,3,2,3,2,2,3,2,2,3,1,2,2,1,2,0,3,2,1,2,2,2,2,2,1, +3,2,1,2,2,2,1,1,1,1,0,0,1,1,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,1,3,3,0,2,1,0,3,2,0,0,3,1,0,1,1,0,1,0,0,0,0,0,1, +1,0,0,1,0,3,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,2,2,2,3,0,0,1,3,0,3,2,0,3,2,2,3,3,3,3,3,1,0,2,2,2,0,2,2,1,2, +0,2,3,0,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,0,2,3,1,3,3,2,3,3,0,3,3,0,3,2,2,3,2,3,3,3,0,0,2,2,3,0,1,1,1,3, +0,0,3,0,0,0,2,2,0,1,3,0,1,2,2,2,3,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1, +3,2,3,3,2,0,3,3,2,2,3,1,3,2,1,3,2,0,1,2,2,0,2,3,2,1,0,3,0,0,0,0, +3,0,0,2,3,1,3,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,3,2,2,2,1,2,0,1,3,1,1,3,1,3,0,0,2,1,1,1,1,2,1,1,1,0,2,1,0,1, +1,2,0,0,0,3,1,1,0,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,3,1,0,0,0,1,0, +3,3,3,3,2,2,2,2,2,1,3,1,1,1,2,0,1,1,2,1,2,1,3,2,0,0,3,1,1,1,1,1, +3,1,0,2,3,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,2,3,0,3,3,0,2,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,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,2,3,1,3,0,0,1,2,0,0,2,0,3,3,2,3,3,3,2,3,0,0,2,2,2,0,0,0,2,2, +0,0,1,0,0,0,0,3,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +0,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,1,2,3,1,3,3,0,0,1,0,3,0,0,0,0,0, +0,0,3,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, +3,3,1,2,3,1,2,3,1,0,3,0,2,2,1,0,2,1,1,2,0,1,0,0,1,1,1,1,0,1,0,0, +1,0,0,0,0,1,1,0,3,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,0,1,1,1,3,1,2,2,2,2,2,2,1,1,1,1,0,3,1,0,1,3,1,1,1,1, +1,1,0,2,0,1,3,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1, +3,0,2,2,1,3,3,2,3,3,0,1,1,0,2,2,1,2,1,3,3,1,0,0,3,2,0,0,0,0,2,1, +0,1,0,0,0,0,1,2,0,1,1,3,1,1,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,3,0,0,1,0,0,0,3,0,0,3,0,3,1,0,1,1,1,3,2,0,0,0,3,0,0,0,0,2,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,1,3,2,1,3,3,1,2,2,0,1,2,1,0,1,2,0,0,0,0,0,3,0,0,0,3,0,0,0,0, +3,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,2,0,3,3,3,2,2,0,1,1,0,1,3,0,0,0,2,2,0,0,0,0,3,1,0,1,0,0,0, +0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,2,3,1,2,0,0,2,1,0,3,1,0,1,2,0,1,1,1,1,3,0,0,3,1,1,0,2,2,1,1, +0,2,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,3,1,2,0,0,2,2,0,1,2,0,1,0,1,3,1,2,1,0,0,0,2,0,3,0,0,0,1,0, +0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,1,2,2,0,0,0,2,0,2,1,0,1,1,0,1,1,1,2,1,0,0,1,1,1,0,2,1,1,1, +0,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1, +0,0,0,2,0,1,3,1,1,1,1,0,0,0,0,3,2,0,1,0,0,0,1,2,0,0,0,1,0,0,0,0, +0,0,0,3,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,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,2,3,2,2,0,0,0,1,0,0,0,0,2,3,2,1,2,2,3,0,0,0,2,3,1,0,0,0,1,1, +0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0, +3,3,2,2,0,1,0,0,0,0,2,0,2,0,1,0,0,0,1,1,0,0,0,2,1,0,1,0,1,1,0,0, +0,1,0,2,0,0,1,0,3,0,1,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,1,0,0,1,0,0,0,0,0,1,1,2,0,0,0,0,1,0,0,1,3,1,0,0,0,0,1,1,0,0, +0,1,0,0,0,0,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0, +3,3,1,1,1,1,2,3,0,0,2,1,1,1,1,1,0,2,1,1,0,0,0,2,1,0,1,2,1,1,0,1, +2,1,0,3,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,3,1,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1, +0,0,0,2,0,0,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, +3,3,2,0,0,0,0,0,0,1,2,1,0,1,1,0,2,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,2,0,0,0,1,3,0,1,0,0,0,2,0,0,0,0,0,0,0,1,2,0,0,0,0,0, +3,3,0,0,1,1,2,0,0,1,2,1,0,1,1,1,0,1,1,0,0,2,1,1,0,1,0,0,1,1,1,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,1,0,0,0,0,1,0,0,0,0,3,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,3,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, +2,3,0,0,1,1,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,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,0,0,0,0,0,0, +1,1,0,1,2,0,1,2,0,0,1,1,0,2,0,1,0,0,1,0,0,0,0,1,0,0,0,2,0,0,0,0, +1,0,0,1,0,1,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,0,0,0,0,0,0,0,1,1,0,1,1,0,2,1,3,0,0,0,0,1,1,0,0,0,0,0,0,0,3, +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, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,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, +2,0,1,0,1,0,0,2,0,0,2,0,0,1,1,2,0,0,1,1,0,0,0,1,0,0,0,1,1,0,0,0, +1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,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,0, +3,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,2,0,0,1,1,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,3,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, +2,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,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,0,0,0,0,0,0,0,0,0, +2,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,1,0,0,1,3,0,0,0, +2,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,2,0,0,1,0,0,0,0, +1,0,0,0,0,0,0,0,0,1,0,0,0,0,2,0,0,0,0,2,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,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,1,0,0,2,1,0,0,1,0,0,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,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,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, +) + +TIS620ThaiModel = { + 'char_to_order_map': TIS620CharToOrderMap, + 'precedence_matrix': ThaiLangModel, + 'typical_positive_ratio': 0.926386, + 'keep_english_letter': False, + 'charset_name': "TIS-620", + 'language': 'Thai', +} diff --git a/flex/lib/python3.6/site-packages/chardet/langturkishmodel.py b/flex/lib/python3.6/site-packages/chardet/langturkishmodel.py new file mode 100644 index 0000000..a427a45 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/langturkishmodel.py @@ -0,0 +1,193 @@ +# -*- coding: utf-8 -*- +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Özgür Baskın - Turkish Language Model +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin5_TurkishCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255, 23, 37, 47, 39, 29, 52, 36, 45, 53, 60, 16, 49, 20, 46, 42, + 48, 69, 44, 35, 31, 51, 38, 62, 65, 43, 56,255,255,255,255,255, +255, 1, 21, 28, 12, 2, 18, 27, 25, 3, 24, 10, 5, 13, 4, 15, + 26, 64, 7, 8, 9, 14, 32, 57, 58, 11, 22,255,255,255,255,255, +180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165, +164,163,162,161,160,159,101,158,157,156,155,154,153,152,151,106, +150,149,148,147,146,145,144,100,143,142,141,140,139,138,137,136, + 94, 80, 93,135,105,134,133, 63,132,131,130,129,128,127,126,125, +124,104, 73, 99, 79, 85,123, 54,122, 98, 92,121,120, 91,103,119, + 68,118,117, 97,116,115, 50, 90,114,113,112,111, 55, 41, 40, 86, + 89, 70, 59, 78, 71, 82, 88, 33, 77, 66, 84, 83,110, 75, 61, 96, + 30, 67,109, 74, 87,102, 34, 95, 81,108, 76, 72, 17, 6, 19,107, +) + +TurkishLangModel = ( +3,2,3,3,3,1,3,3,3,3,3,3,3,3,2,1,1,3,3,1,3,3,0,3,3,3,3,3,0,3,1,3, +3,2,1,0,0,1,1,0,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,2,2,0,0,1,0,0,1, +3,2,2,3,3,0,3,3,3,3,3,3,3,2,3,1,0,3,3,1,3,3,0,3,3,3,3,3,0,3,0,3, +3,1,1,0,1,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,2,2,0,0,0,1,0,1, +3,3,2,3,3,0,3,3,3,3,3,3,3,2,3,1,1,3,3,0,3,3,1,2,3,3,3,3,0,3,0,3, +3,1,1,0,0,0,1,0,0,0,0,1,1,0,1,2,1,0,0,0,1,0,0,0,0,2,0,0,0,0,0,1, +3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,1,3,3,2,0,3,2,1,2,2,1,3,3,0,0,0,2, +2,2,0,1,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,0,1, +3,3,3,2,3,3,1,2,3,3,3,3,3,3,3,1,3,2,1,0,3,2,0,1,2,3,3,2,1,0,0,2, +2,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,0,0,0, +1,0,1,3,3,1,3,3,3,3,3,3,3,1,2,0,0,2,3,0,2,3,0,0,2,2,2,3,0,3,0,1, +2,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, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,0,3,2,0,2,3,2,3,3,1,0,0,2, +3,2,0,0,1,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,0,2,0,0,1, +3,3,3,2,3,3,2,3,3,3,3,2,3,3,3,0,3,3,0,0,2,1,0,0,2,3,2,2,0,0,0,2, +2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,1,0,2,0,0,1, +3,3,3,2,3,3,3,3,3,3,3,2,3,3,3,0,3,2,0,1,3,2,1,1,3,2,3,2,1,0,0,2, +2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, +3,3,3,2,3,3,3,3,3,3,3,2,3,3,3,0,3,2,2,0,2,3,0,0,2,2,2,2,0,0,0,2, +3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,1,0,0,0, +3,3,3,3,3,3,3,2,2,2,2,3,2,3,3,0,3,3,1,1,2,2,0,0,2,2,3,2,0,0,1,3, +0,3,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1, +3,3,3,2,3,3,3,2,1,2,2,3,2,3,3,0,3,2,0,0,1,1,0,1,1,2,1,2,0,0,0,1, +0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0, +3,3,3,2,3,3,2,3,2,2,2,3,3,3,3,1,3,1,1,0,3,2,1,1,3,3,2,3,1,0,0,1, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,0,1, +3,2,2,3,3,0,3,3,3,3,3,3,3,2,2,1,0,3,3,1,3,3,0,1,3,3,2,3,0,3,0,3, +2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +2,2,2,3,3,0,3,3,3,3,3,3,3,3,3,0,0,3,2,0,3,3,0,3,2,3,3,3,0,3,1,3, +2,0,0,0,0,0,0,0,0,0,0,1,0,1,2,0,1,0,0,0,0,0,0,0,2,2,0,0,1,0,0,1, +3,3,3,1,2,3,3,1,0,0,1,0,0,3,3,2,3,0,0,2,0,0,2,0,2,0,0,0,2,0,2,0, +0,3,1,0,1,0,0,0,2,2,1,0,1,1,2,1,2,2,2,0,2,1,1,0,0,0,2,0,0,0,0,0, +1,2,1,3,3,0,3,3,3,3,3,2,3,0,0,0,0,2,3,0,2,3,1,0,2,3,1,3,0,3,0,2, +3,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,1,3,3,2,2,3,2,2,0,1,2,3,0,1,2,1,0,1,0,0,0,1,0,2,2,0,0,0,1, +1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0, +3,3,3,1,3,3,1,1,3,3,1,1,3,3,1,0,2,1,2,0,2,1,0,0,1,1,2,1,0,0,0,2, +2,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, +3,3,3,1,0,2,1,3,0,0,2,0,0,3,3,0,3,0,0,1,0,1,2,0,0,1,1,2,2,0,1,0, +0,1,2,1,1,0,1,0,1,1,1,1,1,0,1,1,1,2,2,1,2,0,1,0,0,0,0,0,0,1,0,0, +3,3,3,2,3,2,3,3,0,2,2,2,3,3,3,0,3,0,0,0,2,2,0,1,2,1,1,1,0,0,0,1, +0,3,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,1,0,0,0, +3,3,3,3,3,3,2,1,2,2,3,3,3,3,2,0,2,0,0,0,2,2,0,0,2,1,3,3,0,0,1,1, +1,1,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0, +1,1,2,3,3,0,3,3,3,3,3,3,2,2,0,2,0,2,3,2,3,2,2,2,2,2,2,2,1,3,2,3, +2,0,2,1,2,2,2,2,1,1,2,2,1,2,2,1,2,0,0,2,1,1,0,2,1,0,0,1,0,0,0,1, +2,3,3,1,1,1,0,1,1,1,2,3,2,1,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0, +0,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, +3,3,3,2,2,2,3,2,3,2,2,1,3,3,3,0,2,1,2,0,2,1,0,0,1,1,1,1,1,0,0,1, +2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,2,0,1,0,0,0, +3,3,3,2,3,3,3,3,3,2,3,1,2,3,3,1,2,0,0,0,0,0,0,0,3,2,1,1,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +3,3,3,2,2,3,3,2,1,1,1,1,1,3,3,0,3,1,0,0,1,1,0,0,3,1,2,1,0,0,0,0, +0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0, +3,3,3,2,2,3,2,2,2,3,2,1,1,3,3,0,3,0,0,0,0,1,0,0,3,1,1,2,0,0,0,1, +1,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,1,1,3,3,0,3,3,3,3,3,2,2,2,1,2,0,2,1,2,2,1,1,0,1,2,2,2,2,2,2,2, +0,0,2,1,2,1,2,1,0,1,1,3,1,2,1,1,2,0,0,2,0,1,0,1,0,1,0,0,0,1,0,1, +3,3,3,1,3,3,3,0,1,1,0,2,2,3,1,0,3,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0, +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, +3,3,2,0,0,2,2,1,0,0,1,0,0,3,3,1,3,0,0,1,1,0,2,0,3,0,0,0,2,0,1,1, +0,1,2,0,1,2,2,0,2,2,2,2,1,0,2,1,1,0,2,0,2,1,2,0,0,0,0,0,0,0,0,0, +3,3,3,1,3,2,3,2,0,2,2,2,1,3,2,0,2,1,2,0,1,2,0,0,1,0,2,2,0,0,0,2, +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,1,1,0,1,0,0,0, +3,3,3,0,3,3,1,1,2,3,1,0,3,2,3,0,3,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0, +1,2,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,3,3,0,3,3,2,3,3,2,2,0,0,0,0,1,2,0,1,3,0,0,0,3,1,1,0,3,0,2, +2,0,0,0,0,0,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, +3,3,3,1,2,2,1,0,3,1,1,1,1,3,3,2,3,0,0,1,0,1,2,0,2,2,0,2,2,0,2,1, +0,2,2,1,1,1,1,0,2,1,1,0,1,1,1,1,2,1,2,1,2,0,1,0,1,0,0,0,0,0,0,0, +3,3,3,0,1,1,3,0,0,1,1,0,0,2,2,0,3,0,0,1,1,0,1,0,0,0,0,0,2,0,0,0, +0,3,1,0,1,0,1,0,2,0,0,1,0,1,0,1,1,1,2,1,1,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,0,2,0,2,0,1,1,1,0,0,3,3,0,2,0,0,1,0,0,2,1,1,0,1,0,1,0,1,0, +0,2,0,1,2,0,2,0,2,1,1,0,1,0,2,1,1,0,2,1,1,0,1,0,0,0,1,1,0,0,0,0, +3,2,3,0,1,0,0,0,0,0,0,0,0,1,2,0,1,0,0,1,0,0,1,0,0,0,0,0,2,0,0,0, +0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,2,1,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,0,0,2,3,0,0,1,0,1,0,2,3,2,3,0,0,1,3,0,2,1,0,0,0,0,2,0,1,0, +0,2,1,0,0,1,1,0,2,1,0,0,1,0,0,1,1,0,1,1,2,0,1,0,0,0,0,1,0,0,0,0, +3,2,2,0,0,1,1,0,0,0,0,0,0,3,1,1,1,0,0,0,0,0,1,0,0,0,0,0,2,0,1,0, +0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,3,3,0,2,3,2,2,1,2,2,1,1,2,0,1,3,2,2,2,0,0,2,2,0,0,0,1,2,1, +3,0,2,1,1,0,1,1,1,0,1,2,2,2,1,1,2,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0, +0,1,1,2,3,0,3,3,3,2,2,2,2,1,0,1,0,1,0,1,2,2,0,0,2,2,1,3,1,1,2,1, +0,0,1,1,2,0,1,1,0,0,1,2,0,2,1,1,2,0,0,1,0,0,0,1,0,1,0,1,0,0,0,0, +3,3,2,0,0,3,1,0,0,0,0,0,0,3,2,1,2,0,0,1,0,0,2,0,0,0,0,0,2,0,1,0, +0,2,1,1,0,0,1,0,1,2,0,0,1,1,0,0,2,1,1,1,1,0,2,0,0,0,0,0,0,0,0,0, +3,3,2,0,0,1,0,0,0,0,1,0,0,3,3,2,2,0,0,1,0,0,2,0,1,0,0,0,2,0,1,0, +0,0,1,1,0,0,2,0,2,1,0,0,1,1,2,1,2,0,2,1,2,1,1,1,0,0,1,1,0,0,0,0, +3,3,2,0,0,2,2,0,0,0,1,1,0,2,2,1,3,1,0,1,0,1,2,0,0,0,0,0,1,0,1,0, +0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,0,0,0,1,0,0,1,0,0,2,3,1,2,0,0,1,0,0,2,0,0,0,1,0,2,0,2,0, +0,1,1,2,2,1,2,0,2,1,1,0,0,1,1,0,1,1,1,1,2,1,1,0,0,0,0,0,0,0,0,0, +3,3,3,0,2,1,2,1,0,0,1,1,0,3,3,1,2,0,0,1,0,0,2,0,2,0,1,1,2,0,0,0, +0,0,1,1,1,1,2,0,1,1,0,1,1,1,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,0,0, +3,3,3,0,2,2,3,2,0,0,1,0,0,2,3,1,0,0,0,0,0,0,2,0,2,0,0,0,2,0,0,0, +0,1,1,0,0,0,1,0,0,1,0,1,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,0,0,0,0,0,0,0,1,0,0,2,2,2,2,0,0,1,0,0,2,0,0,0,0,0,2,0,1,0, +0,0,2,1,1,0,1,0,2,1,1,0,0,1,1,2,1,0,2,0,2,0,1,0,0,0,2,0,0,0,0,0, +0,0,0,2,2,0,2,1,1,1,1,2,2,0,0,1,0,1,0,0,1,3,0,0,0,0,1,0,0,2,1,0, +0,0,1,0,1,0,0,0,0,0,2,1,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +2,0,0,2,3,0,2,3,1,2,2,0,2,0,0,2,0,2,1,1,1,2,1,0,0,1,2,1,1,2,1,0, +1,0,2,0,1,0,1,1,0,0,2,2,1,2,1,1,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,0,2,1,2,0,0,0,1,0,0,3,2,0,1,0,0,1,0,0,2,0,0,0,1,2,1,0,1,0, +0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,2,2,0,2,2,1,1,0,1,1,1,1,1,0,0,1,2,1,1,1,0,1,0,0,0,1,1,1,1, +0,0,2,1,0,1,1,1,0,1,1,2,1,2,1,1,2,0,1,1,2,1,0,2,0,0,0,0,0,0,0,0, +3,2,2,0,0,2,0,0,0,0,0,0,0,2,2,0,2,0,0,1,0,0,2,0,0,0,0,0,2,0,0,0, +0,2,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,3,2,0,2,2,0,1,1,0,1,0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0, +2,0,1,0,1,0,1,1,0,0,1,2,0,1,0,1,1,0,0,1,0,1,0,2,0,0,0,0,0,0,0,0, +2,2,2,0,1,1,0,0,0,1,0,0,0,1,2,0,1,0,0,1,0,0,1,0,0,0,0,1,2,0,1,0, +0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,1,0,1,1,1,0,0,0,0,1,2,0,0,1,0,0,0,1,0,0,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,2,0,0,0,0,0,0,0, +1,1,2,0,1,0,0,0,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,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,1,0,0,0,0,0,2,0,0,0,0,0,1, +0,0,1,2,2,0,2,1,2,1,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,0,0,0,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,1,0,0,0, +2,2,2,0,0,0,1,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,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,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,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,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,0,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,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,1,0,0,0,0,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,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,1,0,0,0,0,0,0,0,0,0,0,2,2,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, +) + +Latin5TurkishModel = { + 'char_to_order_map': Latin5_TurkishCharToOrderMap, + 'precedence_matrix': TurkishLangModel, + 'typical_positive_ratio': 0.970290, + 'keep_english_letter': True, + 'charset_name': "ISO-8859-9", + 'language': 'Turkish', +} diff --git a/flex/lib/python3.6/site-packages/chardet/latin1prober.py b/flex/lib/python3.6/site-packages/chardet/latin1prober.py new file mode 100644 index 0000000..7d1e8c2 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/latin1prober.py @@ -0,0 +1,145 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState + +FREQ_CAT_NUM = 4 + +UDF = 0 # undefined +OTH = 1 # other +ASC = 2 # ascii capital letter +ASS = 3 # ascii small letter +ACV = 4 # accent capital vowel +ACO = 5 # accent capital other +ASV = 6 # accent small vowel +ASO = 7 # accent small other +CLASS_NUM = 8 # total classes + +Latin1_CharToClass = ( + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 00 - 07 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 08 - 0F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 10 - 17 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 18 - 1F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 20 - 27 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 28 - 2F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 30 - 37 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 38 - 3F + OTH, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 40 - 47 + ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 48 - 4F + ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 50 - 57 + ASC, ASC, ASC, OTH, OTH, OTH, OTH, OTH, # 58 - 5F + OTH, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 60 - 67 + ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 68 - 6F + ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 70 - 77 + ASS, ASS, ASS, OTH, OTH, OTH, OTH, OTH, # 78 - 7F + OTH, UDF, OTH, ASO, OTH, OTH, OTH, OTH, # 80 - 87 + OTH, OTH, ACO, OTH, ACO, UDF, ACO, UDF, # 88 - 8F + UDF, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 90 - 97 + OTH, OTH, ASO, OTH, ASO, UDF, ASO, ACO, # 98 - 9F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A0 - A7 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A8 - AF + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B0 - B7 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B8 - BF + ACV, ACV, ACV, ACV, ACV, ACV, ACO, ACO, # C0 - C7 + ACV, ACV, ACV, ACV, ACV, ACV, ACV, ACV, # C8 - CF + ACO, ACO, ACV, ACV, ACV, ACV, ACV, OTH, # D0 - D7 + ACV, ACV, ACV, ACV, ACV, ACO, ACO, ACO, # D8 - DF + ASV, ASV, ASV, ASV, ASV, ASV, ASO, ASO, # E0 - E7 + ASV, ASV, ASV, ASV, ASV, ASV, ASV, ASV, # E8 - EF + ASO, ASO, ASV, ASV, ASV, ASV, ASV, OTH, # F0 - F7 + ASV, ASV, ASV, ASV, ASV, ASO, ASO, ASO, # F8 - FF +) + +# 0 : illegal +# 1 : very unlikely +# 2 : normal +# 3 : very likely +Latin1ClassModel = ( +# UDF OTH ASC ASS ACV ACO ASV ASO + 0, 0, 0, 0, 0, 0, 0, 0, # UDF + 0, 3, 3, 3, 3, 3, 3, 3, # OTH + 0, 3, 3, 3, 3, 3, 3, 3, # ASC + 0, 3, 3, 3, 1, 1, 3, 3, # ASS + 0, 3, 3, 3, 1, 2, 1, 2, # ACV + 0, 3, 3, 3, 3, 3, 3, 3, # ACO + 0, 3, 1, 3, 1, 1, 1, 3, # ASV + 0, 3, 1, 3, 1, 1, 3, 3, # ASO +) + + +class Latin1Prober(CharSetProber): + def __init__(self): + super(Latin1Prober, self).__init__() + self._last_char_class = None + self._freq_counter = None + self.reset() + + def reset(self): + self._last_char_class = OTH + self._freq_counter = [0] * FREQ_CAT_NUM + CharSetProber.reset(self) + + @property + def charset_name(self): + return "ISO-8859-1" + + @property + def language(self): + return "" + + def feed(self, byte_str): + byte_str = self.filter_with_english_letters(byte_str) + for c in byte_str: + char_class = Latin1_CharToClass[c] + freq = Latin1ClassModel[(self._last_char_class * CLASS_NUM) + + char_class] + if freq == 0: + self._state = ProbingState.NOT_ME + break + self._freq_counter[freq] += 1 + self._last_char_class = char_class + + return self.state + + def get_confidence(self): + if self.state == ProbingState.NOT_ME: + return 0.01 + + total = sum(self._freq_counter) + if total < 0.01: + confidence = 0.0 + else: + confidence = ((self._freq_counter[3] - self._freq_counter[1] * 20.0) + / total) + if confidence < 0.0: + confidence = 0.0 + # lower the confidence of latin1 so that other more accurate + # detector can take priority. + confidence = confidence * 0.73 + return confidence diff --git a/flex/lib/python3.6/site-packages/chardet/mbcharsetprober.py b/flex/lib/python3.6/site-packages/chardet/mbcharsetprober.py new file mode 100644 index 0000000..6256ecf --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/mbcharsetprober.py @@ -0,0 +1,91 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Proofpoint, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState, MachineState + + +class MultiByteCharSetProber(CharSetProber): + """ + MultiByteCharSetProber + """ + + def __init__(self, lang_filter=None): + super(MultiByteCharSetProber, self).__init__(lang_filter=lang_filter) + self.distribution_analyzer = None + self.coding_sm = None + self._last_char = [0, 0] + + def reset(self): + super(MultiByteCharSetProber, self).reset() + if self.coding_sm: + self.coding_sm.reset() + if self.distribution_analyzer: + self.distribution_analyzer.reset() + self._last_char = [0, 0] + + @property + def charset_name(self): + raise NotImplementedError + + @property + def language(self): + raise NotImplementedError + + def feed(self, byte_str): + for i in range(len(byte_str)): + coding_state = self.coding_sm.next_state(byte_str[i]) + if coding_state == MachineState.ERROR: + self.logger.debug('%s %s prober hit error at byte %s', + self.charset_name, self.language, i) + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + char_len = self.coding_sm.get_current_charlen() + if i == 0: + self._last_char[1] = byte_str[0] + self.distribution_analyzer.feed(self._last_char, char_len) + else: + self.distribution_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + + self._last_char[0] = byte_str[-1] + + if self.state == ProbingState.DETECTING: + if (self.distribution_analyzer.got_enough_data() and + (self.get_confidence() > self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + return self.distribution_analyzer.get_confidence() diff --git a/flex/lib/python3.6/site-packages/chardet/mbcsgroupprober.py b/flex/lib/python3.6/site-packages/chardet/mbcsgroupprober.py new file mode 100644 index 0000000..530abe7 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/mbcsgroupprober.py @@ -0,0 +1,54 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Proofpoint, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetgroupprober import CharSetGroupProber +from .utf8prober import UTF8Prober +from .sjisprober import SJISProber +from .eucjpprober import EUCJPProber +from .gb2312prober import GB2312Prober +from .euckrprober import EUCKRProber +from .cp949prober import CP949Prober +from .big5prober import Big5Prober +from .euctwprober import EUCTWProber + + +class MBCSGroupProber(CharSetGroupProber): + def __init__(self, lang_filter=None): + super(MBCSGroupProber, self).__init__(lang_filter=lang_filter) + self.probers = [ + UTF8Prober(), + SJISProber(), + EUCJPProber(), + GB2312Prober(), + EUCKRProber(), + CP949Prober(), + Big5Prober(), + EUCTWProber() + ] + self.reset() diff --git a/flex/lib/python3.6/site-packages/chardet/mbcssm.py b/flex/lib/python3.6/site-packages/chardet/mbcssm.py new file mode 100644 index 0000000..8360d0f --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/mbcssm.py @@ -0,0 +1,572 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import MachineState + +# BIG5 + +BIG5_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as legal value + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,1, # 78 - 7f + 4,4,4,4,4,4,4,4, # 80 - 87 + 4,4,4,4,4,4,4,4, # 88 - 8f + 4,4,4,4,4,4,4,4, # 90 - 97 + 4,4,4,4,4,4,4,4, # 98 - 9f + 4,3,3,3,3,3,3,3, # a0 - a7 + 3,3,3,3,3,3,3,3, # a8 - af + 3,3,3,3,3,3,3,3, # b0 - b7 + 3,3,3,3,3,3,3,3, # b8 - bf + 3,3,3,3,3,3,3,3, # c0 - c7 + 3,3,3,3,3,3,3,3, # c8 - cf + 3,3,3,3,3,3,3,3, # d0 - d7 + 3,3,3,3,3,3,3,3, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,3,3,3, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,3,3,0 # f8 - ff +) + +BIG5_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,#08-0f + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START#10-17 +) + +BIG5_CHAR_LEN_TABLE = (0, 1, 1, 2, 0) + +BIG5_SM_MODEL = {'class_table': BIG5_CLS, + 'class_factor': 5, + 'state_table': BIG5_ST, + 'char_len_table': BIG5_CHAR_LEN_TABLE, + 'name': 'Big5'} + +# CP949 + +CP949_CLS = ( + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,0,0, # 00 - 0f + 1,1,1,1,1,1,1,1, 1,1,1,0,1,1,1,1, # 10 - 1f + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, # 20 - 2f + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, # 30 - 3f + 1,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4, # 40 - 4f + 4,4,5,5,5,5,5,5, 5,5,5,1,1,1,1,1, # 50 - 5f + 1,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5, # 60 - 6f + 5,5,5,5,5,5,5,5, 5,5,5,1,1,1,1,1, # 70 - 7f + 0,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6, # 80 - 8f + 6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6, # 90 - 9f + 6,7,7,7,7,7,7,7, 7,7,7,7,7,8,8,8, # a0 - af + 7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7, # b0 - bf + 7,7,7,7,7,7,9,2, 2,3,2,2,2,2,2,2, # c0 - cf + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, # d0 - df + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, # e0 - ef + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,0, # f0 - ff +) + +CP949_ST = ( +#cls= 0 1 2 3 4 5 6 7 8 9 # previous state = + MachineState.ERROR,MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START, 4, 5,MachineState.ERROR, 6, # MachineState.START + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, # MachineState.ERROR + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME, # MachineState.ITS_ME + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START, # 3 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, # 4 + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, # 5 + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START, # 6 +) + +CP949_CHAR_LEN_TABLE = (0, 1, 2, 0, 1, 1, 2, 2, 0, 2) + +CP949_SM_MODEL = {'class_table': CP949_CLS, + 'class_factor': 10, + 'state_table': CP949_ST, + 'char_len_table': CP949_CHAR_LEN_TABLE, + 'name': 'CP949'} + +# EUC-JP + +EUCJP_CLS = ( + 4,4,4,4,4,4,4,4, # 00 - 07 + 4,4,4,4,4,4,5,5, # 08 - 0f + 4,4,4,4,4,4,4,4, # 10 - 17 + 4,4,4,5,4,4,4,4, # 18 - 1f + 4,4,4,4,4,4,4,4, # 20 - 27 + 4,4,4,4,4,4,4,4, # 28 - 2f + 4,4,4,4,4,4,4,4, # 30 - 37 + 4,4,4,4,4,4,4,4, # 38 - 3f + 4,4,4,4,4,4,4,4, # 40 - 47 + 4,4,4,4,4,4,4,4, # 48 - 4f + 4,4,4,4,4,4,4,4, # 50 - 57 + 4,4,4,4,4,4,4,4, # 58 - 5f + 4,4,4,4,4,4,4,4, # 60 - 67 + 4,4,4,4,4,4,4,4, # 68 - 6f + 4,4,4,4,4,4,4,4, # 70 - 77 + 4,4,4,4,4,4,4,4, # 78 - 7f + 5,5,5,5,5,5,5,5, # 80 - 87 + 5,5,5,5,5,5,1,3, # 88 - 8f + 5,5,5,5,5,5,5,5, # 90 - 97 + 5,5,5,5,5,5,5,5, # 98 - 9f + 5,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,2,2,2, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,2,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,0,5 # f8 - ff +) + +EUCJP_ST = ( + 3, 4, 3, 5,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.START,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#10-17 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 3,MachineState.ERROR,#18-1f + 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START#20-27 +) + +EUCJP_CHAR_LEN_TABLE = (2, 2, 2, 3, 1, 0) + +EUCJP_SM_MODEL = {'class_table': EUCJP_CLS, + 'class_factor': 6, + 'state_table': EUCJP_ST, + 'char_len_table': EUCJP_CHAR_LEN_TABLE, + 'name': 'EUC-JP'} + +# EUC-KR + +EUCKR_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 1,1,1,1,1,1,1,1, # 40 - 47 + 1,1,1,1,1,1,1,1, # 48 - 4f + 1,1,1,1,1,1,1,1, # 50 - 57 + 1,1,1,1,1,1,1,1, # 58 - 5f + 1,1,1,1,1,1,1,1, # 60 - 67 + 1,1,1,1,1,1,1,1, # 68 - 6f + 1,1,1,1,1,1,1,1, # 70 - 77 + 1,1,1,1,1,1,1,1, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,3,3,3, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,3,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 2,2,2,2,2,2,2,2, # e0 - e7 + 2,2,2,2,2,2,2,2, # e8 - ef + 2,2,2,2,2,2,2,2, # f0 - f7 + 2,2,2,2,2,2,2,0 # f8 - ff +) + +EUCKR_ST = ( + MachineState.ERROR,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START #08-0f +) + +EUCKR_CHAR_LEN_TABLE = (0, 1, 2, 0) + +EUCKR_SM_MODEL = {'class_table': EUCKR_CLS, + 'class_factor': 4, + 'state_table': EUCKR_ST, + 'char_len_table': EUCKR_CHAR_LEN_TABLE, + 'name': 'EUC-KR'} + +# EUC-TW + +EUCTW_CLS = ( + 2,2,2,2,2,2,2,2, # 00 - 07 + 2,2,2,2,2,2,0,0, # 08 - 0f + 2,2,2,2,2,2,2,2, # 10 - 17 + 2,2,2,0,2,2,2,2, # 18 - 1f + 2,2,2,2,2,2,2,2, # 20 - 27 + 2,2,2,2,2,2,2,2, # 28 - 2f + 2,2,2,2,2,2,2,2, # 30 - 37 + 2,2,2,2,2,2,2,2, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,2, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,6,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,3,4,4,4,4,4,4, # a0 - a7 + 5,5,1,1,1,1,1,1, # a8 - af + 1,1,1,1,1,1,1,1, # b0 - b7 + 1,1,1,1,1,1,1,1, # b8 - bf + 1,1,3,1,3,3,3,3, # c0 - c7 + 3,3,3,3,3,3,3,3, # c8 - cf + 3,3,3,3,3,3,3,3, # d0 - d7 + 3,3,3,3,3,3,3,3, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,3,3,3, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,3,3,0 # f8 - ff +) + +EUCTW_ST = ( + MachineState.ERROR,MachineState.ERROR,MachineState.START, 3, 3, 3, 4,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,MachineState.ERROR,#10-17 + MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.START,MachineState.START,#20-27 + MachineState.START,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START #28-2f +) + +EUCTW_CHAR_LEN_TABLE = (0, 0, 1, 2, 2, 2, 3) + +EUCTW_SM_MODEL = {'class_table': EUCTW_CLS, + 'class_factor': 7, + 'state_table': EUCTW_ST, + 'char_len_table': EUCTW_CHAR_LEN_TABLE, + 'name': 'x-euc-tw'} + +# GB2312 + +GB2312_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 3,3,3,3,3,3,3,3, # 30 - 37 + 3,3,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,4, # 78 - 7f + 5,6,6,6,6,6,6,6, # 80 - 87 + 6,6,6,6,6,6,6,6, # 88 - 8f + 6,6,6,6,6,6,6,6, # 90 - 97 + 6,6,6,6,6,6,6,6, # 98 - 9f + 6,6,6,6,6,6,6,6, # a0 - a7 + 6,6,6,6,6,6,6,6, # a8 - af + 6,6,6,6,6,6,6,6, # b0 - b7 + 6,6,6,6,6,6,6,6, # b8 - bf + 6,6,6,6,6,6,6,6, # c0 - c7 + 6,6,6,6,6,6,6,6, # c8 - cf + 6,6,6,6,6,6,6,6, # d0 - d7 + 6,6,6,6,6,6,6,6, # d8 - df + 6,6,6,6,6,6,6,6, # e0 - e7 + 6,6,6,6,6,6,6,6, # e8 - ef + 6,6,6,6,6,6,6,6, # f0 - f7 + 6,6,6,6,6,6,6,0 # f8 - ff +) + +GB2312_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, 3,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,#10-17 + 4,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + MachineState.ERROR,MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,#20-27 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START #28-2f +) + +# To be accurate, the length of class 6 can be either 2 or 4. +# But it is not necessary to discriminate between the two since +# it is used for frequency analysis only, and we are validating +# each code range there as well. So it is safe to set it to be +# 2 here. +GB2312_CHAR_LEN_TABLE = (0, 1, 1, 1, 1, 1, 2) + +GB2312_SM_MODEL = {'class_table': GB2312_CLS, + 'class_factor': 7, + 'state_table': GB2312_ST, + 'char_len_table': GB2312_CHAR_LEN_TABLE, + 'name': 'GB2312'} + +# Shift_JIS + +SJIS_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,1, # 78 - 7f + 3,3,3,3,3,2,2,3, # 80 - 87 + 3,3,3,3,3,3,3,3, # 88 - 8f + 3,3,3,3,3,3,3,3, # 90 - 97 + 3,3,3,3,3,3,3,3, # 98 - 9f + #0xa0 is illegal in sjis encoding, but some pages does + #contain such byte. We need to be more error forgiven. + 2,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,2,2,2, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,2,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,4,4,4, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,0,0,0) # f8 - ff + + +SJIS_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START #10-17 +) + +SJIS_CHAR_LEN_TABLE = (0, 1, 1, 2, 0, 0) + +SJIS_SM_MODEL = {'class_table': SJIS_CLS, + 'class_factor': 6, + 'state_table': SJIS_ST, + 'char_len_table': SJIS_CHAR_LEN_TABLE, + 'name': 'Shift_JIS'} + +# UCS2-BE + +UCS2BE_CLS = ( + 0,0,0,0,0,0,0,0, # 00 - 07 + 0,0,1,0,0,2,0,0, # 08 - 0f + 0,0,0,0,0,0,0,0, # 10 - 17 + 0,0,0,3,0,0,0,0, # 18 - 1f + 0,0,0,0,0,0,0,0, # 20 - 27 + 0,3,3,3,3,3,0,0, # 28 - 2f + 0,0,0,0,0,0,0,0, # 30 - 37 + 0,0,0,0,0,0,0,0, # 38 - 3f + 0,0,0,0,0,0,0,0, # 40 - 47 + 0,0,0,0,0,0,0,0, # 48 - 4f + 0,0,0,0,0,0,0,0, # 50 - 57 + 0,0,0,0,0,0,0,0, # 58 - 5f + 0,0,0,0,0,0,0,0, # 60 - 67 + 0,0,0,0,0,0,0,0, # 68 - 6f + 0,0,0,0,0,0,0,0, # 70 - 77 + 0,0,0,0,0,0,0,0, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,0,0,0,0,0,0,0, # a0 - a7 + 0,0,0,0,0,0,0,0, # a8 - af + 0,0,0,0,0,0,0,0, # b0 - b7 + 0,0,0,0,0,0,0,0, # b8 - bf + 0,0,0,0,0,0,0,0, # c0 - c7 + 0,0,0,0,0,0,0,0, # c8 - cf + 0,0,0,0,0,0,0,0, # d0 - d7 + 0,0,0,0,0,0,0,0, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,4,5 # f8 - ff +) + +UCS2BE_ST = ( + 5, 7, 7,MachineState.ERROR, 4, 3,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME, 6, 6, 6, 6,MachineState.ERROR,MachineState.ERROR,#10-17 + 6, 6, 6, 6, 6,MachineState.ITS_ME, 6, 6,#18-1f + 6, 6, 6, 6, 5, 7, 7,MachineState.ERROR,#20-27 + 5, 8, 6, 6,MachineState.ERROR, 6, 6, 6,#28-2f + 6, 6, 6, 6,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START #30-37 +) + +UCS2BE_CHAR_LEN_TABLE = (2, 2, 2, 0, 2, 2) + +UCS2BE_SM_MODEL = {'class_table': UCS2BE_CLS, + 'class_factor': 6, + 'state_table': UCS2BE_ST, + 'char_len_table': UCS2BE_CHAR_LEN_TABLE, + 'name': 'UTF-16BE'} + +# UCS2-LE + +UCS2LE_CLS = ( + 0,0,0,0,0,0,0,0, # 00 - 07 + 0,0,1,0,0,2,0,0, # 08 - 0f + 0,0,0,0,0,0,0,0, # 10 - 17 + 0,0,0,3,0,0,0,0, # 18 - 1f + 0,0,0,0,0,0,0,0, # 20 - 27 + 0,3,3,3,3,3,0,0, # 28 - 2f + 0,0,0,0,0,0,0,0, # 30 - 37 + 0,0,0,0,0,0,0,0, # 38 - 3f + 0,0,0,0,0,0,0,0, # 40 - 47 + 0,0,0,0,0,0,0,0, # 48 - 4f + 0,0,0,0,0,0,0,0, # 50 - 57 + 0,0,0,0,0,0,0,0, # 58 - 5f + 0,0,0,0,0,0,0,0, # 60 - 67 + 0,0,0,0,0,0,0,0, # 68 - 6f + 0,0,0,0,0,0,0,0, # 70 - 77 + 0,0,0,0,0,0,0,0, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,0,0,0,0,0,0,0, # a0 - a7 + 0,0,0,0,0,0,0,0, # a8 - af + 0,0,0,0,0,0,0,0, # b0 - b7 + 0,0,0,0,0,0,0,0, # b8 - bf + 0,0,0,0,0,0,0,0, # c0 - c7 + 0,0,0,0,0,0,0,0, # c8 - cf + 0,0,0,0,0,0,0,0, # d0 - d7 + 0,0,0,0,0,0,0,0, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,4,5 # f8 - ff +) + +UCS2LE_ST = ( + 6, 6, 7, 6, 4, 3,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME, 5, 5, 5,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,#10-17 + 5, 5, 5,MachineState.ERROR, 5,MachineState.ERROR, 6, 6,#18-1f + 7, 6, 8, 8, 5, 5, 5,MachineState.ERROR,#20-27 + 5, 5, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5, 5,#28-2f + 5, 5, 5,MachineState.ERROR, 5,MachineState.ERROR,MachineState.START,MachineState.START #30-37 +) + +UCS2LE_CHAR_LEN_TABLE = (2, 2, 2, 2, 2, 2) + +UCS2LE_SM_MODEL = {'class_table': UCS2LE_CLS, + 'class_factor': 6, + 'state_table': UCS2LE_ST, + 'char_len_table': UCS2LE_CHAR_LEN_TABLE, + 'name': 'UTF-16LE'} + +# UTF-8 + +UTF8_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as a legal value + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 1,1,1,1,1,1,1,1, # 40 - 47 + 1,1,1,1,1,1,1,1, # 48 - 4f + 1,1,1,1,1,1,1,1, # 50 - 57 + 1,1,1,1,1,1,1,1, # 58 - 5f + 1,1,1,1,1,1,1,1, # 60 - 67 + 1,1,1,1,1,1,1,1, # 68 - 6f + 1,1,1,1,1,1,1,1, # 70 - 77 + 1,1,1,1,1,1,1,1, # 78 - 7f + 2,2,2,2,3,3,3,3, # 80 - 87 + 4,4,4,4,4,4,4,4, # 88 - 8f + 4,4,4,4,4,4,4,4, # 90 - 97 + 4,4,4,4,4,4,4,4, # 98 - 9f + 5,5,5,5,5,5,5,5, # a0 - a7 + 5,5,5,5,5,5,5,5, # a8 - af + 5,5,5,5,5,5,5,5, # b0 - b7 + 5,5,5,5,5,5,5,5, # b8 - bf + 0,0,6,6,6,6,6,6, # c0 - c7 + 6,6,6,6,6,6,6,6, # c8 - cf + 6,6,6,6,6,6,6,6, # d0 - d7 + 6,6,6,6,6,6,6,6, # d8 - df + 7,8,8,8,8,8,8,8, # e0 - e7 + 8,8,8,8,8,9,8,8, # e8 - ef + 10,11,11,11,11,11,11,11, # f0 - f7 + 12,13,13,13,14,15,0,0 # f8 - ff +) + +UTF8_ST = ( + MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 12, 10,#00-07 + 9, 11, 8, 7, 6, 5, 4, 3,#08-0f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#10-17 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#20-27 + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#28-2f + MachineState.ERROR,MachineState.ERROR, 5, 5, 5, 5,MachineState.ERROR,MachineState.ERROR,#30-37 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#38-3f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5, 5, 5,MachineState.ERROR,MachineState.ERROR,#40-47 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#48-4f + MachineState.ERROR,MachineState.ERROR, 7, 7, 7, 7,MachineState.ERROR,MachineState.ERROR,#50-57 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#58-5f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 7, 7,MachineState.ERROR,MachineState.ERROR,#60-67 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#68-6f + MachineState.ERROR,MachineState.ERROR, 9, 9, 9, 9,MachineState.ERROR,MachineState.ERROR,#70-77 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#78-7f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 9,MachineState.ERROR,MachineState.ERROR,#80-87 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#88-8f + MachineState.ERROR,MachineState.ERROR, 12, 12, 12, 12,MachineState.ERROR,MachineState.ERROR,#90-97 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#98-9f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 12,MachineState.ERROR,MachineState.ERROR,#a0-a7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#a8-af + MachineState.ERROR,MachineState.ERROR, 12, 12, 12,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#b0-b7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#b8-bf + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,#c0-c7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR #c8-cf +) + +UTF8_CHAR_LEN_TABLE = (0, 1, 0, 0, 0, 0, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6) + +UTF8_SM_MODEL = {'class_table': UTF8_CLS, + 'class_factor': 16, + 'state_table': UTF8_ST, + 'char_len_table': UTF8_CHAR_LEN_TABLE, + 'name': 'UTF-8'} diff --git a/flex/lib/python3.6/site-packages/chardet/sbcharsetprober.py b/flex/lib/python3.6/site-packages/chardet/sbcharsetprober.py new file mode 100644 index 0000000..0adb51d --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/sbcharsetprober.py @@ -0,0 +1,132 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import CharacterCategory, ProbingState, SequenceLikelihood + + +class SingleByteCharSetProber(CharSetProber): + SAMPLE_SIZE = 64 + SB_ENOUGH_REL_THRESHOLD = 1024 # 0.25 * SAMPLE_SIZE^2 + POSITIVE_SHORTCUT_THRESHOLD = 0.95 + NEGATIVE_SHORTCUT_THRESHOLD = 0.05 + + def __init__(self, model, reversed=False, name_prober=None): + super(SingleByteCharSetProber, self).__init__() + self._model = model + # TRUE if we need to reverse every pair in the model lookup + self._reversed = reversed + # Optional auxiliary prober for name decision + self._name_prober = name_prober + self._last_order = None + self._seq_counters = None + self._total_seqs = None + self._total_char = None + self._freq_char = None + self.reset() + + def reset(self): + super(SingleByteCharSetProber, self).reset() + # char order of last character + self._last_order = 255 + self._seq_counters = [0] * SequenceLikelihood.get_num_categories() + self._total_seqs = 0 + self._total_char = 0 + # characters that fall in our sampling range + self._freq_char = 0 + + @property + def charset_name(self): + if self._name_prober: + return self._name_prober.charset_name + else: + return self._model['charset_name'] + + @property + def language(self): + if self._name_prober: + return self._name_prober.language + else: + return self._model.get('language') + + def feed(self, byte_str): + if not self._model['keep_english_letter']: + byte_str = self.filter_international_words(byte_str) + if not byte_str: + return self.state + char_to_order_map = self._model['char_to_order_map'] + for i, c in enumerate(byte_str): + # XXX: Order is in range 1-64, so one would think we want 0-63 here, + # but that leads to 27 more test failures than before. + order = char_to_order_map[c] + # XXX: This was SYMBOL_CAT_ORDER before, with a value of 250, but + # CharacterCategory.SYMBOL is actually 253, so we use CONTROL + # to make it closer to the original intent. The only difference + # is whether or not we count digits and control characters for + # _total_char purposes. + if order < CharacterCategory.CONTROL: + self._total_char += 1 + if order < self.SAMPLE_SIZE: + self._freq_char += 1 + if self._last_order < self.SAMPLE_SIZE: + self._total_seqs += 1 + if not self._reversed: + i = (self._last_order * self.SAMPLE_SIZE) + order + model = self._model['precedence_matrix'][i] + else: # reverse the order of the letters in the lookup + i = (order * self.SAMPLE_SIZE) + self._last_order + model = self._model['precedence_matrix'][i] + self._seq_counters[model] += 1 + self._last_order = order + + charset_name = self._model['charset_name'] + if self.state == ProbingState.DETECTING: + if self._total_seqs > self.SB_ENOUGH_REL_THRESHOLD: + confidence = self.get_confidence() + if confidence > self.POSITIVE_SHORTCUT_THRESHOLD: + self.logger.debug('%s confidence = %s, we have a winner', + charset_name, confidence) + self._state = ProbingState.FOUND_IT + elif confidence < self.NEGATIVE_SHORTCUT_THRESHOLD: + self.logger.debug('%s confidence = %s, below negative ' + 'shortcut threshhold %s', charset_name, + confidence, + self.NEGATIVE_SHORTCUT_THRESHOLD) + self._state = ProbingState.NOT_ME + + return self.state + + def get_confidence(self): + r = 0.01 + if self._total_seqs > 0: + r = ((1.0 * self._seq_counters[SequenceLikelihood.POSITIVE]) / + self._total_seqs / self._model['typical_positive_ratio']) + r = r * self._freq_char / self._total_char + if r >= 1.0: + r = 0.99 + return r diff --git a/flex/lib/python3.6/site-packages/chardet/sbcsgroupprober.py b/flex/lib/python3.6/site-packages/chardet/sbcsgroupprober.py new file mode 100644 index 0000000..98e95dc --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/sbcsgroupprober.py @@ -0,0 +1,73 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetgroupprober import CharSetGroupProber +from .sbcharsetprober import SingleByteCharSetProber +from .langcyrillicmodel import (Win1251CyrillicModel, Koi8rModel, + Latin5CyrillicModel, MacCyrillicModel, + Ibm866Model, Ibm855Model) +from .langgreekmodel import Latin7GreekModel, Win1253GreekModel +from .langbulgarianmodel import Latin5BulgarianModel, Win1251BulgarianModel +# from .langhungarianmodel import Latin2HungarianModel, Win1250HungarianModel +from .langthaimodel import TIS620ThaiModel +from .langhebrewmodel import Win1255HebrewModel +from .hebrewprober import HebrewProber +from .langturkishmodel import Latin5TurkishModel + + +class SBCSGroupProber(CharSetGroupProber): + def __init__(self): + super(SBCSGroupProber, self).__init__() + self.probers = [ + SingleByteCharSetProber(Win1251CyrillicModel), + SingleByteCharSetProber(Koi8rModel), + SingleByteCharSetProber(Latin5CyrillicModel), + SingleByteCharSetProber(MacCyrillicModel), + SingleByteCharSetProber(Ibm866Model), + SingleByteCharSetProber(Ibm855Model), + SingleByteCharSetProber(Latin7GreekModel), + SingleByteCharSetProber(Win1253GreekModel), + SingleByteCharSetProber(Latin5BulgarianModel), + SingleByteCharSetProber(Win1251BulgarianModel), + # TODO: Restore Hungarian encodings (iso-8859-2 and windows-1250) + # after we retrain model. + # SingleByteCharSetProber(Latin2HungarianModel), + # SingleByteCharSetProber(Win1250HungarianModel), + SingleByteCharSetProber(TIS620ThaiModel), + SingleByteCharSetProber(Latin5TurkishModel), + ] + hebrew_prober = HebrewProber() + logical_hebrew_prober = SingleByteCharSetProber(Win1255HebrewModel, + False, hebrew_prober) + visual_hebrew_prober = SingleByteCharSetProber(Win1255HebrewModel, True, + hebrew_prober) + hebrew_prober.set_model_probers(logical_hebrew_prober, visual_hebrew_prober) + self.probers.extend([hebrew_prober, logical_hebrew_prober, + visual_hebrew_prober]) + + self.reset() diff --git a/flex/lib/python3.6/site-packages/chardet/sjisprober.py b/flex/lib/python3.6/site-packages/chardet/sjisprober.py new file mode 100644 index 0000000..9e29623 --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/sjisprober.py @@ -0,0 +1,92 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import SJISDistributionAnalysis +from .jpcntx import SJISContextAnalysis +from .mbcssm import SJIS_SM_MODEL +from .enums import ProbingState, MachineState + + +class SJISProber(MultiByteCharSetProber): + def __init__(self): + super(SJISProber, self).__init__() + self.coding_sm = CodingStateMachine(SJIS_SM_MODEL) + self.distribution_analyzer = SJISDistributionAnalysis() + self.context_analyzer = SJISContextAnalysis() + self.reset() + + def reset(self): + super(SJISProber, self).reset() + self.context_analyzer.reset() + + @property + def charset_name(self): + return self.context_analyzer.charset_name + + @property + def language(self): + return "Japanese" + + def feed(self, byte_str): + for i in range(len(byte_str)): + coding_state = self.coding_sm.next_state(byte_str[i]) + if coding_state == MachineState.ERROR: + self.logger.debug('%s %s prober hit error at byte %s', + self.charset_name, self.language, i) + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + char_len = self.coding_sm.get_current_charlen() + if i == 0: + self._last_char[1] = byte_str[0] + self.context_analyzer.feed(self._last_char[2 - char_len:], + char_len) + self.distribution_analyzer.feed(self._last_char, char_len) + else: + self.context_analyzer.feed(byte_str[i + 1 - char_len:i + 3 + - char_len], char_len) + self.distribution_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + + self._last_char[0] = byte_str[-1] + + if self.state == ProbingState.DETECTING: + if (self.context_analyzer.got_enough_data() and + (self.get_confidence() > self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + context_conf = self.context_analyzer.get_confidence() + distrib_conf = self.distribution_analyzer.get_confidence() + return max(context_conf, distrib_conf) diff --git a/flex/lib/python3.6/site-packages/chardet/universaldetector.py b/flex/lib/python3.6/site-packages/chardet/universaldetector.py new file mode 100644 index 0000000..7b4e92d --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/universaldetector.py @@ -0,0 +1,286 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### +""" +Module containing the UniversalDetector detector class, which is the primary +class a user of ``chardet`` should use. + +:author: Mark Pilgrim (initial port to Python) +:author: Shy Shalom (original C code) +:author: Dan Blanchard (major refactoring for 3.0) +:author: Ian Cordasco +""" + + +import codecs +import logging +import re + +from .charsetgroupprober import CharSetGroupProber +from .enums import InputState, LanguageFilter, ProbingState +from .escprober import EscCharSetProber +from .latin1prober import Latin1Prober +from .mbcsgroupprober import MBCSGroupProber +from .sbcsgroupprober import SBCSGroupProber + + +class UniversalDetector(object): + """ + The ``UniversalDetector`` class underlies the ``chardet.detect`` function + and coordinates all of the different charset probers. + + To get a ``dict`` containing an encoding and its confidence, you can simply + run: + + .. code:: + + u = UniversalDetector() + u.feed(some_bytes) + u.close() + detected = u.result + + """ + + MINIMUM_THRESHOLD = 0.20 + HIGH_BYTE_DETECTOR = re.compile(b'[\x80-\xFF]') + ESC_DETECTOR = re.compile(b'(\033|~{)') + WIN_BYTE_DETECTOR = re.compile(b'[\x80-\x9F]') + ISO_WIN_MAP = {'iso-8859-1': 'Windows-1252', + 'iso-8859-2': 'Windows-1250', + 'iso-8859-5': 'Windows-1251', + 'iso-8859-6': 'Windows-1256', + 'iso-8859-7': 'Windows-1253', + 'iso-8859-8': 'Windows-1255', + 'iso-8859-9': 'Windows-1254', + 'iso-8859-13': 'Windows-1257'} + + def __init__(self, lang_filter=LanguageFilter.ALL): + self._esc_charset_prober = None + self._charset_probers = [] + self.result = None + self.done = None + self._got_data = None + self._input_state = None + self._last_char = None + self.lang_filter = lang_filter + self.logger = logging.getLogger(__name__) + self._has_win_bytes = None + self.reset() + + def reset(self): + """ + Reset the UniversalDetector and all of its probers back to their + initial states. This is called by ``__init__``, so you only need to + call this directly in between analyses of different documents. + """ + self.result = {'encoding': None, 'confidence': 0.0, 'language': None} + self.done = False + self._got_data = False + self._has_win_bytes = False + self._input_state = InputState.PURE_ASCII + self._last_char = b'' + if self._esc_charset_prober: + self._esc_charset_prober.reset() + for prober in self._charset_probers: + prober.reset() + + def feed(self, byte_str): + """ + Takes a chunk of a document and feeds it through all of the relevant + charset probers. + + After calling ``feed``, you can check the value of the ``done`` + attribute to see if you need to continue feeding the + ``UniversalDetector`` more data, or if it has made a prediction + (in the ``result`` attribute). + + .. note:: + You should always call ``close`` when you're done feeding in your + document if ``done`` is not already ``True``. + """ + if self.done: + return + + if not len(byte_str): + return + + if not isinstance(byte_str, bytearray): + byte_str = bytearray(byte_str) + + # First check for known BOMs, since these are guaranteed to be correct + if not self._got_data: + # If the data starts with BOM, we know it is UTF + if byte_str.startswith(codecs.BOM_UTF8): + # EF BB BF UTF-8 with BOM + self.result = {'encoding': "UTF-8-SIG", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith((codecs.BOM_UTF32_LE, + codecs.BOM_UTF32_BE)): + # FF FE 00 00 UTF-32, little-endian BOM + # 00 00 FE FF UTF-32, big-endian BOM + self.result = {'encoding': "UTF-32", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith(b'\xFE\xFF\x00\x00'): + # FE FF 00 00 UCS-4, unusual octet order BOM (3412) + self.result = {'encoding': "X-ISO-10646-UCS-4-3412", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith(b'\x00\x00\xFF\xFE'): + # 00 00 FF FE UCS-4, unusual octet order BOM (2143) + self.result = {'encoding': "X-ISO-10646-UCS-4-2143", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith((codecs.BOM_LE, codecs.BOM_BE)): + # FF FE UTF-16, little endian BOM + # FE FF UTF-16, big endian BOM + self.result = {'encoding': "UTF-16", + 'confidence': 1.0, + 'language': ''} + + self._got_data = True + if self.result['encoding'] is not None: + self.done = True + return + + # If none of those matched and we've only see ASCII so far, check + # for high bytes and escape sequences + if self._input_state == InputState.PURE_ASCII: + if self.HIGH_BYTE_DETECTOR.search(byte_str): + self._input_state = InputState.HIGH_BYTE + elif self._input_state == InputState.PURE_ASCII and \ + self.ESC_DETECTOR.search(self._last_char + byte_str): + self._input_state = InputState.ESC_ASCII + + self._last_char = byte_str[-1:] + + # If we've seen escape sequences, use the EscCharSetProber, which + # uses a simple state machine to check for known escape sequences in + # HZ and ISO-2022 encodings, since those are the only encodings that + # use such sequences. + if self._input_state == InputState.ESC_ASCII: + if not self._esc_charset_prober: + self._esc_charset_prober = EscCharSetProber(self.lang_filter) + if self._esc_charset_prober.feed(byte_str) == ProbingState.FOUND_IT: + self.result = {'encoding': + self._esc_charset_prober.charset_name, + 'confidence': + self._esc_charset_prober.get_confidence(), + 'language': + self._esc_charset_prober.language} + self.done = True + # If we've seen high bytes (i.e., those with values greater than 127), + # we need to do more complicated checks using all our multi-byte and + # single-byte probers that are left. The single-byte probers + # use character bigram distributions to determine the encoding, whereas + # the multi-byte probers use a combination of character unigram and + # bigram distributions. + elif self._input_state == InputState.HIGH_BYTE: + if not self._charset_probers: + self._charset_probers = [MBCSGroupProber(self.lang_filter)] + # If we're checking non-CJK encodings, use single-byte prober + if self.lang_filter & LanguageFilter.NON_CJK: + self._charset_probers.append(SBCSGroupProber()) + self._charset_probers.append(Latin1Prober()) + for prober in self._charset_probers: + if prober.feed(byte_str) == ProbingState.FOUND_IT: + self.result = {'encoding': prober.charset_name, + 'confidence': prober.get_confidence(), + 'language': prober.language} + self.done = True + break + if self.WIN_BYTE_DETECTOR.search(byte_str): + self._has_win_bytes = True + + def close(self): + """ + Stop analyzing the current document and come up with a final + prediction. + + :returns: The ``result`` attribute, a ``dict`` with the keys + `encoding`, `confidence`, and `language`. + """ + # Don't bother with checks if we're already done + if self.done: + return self.result + self.done = True + + if not self._got_data: + self.logger.debug('no data received!') + + # Default to ASCII if it is all we've seen so far + elif self._input_state == InputState.PURE_ASCII: + self.result = {'encoding': 'ascii', + 'confidence': 1.0, + 'language': ''} + + # If we have seen non-ASCII, return the best that met MINIMUM_THRESHOLD + elif self._input_state == InputState.HIGH_BYTE: + prober_confidence = None + max_prober_confidence = 0.0 + max_prober = None + for prober in self._charset_probers: + if not prober: + continue + prober_confidence = prober.get_confidence() + if prober_confidence > max_prober_confidence: + max_prober_confidence = prober_confidence + max_prober = prober + if max_prober and (max_prober_confidence > self.MINIMUM_THRESHOLD): + charset_name = max_prober.charset_name + lower_charset_name = max_prober.charset_name.lower() + confidence = max_prober.get_confidence() + # Use Windows encoding name instead of ISO-8859 if we saw any + # extra Windows-specific bytes + if lower_charset_name.startswith('iso-8859'): + if self._has_win_bytes: + charset_name = self.ISO_WIN_MAP.get(lower_charset_name, + charset_name) + self.result = {'encoding': charset_name, + 'confidence': confidence, + 'language': max_prober.language} + + # Log all prober confidences if none met MINIMUM_THRESHOLD + if self.logger.getEffectiveLevel() == logging.DEBUG: + if self.result['encoding'] is None: + self.logger.debug('no probers hit minimum threshold') + for group_prober in self._charset_probers: + if not group_prober: + continue + if isinstance(group_prober, CharSetGroupProber): + for prober in group_prober.probers: + self.logger.debug('%s %s confidence = %s', + prober.charset_name, + prober.language, + prober.get_confidence()) + else: + self.logger.debug('%s %s confidence = %s', + prober.charset_name, + prober.language, + prober.get_confidence()) + return self.result diff --git a/flex/lib/python3.6/site-packages/chardet/utf8prober.py b/flex/lib/python3.6/site-packages/chardet/utf8prober.py new file mode 100644 index 0000000..6c3196c --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/utf8prober.py @@ -0,0 +1,82 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState, MachineState +from .codingstatemachine import CodingStateMachine +from .mbcssm import UTF8_SM_MODEL + + + +class UTF8Prober(CharSetProber): + ONE_CHAR_PROB = 0.5 + + def __init__(self): + super(UTF8Prober, self).__init__() + self.coding_sm = CodingStateMachine(UTF8_SM_MODEL) + self._num_mb_chars = None + self.reset() + + def reset(self): + super(UTF8Prober, self).reset() + self.coding_sm.reset() + self._num_mb_chars = 0 + + @property + def charset_name(self): + return "utf-8" + + @property + def language(self): + return "" + + def feed(self, byte_str): + for c in byte_str: + coding_state = self.coding_sm.next_state(c) + if coding_state == MachineState.ERROR: + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + if self.coding_sm.get_current_charlen() >= 2: + self._num_mb_chars += 1 + + if self.state == ProbingState.DETECTING: + if self.get_confidence() > self.SHORTCUT_THRESHOLD: + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + unlike = 0.99 + if self._num_mb_chars < 6: + unlike *= self.ONE_CHAR_PROB ** self._num_mb_chars + return 1.0 - unlike + else: + return unlike diff --git a/flex/lib/python3.6/site-packages/chardet/version.py b/flex/lib/python3.6/site-packages/chardet/version.py new file mode 100644 index 0000000..bb2a34a --- /dev/null +++ b/flex/lib/python3.6/site-packages/chardet/version.py @@ -0,0 +1,9 @@ +""" +This module exists only to simplify retrieving the version number of chardet +from within setup.py and from chardet subpackages. + +:author: Dan Blanchard (dan.blanchard@gmail.com) +""" + +__version__ = "3.0.4" +VERSION = __version__.split('.') diff --git a/flex/lib/python3.6/site-packages/click-6.7.dist-info/DESCRIPTION.rst b/flex/lib/python3.6/site-packages/click-6.7.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..e118723 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click-6.7.dist-info/DESCRIPTION.rst @@ -0,0 +1,3 @@ +UNKNOWN + + diff --git a/flex/lib/python3.6/site-packages/click-6.7.dist-info/INSTALLER b/flex/lib/python3.6/site-packages/click-6.7.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/flex/lib/python3.6/site-packages/click-6.7.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/flex/lib/python3.6/site-packages/click-6.7.dist-info/METADATA b/flex/lib/python3.6/site-packages/click-6.7.dist-info/METADATA new file mode 100644 index 0000000..1f10885 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click-6.7.dist-info/METADATA @@ -0,0 +1,16 @@ +Metadata-Version: 2.0 +Name: click +Version: 6.7 +Summary: A simple wrapper around optparse for powerful command line utilities. +Home-page: http://github.com/mitsuhiko/click +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +License: UNKNOWN +Platform: UNKNOWN +Classifier: License :: OSI Approved :: BSD License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 + +UNKNOWN + + diff --git a/flex/lib/python3.6/site-packages/click-6.7.dist-info/RECORD b/flex/lib/python3.6/site-packages/click-6.7.dist-info/RECORD new file mode 100644 index 0000000..090a2ca --- /dev/null +++ b/flex/lib/python3.6/site-packages/click-6.7.dist-info/RECORD @@ -0,0 +1,41 @@ +click/__init__.py,sha256=k8R00cFKWI8dhDVKQeLBlAdNh1CxerMEDRiGnr32gdw,2858 +click/_bashcomplete.py,sha256=82rMiibtEurdwBq60NHXVCBuGXJHDpblFO9o2YxJDF0,2423 +click/_compat.py,sha256=j59MpzxYGE-fTGj0A5sg8UI8GhHod1XMojiCA0jvbL0,21011 +click/_termui_impl.py,sha256=Ol1JJhvBRw3l8j1WIU0tOWjQtxxmwGE44lFDbzDqzoA,16395 +click/_textwrap.py,sha256=gwS4m7bdQiJnzaDG8osFcRb-5vn4t4l2qSCy-5csCEc,1198 +click/_unicodefun.py,sha256=A3UOzJw6lEZyol2SBg3fNXgweTutaOzkJ61OB7vik3Y,4204 +click/_winconsole.py,sha256=MzG46DEYPoRyx4SO7EIhFuFZHESgooAfJLIukbB6p5c,7790 +click/core.py,sha256=M0nJ6Kkye7XZXYG7HCbkJWSfy14WHV6bQmGLACrOhKw,70254 +click/decorators.py,sha256=y7CX2needh8iRWafj-QS_hGQFsN24eyXAhx5Y2ATwas,10941 +click/exceptions.py,sha256=rOa0pP3PbSy0_AAPOW9irBEM8AJ3BySN-4z2VUwFVo4,6788 +click/formatting.py,sha256=eh-cypTUAhpI3HD-K4ZpR3vCiURIO62xXvKkR3tNUTM,8889 +click/globals.py,sha256=PAgnKvGxq4YuEIldw3lgYOGBLYwsyxnm1IByBX3BFXo,1515 +click/parser.py,sha256=i01xgYuIA6AwQWEXjshwHSwnTR3gUep4FxJIfyW4ta4,15510 +click/termui.py,sha256=Bp99MSWQtyoWe1_7HggDmA77n--3KLxu7NsZMFMaCUo,21008 +click/testing.py,sha256=kJ9mjtJgwNAlkgKcFf9-ISxufmaPDbbuOHVC9WIvKdY,11002 +click/types.py,sha256=ZGb2lmFs5Vwd9loTRIMbGcqhPVOql8mGoBhWBRT6V4E,18864 +click/utils.py,sha256=1jalPlkUU28JReTEQeeSFtbJd-SirYWBNfjtELBKzT4,14916 +click-6.7.dist-info/DESCRIPTION.rst,sha256=OCTuuN6LcWulhHS3d5rfjdsQtW22n7HENFRh6jC6ego,10 +click-6.7.dist-info/METADATA,sha256=l6lAyogIUXiHKUK_rWguef-EMcvO5C6bXzFCNCcblbQ,424 +click-6.7.dist-info/RECORD,, +click-6.7.dist-info/WHEEL,sha256=5wvfB7GvgZAbKBSE9uX9Zbi6LCL-_KgezgHblXhCRnM,113 +click-6.7.dist-info/metadata.json,sha256=qg0uO6amNHkIkOxnmWX7Xa_DNQMQ62Q6drivuP9Gh1c,571 +click-6.7.dist-info/top_level.txt,sha256=J1ZQogalYS4pphY_lPECoNMfw0HzTSrZglC4Yfwo4xA,6 +click-6.7.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +click/__pycache__/parser.cpython-36.pyc,, +click/__pycache__/exceptions.cpython-36.pyc,, +click/__pycache__/formatting.cpython-36.pyc,, +click/__pycache__/testing.cpython-36.pyc,, +click/__pycache__/types.cpython-36.pyc,, +click/__pycache__/_bashcomplete.cpython-36.pyc,, +click/__pycache__/_compat.cpython-36.pyc,, +click/__pycache__/_winconsole.cpython-36.pyc,, +click/__pycache__/_unicodefun.cpython-36.pyc,, +click/__pycache__/utils.cpython-36.pyc,, +click/__pycache__/_textwrap.cpython-36.pyc,, +click/__pycache__/core.cpython-36.pyc,, +click/__pycache__/termui.cpython-36.pyc,, +click/__pycache__/__init__.cpython-36.pyc,, +click/__pycache__/globals.cpython-36.pyc,, +click/__pycache__/decorators.cpython-36.pyc,, +click/__pycache__/_termui_impl.cpython-36.pyc,, diff --git a/flex/lib/python3.6/site-packages/click-6.7.dist-info/WHEEL b/flex/lib/python3.6/site-packages/click-6.7.dist-info/WHEEL new file mode 100644 index 0000000..7bf9daa --- /dev/null +++ b/flex/lib/python3.6/site-packages/click-6.7.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.30.0.a0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/flex/lib/python3.6/site-packages/click-6.7.dist-info/metadata.json b/flex/lib/python3.6/site-packages/click-6.7.dist-info/metadata.json new file mode 100644 index 0000000..0a4cfb1 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click-6.7.dist-info/metadata.json @@ -0,0 +1 @@ +{"classifiers": ["License :: OSI Approved :: BSD License", "Programming Language :: Python", "Programming Language :: Python :: 3"], "extensions": {"python.details": {"contacts": [{"email": "armin.ronacher@active-4.com", "name": "Armin Ronacher", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://github.com/mitsuhiko/click"}}}, "generator": "bdist_wheel (0.30.0.a0)", "metadata_version": "2.0", "name": "click", "summary": "A simple wrapper around optparse for powerful command line utilities.", "version": "6.7"} \ No newline at end of file diff --git a/flex/lib/python3.6/site-packages/click-6.7.dist-info/top_level.txt b/flex/lib/python3.6/site-packages/click-6.7.dist-info/top_level.txt new file mode 100644 index 0000000..dca9a90 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click-6.7.dist-info/top_level.txt @@ -0,0 +1 @@ +click diff --git a/flex/lib/python3.6/site-packages/click/__init__.py b/flex/lib/python3.6/site-packages/click/__init__.py new file mode 100644 index 0000000..971e55d --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/__init__.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +""" + click + ~~~~~ + + Click is a simple Python module that wraps the stdlib's optparse to make + writing command line scripts fun. Unlike other modules, it's based around + a simple API that does not come with too much magic and is composable. + + In case optparse ever gets removed from the stdlib, it will be shipped by + this module. + + :copyright: (c) 2014 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + +# Core classes +from .core import Context, BaseCommand, Command, MultiCommand, Group, \ + CommandCollection, Parameter, Option, Argument + +# Globals +from .globals import get_current_context + +# Decorators +from .decorators import pass_context, pass_obj, make_pass_decorator, \ + command, group, argument, option, confirmation_option, \ + password_option, version_option, help_option + +# Types +from .types import ParamType, File, Path, Choice, IntRange, Tuple, \ + STRING, INT, FLOAT, BOOL, UUID, UNPROCESSED + +# Utilities +from .utils import echo, get_binary_stream, get_text_stream, open_file, \ + format_filename, get_app_dir, get_os_args + +# Terminal functions +from .termui import prompt, confirm, get_terminal_size, echo_via_pager, \ + progressbar, clear, style, unstyle, secho, edit, launch, getchar, \ + pause + +# Exceptions +from .exceptions import ClickException, UsageError, BadParameter, \ + FileError, Abort, NoSuchOption, BadOptionUsage, BadArgumentUsage, \ + MissingParameter + +# Formatting +from .formatting import HelpFormatter, wrap_text + +# Parsing +from .parser import OptionParser + + +__all__ = [ + # Core classes + 'Context', 'BaseCommand', 'Command', 'MultiCommand', 'Group', + 'CommandCollection', 'Parameter', 'Option', 'Argument', + + # Globals + 'get_current_context', + + # Decorators + 'pass_context', 'pass_obj', 'make_pass_decorator', 'command', 'group', + 'argument', 'option', 'confirmation_option', 'password_option', + 'version_option', 'help_option', + + # Types + 'ParamType', 'File', 'Path', 'Choice', 'IntRange', 'Tuple', 'STRING', + 'INT', 'FLOAT', 'BOOL', 'UUID', 'UNPROCESSED', + + # Utilities + 'echo', 'get_binary_stream', 'get_text_stream', 'open_file', + 'format_filename', 'get_app_dir', 'get_os_args', + + # Terminal functions + 'prompt', 'confirm', 'get_terminal_size', 'echo_via_pager', + 'progressbar', 'clear', 'style', 'unstyle', 'secho', 'edit', 'launch', + 'getchar', 'pause', + + # Exceptions + 'ClickException', 'UsageError', 'BadParameter', 'FileError', + 'Abort', 'NoSuchOption', 'BadOptionUsage', 'BadArgumentUsage', + 'MissingParameter', + + # Formatting + 'HelpFormatter', 'wrap_text', + + # Parsing + 'OptionParser', +] + + +# Controls if click should emit the warning about the use of unicode +# literals. +disable_unicode_literals_warning = False + + +__version__ = '6.7' diff --git a/flex/lib/python3.6/site-packages/click/__pycache__/__init__.cpython-36.pyc b/flex/lib/python3.6/site-packages/click/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eb1743a7a678ecda48525064fa06611b333dfd81 GIT binary patch literal 2735 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 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/click/__pycache__/_compat.cpython-36.pyc b/flex/lib/python3.6/site-packages/click/__pycache__/_compat.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..76c61f2ac8b225d19029ec008dfb8703f06479da GIT binary patch literal 15448 zcmd5@X>1(VeV=QW%jJ@y4$HEvSZiCBMOma|Sw3VdvSdkga`=RKEDcYh)fx#xw@T)0 zmu$IrN{*b}k}GGgW4IHIh3Eafgar5x@?7xT*7uuEeqQz``3;<(D< zZbFTy+`Cq3iyBpVoF~@vEEo$;zOHBs$;`R-SpY<)4fyR<8~r?fk`w{&lCPjGkDDeY0))eemDso=iSUUiq+iR+@wd^cvkf2AOB zKTvw$iq+iXS;2!#dHvtE#Xq%6zTEe^)y!YD)IDl9zTKzpReNxLNPSA(hx2~5R~2!7 zSlzE4!1;ixs|VG-ckR-YYN&_Qeq0??P4%!kfU8H;lsbrBhnnA#c|k|OyDOL`yj8oj zCzt`0kI1|asY3>GHEp0)Ep=EO!6=7STRp0d;_8TcOdZ2`kE+Mj6F47LPpYSIeoP%# zPvd+{J)=(G{J8qGI*IcW>e&S9Qwh|k6R6)-&m~Z6btZv2RA&>Y&l#vyq-NFgnD
!h+v z&*C_RtzBl3EsnRKMaHruQdVJgP5WL%c)e5p3R_S?lOTDSy!Z**V&nh2doo-I5Yi3kc z7FwTE3#x)QpHWH$IG^#IpV&+AHzhfWhy<=63rP~^;XR%>%Kg9tO}x2yLHW)oP$YktrwMN_ZB6FiIhbclmRz=9zjcM34F4R&@Tt6J?e;!)B9rqRTl|P<|yx@8e z7c0PW5jbtwi;l9FoXeJHMJ}Y)zC>!_38a-vOjq}vxe-*B!eXsjEEliWZU)U_7s_HS zESAGctu_;9|Fv)l;cv6tlT9MPJxH5qdoa<$NxVN#;q zhhAY0jpaD@q&;EldvKj1M#g$L1hIX%AoG;1oDH|VEdp{I*18?JYxah%i$rIQ8^~LI z^imLYbTceQH-ciabc=?ZeYjPN%~n*bwmMBUBk<0xW;#)I`YGTz0{)hxNNcVkO$Y_D zDMxb;#g4u?gq)th^ZhsybasGCo-I!+c$)r*(kUF_Q)mKGrPN0bgYWY~|k+bM7dS;2Qxm9n? z`=SkDnQZ<{T<~XWw>s_1W{r*{3omwRt$2K3CC546uQh9t?@wi7FAVBcA%|i1Hq0Am zuyA#Gm^MYcI)WnFZ^xUmV(55Vovql=knPpvz0?mc2_oBfHxgV$4zBNpQDLf|A zL#`Cd-ex;?0i?)c-LKwvM{>yUDJ@)l$wM~89$ehoxn`fW-kMl;zvMnGFLpkF6DyaMZIf5vHBO&8z@s407pA5iAIE9Fmx+EQyqFD%z z{uG|Y*;)tzu(CNEnyXoMo2*i2b?+T#H^Xp!Ve?Q@`hJ}E{YFc5>bx%a{@a~$-MrC7 zPVHWN{iyIwPvce}X2S{lh#}gSu!|s=!G-9EoRb@Yei+SpxvUWpc$5AJ>nR)|o1W}} zT@JkmS>q{BWkmKs>WJ*gsZpFqR9=nYoKpogj`OIR0I9ZUF2L2V%|pgEgXLnaRjf6! z6{=90co3+t*l6jXSkBg{p~lQ?IWSYmIiDmPa&GES?UFVW)EA z5WayLs@85zciKg&9%`j#Pzk~i77^x@al%$3C{}8^(rK729L~t|bn6g#9zCu@LHd0g zgn>30oHpLR+y=Ip8Vd>S_f0w^16!-c@00W_-bTN5D)k?80dLbxdU6uOkx z9t9?t?aaj)STO3*sZ0-SeGG%fIXOqrhKOApG~msGjoAw7z9hi z6D;mq#I$3ArPzytdi^8ud=_y1G>#!o?-V^ggkg8Oxv9K<6yNBhY#u`sQ;W4KzArLG zKhEde7Mcr5la`tj^)0iWxTnm$h(oLhY#b-&;%_XM&y9;bPU*?ToN760O3(^=7(9ou zW5=VkT5vQ%Xt+%lb(}jZ@q-YYJHG`rM?+#ND zkKg1}IC=;Th!{$?uIaLFCn99fbeX&gkx5}0d5f71$L`KNm5sCXRGTeXPI0yo-mK`T zG!h08w0;mftuW4A@Si(Bcly%n5d9R*nli1A;Z*JM7JT6^)adxrUI>004->KJ7~9c- z$Mgc84v-_&a)v9$5u|)Hym#UWzowvLYt>qyeI39%1!pQZHm6oxfLWY&{{w=+3E*$P z%!zr~{iPEV`Ur~w4jPpQBMbtjcvEpEj1X7oLpELA@uaxb24m^<#~7(Q-vwNMlKJ3# zt5zr4bVB3DrxT*vclu_0<;R#2{{6?95#7GqH{)f_DD=gJizD4)#;qew#cSy)@ZD<= zbCKJ7V<_&$_tJ3i5i3%ye6Nz89*J2<+p;>k}4a6L}|vTP{nJ|2Ku`T+zR{{mkQLiie<{Ny2|L;49I1l#}e zHVCf}LJBkfc;*5)gCnHWH}ZAE(YqkYoe1u(f-Sjj#EvtkX=B26c@U>KW879aR5X|+ zG6tESxmm7vZgc!5L|D-=iCTWA_BWi5#JB7`)S7++R|7z$()Ko`A`)S9DI&V#A2>8e z9vCl`8a*SK3cV|=JSwU<^FvgXjQx+Bj?KV`5O5L~T?G}nRky36488PKypHpY01nH_ z&04Um>0jOf6Dp>E!jXuj*>p`2k<@~rieng#77F+Ty~rsC!*GmN!49Ls0{=+YgnwGh zP6E}nNC4~Y8wRIWK({)7Br;?Jon}p}~&_E2*5w0G5T)I77SK$bH*b3`F zA0g<%1aEFuj1|Is4TFdufNLSXi-6BC%-a!?ZmL1j{|7z{sQ|4Epmhq~Hd|M4_rC}$ zNzo6hUf_cv`VPWsC_I8SHw>%lhm~tG-9uyrwR#$Yodo^3PrcR0PItqr@XZ^w5Xz=n zyWY`(VpzErg?(Yyuz33Nne*q9kgMjXpfTgV1_ygH?;Fu|qqw-#2PW7_9LRqws{^!Y z27qvL=vhmAr^680Yj0e3s-$UQ-To zBtj?l2ghCP6wx;svr$NRfl8LT(T84XObiAik^1N}J|L=w*XeG*+R~K(6wx}UBu0lB zW18gHg{i2Tve;PIUbZ*Fw1}4xD}-M7{};lPNs}I7xUU8YWA@-Cgh^fuZQxA_W4fOI zNW$D8VQ|O~y?dcBMy|WII*kcg_q!vP%HSQW7*S5EPh2S@=!SF&9q3}zLRJN8xq+xp z(Qvc7|G~T>@`p2Gz0W|Oan_!-85b^f;CVEHBu^A$(^6p#tpZJ3KOj~#GRSVO`yU5^ zCqDrKFe8b9aIR;L)&LNUsqCg)(y!oc{r?(p&~p%Qu~H4-dI=B?lbdcwcpKCrRq@8f zkxG~YxH0SHWBMU|=DheD+@l}mZ-_gw+5^Zq8L9p969ecXVA0$g9|;h>hoAZ12S^z8 zu>hj8@VVOn!UOs7Oe&qh5gtWDrNE?_-aY6&GeiYA*jnlUP|Q)GZNeX^L&+j+n!x9@tzd)9D+J}2vihi^ZIaawLT5>z|}@oOD$r8t17cU92S=e#7e94Fj8dYDwOGrghf~PzbX&{iq_3Qi;}rE-7af5 z=;#E1QJYg%GpmPAN3BM!Qj{KHvDL)rtQ{$az#=Fv*P!dufU~QNSXFV-Iv_N`gDizs3NPFc-=%rGrOW^*CF~8VL0|2Xm?_E<}yCl>V^036>5D zm3WLZB>us#aSzf1v}h{h4QS?4527j${`0qWop~tbl#G!znoWJ$xs!VZOp4 zx<5*!Q#isG(DV|g-J%UsvVl^;3_v? ziZo!z2Rj8RO6(StallKle28bXZW1z>MWKr0SL1QNpF{}n!ltUHBtyLpijo2aOXhxz zX(;$PT$RQL`VGl8T|}3^CpB}pu#nN>-|CJ&KK7EH=q5j&c?bp+Yz!*^QKlU9&*C1Z z`*9kci;2(g;X~udIjfWXvyktzsfHkd(kKg;DyPtSl7t$9H9Ik*=?ln;@{%hM5%)6Sl#< zO8nxH3zw7qk#_n#oJzx{R{D@H%wZ4Shrr9Lqx&M)_#fzC<7GX z3KgQ$E2FO8B-2bZ5;*iGnP$mDeLrP_y?S^5lzmy~G?Ib7J#KUHinn0T33i)vIv({= z`~?E|{=fH4b=TljNsobzkzz;^0Y8RsU+9Gk+0c479R?_n?pT^MhV*^WORN+v3+N8?z@+Tr`~P+4 zNlgcAq1maip;V&m(m2=F5P>>cF?{7}GFio+=hZK<`3jrfs*@`MEE4GNI5*=As2|A| zynI2Dims7Pcqc!eQzn>Y#?U6THH|C;Fd6TIO3C?Us8L{rBC5^;(B8xjjPo#>YHjJ6 z0Rg)yp08qvfpwh{cR$`FfsA6}r0!&q<2sUXG&c&||I(Ut6NQf!f8&UNWrBE_N~?~z zLXQq4LA*7*L1Ta#B!Ov^F!7x!y3ArX>aXGML;9s3k`lmc9;XTp`SDo_ENwuRS=23h z)JbVkH^hrNr+TYWhT_}->yfG##$$jC8_Z@Fm)iPQ@%b=}+a#G&*4J;Q#gn@Ur05Q) zGW~UaL>8orlgvs%GCn|8KCW5%K4uUY4y6f52^nQ@4~rS{(n3jox9(%r8P8AUj0b;- zbC4794wPX@MQ}GYPD4ARw`MmX>^`2dYtAq;89PQmT&mTdS*yFB0 z(JeILOmK1dm&_tT@$yzIk$EX)>NKUE8>U;ijRMRi783lb}~ z+$c*mQ!)9KVKmmlu!Hz2OkY;HBF*>MQFN9hU-9(C^L&8-8o!2dh>LS8Y1muIU@6u(q` zwL=J_tS_L)1(8W4IOL?+Te9`X{IFaNOs8kL(#)oJu%og#Rv#{RkQL*13`>f%g zMX35)=v84?{>TIFrZYIggJ`&)kaT2=nE#?Da!rh@U6gR}*%ouVEc%obzoYv1@eOKY ziCet;`5-!D7Uty&T;=9-Qb>QkS#8DH%kyV1ygFaXg&KrFqPmp1RJ(p7DtRvj)u@zx zt`)&yDY^5lHUuMu-LPPkk^xKvo1)>f=Imu6O_4x53cmLr;VMOpk2#7UMoYqkvP?}J zYRVxKjWVOF2?K%={$BJ_A{>1HkP)Uh@awp`#EEfW;&eU|lE?EnL{^KX(le1r+r9z0 z`XrtCD#yZ2Pnr*~#He2r(C--=E?g>26$(;qGB8~>&1(%VXi@1}n_*KaJxRA&mxicImvty5M z0}_T9bIJDa)ZYGF-EaP9h>R)tDY zVb`68CTr5IG&v!aDkX|BU%1d!*N-D}0$_bBrHhz>6HUHQ}@!v<1 z|1t0xA|$lpfAfh)mhm6HU=Rum;{trj5aB1-LC`(N*dYhEGr~=S26S0RA;UZ+_saRX z(w4L5W>3HR(!77>!b`8dJa;)BVNMZI7X8bdgu7bOPbSkk!P~uTwxEf#t%XG-+oXap z9_ch|4B^J3lE0(pWJ04?*`JnIT%gKsUKg(_)La2^_LeR;uLq^PoaBwv^ywG*73E(% zcAgQmNc>|{55^KQ6KZ;eSC`qalE}oM7~+u!9 z64RHcs|o3}_>4kRe~HZpXqb7Dh|)WJLhUC?OVou3QPJ0>F&0oIW|hfge4Sl?mkmXy z5q#g})vvSp2Ab0C)-jBZ(nON?G!{ZwDkSw(v={pSBUrkuQG-B#eu!li!=q S$c!Gw+0N(5;W@aq6Wg1l+vVONxyya& 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 H{?`8k&mXA* literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/click/__pycache__/_textwrap.cpython-36.pyc b/flex/lib/python3.6/site-packages/click/__pycache__/_textwrap.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5cc3b6cffff5f0f5b074c45b03217cb672a3e9a8 GIT binary patch literal 1349 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 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/click/__pycache__/decorators.cpython-36.pyc b/flex/lib/python3.6/site-packages/click/__pycache__/decorators.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..919bad482a6f1d0e06e98ef6319cd4e94c24cac9 GIT binary patch literal 11514 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 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/click/__pycache__/formatting.cpython-36.pyc b/flex/lib/python3.6/site-packages/click/__pycache__/formatting.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5f0a473b83d8134c6b63ad78a3899b8a31c954e7 GIT binary patch literal 8567 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 Hg}C%TRk(Iw literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/click/__pycache__/globals.cpython-36.pyc b/flex/lib/python3.6/site-packages/click/__pycache__/globals.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6e9b9ab1b1aa4129c14944f0d084b80c5dfb5eff GIT binary patch literal 1897 zcmZux&2Aev5GHpeS(arNNRYHW6kvlEse(ju8>fhcqG%B`fG_mqi@hlJLGB;xd?&f@^|LrH}lQY{ryh)XLSB|6QRG*RtsVL z9eid89YYLDl;U%Y5yxwE9p{p4_TA7-k|da+hJ|^H`zYxuszsmvE5gwcW?vu zQ4g0*sUj+0M%c}vxqlbF7x0QYpHUY4gjfSywCFlO=#<++XNK5>lc>;|XO=`#L~|0U%I89DE8}S(BFQ zj9Rha;J_mr#zhtlCpk4{yumdgj7LgSt8{J89kN1YL>O-<*CM4_$ZLl>E+mPSCJC20 z*M^uPO58&>rg@a83As!Jtfpd?Sa_^AB7g#A7l{xlM+X7n>U{z?eg(eXz-b$^tkyWHM42Y>Aj;s*bk@>w>z~T%ZA14tCY2}y7}A4fO;LhCilof)^(T3xorUL@tg_b?OF!dB+X&Pm4jm3LKkw;hA7 zS`|^hBkk1m&vXFEvY?g^7E}*nB^l5>i1py<{L4(gJ~}>ROSU{VN6+U+$LaCcM~Bd6 z+2CxDi~Py75RyGP635TP>*;*p@oxH=R8uNVKff;T0^adPV|5nqI2m`KLmveA0N=q4 ztPfyzOYg3zc)foF1B)*3MZoY3t%Hkjh1M7&7J#0^<)a@V!MGDu#xLu5))K14?YZu2 zXLHnRXa}HdkH<_zc04XSkTjdnmMxm+JYzss7}+b&Q`POeJ6)H}^)o(!6$8}-p+Mh- zK61mlxwv}x?qL=DHIyZW0d%nZ{FJ9^0jOPqT9p&Y7aXMO3Wi&%@Q!++hw5>cVXpEm zJT8LTgW7|Q8q)()f#n`llM6h`gH otwQC(?Xy8U`u&A1ckg_*zeyD&bWig(iuTVdyZyV-932OKmFN&o-= literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/click/__pycache__/parser.cpython-36.pyc b/flex/lib/python3.6/site-packages/click/__pycache__/parser.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d30615ecae5042ec265301d39291fcc84a3d0359 GIT binary patch literal 11496 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 EAIqua9smFU literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/click/__pycache__/termui.cpython-36.pyc b/flex/lib/python3.6/site-packages/click/__pycache__/termui.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba6c8f2a111d129df7b90138155f1062aed9fd4e GIT binary patch literal 18941 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 HH;(@=t3xCq literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/click/_bashcomplete.py b/flex/lib/python3.6/site-packages/click/_bashcomplete.py new file mode 100644 index 0000000..d9d26d2 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/_bashcomplete.py @@ -0,0 +1,83 @@ +import os +import re +from .utils import echo +from .parser import split_arg_string +from .core import MultiCommand, Option + + +COMPLETION_SCRIPT = ''' +%(complete_func)s() { + COMPREPLY=( $( env COMP_WORDS="${COMP_WORDS[*]}" \\ + COMP_CWORD=$COMP_CWORD \\ + %(autocomplete_var)s=complete $1 ) ) + return 0 +} + +complete -F %(complete_func)s -o default %(script_names)s +''' + +_invalid_ident_char_re = re.compile(r'[^a-zA-Z0-9_]') + + +def get_completion_script(prog_name, complete_var): + cf_name = _invalid_ident_char_re.sub('', prog_name.replace('-', '_')) + return (COMPLETION_SCRIPT % { + 'complete_func': '_%s_completion' % cf_name, + 'script_names': prog_name, + 'autocomplete_var': complete_var, + }).strip() + ';' + + +def resolve_ctx(cli, prog_name, args): + ctx = cli.make_context(prog_name, args, resilient_parsing=True) + while ctx.protected_args + ctx.args and isinstance(ctx.command, MultiCommand): + a = ctx.protected_args + ctx.args + cmd = ctx.command.get_command(ctx, a[0]) + if cmd is None: + return None + ctx = cmd.make_context(a[0], a[1:], parent=ctx, resilient_parsing=True) + return ctx + + +def get_choices(cli, prog_name, args, incomplete): + ctx = resolve_ctx(cli, prog_name, args) + if ctx is None: + return + + choices = [] + if incomplete and not incomplete[:1].isalnum(): + for param in ctx.command.params: + if not isinstance(param, Option): + continue + choices.extend(param.opts) + choices.extend(param.secondary_opts) + elif isinstance(ctx.command, MultiCommand): + choices.extend(ctx.command.list_commands(ctx)) + + for item in choices: + if item.startswith(incomplete): + yield item + + +def do_complete(cli, prog_name): + cwords = split_arg_string(os.environ['COMP_WORDS']) + cword = int(os.environ['COMP_CWORD']) + args = cwords[1:cword] + try: + incomplete = cwords[cword] + except IndexError: + incomplete = '' + + for item in get_choices(cli, prog_name, args, incomplete): + echo(item) + + return True + + +def bashcomplete(cli, prog_name, complete_var, complete_instr): + if complete_instr == 'source': + echo(get_completion_script(prog_name, complete_var)) + return True + elif complete_instr == 'complete': + return do_complete(cli, prog_name) + return False diff --git a/flex/lib/python3.6/site-packages/click/_compat.py b/flex/lib/python3.6/site-packages/click/_compat.py new file mode 100644 index 0000000..2b43412 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/_compat.py @@ -0,0 +1,648 @@ +import re +import io +import os +import sys +import codecs +from weakref import WeakKeyDictionary + + +PY2 = sys.version_info[0] == 2 +WIN = sys.platform.startswith('win') +DEFAULT_COLUMNS = 80 + + +_ansi_re = re.compile('\033\[((?:\d|;)*)([a-zA-Z])') + + +def get_filesystem_encoding(): + return sys.getfilesystemencoding() or sys.getdefaultencoding() + + +def _make_text_stream(stream, encoding, errors): + if encoding is None: + encoding = get_best_encoding(stream) + if errors is None: + errors = 'replace' + return _NonClosingTextIOWrapper(stream, encoding, errors, + line_buffering=True) + + +def is_ascii_encoding(encoding): + """Checks if a given encoding is ascii.""" + try: + return codecs.lookup(encoding).name == 'ascii' + except LookupError: + return False + + +def get_best_encoding(stream): + """Returns the default stream encoding if not found.""" + rv = getattr(stream, 'encoding', None) or sys.getdefaultencoding() + if is_ascii_encoding(rv): + return 'utf-8' + return rv + + +class _NonClosingTextIOWrapper(io.TextIOWrapper): + + def __init__(self, stream, encoding, errors, **extra): + self._stream = stream = _FixupStream(stream) + io.TextIOWrapper.__init__(self, stream, encoding, errors, **extra) + + # The io module is a place where the Python 3 text behavior + # was forced upon Python 2, so we need to unbreak + # it to look like Python 2. + if PY2: + def write(self, x): + if isinstance(x, str) or is_bytes(x): + try: + self.flush() + except Exception: + pass + return self.buffer.write(str(x)) + return io.TextIOWrapper.write(self, x) + + def writelines(self, lines): + for line in lines: + self.write(line) + + def __del__(self): + try: + self.detach() + except Exception: + pass + + def isatty(self): + # https://bitbucket.org/pypy/pypy/issue/1803 + return self._stream.isatty() + + +class _FixupStream(object): + """The new io interface needs more from streams than streams + traditionally implement. As such, this fix-up code is necessary in + some circumstances. + """ + + def __init__(self, stream): + self._stream = stream + + def __getattr__(self, name): + return getattr(self._stream, name) + + def read1(self, size): + f = getattr(self._stream, 'read1', None) + if f is not None: + return f(size) + # We only dispatch to readline instead of read in Python 2 as we + # do not want cause problems with the different implementation + # of line buffering. + if PY2: + return self._stream.readline(size) + return self._stream.read(size) + + def readable(self): + x = getattr(self._stream, 'readable', None) + if x is not None: + return x() + try: + self._stream.read(0) + except Exception: + return False + return True + + def writable(self): + x = getattr(self._stream, 'writable', None) + if x is not None: + return x() + try: + self._stream.write('') + except Exception: + try: + self._stream.write(b'') + except Exception: + return False + return True + + def seekable(self): + x = getattr(self._stream, 'seekable', None) + if x is not None: + return x() + try: + self._stream.seek(self._stream.tell()) + except Exception: + return False + return True + + +if PY2: + text_type = unicode + bytes = str + raw_input = raw_input + string_types = (str, unicode) + iteritems = lambda x: x.iteritems() + range_type = xrange + + def is_bytes(x): + return isinstance(x, (buffer, bytearray)) + + _identifier_re = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*$') + + # For Windows, we need to force stdout/stdin/stderr to binary if it's + # fetched for that. This obviously is not the most correct way to do + # it as it changes global state. Unfortunately, there does not seem to + # be a clear better way to do it as just reopening the file in binary + # mode does not change anything. + # + # An option would be to do what Python 3 does and to open the file as + # binary only, patch it back to the system, and then use a wrapper + # stream that converts newlines. It's not quite clear what's the + # correct option here. + # + # This code also lives in _winconsole for the fallback to the console + # emulation stream. + # + # There are also Windows environments where the `msvcrt` module is not + # available (which is why we use try-catch instead of the WIN variable + # here), such as the Google App Engine development server on Windows. In + # those cases there is just nothing we can do. + try: + import msvcrt + except ImportError: + set_binary_mode = lambda x: x + else: + def set_binary_mode(f): + try: + fileno = f.fileno() + except Exception: + pass + else: + msvcrt.setmode(fileno, os.O_BINARY) + return f + + def isidentifier(x): + return _identifier_re.search(x) is not None + + def get_binary_stdin(): + return set_binary_mode(sys.stdin) + + def get_binary_stdout(): + return set_binary_mode(sys.stdout) + + def get_binary_stderr(): + return set_binary_mode(sys.stderr) + + def get_text_stdin(encoding=None, errors=None): + rv = _get_windows_console_stream(sys.stdin, encoding, errors) + if rv is not None: + return rv + return _make_text_stream(sys.stdin, encoding, errors) + + def get_text_stdout(encoding=None, errors=None): + rv = _get_windows_console_stream(sys.stdout, encoding, errors) + if rv is not None: + return rv + return _make_text_stream(sys.stdout, encoding, errors) + + def get_text_stderr(encoding=None, errors=None): + rv = _get_windows_console_stream(sys.stderr, encoding, errors) + if rv is not None: + return rv + return _make_text_stream(sys.stderr, encoding, errors) + + def filename_to_ui(value): + if isinstance(value, bytes): + value = value.decode(get_filesystem_encoding(), 'replace') + return value +else: + import io + text_type = str + raw_input = input + string_types = (str,) + range_type = range + isidentifier = lambda x: x.isidentifier() + iteritems = lambda x: iter(x.items()) + + def is_bytes(x): + return isinstance(x, (bytes, memoryview, bytearray)) + + def _is_binary_reader(stream, default=False): + try: + return isinstance(stream.read(0), bytes) + except Exception: + return default + # This happens in some cases where the stream was already + # closed. In this case, we assume the default. + + def _is_binary_writer(stream, default=False): + try: + stream.write(b'') + except Exception: + try: + stream.write('') + return False + except Exception: + pass + return default + return True + + def _find_binary_reader(stream): + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_reader(stream, False): + return stream + + buf = getattr(stream, 'buffer', None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_reader(buf, True): + return buf + + def _find_binary_writer(stream): + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detatching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_writer(stream, False): + return stream + + buf = getattr(stream, 'buffer', None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_writer(buf, True): + return buf + + def _stream_is_misconfigured(stream): + """A stream is misconfigured if its encoding is ASCII.""" + # If the stream does not have an encoding set, we assume it's set + # to ASCII. This appears to happen in certain unittest + # environments. It's not quite clear what the correct behavior is + # but this at least will force Click to recover somehow. + return is_ascii_encoding(getattr(stream, 'encoding', None) or 'ascii') + + def _is_compatible_text_stream(stream, encoding, errors): + stream_encoding = getattr(stream, 'encoding', None) + stream_errors = getattr(stream, 'errors', None) + + # Perfect match. + if stream_encoding == encoding and stream_errors == errors: + return True + + # Otherwise, it's only a compatible stream if we did not ask for + # an encoding. + if encoding is None: + return stream_encoding is not None + + return False + + def _force_correct_text_reader(text_reader, encoding, errors): + if _is_binary_reader(text_reader, False): + binary_reader = text_reader + else: + # If there is no target encoding set, we need to verify that the + # reader is not actually misconfigured. + if encoding is None and not _stream_is_misconfigured(text_reader): + return text_reader + + if _is_compatible_text_stream(text_reader, encoding, errors): + return text_reader + + # If the reader has no encoding, we try to find the underlying + # binary reader for it. If that fails because the environment is + # misconfigured, we silently go with the same reader because this + # is too common to happen. In that case, mojibake is better than + # exceptions. + binary_reader = _find_binary_reader(text_reader) + if binary_reader is None: + return text_reader + + # At this point, we default the errors to replace instead of strict + # because nobody handles those errors anyways and at this point + # we're so fundamentally fucked that nothing can repair it. + if errors is None: + errors = 'replace' + return _make_text_stream(binary_reader, encoding, errors) + + def _force_correct_text_writer(text_writer, encoding, errors): + if _is_binary_writer(text_writer, False): + binary_writer = text_writer + else: + # If there is no target encoding set, we need to verify that the + # writer is not actually misconfigured. + if encoding is None and not _stream_is_misconfigured(text_writer): + return text_writer + + if _is_compatible_text_stream(text_writer, encoding, errors): + return text_writer + + # If the writer has no encoding, we try to find the underlying + # binary writer for it. If that fails because the environment is + # misconfigured, we silently go with the same writer because this + # is too common to happen. In that case, mojibake is better than + # exceptions. + binary_writer = _find_binary_writer(text_writer) + if binary_writer is None: + return text_writer + + # At this point, we default the errors to replace instead of strict + # because nobody handles those errors anyways and at this point + # we're so fundamentally fucked that nothing can repair it. + if errors is None: + errors = 'replace' + return _make_text_stream(binary_writer, encoding, errors) + + def get_binary_stdin(): + reader = _find_binary_reader(sys.stdin) + if reader is None: + raise RuntimeError('Was not able to determine binary ' + 'stream for sys.stdin.') + return reader + + def get_binary_stdout(): + writer = _find_binary_writer(sys.stdout) + if writer is None: + raise RuntimeError('Was not able to determine binary ' + 'stream for sys.stdout.') + return writer + + def get_binary_stderr(): + writer = _find_binary_writer(sys.stderr) + if writer is None: + raise RuntimeError('Was not able to determine binary ' + 'stream for sys.stderr.') + return writer + + def get_text_stdin(encoding=None, errors=None): + rv = _get_windows_console_stream(sys.stdin, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_reader(sys.stdin, encoding, errors) + + def get_text_stdout(encoding=None, errors=None): + rv = _get_windows_console_stream(sys.stdout, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stdout, encoding, errors) + + def get_text_stderr(encoding=None, errors=None): + rv = _get_windows_console_stream(sys.stderr, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stderr, encoding, errors) + + def filename_to_ui(value): + if isinstance(value, bytes): + value = value.decode(get_filesystem_encoding(), 'replace') + else: + value = value.encode('utf-8', 'surrogateescape') \ + .decode('utf-8', 'replace') + return value + + +def get_streerror(e, default=None): + if hasattr(e, 'strerror'): + msg = e.strerror + else: + if default is not None: + msg = default + else: + msg = str(e) + if isinstance(msg, bytes): + msg = msg.decode('utf-8', 'replace') + return msg + + +def open_stream(filename, mode='r', encoding=None, errors='strict', + atomic=False): + # Standard streams first. These are simple because they don't need + # special handling for the atomic flag. It's entirely ignored. + if filename == '-': + if 'w' in mode: + if 'b' in mode: + return get_binary_stdout(), False + return get_text_stdout(encoding=encoding, errors=errors), False + if 'b' in mode: + return get_binary_stdin(), False + return get_text_stdin(encoding=encoding, errors=errors), False + + # Non-atomic writes directly go out through the regular open functions. + if not atomic: + if encoding is None: + return open(filename, mode), True + return io.open(filename, mode, encoding=encoding, errors=errors), True + + # Some usability stuff for atomic writes + if 'a' in mode: + raise ValueError( + 'Appending to an existing file is not supported, because that ' + 'would involve an expensive `copy`-operation to a temporary ' + 'file. Open the file in normal `w`-mode and copy explicitly ' + 'if that\'s what you\'re after.' + ) + if 'x' in mode: + raise ValueError('Use the `overwrite`-parameter instead.') + if 'w' not in mode: + raise ValueError('Atomic writes only make sense with `w`-mode.') + + # Atomic writes are more complicated. They work by opening a file + # as a proxy in the same folder and then using the fdopen + # functionality to wrap it in a Python file. Then we wrap it in an + # atomic file that moves the file over on close. + import tempfile + fd, tmp_filename = tempfile.mkstemp(dir=os.path.dirname(filename), + prefix='.__atomic-write') + + if encoding is not None: + f = io.open(fd, mode, encoding=encoding, errors=errors) + else: + f = os.fdopen(fd, mode) + + return _AtomicFile(f, tmp_filename, filename), True + + +# Used in a destructor call, needs extra protection from interpreter cleanup. +if hasattr(os, 'replace'): + _replace = os.replace + _can_replace = True +else: + _replace = os.rename + _can_replace = not WIN + + +class _AtomicFile(object): + + def __init__(self, f, tmp_filename, real_filename): + self._f = f + self._tmp_filename = tmp_filename + self._real_filename = real_filename + self.closed = False + + @property + def name(self): + return self._real_filename + + def close(self, delete=False): + if self.closed: + return + self._f.close() + if not _can_replace: + try: + os.remove(self._real_filename) + except OSError: + pass + _replace(self._tmp_filename, self._real_filename) + self.closed = True + + def __getattr__(self, name): + return getattr(self._f, name) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, tb): + self.close(delete=exc_type is not None) + + def __repr__(self): + return repr(self._f) + + +auto_wrap_for_ansi = None +colorama = None +get_winterm_size = None + + +def strip_ansi(value): + return _ansi_re.sub('', value) + + +def should_strip_ansi(stream=None, color=None): + if color is None: + if stream is None: + stream = sys.stdin + return not isatty(stream) + return not color + + +# If we're on Windows, we provide transparent integration through +# colorama. This will make ANSI colors through the echo function +# work automatically. +if WIN: + # Windows has a smaller terminal + DEFAULT_COLUMNS = 79 + + from ._winconsole import _get_windows_console_stream + + def _get_argv_encoding(): + import locale + return locale.getpreferredencoding() + + if PY2: + def raw_input(prompt=''): + sys.stderr.flush() + if prompt: + stdout = _default_text_stdout() + stdout.write(prompt) + stdin = _default_text_stdin() + return stdin.readline().rstrip('\r\n') + + try: + import colorama + except ImportError: + pass + else: + _ansi_stream_wrappers = WeakKeyDictionary() + + def auto_wrap_for_ansi(stream, color=None): + """This function wraps a stream so that calls through colorama + are issued to the win32 console API to recolor on demand. It + also ensures to reset the colors if a write call is interrupted + to not destroy the console afterwards. + """ + try: + cached = _ansi_stream_wrappers.get(stream) + except Exception: + cached = None + if cached is not None: + return cached + strip = should_strip_ansi(stream, color) + ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip) + rv = ansi_wrapper.stream + _write = rv.write + + def _safe_write(s): + try: + return _write(s) + except: + ansi_wrapper.reset_all() + raise + + rv.write = _safe_write + try: + _ansi_stream_wrappers[stream] = rv + except Exception: + pass + return rv + + def get_winterm_size(): + win = colorama.win32.GetConsoleScreenBufferInfo( + colorama.win32.STDOUT).srWindow + return win.Right - win.Left, win.Bottom - win.Top +else: + def _get_argv_encoding(): + return getattr(sys.stdin, 'encoding', None) or get_filesystem_encoding() + + _get_windows_console_stream = lambda *x: None + + +def term_len(x): + return len(strip_ansi(x)) + + +def isatty(stream): + try: + return stream.isatty() + except Exception: + return False + + +def _make_cached_stream_func(src_func, wrapper_func): + cache = WeakKeyDictionary() + def func(): + stream = src_func() + try: + rv = cache.get(stream) + except Exception: + rv = None + if rv is not None: + return rv + rv = wrapper_func() + try: + cache[stream] = rv + except Exception: + pass + return rv + return func + + +_default_text_stdin = _make_cached_stream_func( + lambda: sys.stdin, get_text_stdin) +_default_text_stdout = _make_cached_stream_func( + lambda: sys.stdout, get_text_stdout) +_default_text_stderr = _make_cached_stream_func( + lambda: sys.stderr, get_text_stderr) + + +binary_streams = { + 'stdin': get_binary_stdin, + 'stdout': get_binary_stdout, + 'stderr': get_binary_stderr, +} + +text_streams = { + 'stdin': get_text_stdin, + 'stdout': get_text_stdout, + 'stderr': get_text_stderr, +} diff --git a/flex/lib/python3.6/site-packages/click/_termui_impl.py b/flex/lib/python3.6/site-packages/click/_termui_impl.py new file mode 100644 index 0000000..7cfd3d5 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/_termui_impl.py @@ -0,0 +1,547 @@ +""" + click._termui_impl + ~~~~~~~~~~~~~~~~~~ + + This module contains implementations for the termui module. To keep the + import time of Click down, some infrequently used functionality is placed + in this module and only imported as needed. + + :copyright: (c) 2014 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" +import os +import sys +import time +import math +from ._compat import _default_text_stdout, range_type, PY2, isatty, \ + open_stream, strip_ansi, term_len, get_best_encoding, WIN +from .utils import echo +from .exceptions import ClickException + + +if os.name == 'nt': + BEFORE_BAR = '\r' + AFTER_BAR = '\n' +else: + BEFORE_BAR = '\r\033[?25l' + AFTER_BAR = '\033[?25h\n' + + +def _length_hint(obj): + """Returns the length hint of an object.""" + try: + return len(obj) + except (AttributeError, TypeError): + try: + get_hint = type(obj).__length_hint__ + except AttributeError: + return None + try: + hint = get_hint(obj) + except TypeError: + return None + if hint is NotImplemented or \ + not isinstance(hint, (int, long)) or \ + hint < 0: + return None + return hint + + +class ProgressBar(object): + + def __init__(self, iterable, length=None, fill_char='#', empty_char=' ', + bar_template='%(bar)s', info_sep=' ', show_eta=True, + show_percent=None, show_pos=False, item_show_func=None, + label=None, file=None, color=None, width=30): + self.fill_char = fill_char + self.empty_char = empty_char + self.bar_template = bar_template + self.info_sep = info_sep + self.show_eta = show_eta + self.show_percent = show_percent + self.show_pos = show_pos + self.item_show_func = item_show_func + self.label = label or '' + if file is None: + file = _default_text_stdout() + self.file = file + self.color = color + self.width = width + self.autowidth = width == 0 + + if length is None: + length = _length_hint(iterable) + if iterable is None: + if length is None: + raise TypeError('iterable or length is required') + iterable = range_type(length) + self.iter = iter(iterable) + self.length = length + self.length_known = length is not None + self.pos = 0 + self.avg = [] + self.start = self.last_eta = time.time() + self.eta_known = False + self.finished = False + self.max_width = None + self.entered = False + self.current_item = None + self.is_hidden = not isatty(self.file) + self._last_line = None + + def __enter__(self): + self.entered = True + self.render_progress() + return self + + def __exit__(self, exc_type, exc_value, tb): + self.render_finish() + + def __iter__(self): + if not self.entered: + raise RuntimeError('You need to use progress bars in a with block.') + self.render_progress() + return self + + def render_finish(self): + if self.is_hidden: + return + self.file.write(AFTER_BAR) + self.file.flush() + + @property + def pct(self): + if self.finished: + return 1.0 + return min(self.pos / (float(self.length) or 1), 1.0) + + @property + def time_per_iteration(self): + if not self.avg: + return 0.0 + return sum(self.avg) / float(len(self.avg)) + + @property + def eta(self): + if self.length_known and not self.finished: + return self.time_per_iteration * (self.length - self.pos) + return 0.0 + + def format_eta(self): + if self.eta_known: + t = self.eta + 1 + seconds = t % 60 + t /= 60 + minutes = t % 60 + t /= 60 + hours = t % 24 + t /= 24 + if t > 0: + days = t + return '%dd %02d:%02d:%02d' % (days, hours, minutes, seconds) + else: + return '%02d:%02d:%02d' % (hours, minutes, seconds) + return '' + + def format_pos(self): + pos = str(self.pos) + if self.length_known: + pos += '/%s' % self.length + return pos + + def format_pct(self): + return ('% 4d%%' % int(self.pct * 100))[1:] + + def format_progress_line(self): + show_percent = self.show_percent + + info_bits = [] + if self.length_known: + bar_length = int(self.pct * self.width) + bar = self.fill_char * bar_length + bar += self.empty_char * (self.width - bar_length) + if show_percent is None: + show_percent = not self.show_pos + else: + if self.finished: + bar = self.fill_char * self.width + else: + bar = list(self.empty_char * (self.width or 1)) + if self.time_per_iteration != 0: + bar[int((math.cos(self.pos * self.time_per_iteration) + / 2.0 + 0.5) * self.width)] = self.fill_char + bar = ''.join(bar) + + if self.show_pos: + info_bits.append(self.format_pos()) + if show_percent: + info_bits.append(self.format_pct()) + if self.show_eta and self.eta_known and not self.finished: + info_bits.append(self.format_eta()) + if self.item_show_func is not None: + item_info = self.item_show_func(self.current_item) + if item_info is not None: + info_bits.append(item_info) + + return (self.bar_template % { + 'label': self.label, + 'bar': bar, + 'info': self.info_sep.join(info_bits) + }).rstrip() + + def render_progress(self): + from .termui import get_terminal_size + nl = False + + if self.is_hidden: + buf = [self.label] + nl = True + else: + buf = [] + # Update width in case the terminal has been resized + if self.autowidth: + old_width = self.width + self.width = 0 + clutter_length = term_len(self.format_progress_line()) + new_width = max(0, get_terminal_size()[0] - clutter_length) + if new_width < old_width: + buf.append(BEFORE_BAR) + buf.append(' ' * self.max_width) + self.max_width = new_width + self.width = new_width + + clear_width = self.width + if self.max_width is not None: + clear_width = self.max_width + + buf.append(BEFORE_BAR) + line = self.format_progress_line() + line_len = term_len(line) + if self.max_width is None or self.max_width < line_len: + self.max_width = line_len + buf.append(line) + + buf.append(' ' * (clear_width - line_len)) + line = ''.join(buf) + + # Render the line only if it changed. + if line != self._last_line: + self._last_line = line + echo(line, file=self.file, color=self.color, nl=nl) + self.file.flush() + + def make_step(self, n_steps): + self.pos += n_steps + if self.length_known and self.pos >= self.length: + self.finished = True + + if (time.time() - self.last_eta) < 1.0: + return + + self.last_eta = time.time() + self.avg = self.avg[-6:] + [-(self.start - time.time()) / (self.pos)] + + self.eta_known = self.length_known + + def update(self, n_steps): + self.make_step(n_steps) + self.render_progress() + + def finish(self): + self.eta_known = 0 + self.current_item = None + self.finished = True + + def next(self): + if self.is_hidden: + return next(self.iter) + try: + rv = next(self.iter) + self.current_item = rv + except StopIteration: + self.finish() + self.render_progress() + raise StopIteration() + else: + self.update(1) + return rv + + if not PY2: + __next__ = next + del next + + +def pager(text, color=None): + """Decide what method to use for paging through text.""" + stdout = _default_text_stdout() + if not isatty(sys.stdin) or not isatty(stdout): + return _nullpager(stdout, text, color) + pager_cmd = (os.environ.get('PAGER', None) or '').strip() + if pager_cmd: + if WIN: + return _tempfilepager(text, pager_cmd, color) + return _pipepager(text, pager_cmd, color) + if os.environ.get('TERM') in ('dumb', 'emacs'): + return _nullpager(stdout, text, color) + if WIN or sys.platform.startswith('os2'): + return _tempfilepager(text, 'more <', color) + if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0: + return _pipepager(text, 'less', color) + + import tempfile + fd, filename = tempfile.mkstemp() + os.close(fd) + try: + if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0: + return _pipepager(text, 'more', color) + return _nullpager(stdout, text, color) + finally: + os.unlink(filename) + + +def _pipepager(text, cmd, color): + """Page through text by feeding it to another program. Invoking a + pager through this might support colors. + """ + import subprocess + env = dict(os.environ) + + # If we're piping to less we might support colors under the + # condition that + cmd_detail = cmd.rsplit('/', 1)[-1].split() + if color is None and cmd_detail[0] == 'less': + less_flags = os.environ.get('LESS', '') + ' '.join(cmd_detail[1:]) + if not less_flags: + env['LESS'] = '-R' + color = True + elif 'r' in less_flags or 'R' in less_flags: + color = True + + if not color: + text = strip_ansi(text) + + c = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, + env=env) + encoding = get_best_encoding(c.stdin) + try: + c.stdin.write(text.encode(encoding, 'replace')) + c.stdin.close() + except (IOError, KeyboardInterrupt): + pass + + # Less doesn't respect ^C, but catches it for its own UI purposes (aborting + # search or other commands inside less). + # + # That means when the user hits ^C, the parent process (click) terminates, + # but less is still alive, paging the output and messing up the terminal. + # + # If the user wants to make the pager exit on ^C, they should set + # `LESS='-K'`. It's not our decision to make. + while True: + try: + c.wait() + except KeyboardInterrupt: + pass + else: + break + + +def _tempfilepager(text, cmd, color): + """Page through text by invoking a program on a temporary file.""" + import tempfile + filename = tempfile.mktemp() + if not color: + text = strip_ansi(text) + encoding = get_best_encoding(sys.stdout) + with open_stream(filename, 'wb')[0] as f: + f.write(text.encode(encoding)) + try: + os.system(cmd + ' "' + filename + '"') + finally: + os.unlink(filename) + + +def _nullpager(stream, text, color): + """Simply print unformatted text. This is the ultimate fallback.""" + if not color: + text = strip_ansi(text) + stream.write(text) + + +class Editor(object): + + def __init__(self, editor=None, env=None, require_save=True, + extension='.txt'): + self.editor = editor + self.env = env + self.require_save = require_save + self.extension = extension + + def get_editor(self): + if self.editor is not None: + return self.editor + for key in 'VISUAL', 'EDITOR': + rv = os.environ.get(key) + if rv: + return rv + if WIN: + return 'notepad' + for editor in 'vim', 'nano': + if os.system('which %s >/dev/null 2>&1' % editor) == 0: + return editor + return 'vi' + + def edit_file(self, filename): + import subprocess + editor = self.get_editor() + if self.env: + environ = os.environ.copy() + environ.update(self.env) + else: + environ = None + try: + c = subprocess.Popen('%s "%s"' % (editor, filename), + env=environ, shell=True) + exit_code = c.wait() + if exit_code != 0: + raise ClickException('%s: Editing failed!' % editor) + except OSError as e: + raise ClickException('%s: Editing failed: %s' % (editor, e)) + + def edit(self, text): + import tempfile + + text = text or '' + if text and not text.endswith('\n'): + text += '\n' + + fd, name = tempfile.mkstemp(prefix='editor-', suffix=self.extension) + try: + if WIN: + encoding = 'utf-8-sig' + text = text.replace('\n', '\r\n') + else: + encoding = 'utf-8' + text = text.encode(encoding) + + f = os.fdopen(fd, 'wb') + f.write(text) + f.close() + timestamp = os.path.getmtime(name) + + self.edit_file(name) + + if self.require_save \ + and os.path.getmtime(name) == timestamp: + return None + + f = open(name, 'rb') + try: + rv = f.read() + finally: + f.close() + return rv.decode('utf-8-sig').replace('\r\n', '\n') + finally: + os.unlink(name) + + +def open_url(url, wait=False, locate=False): + import subprocess + + def _unquote_file(url): + try: + import urllib + except ImportError: + import urllib + if url.startswith('file://'): + url = urllib.unquote(url[7:]) + return url + + if sys.platform == 'darwin': + args = ['open'] + if wait: + args.append('-W') + if locate: + args.append('-R') + args.append(_unquote_file(url)) + null = open('/dev/null', 'w') + try: + return subprocess.Popen(args, stderr=null).wait() + finally: + null.close() + elif WIN: + if locate: + url = _unquote_file(url) + args = 'explorer /select,"%s"' % _unquote_file( + url.replace('"', '')) + else: + args = 'start %s "" "%s"' % ( + wait and '/WAIT' or '', url.replace('"', '')) + return os.system(args) + + try: + if locate: + url = os.path.dirname(_unquote_file(url)) or '.' + else: + url = _unquote_file(url) + c = subprocess.Popen(['xdg-open', url]) + if wait: + return c.wait() + return 0 + except OSError: + if url.startswith(('http://', 'https://')) and not locate and not wait: + import webbrowser + webbrowser.open(url) + return 0 + return 1 + + +def _translate_ch_to_exc(ch): + if ch == '\x03': + raise KeyboardInterrupt() + if ch == '\x04': + raise EOFError() + + +if WIN: + import msvcrt + + def getchar(echo): + rv = msvcrt.getch() + if echo: + msvcrt.putchar(rv) + _translate_ch_to_exc(rv) + if PY2: + enc = getattr(sys.stdin, 'encoding', None) + if enc is not None: + rv = rv.decode(enc, 'replace') + else: + rv = rv.decode('cp1252', 'replace') + return rv +else: + import tty + import termios + + def getchar(echo): + if not isatty(sys.stdin): + f = open('/dev/tty') + fd = f.fileno() + else: + fd = sys.stdin.fileno() + f = None + try: + old_settings = termios.tcgetattr(fd) + try: + tty.setraw(fd) + ch = os.read(fd, 32) + if echo and isatty(sys.stdout): + sys.stdout.write(ch) + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + sys.stdout.flush() + if f is not None: + f.close() + except termios.error: + pass + _translate_ch_to_exc(ch) + return ch.decode(get_best_encoding(sys.stdin), 'replace') diff --git a/flex/lib/python3.6/site-packages/click/_textwrap.py b/flex/lib/python3.6/site-packages/click/_textwrap.py new file mode 100644 index 0000000..7e77603 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/_textwrap.py @@ -0,0 +1,38 @@ +import textwrap +from contextlib import contextmanager + + +class TextWrapper(textwrap.TextWrapper): + + def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width): + space_left = max(width - cur_len, 1) + + if self.break_long_words: + last = reversed_chunks[-1] + cut = last[:space_left] + res = last[space_left:] + cur_line.append(cut) + reversed_chunks[-1] = res + elif not cur_line: + cur_line.append(reversed_chunks.pop()) + + @contextmanager + def extra_indent(self, indent): + old_initial_indent = self.initial_indent + old_subsequent_indent = self.subsequent_indent + self.initial_indent += indent + self.subsequent_indent += indent + try: + yield + finally: + self.initial_indent = old_initial_indent + self.subsequent_indent = old_subsequent_indent + + def indent_only(self, text): + rv = [] + for idx, line in enumerate(text.splitlines()): + indent = self.initial_indent + if idx > 0: + indent = self.subsequent_indent + rv.append(indent + line) + return '\n'.join(rv) diff --git a/flex/lib/python3.6/site-packages/click/_unicodefun.py b/flex/lib/python3.6/site-packages/click/_unicodefun.py new file mode 100644 index 0000000..9e17a38 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/_unicodefun.py @@ -0,0 +1,118 @@ +import os +import sys +import codecs + +from ._compat import PY2 + + +# If someone wants to vendor click, we want to ensure the +# correct package is discovered. Ideally we could use a +# relative import here but unfortunately Python does not +# support that. +click = sys.modules[__name__.rsplit('.', 1)[0]] + + +def _find_unicode_literals_frame(): + import __future__ + frm = sys._getframe(1) + idx = 1 + while frm is not None: + if frm.f_globals.get('__name__', '').startswith('click.'): + frm = frm.f_back + idx += 1 + elif frm.f_code.co_flags & __future__.unicode_literals.compiler_flag: + return idx + else: + break + return 0 + + +def _check_for_unicode_literals(): + if not __debug__: + return + if not PY2 or click.disable_unicode_literals_warning: + return + bad_frame = _find_unicode_literals_frame() + if bad_frame <= 0: + return + from warnings import warn + warn(Warning('Click detected the use of the unicode_literals ' + '__future__ import. This is heavily discouraged ' + 'because it can introduce subtle bugs in your ' + 'code. You should instead use explicit u"" literals ' + 'for your unicode strings. For more information see ' + 'http://click.pocoo.org/python3/'), + stacklevel=bad_frame) + + +def _verify_python3_env(): + """Ensures that the environment is good for unicode on Python 3.""" + if PY2: + return + try: + import locale + fs_enc = codecs.lookup(locale.getpreferredencoding()).name + except Exception: + fs_enc = 'ascii' + if fs_enc != 'ascii': + return + + extra = '' + if os.name == 'posix': + import subprocess + rv = subprocess.Popen(['locale', '-a'], stdout=subprocess.PIPE, + stderr=subprocess.PIPE).communicate()[0] + good_locales = set() + has_c_utf8 = False + + # Make sure we're operating on text here. + if isinstance(rv, bytes): + rv = rv.decode('ascii', 'replace') + + for line in rv.splitlines(): + locale = line.strip() + if locale.lower().endswith(('.utf-8', '.utf8')): + good_locales.add(locale) + if locale.lower() in ('c.utf8', 'c.utf-8'): + has_c_utf8 = True + + extra += '\n\n' + if not good_locales: + extra += ( + 'Additional information: on this system no suitable UTF-8\n' + 'locales were discovered. This most likely requires resolving\n' + 'by reconfiguring the locale system.' + ) + elif has_c_utf8: + extra += ( + 'This system supports the C.UTF-8 locale which is recommended.\n' + 'You might be able to resolve your issue by exporting the\n' + 'following environment variables:\n\n' + ' export LC_ALL=C.UTF-8\n' + ' export LANG=C.UTF-8' + ) + else: + extra += ( + 'This system lists a couple of UTF-8 supporting locales that\n' + 'you can pick from. The following suitable locales where\n' + 'discovered: %s' + ) % ', '.join(sorted(good_locales)) + + bad_locale = None + for locale in os.environ.get('LC_ALL'), os.environ.get('LANG'): + if locale and locale.lower().endswith(('.utf-8', '.utf8')): + bad_locale = locale + if locale is not None: + break + if bad_locale is not None: + extra += ( + '\n\nClick discovered that you exported a UTF-8 locale\n' + 'but the locale system could not pick up from it because\n' + 'it does not exist. The exported locale is "%s" but it\n' + 'is not supported' + ) % bad_locale + + raise RuntimeError('Click will abort further execution because Python 3 ' + 'was configured to use ASCII as encoding for the ' + 'environment. Consult http://click.pocoo.org/python3/' + 'for mitigation steps.' + extra) diff --git a/flex/lib/python3.6/site-packages/click/_winconsole.py b/flex/lib/python3.6/site-packages/click/_winconsole.py new file mode 100644 index 0000000..9aed942 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/_winconsole.py @@ -0,0 +1,273 @@ +# -*- coding: utf-8 -*- +# This module is based on the excellent work by Adam Bartoš who +# provided a lot of what went into the implementation here in +# the discussion to issue1602 in the Python bug tracker. +# +# There are some general differences in regards to how this works +# compared to the original patches as we do not need to patch +# the entire interpreter but just work in our little world of +# echo and prmopt. + +import io +import os +import sys +import zlib +import time +import ctypes +import msvcrt +from click._compat import _NonClosingTextIOWrapper, text_type, PY2 +from ctypes import byref, POINTER, c_int, c_char, c_char_p, \ + c_void_p, py_object, c_ssize_t, c_ulong, windll, WINFUNCTYPE +try: + from ctypes import pythonapi + PyObject_GetBuffer = pythonapi.PyObject_GetBuffer + PyBuffer_Release = pythonapi.PyBuffer_Release +except ImportError: + pythonapi = None +from ctypes.wintypes import LPWSTR, LPCWSTR + + +c_ssize_p = POINTER(c_ssize_t) + +kernel32 = windll.kernel32 +GetStdHandle = kernel32.GetStdHandle +ReadConsoleW = kernel32.ReadConsoleW +WriteConsoleW = kernel32.WriteConsoleW +GetLastError = kernel32.GetLastError +GetCommandLineW = WINFUNCTYPE(LPWSTR)( + ('GetCommandLineW', windll.kernel32)) +CommandLineToArgvW = WINFUNCTYPE( + POINTER(LPWSTR), LPCWSTR, POINTER(c_int))( + ('CommandLineToArgvW', windll.shell32)) + + +STDIN_HANDLE = GetStdHandle(-10) +STDOUT_HANDLE = GetStdHandle(-11) +STDERR_HANDLE = GetStdHandle(-12) + + +PyBUF_SIMPLE = 0 +PyBUF_WRITABLE = 1 + +ERROR_SUCCESS = 0 +ERROR_NOT_ENOUGH_MEMORY = 8 +ERROR_OPERATION_ABORTED = 995 + +STDIN_FILENO = 0 +STDOUT_FILENO = 1 +STDERR_FILENO = 2 + +EOF = b'\x1a' +MAX_BYTES_WRITTEN = 32767 + + +class Py_buffer(ctypes.Structure): + _fields_ = [ + ('buf', c_void_p), + ('obj', py_object), + ('len', c_ssize_t), + ('itemsize', c_ssize_t), + ('readonly', c_int), + ('ndim', c_int), + ('format', c_char_p), + ('shape', c_ssize_p), + ('strides', c_ssize_p), + ('suboffsets', c_ssize_p), + ('internal', c_void_p) + ] + + if PY2: + _fields_.insert(-1, ('smalltable', c_ssize_t * 2)) + + +# On PyPy we cannot get buffers so our ability to operate here is +# serverly limited. +if pythonapi is None: + get_buffer = None +else: + def get_buffer(obj, writable=False): + buf = Py_buffer() + flags = PyBUF_WRITABLE if writable else PyBUF_SIMPLE + PyObject_GetBuffer(py_object(obj), byref(buf), flags) + try: + buffer_type = c_char * buf.len + return buffer_type.from_address(buf.buf) + finally: + PyBuffer_Release(byref(buf)) + + +class _WindowsConsoleRawIOBase(io.RawIOBase): + + def __init__(self, handle): + self.handle = handle + + def isatty(self): + io.RawIOBase.isatty(self) + return True + + +class _WindowsConsoleReader(_WindowsConsoleRawIOBase): + + def readable(self): + return True + + def readinto(self, b): + bytes_to_be_read = len(b) + if not bytes_to_be_read: + return 0 + elif bytes_to_be_read % 2: + raise ValueError('cannot read odd number of bytes from ' + 'UTF-16-LE encoded console') + + buffer = get_buffer(b, writable=True) + code_units_to_be_read = bytes_to_be_read // 2 + code_units_read = c_ulong() + + rv = ReadConsoleW(self.handle, buffer, code_units_to_be_read, + byref(code_units_read), None) + if GetLastError() == ERROR_OPERATION_ABORTED: + # wait for KeyboardInterrupt + time.sleep(0.1) + if not rv: + raise OSError('Windows error: %s' % GetLastError()) + + if buffer[0] == EOF: + return 0 + return 2 * code_units_read.value + + +class _WindowsConsoleWriter(_WindowsConsoleRawIOBase): + + def writable(self): + return True + + @staticmethod + def _get_error_message(errno): + if errno == ERROR_SUCCESS: + return 'ERROR_SUCCESS' + elif errno == ERROR_NOT_ENOUGH_MEMORY: + return 'ERROR_NOT_ENOUGH_MEMORY' + return 'Windows error %s' % errno + + def write(self, b): + bytes_to_be_written = len(b) + buf = get_buffer(b) + code_units_to_be_written = min(bytes_to_be_written, + MAX_BYTES_WRITTEN) // 2 + code_units_written = c_ulong() + + WriteConsoleW(self.handle, buf, code_units_to_be_written, + byref(code_units_written), None) + bytes_written = 2 * code_units_written.value + + if bytes_written == 0 and bytes_to_be_written > 0: + raise OSError(self._get_error_message(GetLastError())) + return bytes_written + + +class ConsoleStream(object): + + def __init__(self, text_stream, byte_stream): + self._text_stream = text_stream + self.buffer = byte_stream + + @property + def name(self): + return self.buffer.name + + def write(self, x): + if isinstance(x, text_type): + return self._text_stream.write(x) + try: + self.flush() + except Exception: + pass + return self.buffer.write(x) + + def writelines(self, lines): + for line in lines: + self.write(line) + + def __getattr__(self, name): + return getattr(self._text_stream, name) + + def isatty(self): + return self.buffer.isatty() + + def __repr__(self): + return '' % ( + self.name, + self.encoding, + ) + + +def _get_text_stdin(buffer_stream): + text_stream = _NonClosingTextIOWrapper( + io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)), + 'utf-16-le', 'strict', line_buffering=True) + return ConsoleStream(text_stream, buffer_stream) + + +def _get_text_stdout(buffer_stream): + text_stream = _NonClosingTextIOWrapper( + _WindowsConsoleWriter(STDOUT_HANDLE), + 'utf-16-le', 'strict', line_buffering=True) + return ConsoleStream(text_stream, buffer_stream) + + +def _get_text_stderr(buffer_stream): + text_stream = _NonClosingTextIOWrapper( + _WindowsConsoleWriter(STDERR_HANDLE), + 'utf-16-le', 'strict', line_buffering=True) + return ConsoleStream(text_stream, buffer_stream) + + +if PY2: + def _hash_py_argv(): + return zlib.crc32('\x00'.join(sys.argv[1:])) + + _initial_argv_hash = _hash_py_argv() + + def _get_windows_argv(): + argc = c_int(0) + argv_unicode = CommandLineToArgvW(GetCommandLineW(), byref(argc)) + argv = [argv_unicode[i] for i in range(0, argc.value)] + + if not hasattr(sys, 'frozen'): + argv = argv[1:] + while len(argv) > 0: + arg = argv[0] + if not arg.startswith('-') or arg == '-': + break + argv = argv[1:] + if arg.startswith(('-c', '-m')): + break + + return argv[1:] + + +_stream_factories = { + 0: _get_text_stdin, + 1: _get_text_stdout, + 2: _get_text_stderr, +} + + +def _get_windows_console_stream(f, encoding, errors): + if get_buffer is not None and \ + encoding in ('utf-16-le', None) \ + and errors in ('strict', None) and \ + hasattr(f, 'isatty') and f.isatty(): + func = _stream_factories.get(f.fileno()) + if func is not None: + if not PY2: + f = getattr(f, 'buffer') + if f is None: + return None + else: + # If we are on Python 2 we need to set the stream that we + # deal with to binary mode as otherwise the exercise if a + # bit moot. The same problems apply as for + # get_binary_stdin and friends from _compat. + msvcrt.setmode(f.fileno(), os.O_BINARY) + return func(f) diff --git a/flex/lib/python3.6/site-packages/click/core.py b/flex/lib/python3.6/site-packages/click/core.py new file mode 100644 index 0000000..7456451 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/core.py @@ -0,0 +1,1744 @@ +import errno +import os +import sys +from contextlib import contextmanager +from itertools import repeat +from functools import update_wrapper + +from .types import convert_type, IntRange, BOOL +from .utils import make_str, make_default_short_help, echo, get_os_args +from .exceptions import ClickException, UsageError, BadParameter, Abort, \ + MissingParameter +from .termui import prompt, confirm +from .formatting import HelpFormatter, join_options +from .parser import OptionParser, split_opt +from .globals import push_context, pop_context + +from ._compat import PY2, isidentifier, iteritems +from ._unicodefun import _check_for_unicode_literals, _verify_python3_env + + +_missing = object() + + +SUBCOMMAND_METAVAR = 'COMMAND [ARGS]...' +SUBCOMMANDS_METAVAR = 'COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]...' + + +def _bashcomplete(cmd, prog_name, complete_var=None): + """Internal handler for the bash completion support.""" + if complete_var is None: + complete_var = '_%s_COMPLETE' % (prog_name.replace('-', '_')).upper() + complete_instr = os.environ.get(complete_var) + if not complete_instr: + return + + from ._bashcomplete import bashcomplete + if bashcomplete(cmd, prog_name, complete_var, complete_instr): + sys.exit(1) + + +def _check_multicommand(base_command, cmd_name, cmd, register=False): + if not base_command.chain or not isinstance(cmd, MultiCommand): + return + if register: + hint = 'It is not possible to add multi commands as children to ' \ + 'another multi command that is in chain mode' + else: + hint = 'Found a multi command as subcommand to a multi command ' \ + 'that is in chain mode. This is not supported' + raise RuntimeError('%s. Command "%s" is set to chain and "%s" was ' + 'added as subcommand but it in itself is a ' + 'multi command. ("%s" is a %s within a chained ' + '%s named "%s"). This restriction was supposed to ' + 'be lifted in 6.0 but the fix was flawed. This ' + 'will be fixed in Click 7.0' % ( + hint, base_command.name, cmd_name, + cmd_name, cmd.__class__.__name__, + base_command.__class__.__name__, + base_command.name)) + + +def batch(iterable, batch_size): + return list(zip(*repeat(iter(iterable), batch_size))) + + +def invoke_param_callback(callback, ctx, param, value): + code = getattr(callback, '__code__', None) + args = getattr(code, 'co_argcount', 3) + + if args < 3: + # This will become a warning in Click 3.0: + from warnings import warn + warn(Warning('Invoked legacy parameter callback "%s". The new ' + 'signature for such callbacks starting with ' + 'click 2.0 is (ctx, param, value).' + % callback), stacklevel=3) + return callback(ctx, value) + return callback(ctx, param, value) + + +@contextmanager +def augment_usage_errors(ctx, param=None): + """Context manager that attaches extra information to exceptions that + fly. + """ + try: + yield + except BadParameter as e: + if e.ctx is None: + e.ctx = ctx + if param is not None and e.param is None: + e.param = param + raise + except UsageError as e: + if e.ctx is None: + e.ctx = ctx + raise + + +def iter_params_for_processing(invocation_order, declaration_order): + """Given a sequence of parameters in the order as should be considered + for processing and an iterable of parameters that exist, this returns + a list in the correct order as they should be processed. + """ + def sort_key(item): + try: + idx = invocation_order.index(item) + except ValueError: + idx = float('inf') + return (not item.is_eager, idx) + + return sorted(declaration_order, key=sort_key) + + +class Context(object): + """The context is a special internal object that holds state relevant + for the script execution at every single level. It's normally invisible + to commands unless they opt-in to getting access to it. + + The context is useful as it can pass internal objects around and can + control special execution features such as reading data from + environment variables. + + A context can be used as context manager in which case it will call + :meth:`close` on teardown. + + .. versionadded:: 2.0 + Added the `resilient_parsing`, `help_option_names`, + `token_normalize_func` parameters. + + .. versionadded:: 3.0 + Added the `allow_extra_args` and `allow_interspersed_args` + parameters. + + .. versionadded:: 4.0 + Added the `color`, `ignore_unknown_options`, and + `max_content_width` parameters. + + :param command: the command class for this context. + :param parent: the parent context. + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it is usually + the name of the script, for commands below it it's + the name of the script. + :param obj: an arbitrary object of user data. + :param auto_envvar_prefix: the prefix to use for automatic environment + variables. If this is `None` then reading + from environment variables is disabled. This + does not affect manually set environment + variables which are always read. + :param default_map: a dictionary (like object) with default values + for parameters. + :param terminal_width: the width of the terminal. The default is + inherit from parent context. If no context + defines the terminal width then auto + detection will be applied. + :param max_content_width: the maximum width for content rendered by + Click (this currently only affects help + pages). This defaults to 80 characters if + not overridden. In other words: even if the + terminal is larger than that, Click will not + format things wider than 80 characters by + default. In addition to that, formatters might + add some safety mapping on the right. + :param resilient_parsing: if this flag is enabled then Click will + parse without any interactivity or callback + invocation. This is useful for implementing + things such as completion support. + :param allow_extra_args: if this is set to `True` then extra arguments + at the end will not raise an error and will be + kept on the context. The default is to inherit + from the command. + :param allow_interspersed_args: if this is set to `False` then options + and arguments cannot be mixed. The + default is to inherit from the command. + :param ignore_unknown_options: instructs click to ignore options it does + not know and keeps them for later + processing. + :param help_option_names: optionally a list of strings that define how + the default help parameter is named. The + default is ``['--help']``. + :param token_normalize_func: an optional function that is used to + normalize tokens (options, choices, + etc.). This for instance can be used to + implement case insensitive behavior. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are used in texts that Click prints which is by + default not the case. This for instance would affect + help output. + """ + + def __init__(self, command, parent=None, info_name=None, obj=None, + auto_envvar_prefix=None, default_map=None, + terminal_width=None, max_content_width=None, + resilient_parsing=False, allow_extra_args=None, + allow_interspersed_args=None, + ignore_unknown_options=None, help_option_names=None, + token_normalize_func=None, color=None): + #: the parent context or `None` if none exists. + self.parent = parent + #: the :class:`Command` for this context. + self.command = command + #: the descriptive information name + self.info_name = info_name + #: the parsed parameters except if the value is hidden in which + #: case it's not remembered. + self.params = {} + #: the leftover arguments. + self.args = [] + #: protected arguments. These are arguments that are prepended + #: to `args` when certain parsing scenarios are encountered but + #: must be never propagated to another arguments. This is used + #: to implement nested parsing. + self.protected_args = [] + if obj is None and parent is not None: + obj = parent.obj + #: the user object stored. + self.obj = obj + self._meta = getattr(parent, 'meta', {}) + + #: A dictionary (-like object) with defaults for parameters. + if default_map is None \ + and parent is not None \ + and parent.default_map is not None: + default_map = parent.default_map.get(info_name) + self.default_map = default_map + + #: This flag indicates if a subcommand is going to be executed. A + #: group callback can use this information to figure out if it's + #: being executed directly or because the execution flow passes + #: onwards to a subcommand. By default it's None, but it can be + #: the name of the subcommand to execute. + #: + #: If chaining is enabled this will be set to ``'*'`` in case + #: any commands are executed. It is however not possible to + #: figure out which ones. If you require this knowledge you + #: should use a :func:`resultcallback`. + self.invoked_subcommand = None + + if terminal_width is None and parent is not None: + terminal_width = parent.terminal_width + #: The width of the terminal (None is autodetection). + self.terminal_width = terminal_width + + if max_content_width is None and parent is not None: + max_content_width = parent.max_content_width + #: The maximum width of formatted content (None implies a sensible + #: default which is 80 for most things). + self.max_content_width = max_content_width + + if allow_extra_args is None: + allow_extra_args = command.allow_extra_args + #: Indicates if the context allows extra args or if it should + #: fail on parsing. + #: + #: .. versionadded:: 3.0 + self.allow_extra_args = allow_extra_args + + if allow_interspersed_args is None: + allow_interspersed_args = command.allow_interspersed_args + #: Indicates if the context allows mixing of arguments and + #: options or not. + #: + #: .. versionadded:: 3.0 + self.allow_interspersed_args = allow_interspersed_args + + if ignore_unknown_options is None: + ignore_unknown_options = command.ignore_unknown_options + #: Instructs click to ignore options that a command does not + #: understand and will store it on the context for later + #: processing. This is primarily useful for situations where you + #: want to call into external programs. Generally this pattern is + #: strongly discouraged because it's not possibly to losslessly + #: forward all arguments. + #: + #: .. versionadded:: 4.0 + self.ignore_unknown_options = ignore_unknown_options + + if help_option_names is None: + if parent is not None: + help_option_names = parent.help_option_names + else: + help_option_names = ['--help'] + + #: The names for the help options. + self.help_option_names = help_option_names + + if token_normalize_func is None and parent is not None: + token_normalize_func = parent.token_normalize_func + + #: An optional normalization function for tokens. This is + #: options, choices, commands etc. + self.token_normalize_func = token_normalize_func + + #: Indicates if resilient parsing is enabled. In that case Click + #: will do its best to not cause any failures. + self.resilient_parsing = resilient_parsing + + # If there is no envvar prefix yet, but the parent has one and + # the command on this level has a name, we can expand the envvar + # prefix automatically. + if auto_envvar_prefix is None: + if parent is not None \ + and parent.auto_envvar_prefix is not None and \ + self.info_name is not None: + auto_envvar_prefix = '%s_%s' % (parent.auto_envvar_prefix, + self.info_name.upper()) + else: + self.auto_envvar_prefix = auto_envvar_prefix.upper() + self.auto_envvar_prefix = auto_envvar_prefix + + if color is None and parent is not None: + color = parent.color + + #: Controls if styling output is wanted or not. + self.color = color + + self._close_callbacks = [] + self._depth = 0 + + def __enter__(self): + self._depth += 1 + push_context(self) + return self + + def __exit__(self, exc_type, exc_value, tb): + self._depth -= 1 + if self._depth == 0: + self.close() + pop_context() + + @contextmanager + def scope(self, cleanup=True): + """This helper method can be used with the context object to promote + it to the current thread local (see :func:`get_current_context`). + The default behavior of this is to invoke the cleanup functions which + can be disabled by setting `cleanup` to `False`. The cleanup + functions are typically used for things such as closing file handles. + + If the cleanup is intended the context object can also be directly + used as a context manager. + + Example usage:: + + with ctx.scope(): + assert get_current_context() is ctx + + This is equivalent:: + + with ctx: + assert get_current_context() is ctx + + .. versionadded:: 5.0 + + :param cleanup: controls if the cleanup functions should be run or + not. The default is to run these functions. In + some situations the context only wants to be + temporarily pushed in which case this can be disabled. + Nested pushes automatically defer the cleanup. + """ + if not cleanup: + self._depth += 1 + try: + with self as rv: + yield rv + finally: + if not cleanup: + self._depth -= 1 + + @property + def meta(self): + """This is a dictionary which is shared with all the contexts + that are nested. It exists so that click utiltiies can store some + state here if they need to. It is however the responsibility of + that code to manage this dictionary well. + + The keys are supposed to be unique dotted strings. For instance + module paths are a good choice for it. What is stored in there is + irrelevant for the operation of click. However what is important is + that code that places data here adheres to the general semantics of + the system. + + Example usage:: + + LANG_KEY = __name__ + '.lang' + + def set_language(value): + ctx = get_current_context() + ctx.meta[LANG_KEY] = value + + def get_language(): + return get_current_context().meta.get(LANG_KEY, 'en_US') + + .. versionadded:: 5.0 + """ + return self._meta + + def make_formatter(self): + """Creates the formatter for the help and usage output.""" + return HelpFormatter(width=self.terminal_width, + max_width=self.max_content_width) + + def call_on_close(self, f): + """This decorator remembers a function as callback that should be + executed when the context tears down. This is most useful to bind + resource handling to the script execution. For instance, file objects + opened by the :class:`File` type will register their close callbacks + here. + + :param f: the function to execute on teardown. + """ + self._close_callbacks.append(f) + return f + + def close(self): + """Invokes all close callbacks.""" + for cb in self._close_callbacks: + cb() + self._close_callbacks = [] + + @property + def command_path(self): + """The computed command path. This is used for the ``usage`` + information on the help page. It's automatically created by + combining the info names of the chain of contexts to the root. + """ + rv = '' + if self.info_name is not None: + rv = self.info_name + if self.parent is not None: + rv = self.parent.command_path + ' ' + rv + return rv.lstrip() + + def find_root(self): + """Finds the outermost context.""" + node = self + while node.parent is not None: + node = node.parent + return node + + def find_object(self, object_type): + """Finds the closest object of a given type.""" + node = self + while node is not None: + if isinstance(node.obj, object_type): + return node.obj + node = node.parent + + def ensure_object(self, object_type): + """Like :meth:`find_object` but sets the innermost object to a + new instance of `object_type` if it does not exist. + """ + rv = self.find_object(object_type) + if rv is None: + self.obj = rv = object_type() + return rv + + def lookup_default(self, name): + """Looks up the default for a parameter name. This by default + looks into the :attr:`default_map` if available. + """ + if self.default_map is not None: + rv = self.default_map.get(name) + if callable(rv): + rv = rv() + return rv + + def fail(self, message): + """Aborts the execution of the program with a specific error + message. + + :param message: the error message to fail with. + """ + raise UsageError(message, self) + + def abort(self): + """Aborts the script.""" + raise Abort() + + def exit(self, code=0): + """Exits the application with a given exit code.""" + sys.exit(code) + + def get_usage(self): + """Helper method to get formatted usage string for the current + context and command. + """ + return self.command.get_usage(self) + + def get_help(self): + """Helper method to get formatted help page for the current + context and command. + """ + return self.command.get_help(self) + + def invoke(*args, **kwargs): + """Invokes a command callback in exactly the way it expects. There + are two ways to invoke this method: + + 1. the first argument can be a callback and all other arguments and + keyword arguments are forwarded directly to the function. + 2. the first argument is a click command object. In that case all + arguments are forwarded as well but proper click parameters + (options and click arguments) must be keyword arguments and Click + will fill in defaults. + + Note that before Click 3.2 keyword arguments were not properly filled + in against the intention of this code and no context was created. For + more information about this change and why it was done in a bugfix + release see :ref:`upgrade-to-3.2`. + """ + self, callback = args[:2] + ctx = self + + # It's also possible to invoke another command which might or + # might not have a callback. In that case we also fill + # in defaults and make a new context for this command. + if isinstance(callback, Command): + other_cmd = callback + callback = other_cmd.callback + ctx = Context(other_cmd, info_name=other_cmd.name, parent=self) + if callback is None: + raise TypeError('The given command does not have a ' + 'callback that can be invoked.') + + for param in other_cmd.params: + if param.name not in kwargs and param.expose_value: + kwargs[param.name] = param.get_default(ctx) + + args = args[2:] + with augment_usage_errors(self): + with ctx: + return callback(*args, **kwargs) + + def forward(*args, **kwargs): + """Similar to :meth:`invoke` but fills in default keyword + arguments from the current context if the other command expects + it. This cannot invoke callbacks directly, only other commands. + """ + self, cmd = args[:2] + + # It's also possible to invoke another command which might or + # might not have a callback. + if not isinstance(cmd, Command): + raise TypeError('Callback is not a command.') + + for param in self.params: + if param not in kwargs: + kwargs[param] = self.params[param] + + return self.invoke(cmd, **kwargs) + + +class BaseCommand(object): + """The base command implements the minimal API contract of commands. + Most code will never use this as it does not implement a lot of useful + functionality but it can act as the direct subclass of alternative + parsing methods that do not depend on the Click parser. + + For instance, this can be used to bridge Click and other systems like + argparse or docopt. + + Because base commands do not implement a lot of the API that other + parts of Click take for granted, they are not supported for all + operations. For instance, they cannot be used with the decorators + usually and they have no built-in callback system. + + .. versionchanged:: 2.0 + Added the `context_settings` parameter. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + """ + #: the default for the :attr:`Context.allow_extra_args` flag. + allow_extra_args = False + #: the default for the :attr:`Context.allow_interspersed_args` flag. + allow_interspersed_args = True + #: the default for the :attr:`Context.ignore_unknown_options` flag. + ignore_unknown_options = False + + def __init__(self, name, context_settings=None): + #: the name the command thinks it has. Upon registering a command + #: on a :class:`Group` the group will default the command name + #: with this information. You should instead use the + #: :class:`Context`\'s :attr:`~Context.info_name` attribute. + self.name = name + if context_settings is None: + context_settings = {} + #: an optional dictionary with defaults passed to the context. + self.context_settings = context_settings + + def get_usage(self, ctx): + raise NotImplementedError('Base commands cannot get usage') + + def get_help(self, ctx): + raise NotImplementedError('Base commands cannot get help') + + def make_context(self, info_name, args, parent=None, **extra): + """This function when given an info name and arguments will kick + off the parsing and create a new :class:`Context`. It does not + invoke the actual command callback though. + + :param info_name: the info name for this invokation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it's usually + the name of the script, for commands below it it's + the name of the script. + :param args: the arguments to parse as list of strings. + :param parent: the parent context if available. + :param extra: extra keyword arguments forwarded to the context + constructor. + """ + for key, value in iteritems(self.context_settings): + if key not in extra: + extra[key] = value + ctx = Context(self, info_name=info_name, parent=parent, **extra) + with ctx.scope(cleanup=False): + self.parse_args(ctx, args) + return ctx + + def parse_args(self, ctx, args): + """Given a context and a list of arguments this creates the parser + and parses the arguments, then modifies the context as necessary. + This is automatically invoked by :meth:`make_context`. + """ + raise NotImplementedError('Base commands do not know how to parse ' + 'arguments.') + + def invoke(self, ctx): + """Given a context, this invokes the command. The default + implementation is raising a not implemented error. + """ + raise NotImplementedError('Base commands are not invokable by default') + + def main(self, args=None, prog_name=None, complete_var=None, + standalone_mode=True, **extra): + """This is the way to invoke a script with all the bells and + whistles as a command line application. This will always terminate + the application after a call. If this is not wanted, ``SystemExit`` + needs to be caught. + + This method is also available by directly calling the instance of + a :class:`Command`. + + .. versionadded:: 3.0 + Added the `standalone_mode` flag to control the standalone mode. + + :param args: the arguments that should be used for parsing. If not + provided, ``sys.argv[1:]`` is used. + :param prog_name: the program name that should be used. By default + the program name is constructed by taking the file + name from ``sys.argv[0]``. + :param complete_var: the environment variable that controls the + bash completion support. The default is + ``"__COMPLETE"`` with prog name in + uppercase. + :param standalone_mode: the default behavior is to invoke the script + in standalone mode. Click will then + handle exceptions and convert them into + error messages and the function will never + return but shut down the interpreter. If + this is set to `False` they will be + propagated to the caller and the return + value of this function is the return value + of :meth:`invoke`. + :param extra: extra keyword arguments are forwarded to the context + constructor. See :class:`Context` for more information. + """ + # If we are in Python 3, we will verify that the environment is + # sane at this point of reject further execution to avoid a + # broken script. + if not PY2: + _verify_python3_env() + else: + _check_for_unicode_literals() + + if args is None: + args = get_os_args() + else: + args = list(args) + + if prog_name is None: + prog_name = make_str(os.path.basename( + sys.argv and sys.argv[0] or __file__)) + + # Hook for the Bash completion. This only activates if the Bash + # completion is actually enabled, otherwise this is quite a fast + # noop. + _bashcomplete(self, prog_name, complete_var) + + try: + try: + with self.make_context(prog_name, args, **extra) as ctx: + rv = self.invoke(ctx) + if not standalone_mode: + return rv + ctx.exit() + except (EOFError, KeyboardInterrupt): + echo(file=sys.stderr) + raise Abort() + except ClickException as e: + if not standalone_mode: + raise + e.show() + sys.exit(e.exit_code) + except IOError as e: + if e.errno == errno.EPIPE: + sys.exit(1) + else: + raise + except Abort: + if not standalone_mode: + raise + echo('Aborted!', file=sys.stderr) + sys.exit(1) + + def __call__(self, *args, **kwargs): + """Alias for :meth:`main`.""" + return self.main(*args, **kwargs) + + +class Command(BaseCommand): + """Commands are the basic building block of command line interfaces in + Click. A basic command handles command line parsing and might dispatch + more parsing to commands nested below it. + + .. versionchanged:: 2.0 + Added the `context_settings` parameter. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + :param callback: the callback to invoke. This is optional. + :param params: the parameters to register with this command. This can + be either :class:`Option` or :class:`Argument` objects. + :param help: the help string to use for this command. + :param epilog: like the help string but it's printed at the end of the + help page after everything else. + :param short_help: the short help to use for this command. This is + shown on the command listing of the parent command. + :param add_help_option: by default each command registers a ``--help`` + option. This can be disabled by this parameter. + """ + + def __init__(self, name, context_settings=None, callback=None, + params=None, help=None, epilog=None, short_help=None, + options_metavar='[OPTIONS]', add_help_option=True): + BaseCommand.__init__(self, name, context_settings) + #: the callback to execute when the command fires. This might be + #: `None` in which case nothing happens. + self.callback = callback + #: the list of parameters for this command in the order they + #: should show up in the help page and execute. Eager parameters + #: will automatically be handled before non eager ones. + self.params = params or [] + self.help = help + self.epilog = epilog + self.options_metavar = options_metavar + if short_help is None and help: + short_help = make_default_short_help(help) + self.short_help = short_help + self.add_help_option = add_help_option + + def get_usage(self, ctx): + formatter = ctx.make_formatter() + self.format_usage(ctx, formatter) + return formatter.getvalue().rstrip('\n') + + def get_params(self, ctx): + rv = self.params + help_option = self.get_help_option(ctx) + if help_option is not None: + rv = rv + [help_option] + return rv + + def format_usage(self, ctx, formatter): + """Writes the usage line into the formatter.""" + pieces = self.collect_usage_pieces(ctx) + formatter.write_usage(ctx.command_path, ' '.join(pieces)) + + def collect_usage_pieces(self, ctx): + """Returns all the pieces that go into the usage line and returns + it as a list of strings. + """ + rv = [self.options_metavar] + for param in self.get_params(ctx): + rv.extend(param.get_usage_pieces(ctx)) + return rv + + def get_help_option_names(self, ctx): + """Returns the names for the help option.""" + all_names = set(ctx.help_option_names) + for param in self.params: + all_names.difference_update(param.opts) + all_names.difference_update(param.secondary_opts) + return all_names + + def get_help_option(self, ctx): + """Returns the help option object.""" + help_options = self.get_help_option_names(ctx) + if not help_options or not self.add_help_option: + return + + def show_help(ctx, param, value): + if value and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + return Option(help_options, is_flag=True, + is_eager=True, expose_value=False, + callback=show_help, + help='Show this message and exit.') + + def make_parser(self, ctx): + """Creates the underlying option parser for this command.""" + parser = OptionParser(ctx) + parser.allow_interspersed_args = ctx.allow_interspersed_args + parser.ignore_unknown_options = ctx.ignore_unknown_options + for param in self.get_params(ctx): + param.add_to_parser(parser, ctx) + return parser + + def get_help(self, ctx): + """Formats the help into a string and returns it. This creates a + formatter and will call into the following formatting methods: + """ + formatter = ctx.make_formatter() + self.format_help(ctx, formatter) + return formatter.getvalue().rstrip('\n') + + def format_help(self, ctx, formatter): + """Writes the help into the formatter if it exists. + + This calls into the following methods: + + - :meth:`format_usage` + - :meth:`format_help_text` + - :meth:`format_options` + - :meth:`format_epilog` + """ + self.format_usage(ctx, formatter) + self.format_help_text(ctx, formatter) + self.format_options(ctx, formatter) + self.format_epilog(ctx, formatter) + + def format_help_text(self, ctx, formatter): + """Writes the help text to the formatter if it exists.""" + if self.help: + formatter.write_paragraph() + with formatter.indentation(): + formatter.write_text(self.help) + + def format_options(self, ctx, formatter): + """Writes all the options into the formatter if they exist.""" + opts = [] + for param in self.get_params(ctx): + rv = param.get_help_record(ctx) + if rv is not None: + opts.append(rv) + + if opts: + with formatter.section('Options'): + formatter.write_dl(opts) + + def format_epilog(self, ctx, formatter): + """Writes the epilog into the formatter if it exists.""" + if self.epilog: + formatter.write_paragraph() + with formatter.indentation(): + formatter.write_text(self.epilog) + + def parse_args(self, ctx, args): + parser = self.make_parser(ctx) + opts, args, param_order = parser.parse_args(args=args) + + for param in iter_params_for_processing( + param_order, self.get_params(ctx)): + value, args = param.handle_parse_result(ctx, opts, args) + + if args and not ctx.allow_extra_args and not ctx.resilient_parsing: + ctx.fail('Got unexpected extra argument%s (%s)' + % (len(args) != 1 and 's' or '', + ' '.join(map(make_str, args)))) + + ctx.args = args + return args + + def invoke(self, ctx): + """Given a context, this invokes the attached callback (if it exists) + in the right way. + """ + if self.callback is not None: + return ctx.invoke(self.callback, **ctx.params) + + +class MultiCommand(Command): + """A multi command is the basic implementation of a command that + dispatches to subcommands. The most common version is the + :class:`Group`. + + :param invoke_without_command: this controls how the multi command itself + is invoked. By default it's only invoked + if a subcommand is provided. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is enabled by default if + `invoke_without_command` is disabled or disabled + if it's enabled. If enabled this will add + ``--help`` as argument if no arguments are + passed. + :param subcommand_metavar: the string that is used in the documentation + to indicate the subcommand place. + :param chain: if this is set to `True` chaining of multiple subcommands + is enabled. This restricts the form of commands in that + they cannot have optional arguments but it allows + multiple commands to be chained together. + :param result_callback: the result callback to attach to this multi + command. + """ + allow_extra_args = True + allow_interspersed_args = False + + def __init__(self, name=None, invoke_without_command=False, + no_args_is_help=None, subcommand_metavar=None, + chain=False, result_callback=None, **attrs): + Command.__init__(self, name, **attrs) + if no_args_is_help is None: + no_args_is_help = not invoke_without_command + self.no_args_is_help = no_args_is_help + self.invoke_without_command = invoke_without_command + if subcommand_metavar is None: + if chain: + subcommand_metavar = SUBCOMMANDS_METAVAR + else: + subcommand_metavar = SUBCOMMAND_METAVAR + self.subcommand_metavar = subcommand_metavar + self.chain = chain + #: The result callback that is stored. This can be set or + #: overridden with the :func:`resultcallback` decorator. + self.result_callback = result_callback + + if self.chain: + for param in self.params: + if isinstance(param, Argument) and not param.required: + raise RuntimeError('Multi commands in chain mode cannot ' + 'have optional arguments.') + + def collect_usage_pieces(self, ctx): + rv = Command.collect_usage_pieces(self, ctx) + rv.append(self.subcommand_metavar) + return rv + + def format_options(self, ctx, formatter): + Command.format_options(self, ctx, formatter) + self.format_commands(ctx, formatter) + + def resultcallback(self, replace=False): + """Adds a result callback to the chain command. By default if a + result callback is already registered this will chain them but + this can be disabled with the `replace` parameter. The result + callback is invoked with the return value of the subcommand + (or the list of return values from all subcommands if chaining + is enabled) as well as the parameters as they would be passed + to the main callback. + + Example:: + + @click.group() + @click.option('-i', '--input', default=23) + def cli(input): + return 42 + + @cli.resultcallback() + def process_result(result, input): + return result + input + + .. versionadded:: 3.0 + + :param replace: if set to `True` an already existing result + callback will be removed. + """ + def decorator(f): + old_callback = self.result_callback + if old_callback is None or replace: + self.result_callback = f + return f + def function(__value, *args, **kwargs): + return f(old_callback(__value, *args, **kwargs), + *args, **kwargs) + self.result_callback = rv = update_wrapper(function, f) + return rv + return decorator + + def format_commands(self, ctx, formatter): + """Extra format methods for multi methods that adds all the commands + after the options. + """ + rows = [] + for subcommand in self.list_commands(ctx): + cmd = self.get_command(ctx, subcommand) + # What is this, the tool lied about a command. Ignore it + if cmd is None: + continue + + help = cmd.short_help or '' + rows.append((subcommand, help)) + + if rows: + with formatter.section('Commands'): + formatter.write_dl(rows) + + def parse_args(self, ctx, args): + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + rest = Command.parse_args(self, ctx, args) + if self.chain: + ctx.protected_args = rest + ctx.args = [] + elif rest: + ctx.protected_args, ctx.args = rest[:1], rest[1:] + + return ctx.args + + def invoke(self, ctx): + def _process_result(value): + if self.result_callback is not None: + value = ctx.invoke(self.result_callback, value, + **ctx.params) + return value + + if not ctx.protected_args: + # If we are invoked without command the chain flag controls + # how this happens. If we are not in chain mode, the return + # value here is the return value of the command. + # If however we are in chain mode, the return value is the + # return value of the result processor invoked with an empty + # list (which means that no subcommand actually was executed). + if self.invoke_without_command: + if not self.chain: + return Command.invoke(self, ctx) + with ctx: + Command.invoke(self, ctx) + return _process_result([]) + ctx.fail('Missing command.') + + # Fetch args back out + args = ctx.protected_args + ctx.args + ctx.args = [] + ctx.protected_args = [] + + # If we're not in chain mode, we only allow the invocation of a + # single command but we also inform the current context about the + # name of the command to invoke. + if not self.chain: + # Make sure the context is entered so we do not clean up + # resources until the result processor has worked. + with ctx: + cmd_name, cmd, args = self.resolve_command(ctx, args) + ctx.invoked_subcommand = cmd_name + Command.invoke(self, ctx) + sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) + with sub_ctx: + return _process_result(sub_ctx.command.invoke(sub_ctx)) + + # In chain mode we create the contexts step by step, but after the + # base command has been invoked. Because at that point we do not + # know the subcommands yet, the invoked subcommand attribute is + # set to ``*`` to inform the command that subcommands are executed + # but nothing else. + with ctx: + ctx.invoked_subcommand = args and '*' or None + Command.invoke(self, ctx) + + # Otherwise we make every single context and invoke them in a + # chain. In that case the return value to the result processor + # is the list of all invoked subcommand's results. + contexts = [] + while args: + cmd_name, cmd, args = self.resolve_command(ctx, args) + sub_ctx = cmd.make_context(cmd_name, args, parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False) + contexts.append(sub_ctx) + args, sub_ctx.args = sub_ctx.args, [] + + rv = [] + for sub_ctx in contexts: + with sub_ctx: + rv.append(sub_ctx.command.invoke(sub_ctx)) + return _process_result(rv) + + def resolve_command(self, ctx, args): + cmd_name = make_str(args[0]) + original_cmd_name = cmd_name + + # Get the command + cmd = self.get_command(ctx, cmd_name) + + # If we can't find the command but there is a normalization + # function available, we try with that one. + if cmd is None and ctx.token_normalize_func is not None: + cmd_name = ctx.token_normalize_func(cmd_name) + cmd = self.get_command(ctx, cmd_name) + + # If we don't find the command we want to show an error message + # to the user that it was not provided. However, there is + # something else we should do: if the first argument looks like + # an option we want to kick off parsing again for arguments to + # resolve things like --help which now should go to the main + # place. + if cmd is None: + if split_opt(cmd_name)[0]: + self.parse_args(ctx, ctx.args) + ctx.fail('No such command "%s".' % original_cmd_name) + + return cmd_name, cmd, args[1:] + + def get_command(self, ctx, cmd_name): + """Given a context and a command name, this returns a + :class:`Command` object if it exists or returns `None`. + """ + raise NotImplementedError() + + def list_commands(self, ctx): + """Returns a list of subcommand names in the order they should + appear. + """ + return [] + + +class Group(MultiCommand): + """A group allows a command to have subcommands attached. This is the + most common way to implement nesting in Click. + + :param commands: a dictionary of commands. + """ + + def __init__(self, name=None, commands=None, **attrs): + MultiCommand.__init__(self, name, **attrs) + #: the registered subcommands by their exported names. + self.commands = commands or {} + + def add_command(self, cmd, name=None): + """Registers another :class:`Command` with this group. If the name + is not provided, the name of the command is used. + """ + name = name or cmd.name + if name is None: + raise TypeError('Command has no name.') + _check_multicommand(self, name, cmd, register=True) + self.commands[name] = cmd + + def command(self, *args, **kwargs): + """A shortcut decorator for declaring and attaching a command to + the group. This takes the same arguments as :func:`command` but + immediately registers the created command with this instance by + calling into :meth:`add_command`. + """ + def decorator(f): + cmd = command(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + return decorator + + def group(self, *args, **kwargs): + """A shortcut decorator for declaring and attaching a group to + the group. This takes the same arguments as :func:`group` but + immediately registers the created command with this instance by + calling into :meth:`add_command`. + """ + def decorator(f): + cmd = group(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + return decorator + + def get_command(self, ctx, cmd_name): + return self.commands.get(cmd_name) + + def list_commands(self, ctx): + return sorted(self.commands) + + +class CommandCollection(MultiCommand): + """A command collection is a multi command that merges multiple multi + commands together into one. This is a straightforward implementation + that accepts a list of different multi commands as sources and + provides all the commands for each of them. + """ + + def __init__(self, name=None, sources=None, **attrs): + MultiCommand.__init__(self, name, **attrs) + #: The list of registered multi commands. + self.sources = sources or [] + + def add_source(self, multi_cmd): + """Adds a new multi command to the chain dispatcher.""" + self.sources.append(multi_cmd) + + def get_command(self, ctx, cmd_name): + for source in self.sources: + rv = source.get_command(ctx, cmd_name) + if rv is not None: + if self.chain: + _check_multicommand(self, cmd_name, rv) + return rv + + def list_commands(self, ctx): + rv = set() + for source in self.sources: + rv.update(source.list_commands(ctx)) + return sorted(rv) + + +class Parameter(object): + """A parameter to a command comes in two versions: they are either + :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently + not supported by design as some of the internals for parsing are + intentionally not finalized. + + Some settings are supported by both options and arguments. + + .. versionchanged:: 2.0 + Changed signature for parameter callback to also be passed the + parameter. In Click 2.0, the old callback format will still work, + but it will raise a warning to give you change to migrate the + code easier. + + :param param_decls: the parameter declarations for this option or + argument. This is a list of flags or argument + names. + :param type: the type that should be used. Either a :class:`ParamType` + or a Python type. The later is converted into the former + automatically if supported. + :param required: controls if this is optional or not. + :param default: the default value if omitted. This can also be a callable, + in which case it's invoked when the default is needed + without any arguments. + :param callback: a callback that should be executed after the parameter + was matched. This is called as ``fn(ctx, param, + value)`` and needs to return the value. Before Click + 2.0, the signature was ``(ctx, value)``. + :param nargs: the number of arguments to match. If not ``1`` the return + value is a tuple instead of single value. The default for + nargs is ``1`` (except if the type is a tuple, then it's + the arity of the tuple). + :param metavar: how the value is represented in the help page. + :param expose_value: if this is `True` then the value is passed onwards + to the command callback and stored on the context, + otherwise it's skipped. + :param is_eager: eager values are processed before non eager ones. This + should not be set for arguments or it will inverse the + order of processing. + :param envvar: a string or list of strings that are environment variables + that should be checked. + """ + param_type_name = 'parameter' + + def __init__(self, param_decls=None, type=None, required=False, + default=None, callback=None, nargs=None, metavar=None, + expose_value=True, is_eager=False, envvar=None): + self.name, self.opts, self.secondary_opts = \ + self._parse_decls(param_decls or (), expose_value) + + self.type = convert_type(type, default) + + # Default nargs to what the type tells us if we have that + # information available. + if nargs is None: + if self.type.is_composite: + nargs = self.type.arity + else: + nargs = 1 + + self.required = required + self.callback = callback + self.nargs = nargs + self.multiple = False + self.expose_value = expose_value + self.default = default + self.is_eager = is_eager + self.metavar = metavar + self.envvar = envvar + + @property + def human_readable_name(self): + """Returns the human readable name of this parameter. This is the + same as the name for options, but the metavar for arguments. + """ + return self.name + + def make_metavar(self): + if self.metavar is not None: + return self.metavar + metavar = self.type.get_metavar(self) + if metavar is None: + metavar = self.type.name.upper() + if self.nargs != 1: + metavar += '...' + return metavar + + def get_default(self, ctx): + """Given a context variable this calculates the default value.""" + # Otherwise go with the regular default. + if callable(self.default): + rv = self.default() + else: + rv = self.default + return self.type_cast_value(ctx, rv) + + def add_to_parser(self, parser, ctx): + pass + + def consume_value(self, ctx, opts): + value = opts.get(self.name) + if value is None: + value = ctx.lookup_default(self.name) + if value is None: + value = self.value_from_envvar(ctx) + return value + + def type_cast_value(self, ctx, value): + """Given a value this runs it properly through the type system. + This automatically handles things like `nargs` and `multiple` as + well as composite types. + """ + if self.type.is_composite: + if self.nargs <= 1: + raise TypeError('Attempted to invoke composite type ' + 'but nargs has been set to %s. This is ' + 'not supported; nargs needs to be set to ' + 'a fixed value > 1.' % self.nargs) + if self.multiple: + return tuple(self.type(x or (), self, ctx) for x in value or ()) + return self.type(value or (), self, ctx) + + def _convert(value, level): + if level == 0: + return self.type(value, self, ctx) + return tuple(_convert(x, level - 1) for x in value or ()) + return _convert(value, (self.nargs != 1) + bool(self.multiple)) + + def process_value(self, ctx, value): + """Given a value and context this runs the logic to convert the + value as necessary. + """ + # If the value we were given is None we do nothing. This way + # code that calls this can easily figure out if something was + # not provided. Otherwise it would be converted into an empty + # tuple for multiple invocations which is inconvenient. + if value is not None: + return self.type_cast_value(ctx, value) + + def value_is_missing(self, value): + if value is None: + return True + if (self.nargs != 1 or self.multiple) and value == (): + return True + return False + + def full_process_value(self, ctx, value): + value = self.process_value(ctx, value) + + if value is None: + value = self.get_default(ctx) + + if self.required and self.value_is_missing(value): + raise MissingParameter(ctx=ctx, param=self) + + return value + + def resolve_envvar_value(self, ctx): + if self.envvar is None: + return + if isinstance(self.envvar, (tuple, list)): + for envvar in self.envvar: + rv = os.environ.get(envvar) + if rv is not None: + return rv + else: + return os.environ.get(self.envvar) + + def value_from_envvar(self, ctx): + rv = self.resolve_envvar_value(ctx) + if rv is not None and self.nargs != 1: + rv = self.type.split_envvar_value(rv) + return rv + + def handle_parse_result(self, ctx, opts, args): + with augment_usage_errors(ctx, param=self): + value = self.consume_value(ctx, opts) + try: + value = self.full_process_value(ctx, value) + except Exception: + if not ctx.resilient_parsing: + raise + value = None + if self.callback is not None: + try: + value = invoke_param_callback( + self.callback, ctx, self, value) + except Exception: + if not ctx.resilient_parsing: + raise + + if self.expose_value: + ctx.params[self.name] = value + return value, args + + def get_help_record(self, ctx): + pass + + def get_usage_pieces(self, ctx): + return [] + + +class Option(Parameter): + """Options are usually optional values on the command line and + have some extra features that arguments don't have. + + All other parameters are passed onwards to the parameter constructor. + + :param show_default: controls if the default value should be shown on the + help page. Normally, defaults are not shown. + :param prompt: if set to `True` or a non empty string then the user will + be prompted for input if not set. If set to `True` the + prompt will be the option name capitalized. + :param confirmation_prompt: if set then the value will need to be confirmed + if it was prompted for. + :param hide_input: if this is `True` then the input on the prompt will be + hidden from the user. This is useful for password + input. + :param is_flag: forces this option to act as a flag. The default is + auto detection. + :param flag_value: which value should be used for this flag if it's + enabled. This is set to a boolean automatically if + the option string contains a slash to mark two options. + :param multiple: if this is set to `True` then the argument is accepted + multiple times and recorded. This is similar to ``nargs`` + in how it works but supports arbitrary number of + arguments. + :param count: this flag makes an option increment an integer. + :param allow_from_autoenv: if this is enabled then the value of this + parameter will be pulled from an environment + variable in case a prefix is defined on the + context. + :param help: the help string. + """ + param_type_name = 'option' + + def __init__(self, param_decls=None, show_default=False, + prompt=False, confirmation_prompt=False, + hide_input=False, is_flag=None, flag_value=None, + multiple=False, count=False, allow_from_autoenv=True, + type=None, help=None, **attrs): + default_is_missing = attrs.get('default', _missing) is _missing + Parameter.__init__(self, param_decls, type=type, **attrs) + + if prompt is True: + prompt_text = self.name.replace('_', ' ').capitalize() + elif prompt is False: + prompt_text = None + else: + prompt_text = prompt + self.prompt = prompt_text + self.confirmation_prompt = confirmation_prompt + self.hide_input = hide_input + + # Flags + if is_flag is None: + if flag_value is not None: + is_flag = True + else: + is_flag = bool(self.secondary_opts) + if is_flag and default_is_missing: + self.default = False + if flag_value is None: + flag_value = not self.default + self.is_flag = is_flag + self.flag_value = flag_value + if self.is_flag and isinstance(self.flag_value, bool) \ + and type is None: + self.type = BOOL + self.is_bool_flag = True + else: + self.is_bool_flag = False + + # Counting + self.count = count + if count: + if type is None: + self.type = IntRange(min=0) + if default_is_missing: + self.default = 0 + + self.multiple = multiple + self.allow_from_autoenv = allow_from_autoenv + self.help = help + self.show_default = show_default + + # Sanity check for stuff we don't support + if __debug__: + if self.nargs < 0: + raise TypeError('Options cannot have nargs < 0') + if self.prompt and self.is_flag and not self.is_bool_flag: + raise TypeError('Cannot prompt for flags that are not bools.') + if not self.is_bool_flag and self.secondary_opts: + raise TypeError('Got secondary option for non boolean flag.') + if self.is_bool_flag and self.hide_input \ + and self.prompt is not None: + raise TypeError('Hidden input does not work with boolean ' + 'flag prompts.') + if self.count: + if self.multiple: + raise TypeError('Options cannot be multiple and count ' + 'at the same time.') + elif self.is_flag: + raise TypeError('Options cannot be count and flags at ' + 'the same time.') + + def _parse_decls(self, decls, expose_value): + opts = [] + secondary_opts = [] + name = None + possible_names = [] + + for decl in decls: + if isidentifier(decl): + if name is not None: + raise TypeError('Name defined twice') + name = decl + else: + split_char = decl[:1] == '/' and ';' or '/' + if split_char in decl: + first, second = decl.split(split_char, 1) + first = first.rstrip() + if first: + possible_names.append(split_opt(first)) + opts.append(first) + second = second.lstrip() + if second: + secondary_opts.append(second.lstrip()) + else: + possible_names.append(split_opt(decl)) + opts.append(decl) + + if name is None and possible_names: + possible_names.sort(key=lambda x: len(x[0])) + name = possible_names[-1][1].replace('-', '_').lower() + if not isidentifier(name): + name = None + + if name is None: + if not expose_value: + return None, opts, secondary_opts + raise TypeError('Could not determine name for option') + + if not opts and not secondary_opts: + raise TypeError('No options defined but a name was passed (%s). ' + 'Did you mean to declare an argument instead ' + 'of an option?' % name) + + return name, opts, secondary_opts + + def add_to_parser(self, parser, ctx): + kwargs = { + 'dest': self.name, + 'nargs': self.nargs, + 'obj': self, + } + + if self.multiple: + action = 'append' + elif self.count: + action = 'count' + else: + action = 'store' + + if self.is_flag: + kwargs.pop('nargs', None) + if self.is_bool_flag and self.secondary_opts: + parser.add_option(self.opts, action=action + '_const', + const=True, **kwargs) + parser.add_option(self.secondary_opts, action=action + + '_const', const=False, **kwargs) + else: + parser.add_option(self.opts, action=action + '_const', + const=self.flag_value, + **kwargs) + else: + kwargs['action'] = action + parser.add_option(self.opts, **kwargs) + + def get_help_record(self, ctx): + any_prefix_is_slash = [] + + def _write_opts(opts): + rv, any_slashes = join_options(opts) + if any_slashes: + any_prefix_is_slash[:] = [True] + if not self.is_flag and not self.count: + rv += ' ' + self.make_metavar() + return rv + + rv = [_write_opts(self.opts)] + if self.secondary_opts: + rv.append(_write_opts(self.secondary_opts)) + + help = self.help or '' + extra = [] + if self.default is not None and self.show_default: + extra.append('default: %s' % ( + ', '.join('%s' % d for d in self.default) + if isinstance(self.default, (list, tuple)) + else self.default, )) + if self.required: + extra.append('required') + if extra: + help = '%s[%s]' % (help and help + ' ' or '', '; '.join(extra)) + + return ((any_prefix_is_slash and '; ' or ' / ').join(rv), help) + + def get_default(self, ctx): + # If we're a non boolean flag out default is more complex because + # we need to look at all flags in the same group to figure out + # if we're the the default one in which case we return the flag + # value as default. + if self.is_flag and not self.is_bool_flag: + for param in ctx.command.params: + if param.name == self.name and param.default: + return param.flag_value + return None + return Parameter.get_default(self, ctx) + + def prompt_for_value(self, ctx): + """This is an alternative flow that can be activated in the full + value processing if a value does not exist. It will prompt the + user until a valid value exists and then returns the processed + value as result. + """ + # Calculate the default before prompting anything to be stable. + default = self.get_default(ctx) + + # If this is a prompt for a flag we need to handle this + # differently. + if self.is_bool_flag: + return confirm(self.prompt, default) + + return prompt(self.prompt, default=default, + hide_input=self.hide_input, + confirmation_prompt=self.confirmation_prompt, + value_proc=lambda x: self.process_value(ctx, x)) + + def resolve_envvar_value(self, ctx): + rv = Parameter.resolve_envvar_value(self, ctx) + if rv is not None: + return rv + if self.allow_from_autoenv and \ + ctx.auto_envvar_prefix is not None: + envvar = '%s_%s' % (ctx.auto_envvar_prefix, self.name.upper()) + return os.environ.get(envvar) + + def value_from_envvar(self, ctx): + rv = self.resolve_envvar_value(ctx) + if rv is None: + return None + value_depth = (self.nargs != 1) + bool(self.multiple) + if value_depth > 0 and rv is not None: + rv = self.type.split_envvar_value(rv) + if self.multiple and self.nargs != 1: + rv = batch(rv, self.nargs) + return rv + + def full_process_value(self, ctx, value): + if value is None and self.prompt is not None \ + and not ctx.resilient_parsing: + return self.prompt_for_value(ctx) + return Parameter.full_process_value(self, ctx, value) + + +class Argument(Parameter): + """Arguments are positional parameters to a command. They generally + provide fewer features than options but can have infinite ``nargs`` + and are required by default. + + All parameters are passed onwards to the parameter constructor. + """ + param_type_name = 'argument' + + def __init__(self, param_decls, required=None, **attrs): + if required is None: + if attrs.get('default') is not None: + required = False + else: + required = attrs.get('nargs', 1) > 0 + Parameter.__init__(self, param_decls, required=required, **attrs) + if self.default is not None and self.nargs < 0: + raise TypeError('nargs=-1 in combination with a default value ' + 'is not supported.') + + @property + def human_readable_name(self): + if self.metavar is not None: + return self.metavar + return self.name.upper() + + def make_metavar(self): + if self.metavar is not None: + return self.metavar + var = self.name.upper() + if not self.required: + var = '[%s]' % var + if self.nargs != 1: + var += '...' + return var + + def _parse_decls(self, decls, expose_value): + if not decls: + if not expose_value: + return None, [], [] + raise TypeError('Could not determine name for argument') + if len(decls) == 1: + name = arg = decls[0] + name = name.replace('-', '_').lower() + elif len(decls) == 2: + name, arg = decls + else: + raise TypeError('Arguments take exactly one or two ' + 'parameter declarations, got %d' % len(decls)) + return name, [arg], [] + + def get_usage_pieces(self, ctx): + return [self.make_metavar()] + + def add_to_parser(self, parser, ctx): + parser.add_argument(dest=self.name, nargs=self.nargs, + obj=self) + + +# Circular dependency between decorators and core +from .decorators import command, group diff --git a/flex/lib/python3.6/site-packages/click/decorators.py b/flex/lib/python3.6/site-packages/click/decorators.py new file mode 100644 index 0000000..9893452 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/decorators.py @@ -0,0 +1,304 @@ +import sys +import inspect + +from functools import update_wrapper + +from ._compat import iteritems +from ._unicodefun import _check_for_unicode_literals +from .utils import echo +from .globals import get_current_context + + +def pass_context(f): + """Marks a callback as wanting to receive the current context + object as first argument. + """ + def new_func(*args, **kwargs): + return f(get_current_context(), *args, **kwargs) + return update_wrapper(new_func, f) + + +def pass_obj(f): + """Similar to :func:`pass_context`, but only pass the object on the + context onwards (:attr:`Context.obj`). This is useful if that object + represents the state of a nested system. + """ + def new_func(*args, **kwargs): + return f(get_current_context().obj, *args, **kwargs) + return update_wrapper(new_func, f) + + +def make_pass_decorator(object_type, ensure=False): + """Given an object type this creates a decorator that will work + similar to :func:`pass_obj` but instead of passing the object of the + current context, it will find the innermost context of type + :func:`object_type`. + + This generates a decorator that works roughly like this:: + + from functools import update_wrapper + + def decorator(f): + @pass_context + def new_func(ctx, *args, **kwargs): + obj = ctx.find_object(object_type) + return ctx.invoke(f, obj, *args, **kwargs) + return update_wrapper(new_func, f) + return decorator + + :param object_type: the type of the object to pass. + :param ensure: if set to `True`, a new object will be created and + remembered on the context if it's not there yet. + """ + def decorator(f): + def new_func(*args, **kwargs): + ctx = get_current_context() + if ensure: + obj = ctx.ensure_object(object_type) + else: + obj = ctx.find_object(object_type) + if obj is None: + raise RuntimeError('Managed to invoke callback without a ' + 'context object of type %r existing' + % object_type.__name__) + return ctx.invoke(f, obj, *args[1:], **kwargs) + return update_wrapper(new_func, f) + return decorator + + +def _make_command(f, name, attrs, cls): + if isinstance(f, Command): + raise TypeError('Attempted to convert a callback into a ' + 'command twice.') + try: + params = f.__click_params__ + params.reverse() + del f.__click_params__ + except AttributeError: + params = [] + help = attrs.get('help') + if help is None: + help = inspect.getdoc(f) + if isinstance(help, bytes): + help = help.decode('utf-8') + else: + help = inspect.cleandoc(help) + attrs['help'] = help + _check_for_unicode_literals() + return cls(name=name or f.__name__.lower(), + callback=f, params=params, **attrs) + + +def command(name=None, cls=None, **attrs): + """Creates a new :class:`Command` and uses the decorated function as + callback. This will also automatically attach all decorated + :func:`option`\s and :func:`argument`\s as parameters to the command. + + The name of the command defaults to the name of the function. If you + want to change that, you can pass the intended name as the first + argument. + + All keyword arguments are forwarded to the underlying command class. + + Once decorated the function turns into a :class:`Command` instance + that can be invoked as a command line utility or be attached to a + command :class:`Group`. + + :param name: the name of the command. This defaults to the function + name. + :param cls: the command class to instantiate. This defaults to + :class:`Command`. + """ + if cls is None: + cls = Command + def decorator(f): + cmd = _make_command(f, name, attrs, cls) + cmd.__doc__ = f.__doc__ + return cmd + return decorator + + +def group(name=None, **attrs): + """Creates a new :class:`Group` with a function as callback. This + works otherwise the same as :func:`command` just that the `cls` + parameter is set to :class:`Group`. + """ + attrs.setdefault('cls', Group) + return command(name, **attrs) + + +def _param_memo(f, param): + if isinstance(f, Command): + f.params.append(param) + else: + if not hasattr(f, '__click_params__'): + f.__click_params__ = [] + f.__click_params__.append(param) + + +def argument(*param_decls, **attrs): + """Attaches an argument to the command. All positional arguments are + passed as parameter declarations to :class:`Argument`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Argument` instance manually + and attaching it to the :attr:`Command.params` list. + + :param cls: the argument class to instantiate. This defaults to + :class:`Argument`. + """ + def decorator(f): + ArgumentClass = attrs.pop('cls', Argument) + _param_memo(f, ArgumentClass(param_decls, **attrs)) + return f + return decorator + + +def option(*param_decls, **attrs): + """Attaches an option to the command. All positional arguments are + passed as parameter declarations to :class:`Option`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Option` instance manually + and attaching it to the :attr:`Command.params` list. + + :param cls: the option class to instantiate. This defaults to + :class:`Option`. + """ + def decorator(f): + if 'help' in attrs: + attrs['help'] = inspect.cleandoc(attrs['help']) + OptionClass = attrs.pop('cls', Option) + _param_memo(f, OptionClass(param_decls, **attrs)) + return f + return decorator + + +def confirmation_option(*param_decls, **attrs): + """Shortcut for confirmation prompts that can be ignored by passing + ``--yes`` as parameter. + + This is equivalent to decorating a function with :func:`option` with + the following parameters:: + + def callback(ctx, param, value): + if not value: + ctx.abort() + + @click.command() + @click.option('--yes', is_flag=True, callback=callback, + expose_value=False, prompt='Do you want to continue?') + def dropdb(): + pass + """ + def decorator(f): + def callback(ctx, param, value): + if not value: + ctx.abort() + attrs.setdefault('is_flag', True) + attrs.setdefault('callback', callback) + attrs.setdefault('expose_value', False) + attrs.setdefault('prompt', 'Do you want to continue?') + attrs.setdefault('help', 'Confirm the action without prompting.') + return option(*(param_decls or ('--yes',)), **attrs)(f) + return decorator + + +def password_option(*param_decls, **attrs): + """Shortcut for password prompts. + + This is equivalent to decorating a function with :func:`option` with + the following parameters:: + + @click.command() + @click.option('--password', prompt=True, confirmation_prompt=True, + hide_input=True) + def changeadmin(password): + pass + """ + def decorator(f): + attrs.setdefault('prompt', True) + attrs.setdefault('confirmation_prompt', True) + attrs.setdefault('hide_input', True) + return option(*(param_decls or ('--password',)), **attrs)(f) + return decorator + + +def version_option(version=None, *param_decls, **attrs): + """Adds a ``--version`` option which immediately ends the program + printing out the version number. This is implemented as an eager + option that prints the version and exits the program in the callback. + + :param version: the version number to show. If not provided Click + attempts an auto discovery via setuptools. + :param prog_name: the name of the program (defaults to autodetection) + :param message: custom message to show instead of the default + (``'%(prog)s, version %(version)s'``) + :param others: everything else is forwarded to :func:`option`. + """ + if version is None: + module = sys._getframe(1).f_globals.get('__name__') + def decorator(f): + prog_name = attrs.pop('prog_name', None) + message = attrs.pop('message', '%(prog)s, version %(version)s') + + def callback(ctx, param, value): + if not value or ctx.resilient_parsing: + return + prog = prog_name + if prog is None: + prog = ctx.find_root().info_name + ver = version + if ver is None: + try: + import pkg_resources + except ImportError: + pass + else: + for dist in pkg_resources.working_set: + scripts = dist.get_entry_map().get('console_scripts') or {} + for script_name, entry_point in iteritems(scripts): + if entry_point.module_name == module: + ver = dist.version + break + if ver is None: + raise RuntimeError('Could not determine version') + echo(message % { + 'prog': prog, + 'version': ver, + }, color=ctx.color) + ctx.exit() + + attrs.setdefault('is_flag', True) + attrs.setdefault('expose_value', False) + attrs.setdefault('is_eager', True) + attrs.setdefault('help', 'Show the version and exit.') + attrs['callback'] = callback + return option(*(param_decls or ('--version',)), **attrs)(f) + return decorator + + +def help_option(*param_decls, **attrs): + """Adds a ``--help`` option which immediately ends the program + printing out the help page. This is usually unnecessary to add as + this is added by default to all commands unless suppressed. + + Like :func:`version_option`, this is implemented as eager option that + prints in the callback and exits. + + All arguments are forwarded to :func:`option`. + """ + def decorator(f): + def callback(ctx, param, value): + if value and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + attrs.setdefault('is_flag', True) + attrs.setdefault('expose_value', False) + attrs.setdefault('help', 'Show this message and exit.') + attrs.setdefault('is_eager', True) + attrs['callback'] = callback + return option(*(param_decls or ('--help',)), **attrs)(f) + return decorator + + +# Circular dependencies between core and decorators +from .core import Command, Group, Argument, Option diff --git a/flex/lib/python3.6/site-packages/click/exceptions.py b/flex/lib/python3.6/site-packages/click/exceptions.py new file mode 100644 index 0000000..74a4542 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/exceptions.py @@ -0,0 +1,201 @@ +from ._compat import PY2, filename_to_ui, get_text_stderr +from .utils import echo + + +class ClickException(Exception): + """An exception that Click can handle and show to the user.""" + + #: The exit code for this exception + exit_code = 1 + + def __init__(self, message): + if PY2: + if message is not None: + message = message.encode('utf-8') + Exception.__init__(self, message) + self.message = message + + def format_message(self): + return self.message + + def show(self, file=None): + if file is None: + file = get_text_stderr() + echo('Error: %s' % self.format_message(), file=file) + + +class UsageError(ClickException): + """An internal exception that signals a usage error. This typically + aborts any further handling. + + :param message: the error message to display. + :param ctx: optionally the context that caused this error. Click will + fill in the context automatically in some situations. + """ + exit_code = 2 + + def __init__(self, message, ctx=None): + ClickException.__init__(self, message) + self.ctx = ctx + + def show(self, file=None): + if file is None: + file = get_text_stderr() + color = None + if self.ctx is not None: + color = self.ctx.color + echo(self.ctx.get_usage() + '\n', file=file, color=color) + echo('Error: %s' % self.format_message(), file=file, color=color) + + +class BadParameter(UsageError): + """An exception that formats out a standardized error message for a + bad parameter. This is useful when thrown from a callback or type as + Click will attach contextual information to it (for instance, which + parameter it is). + + .. versionadded:: 2.0 + + :param param: the parameter object that caused this error. This can + be left out, and Click will attach this info itself + if possible. + :param param_hint: a string that shows up as parameter name. This + can be used as alternative to `param` in cases + where custom validation should happen. If it is + a string it's used as such, if it's a list then + each item is quoted and separated. + """ + + def __init__(self, message, ctx=None, param=None, + param_hint=None): + UsageError.__init__(self, message, ctx) + self.param = param + self.param_hint = param_hint + + def format_message(self): + if self.param_hint is not None: + param_hint = self.param_hint + elif self.param is not None: + param_hint = self.param.opts or [self.param.human_readable_name] + else: + return 'Invalid value: %s' % self.message + if isinstance(param_hint, (tuple, list)): + param_hint = ' / '.join('"%s"' % x for x in param_hint) + return 'Invalid value for %s: %s' % (param_hint, self.message) + + +class MissingParameter(BadParameter): + """Raised if click required an option or argument but it was not + provided when invoking the script. + + .. versionadded:: 4.0 + + :param param_type: a string that indicates the type of the parameter. + The default is to inherit the parameter type from + the given `param`. Valid values are ``'parameter'``, + ``'option'`` or ``'argument'``. + """ + + def __init__(self, message=None, ctx=None, param=None, + param_hint=None, param_type=None): + BadParameter.__init__(self, message, ctx, param, param_hint) + self.param_type = param_type + + def format_message(self): + if self.param_hint is not None: + param_hint = self.param_hint + elif self.param is not None: + param_hint = self.param.opts or [self.param.human_readable_name] + else: + param_hint = None + if isinstance(param_hint, (tuple, list)): + param_hint = ' / '.join('"%s"' % x for x in param_hint) + + param_type = self.param_type + if param_type is None and self.param is not None: + param_type = self.param.param_type_name + + msg = self.message + if self.param is not None: + msg_extra = self.param.type.get_missing_message(self.param) + if msg_extra: + if msg: + msg += '. ' + msg_extra + else: + msg = msg_extra + + return 'Missing %s%s%s%s' % ( + param_type, + param_hint and ' %s' % param_hint or '', + msg and '. ' or '.', + msg or '', + ) + + +class NoSuchOption(UsageError): + """Raised if click attempted to handle an option that does not + exist. + + .. versionadded:: 4.0 + """ + + def __init__(self, option_name, message=None, possibilities=None, + ctx=None): + if message is None: + message = 'no such option: %s' % option_name + UsageError.__init__(self, message, ctx) + self.option_name = option_name + self.possibilities = possibilities + + def format_message(self): + bits = [self.message] + if self.possibilities: + if len(self.possibilities) == 1: + bits.append('Did you mean %s?' % self.possibilities[0]) + else: + possibilities = sorted(self.possibilities) + bits.append('(Possible options: %s)' % ', '.join(possibilities)) + return ' '.join(bits) + + +class BadOptionUsage(UsageError): + """Raised if an option is generally supplied but the use of the option + was incorrect. This is for instance raised if the number of arguments + for an option is not correct. + + .. versionadded:: 4.0 + """ + + def __init__(self, message, ctx=None): + UsageError.__init__(self, message, ctx) + + +class BadArgumentUsage(UsageError): + """Raised if an argument is generally supplied but the use of the argument + was incorrect. This is for instance raised if the number of values + for an argument is not correct. + + .. versionadded:: 6.0 + """ + + def __init__(self, message, ctx=None): + UsageError.__init__(self, message, ctx) + + +class FileError(ClickException): + """Raised if a file cannot be opened.""" + + def __init__(self, filename, hint=None): + ui_filename = filename_to_ui(filename) + if hint is None: + hint = 'unknown error' + ClickException.__init__(self, hint) + self.ui_filename = ui_filename + self.filename = filename + + def format_message(self): + return 'Could not open file %s: %s' % (self.ui_filename, self.message) + + +class Abort(RuntimeError): + """An internal signalling exception that signals Click to abort.""" diff --git a/flex/lib/python3.6/site-packages/click/formatting.py b/flex/lib/python3.6/site-packages/click/formatting.py new file mode 100644 index 0000000..a3d6a4d --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/formatting.py @@ -0,0 +1,256 @@ +from contextlib import contextmanager +from .termui import get_terminal_size +from .parser import split_opt +from ._compat import term_len + + +# Can force a width. This is used by the test system +FORCED_WIDTH = None + + +def measure_table(rows): + widths = {} + for row in rows: + for idx, col in enumerate(row): + widths[idx] = max(widths.get(idx, 0), term_len(col)) + return tuple(y for x, y in sorted(widths.items())) + + +def iter_rows(rows, col_count): + for row in rows: + row = tuple(row) + yield row + ('',) * (col_count - len(row)) + + +def wrap_text(text, width=78, initial_indent='', subsequent_indent='', + preserve_paragraphs=False): + """A helper function that intelligently wraps text. By default, it + assumes that it operates on a single paragraph of text but if the + `preserve_paragraphs` parameter is provided it will intelligently + handle paragraphs (defined by two empty lines). + + If paragraphs are handled, a paragraph can be prefixed with an empty + line containing the ``\\b`` character (``\\x08``) to indicate that + no rewrapping should happen in that block. + + :param text: the text that should be rewrapped. + :param width: the maximum width for the text. + :param initial_indent: the initial indent that should be placed on the + first line as a string. + :param subsequent_indent: the indent string that should be placed on + each consecutive line. + :param preserve_paragraphs: if this flag is set then the wrapping will + intelligently handle paragraphs. + """ + from ._textwrap import TextWrapper + text = text.expandtabs() + wrapper = TextWrapper(width, initial_indent=initial_indent, + subsequent_indent=subsequent_indent, + replace_whitespace=False) + if not preserve_paragraphs: + return wrapper.fill(text) + + p = [] + buf = [] + indent = None + + def _flush_par(): + if not buf: + return + if buf[0].strip() == '\b': + p.append((indent or 0, True, '\n'.join(buf[1:]))) + else: + p.append((indent or 0, False, ' '.join(buf))) + del buf[:] + + for line in text.splitlines(): + if not line: + _flush_par() + indent = None + else: + if indent is None: + orig_len = term_len(line) + line = line.lstrip() + indent = orig_len - term_len(line) + buf.append(line) + _flush_par() + + rv = [] + for indent, raw, text in p: + with wrapper.extra_indent(' ' * indent): + if raw: + rv.append(wrapper.indent_only(text)) + else: + rv.append(wrapper.fill(text)) + + return '\n\n'.join(rv) + + +class HelpFormatter(object): + """This class helps with formatting text-based help pages. It's + usually just needed for very special internal cases, but it's also + exposed so that developers can write their own fancy outputs. + + At present, it always writes into memory. + + :param indent_increment: the additional increment for each level. + :param width: the width for the text. This defaults to the terminal + width clamped to a maximum of 78. + """ + + def __init__(self, indent_increment=2, width=None, max_width=None): + self.indent_increment = indent_increment + if max_width is None: + max_width = 80 + if width is None: + width = FORCED_WIDTH + if width is None: + width = max(min(get_terminal_size()[0], max_width) - 2, 50) + self.width = width + self.current_indent = 0 + self.buffer = [] + + def write(self, string): + """Writes a unicode string into the internal buffer.""" + self.buffer.append(string) + + def indent(self): + """Increases the indentation.""" + self.current_indent += self.indent_increment + + def dedent(self): + """Decreases the indentation.""" + self.current_indent -= self.indent_increment + + def write_usage(self, prog, args='', prefix='Usage: '): + """Writes a usage line into the buffer. + + :param prog: the program name. + :param args: whitespace separated list of arguments. + :param prefix: the prefix for the first line. + """ + usage_prefix = '%*s%s ' % (self.current_indent, prefix, prog) + text_width = self.width - self.current_indent + + if text_width >= (term_len(usage_prefix) + 20): + # The arguments will fit to the right of the prefix. + indent = ' ' * term_len(usage_prefix) + self.write(wrap_text(args, text_width, + initial_indent=usage_prefix, + subsequent_indent=indent)) + else: + # The prefix is too long, put the arguments on the next line. + self.write(usage_prefix) + self.write('\n') + indent = ' ' * (max(self.current_indent, term_len(prefix)) + 4) + self.write(wrap_text(args, text_width, + initial_indent=indent, + subsequent_indent=indent)) + + self.write('\n') + + def write_heading(self, heading): + """Writes a heading into the buffer.""" + self.write('%*s%s:\n' % (self.current_indent, '', heading)) + + def write_paragraph(self): + """Writes a paragraph into the buffer.""" + if self.buffer: + self.write('\n') + + def write_text(self, text): + """Writes re-indented text into the buffer. This rewraps and + preserves paragraphs. + """ + text_width = max(self.width - self.current_indent, 11) + indent = ' ' * self.current_indent + self.write(wrap_text(text, text_width, + initial_indent=indent, + subsequent_indent=indent, + preserve_paragraphs=True)) + self.write('\n') + + def write_dl(self, rows, col_max=30, col_spacing=2): + """Writes a definition list into the buffer. This is how options + and commands are usually formatted. + + :param rows: a list of two item tuples for the terms and values. + :param col_max: the maximum width of the first column. + :param col_spacing: the number of spaces between the first and + second column. + """ + rows = list(rows) + widths = measure_table(rows) + if len(widths) != 2: + raise TypeError('Expected two columns for definition list') + + first_col = min(widths[0], col_max) + col_spacing + + for first, second in iter_rows(rows, len(widths)): + self.write('%*s%s' % (self.current_indent, '', first)) + if not second: + self.write('\n') + continue + if term_len(first) <= first_col - col_spacing: + self.write(' ' * (first_col - term_len(first))) + else: + self.write('\n') + self.write(' ' * (first_col + self.current_indent)) + + text_width = max(self.width - first_col - 2, 10) + lines = iter(wrap_text(second, text_width).splitlines()) + if lines: + self.write(next(lines) + '\n') + for line in lines: + self.write('%*s%s\n' % ( + first_col + self.current_indent, '', line)) + else: + self.write('\n') + + @contextmanager + def section(self, name): + """Helpful context manager that writes a paragraph, a heading, + and the indents. + + :param name: the section name that is written as heading. + """ + self.write_paragraph() + self.write_heading(name) + self.indent() + try: + yield + finally: + self.dedent() + + @contextmanager + def indentation(self): + """A context manager that increases the indentation.""" + self.indent() + try: + yield + finally: + self.dedent() + + def getvalue(self): + """Returns the buffer contents.""" + return ''.join(self.buffer) + + +def join_options(options): + """Given a list of option strings this joins them in the most appropriate + way and returns them in the form ``(formatted_string, + any_prefix_is_slash)`` where the second item in the tuple is a flag that + indicates if any of the option prefixes was a slash. + """ + rv = [] + any_prefix_is_slash = False + for opt in options: + prefix = split_opt(opt)[0] + if prefix == '/': + any_prefix_is_slash = True + rv.append((len(prefix), opt)) + + rv.sort(key=lambda x: x[0]) + + rv = ', '.join(x[1] for x in rv) + return rv, any_prefix_is_slash diff --git a/flex/lib/python3.6/site-packages/click/globals.py b/flex/lib/python3.6/site-packages/click/globals.py new file mode 100644 index 0000000..14338e6 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/globals.py @@ -0,0 +1,48 @@ +from threading import local + + +_local = local() + + +def get_current_context(silent=False): + """Returns the current click context. This can be used as a way to + access the current context object from anywhere. This is a more implicit + alternative to the :func:`pass_context` decorator. This function is + primarily useful for helpers such as :func:`echo` which might be + interested in changing it's behavior based on the current context. + + To push the current context, :meth:`Context.scope` can be used. + + .. versionadded:: 5.0 + + :param silent: is set to `True` the return value is `None` if no context + is available. The default behavior is to raise a + :exc:`RuntimeError`. + """ + try: + return getattr(_local, 'stack')[-1] + except (AttributeError, IndexError): + if not silent: + raise RuntimeError('There is no active click context.') + + +def push_context(ctx): + """Pushes a new context to the current stack.""" + _local.__dict__.setdefault('stack', []).append(ctx) + + +def pop_context(): + """Removes the top level from the stack.""" + _local.stack.pop() + + +def resolve_color_default(color=None): + """"Internal helper to get the default value of the color flag. If a + value is passed it's returned unchanged, otherwise it's looked up from + the current context. + """ + if color is not None: + return color + ctx = get_current_context(silent=True) + if ctx is not None: + return ctx.color diff --git a/flex/lib/python3.6/site-packages/click/parser.py b/flex/lib/python3.6/site-packages/click/parser.py new file mode 100644 index 0000000..9775c9f --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/parser.py @@ -0,0 +1,426 @@ +# -*- coding: utf-8 -*- +""" + click.parser + ~~~~~~~~~~~~ + + This module started out as largely a copy paste from the stdlib's + optparse module with the features removed that we do not need from + optparse because we implement them in Click on a higher level (for + instance type handling, help formatting and a lot more). + + The plan is to remove more and more from here over time. + + The reason this is a different module and not optparse from the stdlib + is that there are differences in 2.x and 3.x about the error messages + generated and optparse in the stdlib uses gettext for no good reason + and might cause us issues. +""" +import re +from collections import deque +from .exceptions import UsageError, NoSuchOption, BadOptionUsage, \ + BadArgumentUsage + + +def _unpack_args(args, nargs_spec): + """Given an iterable of arguments and an iterable of nargs specifications, + it returns a tuple with all the unpacked arguments at the first index + and all remaining arguments as the second. + + The nargs specification is the number of arguments that should be consumed + or `-1` to indicate that this position should eat up all the remainders. + + Missing items are filled with `None`. + """ + args = deque(args) + nargs_spec = deque(nargs_spec) + rv = [] + spos = None + + def _fetch(c): + try: + if spos is None: + return c.popleft() + else: + return c.pop() + except IndexError: + return None + + while nargs_spec: + nargs = _fetch(nargs_spec) + if nargs == 1: + rv.append(_fetch(args)) + elif nargs > 1: + x = [_fetch(args) for _ in range(nargs)] + # If we're reversed, we're pulling in the arguments in reverse, + # so we need to turn them around. + if spos is not None: + x.reverse() + rv.append(tuple(x)) + elif nargs < 0: + if spos is not None: + raise TypeError('Cannot have two nargs < 0') + spos = len(rv) + rv.append(None) + + # spos is the position of the wildcard (star). If it's not `None`, + # we fill it with the remainder. + if spos is not None: + rv[spos] = tuple(args) + args = [] + rv[spos + 1:] = reversed(rv[spos + 1:]) + + return tuple(rv), list(args) + + +def _error_opt_args(nargs, opt): + if nargs == 1: + raise BadOptionUsage('%s option requires an argument' % opt) + raise BadOptionUsage('%s option requires %d arguments' % (opt, nargs)) + + +def split_opt(opt): + first = opt[:1] + if first.isalnum(): + return '', opt + if opt[1:2] == first: + return opt[:2], opt[2:] + return first, opt[1:] + + +def normalize_opt(opt, ctx): + if ctx is None or ctx.token_normalize_func is None: + return opt + prefix, opt = split_opt(opt) + return prefix + ctx.token_normalize_func(opt) + + +def split_arg_string(string): + """Given an argument string this attempts to split it into small parts.""" + rv = [] + for match in re.finditer(r"('([^'\\]*(?:\\.[^'\\]*)*)'" + r'|"([^"\\]*(?:\\.[^"\\]*)*)"' + r'|\S+)\s*', string, re.S): + arg = match.group().strip() + if arg[:1] == arg[-1:] and arg[:1] in '"\'': + arg = arg[1:-1].encode('ascii', 'backslashreplace') \ + .decode('unicode-escape') + try: + arg = type(string)(arg) + except UnicodeError: + pass + rv.append(arg) + return rv + + +class Option(object): + + def __init__(self, opts, dest, action=None, nargs=1, const=None, obj=None): + self._short_opts = [] + self._long_opts = [] + self.prefixes = set() + + for opt in opts: + prefix, value = split_opt(opt) + if not prefix: + raise ValueError('Invalid start character for option (%s)' + % opt) + self.prefixes.add(prefix[0]) + if len(prefix) == 1 and len(value) == 1: + self._short_opts.append(opt) + else: + self._long_opts.append(opt) + self.prefixes.add(prefix) + + if action is None: + action = 'store' + + self.dest = dest + self.action = action + self.nargs = nargs + self.const = const + self.obj = obj + + @property + def takes_value(self): + return self.action in ('store', 'append') + + def process(self, value, state): + if self.action == 'store': + state.opts[self.dest] = value + elif self.action == 'store_const': + state.opts[self.dest] = self.const + elif self.action == 'append': + state.opts.setdefault(self.dest, []).append(value) + elif self.action == 'append_const': + state.opts.setdefault(self.dest, []).append(self.const) + elif self.action == 'count': + state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 + else: + raise ValueError('unknown action %r' % self.action) + state.order.append(self.obj) + + +class Argument(object): + + def __init__(self, dest, nargs=1, obj=None): + self.dest = dest + self.nargs = nargs + self.obj = obj + + def process(self, value, state): + if self.nargs > 1: + holes = sum(1 for x in value if x is None) + if holes == len(value): + value = None + elif holes != 0: + raise BadArgumentUsage('argument %s takes %d values' + % (self.dest, self.nargs)) + state.opts[self.dest] = value + state.order.append(self.obj) + + +class ParsingState(object): + + def __init__(self, rargs): + self.opts = {} + self.largs = [] + self.rargs = rargs + self.order = [] + + +class OptionParser(object): + """The option parser is an internal class that is ultimately used to + parse options and arguments. It's modelled after optparse and brings + a similar but vastly simplified API. It should generally not be used + directly as the high level Click classes wrap it for you. + + It's not nearly as extensible as optparse or argparse as it does not + implement features that are implemented on a higher level (such as + types or defaults). + + :param ctx: optionally the :class:`~click.Context` where this parser + should go with. + """ + + def __init__(self, ctx=None): + #: The :class:`~click.Context` for this parser. This might be + #: `None` for some advanced use cases. + self.ctx = ctx + #: This controls how the parser deals with interspersed arguments. + #: If this is set to `False`, the parser will stop on the first + #: non-option. Click uses this to implement nested subcommands + #: safely. + self.allow_interspersed_args = True + #: This tells the parser how to deal with unknown options. By + #: default it will error out (which is sensible), but there is a + #: second mode where it will ignore it and continue processing + #: after shifting all the unknown options into the resulting args. + self.ignore_unknown_options = False + if ctx is not None: + self.allow_interspersed_args = ctx.allow_interspersed_args + self.ignore_unknown_options = ctx.ignore_unknown_options + self._short_opt = {} + self._long_opt = {} + self._opt_prefixes = set(['-', '--']) + self._args = [] + + def add_option(self, opts, dest, action=None, nargs=1, const=None, + obj=None): + """Adds a new option named `dest` to the parser. The destination + is not inferred (unlike with optparse) and needs to be explicitly + provided. Action can be any of ``store``, ``store_const``, + ``append``, ``appnd_const`` or ``count``. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + if obj is None: + obj = dest + opts = [normalize_opt(opt, self.ctx) for opt in opts] + option = Option(opts, dest, action=action, nargs=nargs, + const=const, obj=obj) + self._opt_prefixes.update(option.prefixes) + for opt in option._short_opts: + self._short_opt[opt] = option + for opt in option._long_opts: + self._long_opt[opt] = option + + def add_argument(self, dest, nargs=1, obj=None): + """Adds a positional argument named `dest` to the parser. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + if obj is None: + obj = dest + self._args.append(Argument(dest=dest, nargs=nargs, obj=obj)) + + def parse_args(self, args): + """Parses positional arguments and returns ``(values, args, order)`` + for the parsed options and arguments as well as the leftover + arguments if there are any. The order is a list of objects as they + appear on the command line. If arguments appear multiple times they + will be memorized multiple times as well. + """ + state = ParsingState(args) + try: + self._process_args_for_options(state) + self._process_args_for_args(state) + except UsageError: + if self.ctx is None or not self.ctx.resilient_parsing: + raise + return state.opts, state.largs, state.order + + def _process_args_for_args(self, state): + pargs, args = _unpack_args(state.largs + state.rargs, + [x.nargs for x in self._args]) + + for idx, arg in enumerate(self._args): + arg.process(pargs[idx], state) + + state.largs = args + state.rargs = [] + + def _process_args_for_options(self, state): + while state.rargs: + arg = state.rargs.pop(0) + arglen = len(arg) + # Double dashes always handled explicitly regardless of what + # prefixes are valid. + if arg == '--': + return + elif arg[:1] in self._opt_prefixes and arglen > 1: + self._process_opts(arg, state) + elif self.allow_interspersed_args: + state.largs.append(arg) + else: + state.rargs.insert(0, arg) + return + + # Say this is the original argument list: + # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] + # ^ + # (we are about to process arg(i)). + # + # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of + # [arg0, ..., arg(i-1)] (any options and their arguments will have + # been removed from largs). + # + # The while loop will usually consume 1 or more arguments per pass. + # If it consumes 1 (eg. arg is an option that takes no arguments), + # then after _process_arg() is done the situation is: + # + # largs = subset of [arg0, ..., arg(i)] + # rargs = [arg(i+1), ..., arg(N-1)] + # + # If allow_interspersed_args is false, largs will always be + # *empty* -- still a subset of [arg0, ..., arg(i-1)], but + # not a very interesting subset! + + def _match_long_opt(self, opt, explicit_value, state): + if opt not in self._long_opt: + possibilities = [word for word in self._long_opt + if word.startswith(opt)] + raise NoSuchOption(opt, possibilities=possibilities) + + option = self._long_opt[opt] + if option.takes_value: + # At this point it's safe to modify rargs by injecting the + # explicit value, because no exception is raised in this + # branch. This means that the inserted value will be fully + # consumed. + if explicit_value is not None: + state.rargs.insert(0, explicit_value) + + nargs = option.nargs + if len(state.rargs) < nargs: + _error_opt_args(nargs, opt) + elif nargs == 1: + value = state.rargs.pop(0) + else: + value = tuple(state.rargs[:nargs]) + del state.rargs[:nargs] + + elif explicit_value is not None: + raise BadOptionUsage('%s option does not take a value' % opt) + + else: + value = None + + option.process(value, state) + + def _match_short_opt(self, arg, state): + stop = False + i = 1 + prefix = arg[0] + unknown_options = [] + + for ch in arg[1:]: + opt = normalize_opt(prefix + ch, self.ctx) + option = self._short_opt.get(opt) + i += 1 + + if not option: + if self.ignore_unknown_options: + unknown_options.append(ch) + continue + raise NoSuchOption(opt) + if option.takes_value: + # Any characters left in arg? Pretend they're the + # next arg, and stop consuming characters of arg. + if i < len(arg): + state.rargs.insert(0, arg[i:]) + stop = True + + nargs = option.nargs + if len(state.rargs) < nargs: + _error_opt_args(nargs, opt) + elif nargs == 1: + value = state.rargs.pop(0) + else: + value = tuple(state.rargs[:nargs]) + del state.rargs[:nargs] + + else: + value = None + + option.process(value, state) + + if stop: + break + + # If we got any unknown options we re-combinate the string of the + # remaining options and re-attach the prefix, then report that + # to the state as new larg. This way there is basic combinatorics + # that can be achieved while still ignoring unknown arguments. + if self.ignore_unknown_options and unknown_options: + state.largs.append(prefix + ''.join(unknown_options)) + + def _process_opts(self, arg, state): + explicit_value = None + # Long option handling happens in two parts. The first part is + # supporting explicitly attached values. In any case, we will try + # to long match the option first. + if '=' in arg: + long_opt, explicit_value = arg.split('=', 1) + else: + long_opt = arg + norm_long_opt = normalize_opt(long_opt, self.ctx) + + # At this point we will match the (assumed) long option through + # the long option matching code. Note that this allows options + # like "-foo" to be matched as long options. + try: + self._match_long_opt(norm_long_opt, explicit_value, state) + except NoSuchOption: + # At this point the long option matching failed, and we need + # to try with short options. However there is a special rule + # which says, that if we have a two character options prefix + # (applies to "--foo" for instance), we do not dispatch to the + # short option code and will instead raise the no option + # error. + if arg[:2] not in self._opt_prefixes: + return self._match_short_opt(arg, state) + if not self.ignore_unknown_options: + raise + state.largs.append(arg) diff --git a/flex/lib/python3.6/site-packages/click/termui.py b/flex/lib/python3.6/site-packages/click/termui.py new file mode 100644 index 0000000..d9fba52 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/termui.py @@ -0,0 +1,539 @@ +import os +import sys +import struct + +from ._compat import raw_input, text_type, string_types, \ + isatty, strip_ansi, get_winterm_size, DEFAULT_COLUMNS, WIN +from .utils import echo +from .exceptions import Abort, UsageError +from .types import convert_type +from .globals import resolve_color_default + + +# The prompt functions to use. The doc tools currently override these +# functions to customize how they work. +visible_prompt_func = raw_input + +_ansi_colors = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', + 'cyan', 'white', 'reset') +_ansi_reset_all = '\033[0m' + + +def hidden_prompt_func(prompt): + import getpass + return getpass.getpass(prompt) + + +def _build_prompt(text, suffix, show_default=False, default=None): + prompt = text + if default is not None and show_default: + prompt = '%s [%s]' % (prompt, default) + return prompt + suffix + + +def prompt(text, default=None, hide_input=False, + confirmation_prompt=False, type=None, + value_proc=None, prompt_suffix=': ', + show_default=True, err=False): + """Prompts a user for input. This is a convenience function that can + be used to prompt a user for input later. + + If the user aborts the input by sending a interrupt signal, this + function will catch it and raise a :exc:`Abort` exception. + + .. versionadded:: 6.0 + Added unicode support for cmd.exe on Windows. + + .. versionadded:: 4.0 + Added the `err` parameter. + + :param text: the text to show for the prompt. + :param default: the default value to use if no input happens. If this + is not given it will prompt until it's aborted. + :param hide_input: if this is set to true then the input value will + be hidden. + :param confirmation_prompt: asks for confirmation for the value. + :param type: the type to use to check the value against. + :param value_proc: if this parameter is provided it's a function that + is invoked instead of the type conversion to + convert a value. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + """ + result = None + + def prompt_func(text): + f = hide_input and hidden_prompt_func or visible_prompt_func + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(text, nl=False, err=err) + return f('') + except (KeyboardInterrupt, EOFError): + # getpass doesn't print a newline if the user aborts input with ^C. + # Allegedly this behavior is inherited from getpass(3). + # A doc bug has been filed at https://bugs.python.org/issue24711 + if hide_input: + echo(None, err=err) + raise Abort() + + if value_proc is None: + value_proc = convert_type(type, default) + + prompt = _build_prompt(text, prompt_suffix, show_default, default) + + while 1: + while 1: + value = prompt_func(prompt) + if value: + break + # If a default is set and used, then the confirmation + # prompt is always skipped because that's the only thing + # that really makes sense. + elif default is not None: + return default + try: + result = value_proc(value) + except UsageError as e: + echo('Error: %s' % e.message, err=err) + continue + if not confirmation_prompt: + return result + while 1: + value2 = prompt_func('Repeat for confirmation: ') + if value2: + break + if value == value2: + return result + echo('Error: the two entered values do not match', err=err) + + +def confirm(text, default=False, abort=False, prompt_suffix=': ', + show_default=True, err=False): + """Prompts for confirmation (yes/no question). + + If the user aborts the input by sending a interrupt signal this + function will catch it and raise a :exc:`Abort` exception. + + .. versionadded:: 4.0 + Added the `err` parameter. + + :param text: the question to ask. + :param default: the default for the prompt. + :param abort: if this is set to `True` a negative answer aborts the + exception by raising :exc:`Abort`. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + """ + prompt = _build_prompt(text, prompt_suffix, show_default, + default and 'Y/n' or 'y/N') + while 1: + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(prompt, nl=False, err=err) + value = visible_prompt_func('').lower().strip() + except (KeyboardInterrupt, EOFError): + raise Abort() + if value in ('y', 'yes'): + rv = True + elif value in ('n', 'no'): + rv = False + elif value == '': + rv = default + else: + echo('Error: invalid input', err=err) + continue + break + if abort and not rv: + raise Abort() + return rv + + +def get_terminal_size(): + """Returns the current size of the terminal as tuple in the form + ``(width, height)`` in columns and rows. + """ + # If shutil has get_terminal_size() (Python 3.3 and later) use that + if sys.version_info >= (3, 3): + import shutil + shutil_get_terminal_size = getattr(shutil, 'get_terminal_size', None) + if shutil_get_terminal_size: + sz = shutil_get_terminal_size() + return sz.columns, sz.lines + + if get_winterm_size is not None: + return get_winterm_size() + + def ioctl_gwinsz(fd): + try: + import fcntl + import termios + cr = struct.unpack( + 'hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) + except Exception: + return + return cr + + cr = ioctl_gwinsz(0) or ioctl_gwinsz(1) or ioctl_gwinsz(2) + if not cr: + try: + fd = os.open(os.ctermid(), os.O_RDONLY) + try: + cr = ioctl_gwinsz(fd) + finally: + os.close(fd) + except Exception: + pass + if not cr or not cr[0] or not cr[1]: + cr = (os.environ.get('LINES', 25), + os.environ.get('COLUMNS', DEFAULT_COLUMNS)) + return int(cr[1]), int(cr[0]) + + +def echo_via_pager(text, color=None): + """This function takes a text and shows it via an environment specific + pager on stdout. + + .. versionchanged:: 3.0 + Added the `color` flag. + + :param text: the text to page. + :param color: controls if the pager supports ANSI colors or not. The + default is autodetection. + """ + color = resolve_color_default(color) + if not isinstance(text, string_types): + text = text_type(text) + from ._termui_impl import pager + return pager(text + '\n', color) + + +def progressbar(iterable=None, length=None, label=None, show_eta=True, + show_percent=None, show_pos=False, + item_show_func=None, fill_char='#', empty_char='-', + bar_template='%(label)s [%(bar)s] %(info)s', + info_sep=' ', width=36, file=None, color=None): + """This function creates an iterable context manager that can be used + to iterate over something while showing a progress bar. It will + either iterate over the `iterable` or `length` items (that are counted + up). While iteration happens, this function will print a rendered + progress bar to the given `file` (defaults to stdout) and will attempt + to calculate remaining time and more. By default, this progress bar + will not be rendered if the file is not a terminal. + + The context manager creates the progress bar. When the context + manager is entered the progress bar is already displayed. With every + iteration over the progress bar, the iterable passed to the bar is + advanced and the bar is updated. When the context manager exits, + a newline is printed and the progress bar is finalized on screen. + + No printing must happen or the progress bar will be unintentionally + destroyed. + + Example usage:: + + with progressbar(items) as bar: + for item in bar: + do_something_with(item) + + Alternatively, if no iterable is specified, one can manually update the + progress bar through the `update()` method instead of directly + iterating over the progress bar. The update method accepts the number + of steps to increment the bar with:: + + with progressbar(length=chunks.total_bytes) as bar: + for chunk in chunks: + process_chunk(chunk) + bar.update(chunks.bytes) + + .. versionadded:: 2.0 + + .. versionadded:: 4.0 + Added the `color` parameter. Added a `update` method to the + progressbar object. + + :param iterable: an iterable to iterate over. If not provided the length + is required. + :param length: the number of items to iterate over. By default the + progressbar will attempt to ask the iterator about its + length, which might or might not work. If an iterable is + also provided this parameter can be used to override the + length. If an iterable is not provided the progress bar + will iterate over a range of that length. + :param label: the label to show next to the progress bar. + :param show_eta: enables or disables the estimated time display. This is + automatically disabled if the length cannot be + determined. + :param show_percent: enables or disables the percentage display. The + default is `True` if the iterable has a length or + `False` if not. + :param show_pos: enables or disables the absolute position display. The + default is `False`. + :param item_show_func: a function called with the current item which + can return a string to show the current item + next to the progress bar. Note that the current + item can be `None`! + :param fill_char: the character to use to show the filled part of the + progress bar. + :param empty_char: the character to use to show the non-filled part of + the progress bar. + :param bar_template: the format string to use as template for the bar. + The parameters in it are ``label`` for the label, + ``bar`` for the progress bar and ``info`` for the + info section. + :param info_sep: the separator between multiple info items (eta etc.) + :param width: the width of the progress bar in characters, 0 means full + terminal width + :param file: the file to write to. If this is not a terminal then + only the label is printed. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are included anywhere in the progress bar output + which is not the case by default. + """ + from ._termui_impl import ProgressBar + color = resolve_color_default(color) + return ProgressBar(iterable=iterable, length=length, show_eta=show_eta, + show_percent=show_percent, show_pos=show_pos, + item_show_func=item_show_func, fill_char=fill_char, + empty_char=empty_char, bar_template=bar_template, + info_sep=info_sep, file=file, label=label, + width=width, color=color) + + +def clear(): + """Clears the terminal screen. This will have the effect of clearing + the whole visible space of the terminal and moving the cursor to the + top left. This does not do anything if not connected to a terminal. + + .. versionadded:: 2.0 + """ + if not isatty(sys.stdout): + return + # If we're on Windows and we don't have colorama available, then we + # clear the screen by shelling out. Otherwise we can use an escape + # sequence. + if WIN: + os.system('cls') + else: + sys.stdout.write('\033[2J\033[1;1H') + + +def style(text, fg=None, bg=None, bold=None, dim=None, underline=None, + blink=None, reverse=None, reset=True): + """Styles a text with ANSI styles and returns the new string. By + default the styling is self contained which means that at the end + of the string a reset code is issued. This can be prevented by + passing ``reset=False``. + + Examples:: + + click.echo(click.style('Hello World!', fg='green')) + click.echo(click.style('ATTENTION!', blink=True)) + click.echo(click.style('Some things', reverse=True, fg='cyan')) + + Supported color names: + + * ``black`` (might be a gray) + * ``red`` + * ``green`` + * ``yellow`` (might be an orange) + * ``blue`` + * ``magenta`` + * ``cyan`` + * ``white`` (might be light gray) + * ``reset`` (reset the color code only) + + .. versionadded:: 2.0 + + :param text: the string to style with ansi codes. + :param fg: if provided this will become the foreground color. + :param bg: if provided this will become the background color. + :param bold: if provided this will enable or disable bold mode. + :param dim: if provided this will enable or disable dim mode. This is + badly supported. + :param underline: if provided this will enable or disable underline. + :param blink: if provided this will enable or disable blinking. + :param reverse: if provided this will enable or disable inverse + rendering (foreground becomes background and the + other way round). + :param reset: by default a reset-all code is added at the end of the + string which means that styles do not carry over. This + can be disabled to compose styles. + """ + bits = [] + if fg: + try: + bits.append('\033[%dm' % (_ansi_colors.index(fg) + 30)) + except ValueError: + raise TypeError('Unknown color %r' % fg) + if bg: + try: + bits.append('\033[%dm' % (_ansi_colors.index(bg) + 40)) + except ValueError: + raise TypeError('Unknown color %r' % bg) + if bold is not None: + bits.append('\033[%dm' % (1 if bold else 22)) + if dim is not None: + bits.append('\033[%dm' % (2 if dim else 22)) + if underline is not None: + bits.append('\033[%dm' % (4 if underline else 24)) + if blink is not None: + bits.append('\033[%dm' % (5 if blink else 25)) + if reverse is not None: + bits.append('\033[%dm' % (7 if reverse else 27)) + bits.append(text) + if reset: + bits.append(_ansi_reset_all) + return ''.join(bits) + + +def unstyle(text): + """Removes ANSI styling information from a string. Usually it's not + necessary to use this function as Click's echo function will + automatically remove styling if necessary. + + .. versionadded:: 2.0 + + :param text: the text to remove style information from. + """ + return strip_ansi(text) + + +def secho(text, file=None, nl=True, err=False, color=None, **styles): + """This function combines :func:`echo` and :func:`style` into one + call. As such the following two calls are the same:: + + click.secho('Hello World!', fg='green') + click.echo(click.style('Hello World!', fg='green')) + + All keyword arguments are forwarded to the underlying functions + depending on which one they go with. + + .. versionadded:: 2.0 + """ + return echo(style(text, **styles), file=file, nl=nl, err=err, color=color) + + +def edit(text=None, editor=None, env=None, require_save=True, + extension='.txt', filename=None): + r"""Edits the given text in the defined editor. If an editor is given + (should be the full path to the executable but the regular operating + system search path is used for finding the executable) it overrides + the detected editor. Optionally, some environment variables can be + used. If the editor is closed without changes, `None` is returned. In + case a file is edited directly the return value is always `None` and + `require_save` and `extension` are ignored. + + If the editor cannot be opened a :exc:`UsageError` is raised. + + Note for Windows: to simplify cross-platform usage, the newlines are + automatically converted from POSIX to Windows and vice versa. As such, + the message here will have ``\n`` as newline markers. + + :param text: the text to edit. + :param editor: optionally the editor to use. Defaults to automatic + detection. + :param env: environment variables to forward to the editor. + :param require_save: if this is true, then not saving in the editor + will make the return value become `None`. + :param extension: the extension to tell the editor about. This defaults + to `.txt` but changing this might change syntax + highlighting. + :param filename: if provided it will edit this file instead of the + provided text contents. It will not use a temporary + file as an indirection in that case. + """ + from ._termui_impl import Editor + editor = Editor(editor=editor, env=env, require_save=require_save, + extension=extension) + if filename is None: + return editor.edit(text) + editor.edit_file(filename) + + +def launch(url, wait=False, locate=False): + """This function launches the given URL (or filename) in the default + viewer application for this file type. If this is an executable, it + might launch the executable in a new session. The return value is + the exit code of the launched application. Usually, ``0`` indicates + success. + + Examples:: + + click.launch('http://click.pocoo.org/') + click.launch('/my/downloaded/file', locate=True) + + .. versionadded:: 2.0 + + :param url: URL or filename of the thing to launch. + :param wait: waits for the program to stop. + :param locate: if this is set to `True` then instead of launching the + application associated with the URL it will attempt to + launch a file manager with the file located. This + might have weird effects if the URL does not point to + the filesystem. + """ + from ._termui_impl import open_url + return open_url(url, wait=wait, locate=locate) + + +# If this is provided, getchar() calls into this instead. This is used +# for unittesting purposes. +_getchar = None + + +def getchar(echo=False): + """Fetches a single character from the terminal and returns it. This + will always return a unicode character and under certain rare + circumstances this might return more than one character. The + situations which more than one character is returned is when for + whatever reason multiple characters end up in the terminal buffer or + standard input was not actually a terminal. + + Note that this will always read from the terminal, even if something + is piped into the standard input. + + .. versionadded:: 2.0 + + :param echo: if set to `True`, the character read will also show up on + the terminal. The default is to not show it. + """ + f = _getchar + if f is None: + from ._termui_impl import getchar as f + return f(echo) + + +def pause(info='Press any key to continue ...', err=False): + """This command stops execution and waits for the user to press any + key to continue. This is similar to the Windows batch "pause" + command. If the program is not run through a terminal, this command + will instead do nothing. + + .. versionadded:: 2.0 + + .. versionadded:: 4.0 + Added the `err` parameter. + + :param info: the info string to print before pausing. + :param err: if set to message goes to ``stderr`` instead of + ``stdout``, the same as with echo. + """ + if not isatty(sys.stdin) or not isatty(sys.stdout): + return + try: + if info: + echo(info, nl=False, err=err) + try: + getchar() + except (KeyboardInterrupt, EOFError): + pass + finally: + if info: + echo(err=err) diff --git a/flex/lib/python3.6/site-packages/click/testing.py b/flex/lib/python3.6/site-packages/click/testing.py new file mode 100644 index 0000000..4416c77 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/testing.py @@ -0,0 +1,322 @@ +import os +import sys +import shutil +import tempfile +import contextlib + +from ._compat import iteritems, PY2 + + +# If someone wants to vendor click, we want to ensure the +# correct package is discovered. Ideally we could use a +# relative import here but unfortunately Python does not +# support that. +clickpkg = sys.modules[__name__.rsplit('.', 1)[0]] + + +if PY2: + from cStringIO import StringIO +else: + import io + from ._compat import _find_binary_reader + + +class EchoingStdin(object): + + def __init__(self, input, output): + self._input = input + self._output = output + + def __getattr__(self, x): + return getattr(self._input, x) + + def _echo(self, rv): + self._output.write(rv) + return rv + + def read(self, n=-1): + return self._echo(self._input.read(n)) + + def readline(self, n=-1): + return self._echo(self._input.readline(n)) + + def readlines(self): + return [self._echo(x) for x in self._input.readlines()] + + def __iter__(self): + return iter(self._echo(x) for x in self._input) + + def __repr__(self): + return repr(self._input) + + +def make_input_stream(input, charset): + # Is already an input stream. + if hasattr(input, 'read'): + if PY2: + return input + rv = _find_binary_reader(input) + if rv is not None: + return rv + raise TypeError('Could not find binary reader for input stream.') + + if input is None: + input = b'' + elif not isinstance(input, bytes): + input = input.encode(charset) + if PY2: + return StringIO(input) + return io.BytesIO(input) + + +class Result(object): + """Holds the captured result of an invoked CLI script.""" + + def __init__(self, runner, output_bytes, exit_code, exception, + exc_info=None): + #: The runner that created the result + self.runner = runner + #: The output as bytes. + self.output_bytes = output_bytes + #: The exit code as integer. + self.exit_code = exit_code + #: The exception that happend if one did. + self.exception = exception + #: The traceback + self.exc_info = exc_info + + @property + def output(self): + """The output as unicode string.""" + return self.output_bytes.decode(self.runner.charset, 'replace') \ + .replace('\r\n', '\n') + + def __repr__(self): + return '' % ( + self.exception and repr(self.exception) or 'okay', + ) + + +class CliRunner(object): + """The CLI runner provides functionality to invoke a Click command line + script for unittesting purposes in a isolated environment. This only + works in single-threaded systems without any concurrency as it changes the + global interpreter state. + + :param charset: the character set for the input and output data. This is + UTF-8 by default and should not be changed currently as + the reporting to Click only works in Python 2 properly. + :param env: a dictionary with environment variables for overriding. + :param echo_stdin: if this is set to `True`, then reading from stdin writes + to stdout. This is useful for showing examples in + some circumstances. Note that regular prompts + will automatically echo the input. + """ + + def __init__(self, charset=None, env=None, echo_stdin=False): + if charset is None: + charset = 'utf-8' + self.charset = charset + self.env = env or {} + self.echo_stdin = echo_stdin + + def get_default_prog_name(self, cli): + """Given a command object it will return the default program name + for it. The default is the `name` attribute or ``"root"`` if not + set. + """ + return cli.name or 'root' + + def make_env(self, overrides=None): + """Returns the environment overrides for invoking a script.""" + rv = dict(self.env) + if overrides: + rv.update(overrides) + return rv + + @contextlib.contextmanager + def isolation(self, input=None, env=None, color=False): + """A context manager that sets up the isolation for invoking of a + command line tool. This sets up stdin with the given input data + and `os.environ` with the overrides from the given dictionary. + This also rebinds some internals in Click to be mocked (like the + prompt functionality). + + This is automatically done in the :meth:`invoke` method. + + .. versionadded:: 4.0 + The ``color`` parameter was added. + + :param input: the input stream to put into sys.stdin. + :param env: the environment overrides as dictionary. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + """ + input = make_input_stream(input, self.charset) + + old_stdin = sys.stdin + old_stdout = sys.stdout + old_stderr = sys.stderr + old_forced_width = clickpkg.formatting.FORCED_WIDTH + clickpkg.formatting.FORCED_WIDTH = 80 + + env = self.make_env(env) + + if PY2: + sys.stdout = sys.stderr = bytes_output = StringIO() + if self.echo_stdin: + input = EchoingStdin(input, bytes_output) + else: + bytes_output = io.BytesIO() + if self.echo_stdin: + input = EchoingStdin(input, bytes_output) + input = io.TextIOWrapper(input, encoding=self.charset) + sys.stdout = sys.stderr = io.TextIOWrapper( + bytes_output, encoding=self.charset) + + sys.stdin = input + + def visible_input(prompt=None): + sys.stdout.write(prompt or '') + val = input.readline().rstrip('\r\n') + sys.stdout.write(val + '\n') + sys.stdout.flush() + return val + + def hidden_input(prompt=None): + sys.stdout.write((prompt or '') + '\n') + sys.stdout.flush() + return input.readline().rstrip('\r\n') + + def _getchar(echo): + char = sys.stdin.read(1) + if echo: + sys.stdout.write(char) + sys.stdout.flush() + return char + + default_color = color + def should_strip_ansi(stream=None, color=None): + if color is None: + return not default_color + return not color + + old_visible_prompt_func = clickpkg.termui.visible_prompt_func + old_hidden_prompt_func = clickpkg.termui.hidden_prompt_func + old__getchar_func = clickpkg.termui._getchar + old_should_strip_ansi = clickpkg.utils.should_strip_ansi + clickpkg.termui.visible_prompt_func = visible_input + clickpkg.termui.hidden_prompt_func = hidden_input + clickpkg.termui._getchar = _getchar + clickpkg.utils.should_strip_ansi = should_strip_ansi + + old_env = {} + try: + for key, value in iteritems(env): + old_env[key] = os.environ.get(key) + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + yield bytes_output + finally: + for key, value in iteritems(old_env): + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + sys.stdout = old_stdout + sys.stderr = old_stderr + sys.stdin = old_stdin + clickpkg.termui.visible_prompt_func = old_visible_prompt_func + clickpkg.termui.hidden_prompt_func = old_hidden_prompt_func + clickpkg.termui._getchar = old__getchar_func + clickpkg.utils.should_strip_ansi = old_should_strip_ansi + clickpkg.formatting.FORCED_WIDTH = old_forced_width + + def invoke(self, cli, args=None, input=None, env=None, + catch_exceptions=True, color=False, **extra): + """Invokes a command in an isolated environment. The arguments are + forwarded directly to the command line script, the `extra` keyword + arguments are passed to the :meth:`~clickpkg.Command.main` function of + the command. + + This returns a :class:`Result` object. + + .. versionadded:: 3.0 + The ``catch_exceptions`` parameter was added. + + .. versionchanged:: 3.0 + The result object now has an `exc_info` attribute with the + traceback if available. + + .. versionadded:: 4.0 + The ``color`` parameter was added. + + :param cli: the command to invoke + :param args: the arguments to invoke + :param input: the input data for `sys.stdin`. + :param env: the environment overrides. + :param catch_exceptions: Whether to catch any other exceptions than + ``SystemExit``. + :param extra: the keyword arguments to pass to :meth:`main`. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + """ + exc_info = None + with self.isolation(input=input, env=env, color=color) as out: + exception = None + exit_code = 0 + + try: + cli.main(args=args or (), + prog_name=self.get_default_prog_name(cli), **extra) + except SystemExit as e: + if e.code != 0: + exception = e + + exc_info = sys.exc_info() + + exit_code = e.code + if not isinstance(exit_code, int): + sys.stdout.write(str(exit_code)) + sys.stdout.write('\n') + exit_code = 1 + except Exception as e: + if not catch_exceptions: + raise + exception = e + exit_code = -1 + exc_info = sys.exc_info() + finally: + sys.stdout.flush() + output = out.getvalue() + + return Result(runner=self, + output_bytes=output, + exit_code=exit_code, + exception=exception, + exc_info=exc_info) + + @contextlib.contextmanager + def isolated_filesystem(self): + """A context manager that creates a temporary folder and changes + the current working directory to it for isolated filesystem tests. + """ + cwd = os.getcwd() + t = tempfile.mkdtemp() + os.chdir(t) + try: + yield t + finally: + os.chdir(cwd) + try: + shutil.rmtree(t) + except (OSError, IOError): + pass diff --git a/flex/lib/python3.6/site-packages/click/types.py b/flex/lib/python3.6/site-packages/click/types.py new file mode 100644 index 0000000..3639002 --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/types.py @@ -0,0 +1,550 @@ +import os +import stat + +from ._compat import open_stream, text_type, filename_to_ui, \ + get_filesystem_encoding, get_streerror, _get_argv_encoding, PY2 +from .exceptions import BadParameter +from .utils import safecall, LazyFile + + +class ParamType(object): + """Helper for converting values through types. The following is + necessary for a valid type: + + * it needs a name + * it needs to pass through None unchanged + * it needs to convert from a string + * it needs to convert its result type through unchanged + (eg: needs to be idempotent) + * it needs to be able to deal with param and context being `None`. + This can be the case when the object is used with prompt + inputs. + """ + is_composite = False + + #: the descriptive name of this type + name = None + + #: if a list of this type is expected and the value is pulled from a + #: string environment variable, this is what splits it up. `None` + #: means any whitespace. For all parameters the general rule is that + #: whitespace splits them up. The exception are paths and files which + #: are split by ``os.path.pathsep`` by default (":" on Unix and ";" on + #: Windows). + envvar_list_splitter = None + + def __call__(self, value, param=None, ctx=None): + if value is not None: + return self.convert(value, param, ctx) + + def get_metavar(self, param): + """Returns the metavar default for this param if it provides one.""" + + def get_missing_message(self, param): + """Optionally might return extra information about a missing + parameter. + + .. versionadded:: 2.0 + """ + + def convert(self, value, param, ctx): + """Converts the value. This is not invoked for values that are + `None` (the missing value). + """ + return value + + def split_envvar_value(self, rv): + """Given a value from an environment variable this splits it up + into small chunks depending on the defined envvar list splitter. + + If the splitter is set to `None`, which means that whitespace splits, + then leading and trailing whitespace is ignored. Otherwise, leading + and trailing splitters usually lead to empty items being included. + """ + return (rv or '').split(self.envvar_list_splitter) + + def fail(self, message, param=None, ctx=None): + """Helper method to fail with an invalid value message.""" + raise BadParameter(message, ctx=ctx, param=param) + + +class CompositeParamType(ParamType): + is_composite = True + + @property + def arity(self): + raise NotImplementedError() + + +class FuncParamType(ParamType): + + def __init__(self, func): + self.name = func.__name__ + self.func = func + + def convert(self, value, param, ctx): + try: + return self.func(value) + except ValueError: + try: + value = text_type(value) + except UnicodeError: + value = str(value).decode('utf-8', 'replace') + self.fail(value, param, ctx) + + +class UnprocessedParamType(ParamType): + name = 'text' + + def convert(self, value, param, ctx): + return value + + def __repr__(self): + return 'UNPROCESSED' + + +class StringParamType(ParamType): + name = 'text' + + def convert(self, value, param, ctx): + if isinstance(value, bytes): + enc = _get_argv_encoding() + try: + value = value.decode(enc) + except UnicodeError: + fs_enc = get_filesystem_encoding() + if fs_enc != enc: + try: + value = value.decode(fs_enc) + except UnicodeError: + value = value.decode('utf-8', 'replace') + return value + return value + + def __repr__(self): + return 'STRING' + + +class Choice(ParamType): + """The choice type allows a value to be checked against a fixed set of + supported values. All of these values have to be strings. + + See :ref:`choice-opts` for an example. + """ + name = 'choice' + + def __init__(self, choices): + self.choices = choices + + def get_metavar(self, param): + return '[%s]' % '|'.join(self.choices) + + def get_missing_message(self, param): + return 'Choose from %s.' % ', '.join(self.choices) + + def convert(self, value, param, ctx): + # Exact match + if value in self.choices: + return value + + # Match through normalization + if ctx is not None and \ + ctx.token_normalize_func is not None: + value = ctx.token_normalize_func(value) + for choice in self.choices: + if ctx.token_normalize_func(choice) == value: + return choice + + self.fail('invalid choice: %s. (choose from %s)' % + (value, ', '.join(self.choices)), param, ctx) + + def __repr__(self): + return 'Choice(%r)' % list(self.choices) + + +class IntParamType(ParamType): + name = 'integer' + + def convert(self, value, param, ctx): + try: + return int(value) + except (ValueError, UnicodeError): + self.fail('%s is not a valid integer' % value, param, ctx) + + def __repr__(self): + return 'INT' + + +class IntRange(IntParamType): + """A parameter that works similar to :data:`click.INT` but restricts + the value to fit into a range. The default behavior is to fail if the + value falls outside the range, but it can also be silently clamped + between the two edges. + + See :ref:`ranges` for an example. + """ + name = 'integer range' + + def __init__(self, min=None, max=None, clamp=False): + self.min = min + self.max = max + self.clamp = clamp + + def convert(self, value, param, ctx): + rv = IntParamType.convert(self, value, param, ctx) + if self.clamp: + if self.min is not None and rv < self.min: + return self.min + if self.max is not None and rv > self.max: + return self.max + if self.min is not None and rv < self.min or \ + self.max is not None and rv > self.max: + if self.min is None: + self.fail('%s is bigger than the maximum valid value ' + '%s.' % (rv, self.max), param, ctx) + elif self.max is None: + self.fail('%s is smaller than the minimum valid value ' + '%s.' % (rv, self.min), param, ctx) + else: + self.fail('%s is not in the valid range of %s to %s.' + % (rv, self.min, self.max), param, ctx) + return rv + + def __repr__(self): + return 'IntRange(%r, %r)' % (self.min, self.max) + + +class BoolParamType(ParamType): + name = 'boolean' + + def convert(self, value, param, ctx): + if isinstance(value, bool): + return bool(value) + value = value.lower() + if value in ('true', '1', 'yes', 'y'): + return True + elif value in ('false', '0', 'no', 'n'): + return False + self.fail('%s is not a valid boolean' % value, param, ctx) + + def __repr__(self): + return 'BOOL' + + +class FloatParamType(ParamType): + name = 'float' + + def convert(self, value, param, ctx): + try: + return float(value) + except (UnicodeError, ValueError): + self.fail('%s is not a valid floating point value' % + value, param, ctx) + + def __repr__(self): + return 'FLOAT' + + +class UUIDParameterType(ParamType): + name = 'uuid' + + def convert(self, value, param, ctx): + import uuid + try: + if PY2 and isinstance(value, text_type): + value = value.encode('ascii') + return uuid.UUID(value) + except (UnicodeError, ValueError): + self.fail('%s is not a valid UUID value' % value, param, ctx) + + def __repr__(self): + return 'UUID' + + +class File(ParamType): + """Declares a parameter to be a file for reading or writing. The file + is automatically closed once the context tears down (after the command + finished working). + + Files can be opened for reading or writing. The special value ``-`` + indicates stdin or stdout depending on the mode. + + By default, the file is opened for reading text data, but it can also be + opened in binary mode or for writing. The encoding parameter can be used + to force a specific encoding. + + The `lazy` flag controls if the file should be opened immediately or + upon first IO. The default is to be non lazy for standard input and + output streams as well as files opened for reading, lazy otherwise. + + Starting with Click 2.0, files can also be opened atomically in which + case all writes go into a separate file in the same folder and upon + completion the file will be moved over to the original location. This + is useful if a file regularly read by other users is modified. + + See :ref:`file-args` for more information. + """ + name = 'filename' + envvar_list_splitter = os.path.pathsep + + def __init__(self, mode='r', encoding=None, errors='strict', lazy=None, + atomic=False): + self.mode = mode + self.encoding = encoding + self.errors = errors + self.lazy = lazy + self.atomic = atomic + + def resolve_lazy_flag(self, value): + if self.lazy is not None: + return self.lazy + if value == '-': + return False + elif 'w' in self.mode: + return True + return False + + def convert(self, value, param, ctx): + try: + if hasattr(value, 'read') or hasattr(value, 'write'): + return value + + lazy = self.resolve_lazy_flag(value) + + if lazy: + f = LazyFile(value, self.mode, self.encoding, self.errors, + atomic=self.atomic) + if ctx is not None: + ctx.call_on_close(f.close_intelligently) + return f + + f, should_close = open_stream(value, self.mode, + self.encoding, self.errors, + atomic=self.atomic) + # If a context is provided, we automatically close the file + # at the end of the context execution (or flush out). If a + # context does not exist, it's the caller's responsibility to + # properly close the file. This for instance happens when the + # type is used with prompts. + if ctx is not None: + if should_close: + ctx.call_on_close(safecall(f.close)) + else: + ctx.call_on_close(safecall(f.flush)) + return f + except (IOError, OSError) as e: + self.fail('Could not open file: %s: %s' % ( + filename_to_ui(value), + get_streerror(e), + ), param, ctx) + + +class Path(ParamType): + """The path type is similar to the :class:`File` type but it performs + different checks. First of all, instead of returning an open file + handle it returns just the filename. Secondly, it can perform various + basic checks about what the file or directory should be. + + .. versionchanged:: 6.0 + `allow_dash` was added. + + :param exists: if set to true, the file or directory needs to exist for + this value to be valid. If this is not required and a + file does indeed not exist, then all further checks are + silently skipped. + :param file_okay: controls if a file is a possible value. + :param dir_okay: controls if a directory is a possible value. + :param writable: if true, a writable check is performed. + :param readable: if true, a readable check is performed. + :param resolve_path: if this is true, then the path is fully resolved + before the value is passed onwards. This means + that it's absolute and symlinks are resolved. + :param allow_dash: If this is set to `True`, a single dash to indicate + standard streams is permitted. + :param type: optionally a string type that should be used to + represent the path. The default is `None` which + means the return value will be either bytes or + unicode depending on what makes most sense given the + input data Click deals with. + """ + envvar_list_splitter = os.path.pathsep + + def __init__(self, exists=False, file_okay=True, dir_okay=True, + writable=False, readable=True, resolve_path=False, + allow_dash=False, path_type=None): + self.exists = exists + self.file_okay = file_okay + self.dir_okay = dir_okay + self.writable = writable + self.readable = readable + self.resolve_path = resolve_path + self.allow_dash = allow_dash + self.type = path_type + + if self.file_okay and not self.dir_okay: + self.name = 'file' + self.path_type = 'File' + if self.dir_okay and not self.file_okay: + self.name = 'directory' + self.path_type = 'Directory' + else: + self.name = 'path' + self.path_type = 'Path' + + def coerce_path_result(self, rv): + if self.type is not None and not isinstance(rv, self.type): + if self.type is text_type: + rv = rv.decode(get_filesystem_encoding()) + else: + rv = rv.encode(get_filesystem_encoding()) + return rv + + def convert(self, value, param, ctx): + rv = value + + is_dash = self.file_okay and self.allow_dash and rv in (b'-', '-') + + if not is_dash: + if self.resolve_path: + rv = os.path.realpath(rv) + + try: + st = os.stat(rv) + except OSError: + if not self.exists: + return self.coerce_path_result(rv) + self.fail('%s "%s" does not exist.' % ( + self.path_type, + filename_to_ui(value) + ), param, ctx) + + if not self.file_okay and stat.S_ISREG(st.st_mode): + self.fail('%s "%s" is a file.' % ( + self.path_type, + filename_to_ui(value) + ), param, ctx) + if not self.dir_okay and stat.S_ISDIR(st.st_mode): + self.fail('%s "%s" is a directory.' % ( + self.path_type, + filename_to_ui(value) + ), param, ctx) + if self.writable and not os.access(value, os.W_OK): + self.fail('%s "%s" is not writable.' % ( + self.path_type, + filename_to_ui(value) + ), param, ctx) + if self.readable and not os.access(value, os.R_OK): + self.fail('%s "%s" is not readable.' % ( + self.path_type, + filename_to_ui(value) + ), param, ctx) + + return self.coerce_path_result(rv) + + +class Tuple(CompositeParamType): + """The default behavior of Click is to apply a type on a value directly. + This works well in most cases, except for when `nargs` is set to a fixed + count and different types should be used for different items. In this + case the :class:`Tuple` type can be used. This type can only be used + if `nargs` is set to a fixed number. + + For more information see :ref:`tuple-type`. + + This can be selected by using a Python tuple literal as a type. + + :param types: a list of types that should be used for the tuple items. + """ + + def __init__(self, types): + self.types = [convert_type(ty) for ty in types] + + @property + def name(self): + return "<" + " ".join(ty.name for ty in self.types) + ">" + + @property + def arity(self): + return len(self.types) + + def convert(self, value, param, ctx): + if len(value) != len(self.types): + raise TypeError('It would appear that nargs is set to conflict ' + 'with the composite type arity.') + return tuple(ty(x, param, ctx) for ty, x in zip(self.types, value)) + + +def convert_type(ty, default=None): + """Converts a callable or python ty into the most appropriate param + ty. + """ + guessed_type = False + if ty is None and default is not None: + if isinstance(default, tuple): + ty = tuple(map(type, default)) + else: + ty = type(default) + guessed_type = True + + if isinstance(ty, tuple): + return Tuple(ty) + if isinstance(ty, ParamType): + return ty + if ty is text_type or ty is str or ty is None: + return STRING + if ty is int: + return INT + # Booleans are only okay if not guessed. This is done because for + # flags the default value is actually a bit of a lie in that it + # indicates which of the flags is the one we want. See get_default() + # for more information. + if ty is bool and not guessed_type: + return BOOL + if ty is float: + return FLOAT + if guessed_type: + return STRING + + # Catch a common mistake + if __debug__: + try: + if issubclass(ty, ParamType): + raise AssertionError('Attempted to use an uninstantiated ' + 'parameter type (%s).' % ty) + except TypeError: + pass + return FuncParamType(ty) + + +#: A dummy parameter type that just does nothing. From a user's +#: perspective this appears to just be the same as `STRING` but internally +#: no string conversion takes place. This is necessary to achieve the +#: same bytes/unicode behavior on Python 2/3 in situations where you want +#: to not convert argument types. This is usually useful when working +#: with file paths as they can appear in bytes and unicode. +#: +#: For path related uses the :class:`Path` type is a better choice but +#: there are situations where an unprocessed type is useful which is why +#: it is is provided. +#: +#: .. versionadded:: 4.0 +UNPROCESSED = UnprocessedParamType() + +#: A unicode string parameter type which is the implicit default. This +#: can also be selected by using ``str`` as type. +STRING = StringParamType() + +#: An integer parameter. This can also be selected by using ``int`` as +#: type. +INT = IntParamType() + +#: A floating point value parameter. This can also be selected by using +#: ``float`` as type. +FLOAT = FloatParamType() + +#: A boolean parameter. This is the default for boolean flags. This can +#: also be selected by using ``bool`` as a type. +BOOL = BoolParamType() + +#: A UUID parameter. +UUID = UUIDParameterType() diff --git a/flex/lib/python3.6/site-packages/click/utils.py b/flex/lib/python3.6/site-packages/click/utils.py new file mode 100644 index 0000000..eee626d --- /dev/null +++ b/flex/lib/python3.6/site-packages/click/utils.py @@ -0,0 +1,415 @@ +import os +import sys + +from .globals import resolve_color_default + +from ._compat import text_type, open_stream, get_filesystem_encoding, \ + get_streerror, string_types, PY2, binary_streams, text_streams, \ + filename_to_ui, auto_wrap_for_ansi, strip_ansi, should_strip_ansi, \ + _default_text_stdout, _default_text_stderr, is_bytes, WIN + +if not PY2: + from ._compat import _find_binary_writer +elif WIN: + from ._winconsole import _get_windows_argv, \ + _hash_py_argv, _initial_argv_hash + + +echo_native_types = string_types + (bytes, bytearray) + + +def _posixify(name): + return '-'.join(name.split()).lower() + + +def safecall(func): + """Wraps a function so that it swallows exceptions.""" + def wrapper(*args, **kwargs): + try: + return func(*args, **kwargs) + except Exception: + pass + return wrapper + + +def make_str(value): + """Converts a value into a valid string.""" + if isinstance(value, bytes): + try: + return value.decode(get_filesystem_encoding()) + except UnicodeError: + return value.decode('utf-8', 'replace') + return text_type(value) + + +def make_default_short_help(help, max_length=45): + words = help.split() + total_length = 0 + result = [] + done = False + + for word in words: + if word[-1:] == '.': + done = True + new_length = result and 1 + len(word) or len(word) + if total_length + new_length > max_length: + result.append('...') + done = True + else: + if result: + result.append(' ') + result.append(word) + if done: + break + total_length += new_length + + return ''.join(result) + + +class LazyFile(object): + """A lazy file works like a regular file but it does not fully open + the file but it does perform some basic checks early to see if the + filename parameter does make sense. This is useful for safely opening + files for writing. + """ + + def __init__(self, filename, mode='r', encoding=None, errors='strict', + atomic=False): + self.name = filename + self.mode = mode + self.encoding = encoding + self.errors = errors + self.atomic = atomic + + if filename == '-': + self._f, self.should_close = open_stream(filename, mode, + encoding, errors) + else: + if 'r' in mode: + # Open and close the file in case we're opening it for + # reading so that we can catch at least some errors in + # some cases early. + open(filename, mode).close() + self._f = None + self.should_close = True + + def __getattr__(self, name): + return getattr(self.open(), name) + + def __repr__(self): + if self._f is not None: + return repr(self._f) + return '' % (self.name, self.mode) + + def open(self): + """Opens the file if it's not yet open. This call might fail with + a :exc:`FileError`. Not handling this error will produce an error + that Click shows. + """ + if self._f is not None: + return self._f + try: + rv, self.should_close = open_stream(self.name, self.mode, + self.encoding, + self.errors, + atomic=self.atomic) + except (IOError, OSError) as e: + from .exceptions import FileError + raise FileError(self.name, hint=get_streerror(e)) + self._f = rv + return rv + + def close(self): + """Closes the underlying file, no matter what.""" + if self._f is not None: + self._f.close() + + def close_intelligently(self): + """This function only closes the file if it was opened by the lazy + file wrapper. For instance this will never close stdin. + """ + if self.should_close: + self.close() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, tb): + self.close_intelligently() + + def __iter__(self): + self.open() + return iter(self._f) + + +class KeepOpenFile(object): + + def __init__(self, file): + self._file = file + + def __getattr__(self, name): + return getattr(self._file, name) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, tb): + pass + + def __repr__(self): + return repr(self._file) + + def __iter__(self): + return iter(self._file) + + +def echo(message=None, file=None, nl=True, err=False, color=None): + """Prints a message plus a newline to the given file or stdout. On + first sight, this looks like the print function, but it has improved + support for handling Unicode and binary data that does not fail no + matter how badly configured the system is. + + Primarily it means that you can print binary data as well as Unicode + data on both 2.x and 3.x to the given file in the most appropriate way + possible. This is a very carefree function as in that it will try its + best to not fail. As of Click 6.0 this includes support for unicode + output on the Windows console. + + In addition to that, if `colorama`_ is installed, the echo function will + also support clever handling of ANSI codes. Essentially it will then + do the following: + + - add transparent handling of ANSI color codes on Windows. + - hide ANSI codes automatically if the destination file is not a + terminal. + + .. _colorama: http://pypi.python.org/pypi/colorama + + .. versionchanged:: 6.0 + As of Click 6.0 the echo function will properly support unicode + output on the windows console. Not that click does not modify + the interpreter in any way which means that `sys.stdout` or the + print statement or function will still not provide unicode support. + + .. versionchanged:: 2.0 + Starting with version 2.0 of Click, the echo function will work + with colorama if it's installed. + + .. versionadded:: 3.0 + The `err` parameter was added. + + .. versionchanged:: 4.0 + Added the `color` flag. + + :param message: the message to print + :param file: the file to write to (defaults to ``stdout``) + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``. This is faster and easier than calling + :func:`get_text_stderr` yourself. + :param nl: if set to `True` (the default) a newline is printed afterwards. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. + """ + if file is None: + if err: + file = _default_text_stderr() + else: + file = _default_text_stdout() + + # Convert non bytes/text into the native string type. + if message is not None and not isinstance(message, echo_native_types): + message = text_type(message) + + if nl: + message = message or u'' + if isinstance(message, text_type): + message += u'\n' + else: + message += b'\n' + + # If there is a message, and we're in Python 3, and the value looks + # like bytes, we manually need to find the binary stream and write the + # message in there. This is done separately so that most stream + # types will work as you would expect. Eg: you can write to StringIO + # for other cases. + if message and not PY2 and is_bytes(message): + binary_file = _find_binary_writer(file) + if binary_file is not None: + file.flush() + binary_file.write(message) + binary_file.flush() + return + + # ANSI-style support. If there is no message or we are dealing with + # bytes nothing is happening. If we are connected to a file we want + # to strip colors. If we are on windows we either wrap the stream + # to strip the color or we use the colorama support to translate the + # ansi codes to API calls. + if message and not is_bytes(message): + color = resolve_color_default(color) + if should_strip_ansi(file, color): + message = strip_ansi(message) + elif WIN: + if auto_wrap_for_ansi is not None: + file = auto_wrap_for_ansi(file) + elif not color: + message = strip_ansi(message) + + if message: + file.write(message) + file.flush() + + +def get_binary_stream(name): + """Returns a system stream for byte processing. This essentially + returns the stream from the sys module with the given name but it + solves some compatibility issues between different Python versions. + Primarily this function is necessary for getting binary streams on + Python 3. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + """ + opener = binary_streams.get(name) + if opener is None: + raise TypeError('Unknown standard stream %r' % name) + return opener() + + +def get_text_stream(name, encoding=None, errors='strict'): + """Returns a system stream for text processing. This usually returns + a wrapped stream around a binary stream returned from + :func:`get_binary_stream` but it also can take shortcuts on Python 3 + for already correctly configured streams. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + :param encoding: overrides the detected default encoding. + :param errors: overrides the default error mode. + """ + opener = text_streams.get(name) + if opener is None: + raise TypeError('Unknown standard stream %r' % name) + return opener(encoding, errors) + + +def open_file(filename, mode='r', encoding=None, errors='strict', + lazy=False, atomic=False): + """This is similar to how the :class:`File` works but for manual + usage. Files are opened non lazy by default. This can open regular + files as well as stdin/stdout if ``'-'`` is passed. + + If stdin/stdout is returned the stream is wrapped so that the context + manager will not close the stream accidentally. This makes it possible + to always use the function like this without having to worry to + accidentally close a standard stream:: + + with open_file(filename) as f: + ... + + .. versionadded:: 3.0 + + :param filename: the name of the file to open (or ``'-'`` for stdin/stdout). + :param mode: the mode in which to open the file. + :param encoding: the encoding to use. + :param errors: the error handling for this file. + :param lazy: can be flipped to true to open the file lazily. + :param atomic: in atomic mode writes go into a temporary file and it's + moved on close. + """ + if lazy: + return LazyFile(filename, mode, encoding, errors, atomic=atomic) + f, should_close = open_stream(filename, mode, encoding, errors, + atomic=atomic) + if not should_close: + f = KeepOpenFile(f) + return f + + +def get_os_args(): + """This returns the argument part of sys.argv in the most appropriate + form for processing. What this means is that this return value is in + a format that works for Click to process but does not necessarily + correspond well to what's actually standard for the interpreter. + + On most environments the return value is ``sys.argv[:1]`` unchanged. + However if you are on Windows and running Python 2 the return value + will actually be a list of unicode strings instead because the + default behavior on that platform otherwise will not be able to + carry all possible values that sys.argv can have. + + .. versionadded:: 6.0 + """ + # We can only extract the unicode argv if sys.argv has not been + # changed since the startup of the application. + if PY2 and WIN and _initial_argv_hash == _hash_py_argv(): + return _get_windows_argv() + return sys.argv[1:] + + +def format_filename(filename, shorten=False): + """Formats a filename for user display. The main purpose of this + function is to ensure that the filename can be displayed at all. This + will decode the filename to unicode if necessary in a way that it will + not fail. Optionally, it can shorten the filename to not include the + full path to the filename. + + :param filename: formats a filename for UI display. This will also convert + the filename into unicode without failing. + :param shorten: this optionally shortens the filename to strip of the + path that leads up to it. + """ + if shorten: + filename = os.path.basename(filename) + return filename_to_ui(filename) + + +def get_app_dir(app_name, roaming=True, force_posix=False): + r"""Returns the config folder for the application. The default behavior + is to return whatever is most appropriate for the operating system. + + To give you an idea, for an app called ``"Foo Bar"``, something like + the following folders could be returned: + + Mac OS X: + ``~/Library/Application Support/Foo Bar`` + Mac OS X (POSIX): + ``~/.foo-bar`` + Unix: + ``~/.config/foo-bar`` + Unix (POSIX): + ``~/.foo-bar`` + Win XP (roaming): + ``C:\Documents and Settings\\Local Settings\Application Data\Foo Bar`` + Win XP (not roaming): + ``C:\Documents and Settings\\Application Data\Foo Bar`` + Win 7 (roaming): + ``C:\Users\\AppData\Roaming\Foo Bar`` + Win 7 (not roaming): + ``C:\Users\\AppData\Local\Foo Bar`` + + .. versionadded:: 2.0 + + :param app_name: the application name. This should be properly capitalized + and can contain whitespace. + :param roaming: controls if the folder should be roaming or not on Windows. + Has no affect otherwise. + :param force_posix: if this is set to `True` then on any POSIX system the + folder will be stored in the home folder with a leading + dot instead of the XDG config home or darwin's + application support folder. + """ + if WIN: + key = roaming and 'APPDATA' or 'LOCALAPPDATA' + folder = os.environ.get(key) + if folder is None: + folder = os.path.expanduser('~') + return os.path.join(folder, app_name) + if force_posix: + return os.path.join(os.path.expanduser('~/.' + _posixify(app_name))) + if sys.platform == 'darwin': + return os.path.join(os.path.expanduser( + '~/Library/Application Support'), app_name) + return os.path.join( + os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config')), + _posixify(app_name)) diff --git a/flex/lib/python3.6/site-packages/django/conf/locale/en/__pycache__/__init__.cpython-36.pyc b/flex/lib/python3.6/site-packages/django/conf/locale/en/__pycache__/__init__.cpython-36.pyc index 56c726ef9008b0b3960e310f975adc5a8f6bd09f..567abf830a71589a4bb189ba8fc24858bff79321 100644 GIT binary patch delta 96 zcmX@kc!-hBn3tE!ZPP?HOTT>m(BjmhV*TvIqLPfv?1IvqoYb5|eV5eY?2`Nf{fxxq w?3Bc^%wm1FoYV^aG!T)KnWSG(S(1^TXRK$YUz}Nzs#^e5mYAMeJaLjK09EuNvj6}9 delta 101 zcmX@ac$|^Vn3tDp@9c?emcb?Z1x1-E_kPNbbV5F;KP`t0d zUx)`xg8+o*;ur}N5e)Y54+@D#Hg)nlMzQ)^f^MEc!61pqcz?I}a93CFTS8z}o_+zL zAyDnXx5VJKqKXT;xH^0KI{L&1y9PK0IfnQL-4Y7%@DB}k^m9QH`kOrxq3KXD1ewWMpO+l;-55<|OL7q!wqF$~NoR_LdJh@8wM{esGpjQl)fJv05{%#u{y0-& delta 341 zcmdnNwwH~~n3tDp@9d3iEsQBq+%AqGuJLaELB5V5QQRS(zHkmdNCsIzFw)gADBjoK zFT?|;K>)&Yag2nC2nKuj2Zh8Vn>zU&qgZ{Epqpnd?;cc9G6sF!?4%|L}$pvtRIOnJ>c%Ux8J=n%Y*>4YgxX16oeSRMv@CPYhQxD-0f0W9z>M?Ba4QTOJs@K&Mc*>u`Cf|fD zz6EXGh7Rw*Hs6LFz5}~_7xwrbba@x{`F{G$oO%Wa{2-f=2Pe<@bF6Y+9l{a+4sRR$ zg}-o|X*DnZsW3c!<(g3{{Z6NniZ2-io{sw31$h?f5$m}|`Ya0BZ&Hsg<#^C$>}~Sc zFnONH&;+MaT`)iL#vsE)`l%B)^jSYrDmpW)Cr!d)?RrVzNfx_FB6VomSJ95VD8A6a zV3-`S4X?#^w|Dkg?}EM55QOY~6uRC}>UQe%NTGw!$RqaZ_@_-~q-4Lmef{R$@f(b# z8AMt#UnXv#(EDX+yS=m9-u*=T(#qPR+lzF9LRm{c(9%mM#jfWucNRZ3|ceR8EYjluq{#_hjzxu&=>tcN!z>< zbp+xnR-`ZN;y@-MHI=>qX^cCN#x4_^NQjl2NP*4KL2sN$I}7ee3Oxyo&fUHgCs7ch z^F&J*#95FGg%@GZ&y!ZkR=u&-I050tvCR&wqbJ!r24e+LXcy33T9ELPb72zK8`(OU zf7V+C+Z?*)v*DF{J4a+{IUyF@K8{f&!{FN3uF)*TG>z+6lMJ(V=9L=DSO+1sehzc> z$-|^{yZjA-38LwsRkaNh3_@370;f1zw}%aGOdrEc$&K{M;Z<>1n8rP{^HZW9gn=0% zvowg3>(b=8C*y?rvN$zNq)Q=%ADxAE1nIup^7v|KAKtaTw~oM+JRxjVh*PO)m_qR8+4Oz9 zF2!j2B=Y+8%{alALFb7qodn^DyQ>SR=pr$BEJQn`mI-DMYza%o_0|kL%X!*S_FqLv7j304SJ32q?RJT9TWN$M?vHGfB z^5iu!dW)`|$pCnr3_h>kpBa5XJ_!EvI=IfK_~Ld>UERSC91tU;BY_q*c)}yuki$hz@1HmXvdh?3yA!& kl0VQC3_~d73WZv>mYvTnB5vkcZZ(HmzU$NqrF<>>Kgtt3I{*Lx literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/flask/__pycache__/__main__.cpython-36.pyc b/flex/lib/python3.6/site-packages/flask/__pycache__/__main__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..50e6f9fd9907e682cd5046b360d538de79aa2061 GIT binary patch literal 467 zcmY*V!Ab)$5KX$()1${6tGs8^g@lJMj{Lc^C-Gcypfj{tEe&xdMJ7S;p{RhR%IKn5CXQ@0YPo{?jwi3BsL2%Rzzrw%ht<3_+_sp1+l1~o7I9D>#`aRIHI{y zL^C9X=HYTYrFk(m;(0Ji(E$z6ar5XD^`@w0l+frg*MttZ3CpijDJa*Lr|7zKdx$LO z=>G1e{m^Nb7gTOIVthn|w4pz*ucdxF7eD~#)rIn>0Cu;C#VTiG$sdC1yoNE$DaMNh zO%!*TN2M?euik*Exu>Kb8Wl!N$cRT1VxoR788eb;k`~@Bqh8_R_ literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/flask/__pycache__/_compat.cpython-36.pyc b/flex/lib/python3.6/site-packages/flask/__pycache__/_compat.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cffadd3ad7763326ad71fd81b5bf3586bf7749f6 GIT binary patch literal 3163 zcmbVOPjeeJ6qk0_j_o>W+NNn!3W)zTw03DzrpZ7CD4}!!Q<}`s`l4B{s(Od14_0!Yu{n1{Zp054+OVs(JM#yjE zNIMJT525Q7N{ApGBB<~Z+M$wed4etw;rG3cF9K0|LOOx;^_DDk%Cgj>ohexXSruhB zR})k2c|ug&vkpkrWO^{unW021h?+R@gmzBKpfj6(CQl)TJk|3MMV^LdRn*5g(_@^O zBRFRY962XWjws;Gic?_EtT-*s!1Jt_>&(k@l8UnoFbgGM%wU5@yr44BHHMBr_Qk zGMDKAKrW-W7e{Qo&SAjX*fa}!mZK~ms(545EVD~dgI&A&?hV!*vX9gtPT9RI4Wmt| znr_{45=S!Ca+!U+_Q_?YrDR{+xwYC}TV=gWu|cN56luaZ(aqZL7;x?1J&+MFour0t(USh}lxP&x5ux0S1SCp5CP6RK7(O9Y&|)l;qO{dZIKaB=CX*b{q8 zdhup|acQvh-r`kg8)<93mB;y&?slArD~s{cjrd`=-*S!_%dvZ!`OsG0Pr^Z0ge$XX z4s@c*AdXp!<~wWaFfd^679Eihbyhb#8^lH`8}#K+;|av!2~_C-?>r0~`hNgcQ?SUE zcfw>_0{Go{|0^G02&TfS%WxCH|~5Dp$*vZIpO9ayzJ90vhVe) zY7Rzp-y6}#bRW7XJPce-b8b`^$!-|+Ikz*9VzYUuY53MNxh=UP!?63*aqX0nDvY&! z2{zN{CqirRQ>S5cjM+(mRbU1jMn+>3;2h|#!dd@F>D#dCS$F*lXbnN1>#2ACD{K{E zpXa2@2dH~DgzT{~MVCx|nK_FtGt>Q`ou#s|Tw{(tc5Ln#aT9;ekBQqSoZ{8+1Zd<% zuKMj~maL%-Gvg&ANDx6?f_Uw{(zfYcxe2~M!TEL?N12e|`LaxL1YwOO;3+@56kJ3| z=w$EBc#tP@AXB5c$vD=-bffuxl0{*nS71ce3xmUvbHE2s0sMqKc4P zZ1}`}2D-*7_5NUe#^{wgO|=6T+g#`5+V936ATWKim$JVn)3TxP_UXdJ)H1 z1CCfxot*jum~eJfsCo^?_9Rp}xKu+mVW~XuY>`^%QxV{ImMDQk$~NF%Zm3BB z{?nCNm`ZJ+Wzs9S!0>TbgROE786zPZzQ#?*j+sGV;C?(c*#f6=?QQ%oW{)8Tlh{+I z4SW!e;L3JY+-uva+>L-p87ipPQ=6dW0Zm!)ZDFzVg6%?U zK~1;eF?y{|rBZS%Vi?mpnR z*6)9L`yOAte`j4`aku5HyCoyzPGx64(poA5-+!x0Wnk_)7~+P1#|?bo6bZG0X6esB w1VGRXt@r^AXqlEhAPh8huU0C94#x)?7?msY0j<;7DUW(EHwP==4Mwx{FXhIuz5oCK literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/flask/__pycache__/app.cpython-36.pyc b/flex/lib/python3.6/site-packages/flask/__pycache__/app.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e452623e48e98c81e95dad628459015ad39ae75d GIT binary patch literal 62944 zcmeIb3v?V=dLGtqG=K&OlHhYVGd-LKff*9yJa-2>oE;DZAG;io3t(P7Guz$hDu504 z15?!?i556oFIPJwS+lE1E6ZA~*K0eGthHoI*4vTwSf4m2wj(F8^*EK-Ifc~DZXHZpLb?er>|NZa(zW;rCWMt@ff2mgbpUx%||11&t zm%;T*`19XSCK67flyH(xs*x-u<(w*|a85VU%}gniD^QGsT)1~R= z$4Vb-zEFChdAf93o{cwNY<|4-@#agVmzp!BndX_&nPkGv+)k8c-Lp8(Is2UbpG%a^ zIR~7BIG;bCa1J?#KbLS0yN7P4OBbBfVq)^X?yn9N@o%M3^{-7;*VpCOyXN1J{9L+P z_lwQ8v(a#i_2zoRZMv@G5yy&}b z@zTZFx%tJp;!4{?Gd#EGxSeXf;ZF^HlL$6HnG7?5$xM)bxw;-?7SP3D*Mj@bhU<40T&M1# z6T#4#je5hG^Srhs@y}DHV*p>~^lUo%wcW zrqO8Ma2?c9b#%SK9>-m&ZZtY&*VN*F6O$q_IS}kEU#ZrvRaf0J?TwamS%4S}YZGA$xXT->tb27b6=c?Y^ekO#)bV4$G&{fG`s-~B4Q}q5ZMRnH zt23RBS6|-fxIs?cm`n$wx;$=l+?#;j%=)^y9xd}n=jQoFd%4>10rx#+PeHp}>)b5+ z9keMJ(6@pCAAKZ{ldBlBBa3cr!*gfb?Q3;+Q9TjhuT*O;KD_^I-CwVEYFF#6)lbx0 zYt>8bs^faW@LcP9-D|gqwZVhvsRDk-1u7FO_+bF8h8ksncbOKUHC_i}H)d`CY<0pu z*tgp5*oNCt48~2tj$8H6in7zb(FzU#>1qlX<>&+S9zFG{b>9sNJ^+aqI-Bbl(Ln-E zu7eQ_pS$XM>Pd}g!hbxc@i&V<{~!*X#8#q{yq)sLJIO83&kvG|xPuv<;`9I@(E`WE z$PLx~dJ8>k)m)D?;A!@HwXxy;WWswEzrXeAlj~mnIskL>deu9*(ry5T{>c^ZvW&@pZVyuXP$39|J*aD@Nczsa_QuHef`8Tr^<d!x0e`opHNuewH z2rx{oZw9-{&FVF`Y$xgob|HsDA~}TrypQ0@_A`YaY$gBv{W!drSP_o#x%{mp`kZ_} zahr53-M#i2CbwU#7Mn8lihdges@f^mJ4H+f%$_D6VusYN6+v_a-$~R!(pE^y6dA00 zey6BMv3R43R~nvMbvBDvt1YMDI*LZw=9#8F$mTtQ!&YJ~;f>>%^u{}2X}6P~MH9Es z=&j^eQ(LJoU|29D)g}gT2E?tiv0mhq6q?EJ)v67ArdVA8Q4tEevaLy`DaE1?<_&)X z?`)z|4vDYJZelL8lcdmqx+TgtKxJ{q&~kpS)dq-~>un->5q$(;YHhFDX?uPVV0?={rfRX%)|CT}jpAl|!z+>s=?3`6 ziy+I@<*M(>NHoxNw7>-!-9$yLRg45{N5eWCJI!k_Yin+C*~OUR3q4(wIqL(m-gQ-h zkaB+t^dT!_4vNFcD_}KKI2fJr@dgJ$QTcR`@!iHskg0mBevrF%gJ;Z?P*0 zP|)l|XezN*V{svwALu?LW2IG0}kh>SBqHjzly)0guOnEQjioCk0o$2pJlKAZ<}-jDN; zd%zj~AXPeu>w>;MgzFJJKaBGz&iA=T*6uGofa8OuqWh4u%NbiuIlDhdmX5j)xeq&g zoV_0;aUAD=?jsaf^zQ?5@1PtHp~NA1e%QHBp6|h(Be=)^?njvizH$U#d(?fbbj%qq zO}LW~e;#*!(Rs)@`nhE33Fl$w5%lx8^QiL}&L_~{(%e&m~a9 zDRU!u1JfO0J(q`IF8mxqb%spLCv*>t~%`a-Mdc!S|kXo^_tX zcRu3$vhz{rdEEJ^Gwpl~cb<1%a8Bbq?Y!uG9OsWYFF7+fzu=s4W^q34oOR}Ke$n|A z=bUpMZ+_hQTh0aNBCcL?KH+>4&t{xU&dWHTaps-NI78TTt~j5PHq1E-&LZxe!@d99 zS#nU&g(PQ~`Du~>D!pVD9&rn zmz^KO`I_?;=P%&gaK7sNMVyB>r z{a2lz#I^5y-T7;H-f@1)`DvUtoWJh;4VHHkdH=Un%egWrAXB=GR z?*!R%l;W#DJC;Z+U3HaAuLbd_++N)-t&{9lYmn)|5lB%rsTH26CHZ3UA~=O#T(5#u zI#Q}tZMwy_a8JWhz%sO0sUJuc5gs&EEMA7_LAH#_YGAIU@A!424i14fun8fp_uSPw zM59g0{!$fNCoIHpO)wGOdu8EL(S!8PpIWdhLgayrx&dxRjf8z{Zq%-#sU8@X)J8Bx zdtus+rfo^M(f@u}EPW+|{o;!hWP8^CJ4s)+nh-E{)!V&O!!+KEm!& z{#b`}P8NlxMI;bY(R$SbbSVVr24G;?=mS9neqUS%hs2wv_(auw^G3aMRRO(KoL;Fn z-04cW47s&aE<^gNfJ;-0lh#j?!&i$G2A!%0=qMF$Vr>ILP_=iA!KrYajfUi#1fW-cE zMR2*omWr%On2G$*1PDz_HBM+rXUE3X@v%&0drJETs0z#v_L?~ z=fL6O>7v}5D3^&e$WaihA4 zwgT3WX{pK=MbinZyb9eM(k836tv8?0*m7Jo(@5E5vAtp%!>fjY~QaLj}f%G$XK zDq~4?=SI7TPOE_={@jSp1GX)S>&JS&d2G^tt+%KF{*(`uqcd@A>e%F)r{30+goR(b z3N?iTQtf=4+DngiLJn}F?Ome=&;mn1v%>);nXk64h4@P7w{L`qEcnrYaR4K;v5qmm zpa<757g0+rwhBJluB?NqtZX#!)-3b@l9&jxa~jCYAWR!gG5h#MYAp_lHwM;Lqckal z2-^k~)klY&I3u(B#Nwwe%`~8!HaBfm_WO!6vSVTZ<4b~Zh9E}pK_FX%C1Dj71J|*2 zq5b$m5vmY4Dc%c}Uo{n2XSC@UBkG09k_6QfN{Fp%V_im~6V7|o81e$V+GzV7)H@OF zD#t+3vfXNgeO#|Y8HWaJ8dnE*Me`~>C`Y?wMff*bWgD`s6vYC63fvhMla^BniL*xb zDx_8i=xPOIMBh?u95*OCRE%5!Qygs~cGg*{?H6x| ze$DS_76;a_?duMJXN z9k>9SWf0vonzUovKUKNNGcZ*s=5@ne2Iier7Czxprp0%xO3Sc4!>%PNZI)Khh#`i8 zhnDq(T*cZX<|j>!!9{73h|I}t{h^V=w7}wGpWaj|$JA$zRV)f_ugr*pm`(%%M_hqc z_cbzdu@3eid8~`lAuYu!wrWZ%nyy*T9YGxtCwdSl-qkx+0ub0Q0}6NP>m94w2@ZA& z5+5PbLGW&foxekw%sh=@Yjid!nD!YK+&Z&K&Q1q_42{Mg^vTr9F10}aDPRCdcWA$n zXhkYl{u%0U;8IFF0kjEaQ}G>Z>RgQ>f_Vp0J8W?<4o%Ummnplw9hfE;TTsxIl;YQ+4N~pc z3E*Oog#bf-4iLdbREKos6ekFJGsap01)Rk9v_reV+N;GYO7DDH*Z|xu(D(FPlZr#T zt|NqZc_+MWR$Izot;Jgf(^}NC!RuL?GU*neNgd{mB>fosFkQu8v#K0OWl5n#o(KWMV4? zdw=>iEN-}l3#OcQ*zC-_$KIgr85ogU-PykF0qxh0G|I;#jpH5lnbZJ@L-)vuOpHXK*bgx5Efixj&448Shw&b|GcqwBrjw_Uzo5SI!3m zOLL1$7w69hLyL2>3v)~5PtLs&>|LB&T)cRBzC3&R@+U9OmFH((o(m3NnOk^yW`1sd zscar!x_EAG>Eg?ClgZKuhYu710u(53aAxpFcmhARp=OTca=VsVNZDsVZiq>({F5Zg(tlo4mV>AsVtm zw|@>l2lQ;7|0exA96|^BWRO#OrS~vyE`7709%Z3*d47<&+Ucx!$0A(iBz>uqN4yIt z=Uv1h7{9V``O3`snWee%-0QP*SC#;l#o+!c3v-Ke3$M-rLi0;=uP>DWEc@L11Yf_z z!#od{aVYK6-Mla}fA$i(d*w1b`i2OaJ%f`Act<_Vql#aKExJS2|*DFU*}opDvW=W@ayx7v?_o z3h<(|hl3|w#He4In?JvF!Fw4^3JxqS%v>p-nK^5Umgg20E-x$wxtTmYDtF3+4L+5x_E=kV^_*)ptx<;B?xb1%=8Mn16!2+SqP|y_E~6yB z9^{l{MhC8PF8j4X^o{?9@JDhc#N!HRLI+O5Es~1tRv!LZM7?aKoW!+3Z<-F8Myi>< zHHdqIos5&YopiEJ?gJq+x6)f6Ehu+kD-AM}-O9+XSGO|wmD|eUSKhk{syT2waVysv z@8s78*M_#>(DAoA!*u9;Ho28U*#gRpY~eSqM;*}F@-EyN!+Cd|zxK#+FQ2UKt+Ukl zD(~-;`}^hkfLtGx;~}|oSg!Ar;}Iv(xqme&?>-<;AC&t=xqe8lk9Hou%~~IE@;E-) zc}#vC!#5{>0G=?MC-Ikc1`i-&2Um~7?UYU?I!~+}$FCF8`X_|c7Umh4U?8uxv|!M( zX-$ZQ4t6KCBrobloaX8$Mh5>T$v=q$?$@q0z&#t?*I|-^Qf>LCsYP3^#Gu`z6_qS^ z83ts8NPuzAgd&Q(K?f{te5xi0CsXITV<%tWGcov3l6ujr@cXGC52aS3If6kO$uT+Q z?Z(p}Z%n-29DXWFe~u4!^>ii}(KnRTiP!{CL^wkc4q`eZieZpygP5@)LALIr3&GH< z3=&Y`EeJ|LH8A6=vcuxgSF&4>)8~P5qfIkJFsv*KqCp13>ZbZJYWpD)3?c(u#@LjV zgB#RzPwaP@>SAz^<04T8y`{&MOW1NVTAuyju)Z5}_=?Nc5B7?iz2}AfjL~4=M$i32 z_CBaPIw>(4>Kg~xCNV7{kOZ7q$CCKLK0eS~M7}8<^(Htp_gPFel|^1Wh%l2zgWOL( z6L~VUjA1~81|qP6v9kS9ZhNpvcvm?51FT+xhMLuN?|I%L4hQ4q9tbgTsI>cP)o0)h zZ6F#e3a}@LJ%k>W(wGm-vn602_70)8QhsKA{k+%SK-d)VbaF_E8XZ0x*7XsAygD1O z#=|lX>nw24VvrHqwTZ*4u?&Tp9#O@+ihGNooBr##NM!QKR5FkM;BCi$nN&WR!CHv8%E<`%9mWJ$?GqRr|IhSMD3`-X+yh?0yo#V8!i)PS5d_=6I;C)m= zREo@$2R|POljri3>6!W74c<+uG3f(NM4C~&ihamGhF}CIE$t)^CCF!Qr*9!N$4P@{PB;k8>15WjYdJX%Y(ba@=gk~K z2lzg^k*$`2f=fG_!9eB3>4L#EE(6iPCB#OQCaYbE#fT4$@e8_?m{`OwvWgHyTA0P# z$Wq=$OFQqvcqQt;J%(HQ$4n!{At5b6MdDX=5F*#8ZYm=l!hu@0HOkG@QtI0s`**Qp z?06UeQTpHp^1M21hhcS4ViA4WT2(l$+%BQ}>yBp8BH0`Po=y^`VtHP zAE`10X}GF_0p@0AlS>J>kPmZco^Sb zrP5C!s8r(qYdcWtUD)+%jGGc%!8jaOp;|W(OjxYKJ_A1;f?KUU0!ZM=_pN1`sMBv4 ztZlsLkFm1m;mtdtbtX zURd7`?jdGnD=4&EA=EEhpyxHvA2vY0!&?^mr0G;z1kIOmLFjvjd8Fd9mI5)AUm%+4 zFHS>M;q&R(bNRKX>?E0H_Eu8aMs6oFC|yq6LPX?Z;!}x*#On!%95Yk>2FUA-4FaIF z2%MX`B%)-+1hdd~C5Ekto-H&lv^g0=Tzot+Bp^(vl_$SLiOJZ$B2|GihlAMTEfeCd zgjhobO{B;KLLMQQAwF8ZVB)iteT&oW0=+|i8$mPL@f!<3Ux53KDvoxGn!Vg z%hq?f-3M#l(qn$QX1){{rIAnxelE*@FG}$dEq*ui(b_2~Mh+43ll!$j6$c^sQ-$;2X!ujm4G-#micJY&_cq>q2h-%BEl9~+St8TjU8<$_S^vgHZKB=x z1s`M9Lo#JF(%R->t|!Zh;y0vo#{1gg5`_y8mx3x3MVl$LPm#FUZ^W%DvxtsT(b%EC zySIhh-mv{1=pIo0-d4tnm?TB~lfhz~D+de2Bk93fu?F)ijvysCrX?CYS#>bJujmLa zH8#>WMGYddG)(pcjx>P$7O`dTJh7DHbx<6bvK7}Nm038$nyWN(1Z5jpjS~-?f4RI~Ndj}PMhBzWp!(a~L7$pDQ z3R5EX20KTHA6fhfj!ff%D5 zlMQ97SUZ+j@)(aG^BtCTCCHk_D~MuhF|YxWwGNkH*pkEr0s0oa5lk>5Uvx5x3j^E> zVzqdUAg}g%jBHgLRIwbPRW{;JW06IpO6WagAO%8Kh?fle)A4eg&8jAG_uTUwpAYh; z|3MmyL%M?}%x_S3uFeqYJR*i?*0B6Y$h{u^AP12J3k6CA?KKh$Qjc8YT|-r0u!El; zg~$j(e!m+09W7Sga*as9e>_`loek?GI>|K*J%%|0wGPBW6N;~6pf4jhk-jYxpBPT! z$T%@nOgByS}}<+y$mpWB9k+&3868FJhZP(b9KPB&`7%XlyS|r zhpR&9f5ws)*b^B_2_%C+U~9VJA@mSpQaEdM0EX$&_Q(zMgklqLsm9e$kq=Tgt%uqi zF(&rU-&j_*A_{t`x4Y)S^h@}}k>!`gaqE7&igsAecZgj7uGk6C^+)IFjQ zt$)E7!69*)#UCQpLxOV)q-HC5ZNNJMY!ku*8wk$0a|w6SP8z0%4AjIk<`;-l>V-s$ z=51gnuW^-CtA@Tn;+0ys>{e zm))z?>veK&J1zQ2EYJ3Nstgq>G%SpiBEDBDk+p;3JtWscd^2b)3~MIej>g1WmNDJoR6$HF-+x^f1}B<)DVt2SZY(rOoqpNs*vnHpyumNGPs?w zm>3CEt7a^xE=7dfT#=WoeywNLaFDt3O$$vLe}edBtfJDDx5t_ct?%7X+MpJTwe(_sPEdS<(dF}x3J+i1op_A_B?-0%ebN8T{lG}?|osPp{ z<#mc^T0$={FTqw4)_QoR0q=bGr;J%Is?u5t$;lLIKv*5a_&hUh#kp#+%c$(4cTI6w zK?{14SuI2{n!234a~$%CGS{jQw|gGI`K51Vr>=IIjc;Xm!to}qb5l2Y4_=zTiJp2t z$HUL_@C!J=en8)@PnpXYR`ZnC*`glt#rry5_#X*ongJ3ynyHOoyaQRc5T{$v3dQ6b z5GH`ruv@1n97|k5QpA!pb);JvL>8#uh%8u3T+4Z9I$6=O6I<|!+)h!eTFW8IAba!R zR_bix?Xg=q+!;Wu0my1H@y?akIFbWfS^iS9r@9x7e?`(U2t}~q2TP=@Qz5Y!$+*yh z;o^$GLf@z}UjxX6LQdmoX))0RWmj40%T-5`GXSesWcioK8e9zxiGd`@e9+cnJ`9=l z27IoRUAZPiuRu1%S(~&kbj3pPYlY$Hs2*`fXbNWEd|T8-1oZNYsL(3@r>34$>($x_ z(yt?Hgfj1iR38!r-!WekjZnw#X{rt{3vHHIBiGv^+a;{wh9WAut3qRxR;Fz0bMlGp z*WAqrVr%hSSF2P8^9}TYLE5rTy^2Ky%1;I1Uq(_^w8^q;+XOR4<_z#aDCDXNk8RmD zmh+Q&@6P}yy@zlJ(w+9YNHxKrDn_WcaXWG6e^8UJx_L#*EI84}TorpzuMLavmO`F%d(?GG@B%@UCSaX}r$A zS^W8r+xiXpN`@T4D;j)={ZsZtsr7Eu)9 z9wk!mvpmS4>3~FfGlD@|eeb~R5etvB$&5(~u(U3u0!G8|nC(St#1#G`#T&*SL*D$a z;a~$cvvfp=*Y}{4f!_|EU|5H)U|3R478DV2RNf^AM^L>>o%B|2E#u_Cky6e8C?8a^ zR>sML{y~`o#asqmMCd168o8~^+JHkfEq9yITKq+|PJVUA5$lC-L9t73WxfEK_!`_E z&M@A~YX?Z7`gb9iE^v^9bVQOjV2J}4(jhPuJRd*ZHqMuQYq9I z4EMw&6b>pXT+idcy2-_`P+r7hpcnO$!Z6W@Ue;#Ezv)8BLGF+Z7#Ofj15%vMr6Kwb zNiH(vsBA!jmGMugh8YT=o=#2fJIr{B`1ou%y=Qy&Agl&(vHwqG2=uHH(BdQb{B4|vP5fq4`Hkp;}j~ztR zL#du}AG#woVBD9h4i~CztgBQe=$z4u2puIL+PXw(Gg=suQ#BEj?o3yJL;f`?=kgoI zI;@#Qm+R|Xrz&#^Ak?3T^bqtgw*2>#ge8XgWoSF0YJ+JYGO_)qFjG-#fSOv^>=2CsFRTcix4WkMIDL5GM z-pSkXvBpqw>1@nsbSnDYB>>M@Fo}&MOAP7fYDXGwxzL;du2dp{+UTN@iXxxWBH2}} zs8sS8uS8J+JQ~Q1fZ5n?O%ZHrCJ300otl#WjtShNO#_7WKQ)pep{!m?`^O0OnbwltSZ` z@umM4r5=FUtdQ;pQAmbJ0AT?Ov3ZBOFcraswzXRDPZm6BrBKf&w9C+JDI&ByeA~cS zofnb8F2<|Ef*Ls57N+2%e-Pn;k>E}=tSgGiE+Q+O>oqok`2D+rZ@%Vw*San;KpEHq zJz~@&);^t}0V`MKr76CI+NUs+%RXYu8m{8a%=)n7CnGC>!`_)7fT6Ie`R<@a6R!k; z>|4oc31h6k4{K(rK$d0bgZgDiz`4o6(pYaJy>FljFSW%p9rK+;R2#zLMz^R@2~{^C!0{kAv(fWg{SG2 zlmnjtLg-UJqOyl&t3L!0aaLRSt59fRMMSDT3WF48gd@f!|8uw<86rE3RY_E_0n@wG zLTY*y2B0D}O(Nj5NNGCo%Vg~!_Jj&9G*L2G=4R04q!ExrR6Z@qA{L>%pw=iKx~?J( z6^^6$jKt1Ul&e%wV9L~dx~RDcYLR$n-Qf^1BVR)MA@HhDG3Nuk(5I)05NkS5<0XL9|#d$MIr;0!@yQC=;ZLA|I3UDVs|iuiII4*hU@~w zQwHeUFKc#Uj1?QLPF*RuP-u)vJ$f7h7{g=oJ}DHBOaaKo5uDQFtztmL(X~CK<__p3!jZ_~7Rz*evk=o+ zL8h>i1dGH^6lcX5sGd(m%1&+vIFPAm;`=9<=I?m%aRL*k$91N^?Jx05EIU<(A_CBG zRj+7fr;F;HsrB~y#L@V}qwx?s*1>-e{#|b(+T!D^deW{snAp~!c$a%7mjX7hC|YF< z&vu-a@%ElRc80+x2=$sm?w0VIBEsmrOz*}+4n}{?U8jhmE^E1(w!bS)x zpmi*nV)1#4*$P$2kbO;V`hG%cif8*E?3X}8L^G~Q8d*OY$i+Y&)c`H{a>jDzSC{L| zd>L&hNQ3dRX}Tl~7`F{61G4}Jqm_jPqVMiJT|y!p0>3}hA_h0~3X>gRs~G$hb;$sc z6PJxZ&on{kH}7LQ9s3MoYGy7;=#Fg;6srTF6*AFsR1DPmi{?nv6lCZ}7UN)uGy1V+2_e2< zP2=uu)dvL$yV3W}I-#Q&lb+G`{xR;o&r#;+CGy=pf^}2T*K2qz|9Ga{J&Qky5)KC# zws(g7C9A)PAzp-iLrr-zLXdAE9jj$A%Hr<>#N=R{BwDku02O`7jyzmYl5RK}=%wpr z;LOhBWb0Go1tt7DGEVy2O3ySMR20ic#}OeO3YVmn(SIf_-@8@^qqK$O-%uEtm0Kh3 zVkAX(7)TVYh}SBmWXK#X9w`BKXGBuZH6~do0ZaZ71{O)Q(F?2|lliD4O(ZNPU`&|E z#=S`N+j#E>EfNhGB#Ks41765Ko{4LML|iFkkVu7)bbrwh2t^m7GXW`=>xv5N*6lR> zwojtPeTRlWL&fg>fe)XH-O#y=Ot6Iw6?=!eaj(5D_>V8HzrJ-ok0f=uQM$q=3sAte3^YR0LLJx3W^^ zg^suwaWB0-?Tp^a!WEhAWNxRt`A*hBSjA_Pog5vLpG$0I&tiU{zHBEaZ{=4Kw^_gX zHOM+{4QvfaysUBw{n*e)Pebz-%749I6e#eQ-<~@ zxJt1swoC`-5CS`7-oXiqFcBnc7{%S;wE{S5@>ZTnEv^l=|6nV>mA;n7(@bZ?8QDsy zSxoEJ+VB>7?a<%7t9l#0+SzuiC9xdUqDkkA>F}CFPQx5g>j3L@?$*%Z07rluavGbx zo&*+_70DGWEAJ^E!5*X{^uf}NZ70MS+``0+%IcUil5rtI7eql4K#mzDJd(`U(4wdvl_XZYnN3%LFbW6a_9;`tX!Bf-(o)F0bNN3pFFk~-+N)#fuVn%$Q=)zRG`}?JO)%qdd1DAjb%jPvR4V7^mMYBkTDfw0 z5m!aGQ=8(Noikw;KMWCS-m!DyR##qFWe(PrLXU#1M_sU9tCML}Di`Kv&Q>bOqTbsU z^Lvp?GKm(#ganbXrUJo&mH3nkYu&LbJuA@!0XL*XEi6$pmqhOd@yu|9&6@XCAg&;z zg2Wg5K^jo%mS@x^Rux``WYaW5}FIHac`Ex;*K z>0I~Rt1&Wy3_KF=4=klIMz7SOrNq4nQJf=gCbgwK)5S-z*^Kv3(cZ~XZy!!U8rEg+ z16+Ae^Kg>)2A8l|l=zE~2E*+HX>0Y6SwPlfn*A z$b<&rFWLG@40B9lsMcPi)w|a!zEHd^nL&NBADQfJhBc+qTzmB5t7XkdX2J z7Y_a(8R>syq=qFM@%Gzdq%ocb@{~Y)i(1h3zO1@%xPBt}erhfGKKL6Wg5OUtB3SR) zClnc$x&IY!37N(9i@YX#hG|pC^uOedF!L>ma4=}e%yamv&ELAmu96dNB4l{BxX^ZE z7m}Lg8~+Et!L|9@KPunLN_`LTTkK`xAOhr-|3~S+mX?!_n?Erbk(ML4MNx7XK}gBF z{~|`lx%-YXSb=g|X&S_r?9=MzX1wOqZW?_Ft0_HkOp7H`=1w2&To>u5pKD@!R2MlK zs-AuImZ*ARK4_VQMG+d72^v8W<$ih}BG3B?+BaznL+WE;-#8HofD1%}o}u?RROjtL zfX8+pQlgIe@{XgfgYu=)aKNKq;aJN@U$7q-9!;BUdFBJQM-;W#qgnj<=Ww89kK0pn zSHvyYd2c0KSX6{99AO8hJqEJ76e23BM#m;*Fn4k17y)&0m^OYJO3 zkC^yHG=hl!ZNp`NB3j#kHVyZf&-EoDIz5Tjc)M`mPMAiC4+iJVR;-@SE!)kH+(-ylpi#iM=1~y-;c#Mr$m7Reh<0IfvCGyz* zq0qu?wv2*!A6=mhas#6>6>I2>KtW_f#QFiP&bJWr08PZMpF>_53t^fHI93|BfY(?T zA$rMn3@*y{z!AfmjGyc=R;dsa6>h}<1EO?>wd(a@)^UO{*OpxAqiu!3rN~O!$kL-5 z+>OhA0j?|hV${O-NMl0#A(Xk^opxj_UqRQ5T~;&pc%n}lYGoa|n0VSqjJYk+dFLSl zeBpO zlz_ll4Rqs3W2K^C_qGo8laW4eMHprk(&ivR4&A}K$w~h=8Y$A25{y%x+z>%rWa2`! zvN!G5o`ArlgH)mgY7~_Ck7oixgeC$4E;5Kc5QPw;0%x`ofPQr*vJZ{a!*piY*CP~= zLC84w`%!-jek=DYJOnipR|G70)%xny4hWDW^g&fHq6h}Gz_RRHwjQx%-1GdQAo~aC znF-Diz=>W%6+?+q0>b_Mhx*SFm=rD(113vP|AN;0$|ax#tN`@_E+C0wxjSUcgWR7R z8KK~YG(zKB z?iRq<^K2VtVp&P6v$gcX={X~L_Pnve?XnuOCdWSMzQ?3wy*4dFyoGB-S18&LlyhUh6-dN;(N#!9n z@3$Ebb|45JQfU5eP@tIFN!6mC^-$Avvs#>)t6=>Ojps%z4YxHD{f|)Pd{o7wiF)O( z&cI^FSl%(-X<9I+`U~M=Ff?t^d3F$HAJSq9WFAu)`0j+iP3qP%xBuq!^ob|m4uvJn z8rTZO4U|a?(c)2Mwr^h|-ws<5lBMk(voGA48EktoQ2Q#x)U)&1uSp@n1z{M;#o!a`p&ik`+qHHANA^k5R|A0x&1 z>q0TiKBI<<2t^U_$GM32hbaEbmSyBk;`lx|^C3ybB6!fZMKTzDe9r`fh5v-e1*_gh zEb2bCuc$ZOiPko1f%u3P*O)xjZ)JogC0v_jaY_*YlD;|^UD0DI_=%?&SJIgPm$*7r zbL$Ot<-g-~@X5)^;uFOuw|$uv$=4r6O=!WXel1`j-3nRi-qVa|1MQ=J>dKQ5Mf~0f zVV^OwUtp{3KWlIKlOTh;V<^ow-JJ;jjwMJWf{!Uvp``(=o!+viZ1aNPk z?|mEO?~m?4{-g^Zn)vap{-p2ULxeGeG03vnzW4uv;N6uf{t*iO_m(OSnfTppDD)v| z;;-MU7=_G5vRDhN=hP-yCe56gBKJ%nb$UAU-gk^v7FEoGXZ^d~Ncspj3C0{t6H5&DT?s+K=44GP6DRp0++zqzZA z7^cd6csf+w2jss4DN^-XQFv;HpjJC_y%L#v|4))E^|Y{OD%plvcE$@c@04Z`Q(5c_ zhC+Ei1*&sz^eG8g{$YeZ={<;I^hpntm;z8S&sJV${!yAv5KWz2rT&h!1dMK0nYF5i zB16T9GTRH-I9XFelc8HQ#50YET~ZqoGi`Xa zZ!4*UO@L|T1nmYYNgISDCY(`vu>(V#1t#PmMlQoNN6k@7H7c>2%_<^Mj5I2*Y7rtQ|y0dPYpcf1IJk zKy#-*v$c)|q8br^7p?`MQZzwSKl&fZrl0b@3-Gur+|5pRX3d6#k?yt7AHr%!y}yoz zeym_@4DNN-Y(!>F&!o|#q4GHIFl}HOfgRb*8%gibsUmF%Rp2dJ?E5SEhj3Cq@}wY&8U*e+TCGBQmexlplM6bNJyg~ahTmY z>;kQ%;-N(MRh}*w(9|kT#wPR{>aF{VW zv3ZdV(JAj@^LPihI5JJb4@qAo<#FJZ%uJKQut$JI;i>fv|7y=|#K>A0kt9not)5UkEC1J`-s#Mo2W9q2G|)_PH^brzH3QehSy<6N4`Qj zq9oHs)Pr@N`O#n=$1*UzU1x|C#gM*8CRZ#;QSLRY$nP-E9TuNlZ`Z>BakIP{i^#Zw zg^qdaC`B|l@~BB7J~;m98I#gYng1+FScjRxPW8bcD}G2*(+Fu?>XAN#Qf~V=xHd+%FAt36%R9?FagtIfB)-7=i_t`h z(cF2QvHY0ifI(l(T!nv%O*TEVJwjdeCN|osV=-Z4lLM=L%w`psBtOItY(IeXc32H$ z@PXDUlW#Fvok>b1j$j0F17~!en7X1-pfhGa0x1KaayEEax)ooSpd<4u*aGm5`_u7t zq%t!*285~NNFn%-g4?ZoW)ov(undWsvYg@(aEkrLIHSz6J0zUKW_)^v73nz<6owJU3=i>S`=~-UYHu_khUu+xqUbHdRgzs=Y%LWpZ+l(vg(wh<5j42%(@Ey5zC zc~1!oluyH{Or}hmhZR-C1Vg?c<_!C)t&Ea|E==)=0a@7W3E^VGOt1z@H7i{59m>?? zl;6#naZd`>ey*pIF2=TYza4@c{8Dci)xYSs1@T{-1^guEvgx}7XAs_S>sL1#kc#PC zGf=iO#y~fO)Q(U#%iV1#y(rYuSCU%Ef(>eFYf|ZN1i-qG78D_#OY;9Xj6ZYFFfI^q zrd!`1gRG91iWac&L_vv{A{P6vl)LA(?LdfrNXFZQ)~FM;$0cC8qmV+%O$?JZ$F zI`l{OxnLIevs)SLJi^2T$OaG6rJp0>AhW@3H_l<%Iq4P@S4pA)eP7API)X(8ggC3E zj{o^HKMFC>B=ZP?W7AGT(P%VKgldzRtYl7vTaSoIkiJiZ-DF_-^QdMjn^MPz3DHfMd-aO7_DAUx_pLZ;Z68=_DK8_z; z$|@N+M$H!CL|1{lY)>h7#a=C|9sbS*%tJ1&1$|R7SVp@6#f&Ue#;Qc5YNj5d5*=`o zT0GeaU)3Zh4q6mc)-V>pmXaMv4eRCXHT zFU)rDC@DurwuMw_gQ{P|tFuht1p@?h=H3yAEI3EdB#laplv7r!aA+(T!XeTo%Sy#$ zBXJ*cp7v?_o%G}~od2V6h^1`Ar z3^9=|=!?mpF3i?eB(kz<5|iAU1iQ9UqFs6J_1U>-;)mWELs3U8JwQgyoK4r_$O|m0 zVxMeTnBKD_HzZ;g#o4i~Wl|#?EEZV8kopnghyx%jjHZ#CMq~#l{@m_?d)X-bUfpQG zxDa_oG*k;PyBz}HXnKpyQ`VV8mW@-!0nVXtt-k3m!C))0Ux-?A`pu=#LEya&1YYvq z!torYl83Vj!z3j&o*J23@kpp(FHy8-QvD_;71J&yMlq>CfU#oC$okt$+X;mwMq!w8 z1wT6AAGZ^4rEei`HJB;Za3P1+;Z91g=VG=Z?gNjlPi`j*YKM44)-q`t?n(|JoA2oL zPM*2DwlWg=EpLzxR(}xWLSU`d;!}UuBS=#(jeMM+7NE*hMlTr*@^(ps1-v2{+`Mfj zzU%^0r7d)a@cN$U`nN!OuhzNA0EALtfKJ%H92x~>?pr}lvwH30?MuBXI!S^?G219x zhtPT#{zmj%)03(t%~~V}E_$$DVWRCo&8+~aR<@gMKJG%dJN{GKVg~H(1;!h-&su#())q*+^D}z*LIpoiMSOa2WBTE*3+w$k3 z(PUv@Ki1R@L6CqV6lV|dxB6rA&28As4Wf}x4nm{~KV8dovfQglBE)mv1%>V2+0Hl^l^(loGbvLBz={(CEtRe;DVQZ?Go9V zL2?A6Y22`~QQeGrZu$|}P*_1oF_(5K+xYwve(s^4BQA+f4hh!3e+;$}zzhWLKD(yWHkLd_&Rc;4zBC+t0%R9;}cWnFM2+Uf4$dKJlL+ z!imAr6lOpwhx{9(SYOKh%CKd+w&nJ|W+wpUBdQ1@9~E&y`G}ztM1A~aR*AZpVq7EgLSUgY*(%m@;Hkauhyc^ENnHBc3RY7vVQT zabXF#r*%kSypaUF7y=bBVZTpCuYDVF=B_=>g416AEL)+mE#%AH@i~JuOe^`QUwrdX z|83|NM3H%DAU_Jg23h%}(oCAXkyGrueO^ouG|=I*%76* zYe$q}8ywL>0wCa`>QpCvJH=nP&Nu@|zxf#Nem3c3oNOc8%-v#~y{I6#m&17Ht5ax% z?VzSCWOhvZ>d8(_4t5BG#G}(h2`ALN$C34^maYgZRNV%`oK>$025>buE2Vg*-jy2R zx8bTj+>-ecdVEP(5I6&w)n;;1S(ZSeJlqX4m6=zCM%{3avE^WksNOaUgr&ZMg_F#) zrx1g22;2(;+?vvz!qTE&hkIDE&_%f9w77{dufxz}N!}A=*dXtJ!4SwMCtSmJ4vS>C z794YScAQzxMj4g zqb$Q4ihu}eiK2Tz2zz;3t%r$eqGtiqMj;R~S&y+O?(ohwV}nqVC48EKA@&s|)=7#; z*$`bPYsI}R_8rZ^q2?hIgC^c1eZIxUk-tqmPYtbhWo4S#_v;Ih?ULWj + +
+
+

Console Locked

+

+ The console is locked and needs to be unlocked by entering the PIN. + You can find the PIN printed out on the standard output of your + shell that runs the server. +

+

PIN: + + +

+
+
+ + +''' + +PAGE_HTML = HEADER + u'''\ +

%(exception_type)s

+
+

%(exception)s

+
+

Traceback (most recent call last)

+%(summary)s +
+
+ The debugger caught an exception in your WSGI application. You can now + look at the traceback which led to the error. + If you enable JavaScript you can also use additional features such as code + execution (if the evalex feature is enabled), automatic pasting of the + exceptions and much more. +
+''' + FOOTER + ''' + +''' + +CONSOLE_HTML = HEADER + u'''\ +

Interactive Console

+
+In this console you can execute Python expressions in the context of the +application. The initial namespace was created by the debugger automatically. +
+
The Console requires JavaScript.
+''' + FOOTER + +SUMMARY_HTML = u'''\ +
+ %(title)s +
    %(frames)s
+ %(description)s +
+''' + +FRAME_HTML = u'''\ +
+

File "%(filename)s", + line %(lineno)s, + in %(function_name)s

+
%(lines)s
+
+''' + +SOURCE_LINE_HTML = u'''\ + + %(lineno)s + %(code)s + +''' + + +def render_console_html(secret, evalex_trusted=True): + return CONSOLE_HTML % { + 'evalex': 'true', + 'evalex_trusted': evalex_trusted and 'true' or 'false', + 'console': 'true', + 'title': 'Console', + 'secret': secret, + 'traceback_id': -1 + } + + +def get_current_traceback(ignore_system_exceptions=False, + show_hidden_frames=False, skip=0): + """Get the current exception info as `Traceback` object. Per default + calling this method will reraise system exceptions such as generator exit, + system exit or others. This behavior can be disabled by passing `False` + to the function as first parameter. + """ + exc_type, exc_value, tb = sys.exc_info() + if ignore_system_exceptions and exc_type in system_exceptions: + raise + for x in range_type(skip): + if tb.tb_next is None: + break + tb = tb.tb_next + tb = Traceback(exc_type, exc_value, tb) + if not show_hidden_frames: + tb.filter_hidden_frames() + return tb + + +class Line(object): + """Helper for the source renderer.""" + __slots__ = ('lineno', 'code', 'in_frame', 'current') + + def __init__(self, lineno, code): + self.lineno = lineno + self.code = code + self.in_frame = False + self.current = False + + def classes(self): + rv = ['line'] + if self.in_frame: + rv.append('in-frame') + if self.current: + rv.append('current') + return rv + classes = property(classes) + + def render(self): + return SOURCE_LINE_HTML % { + 'classes': u' '.join(self.classes), + 'lineno': self.lineno, + 'code': escape(self.code) + } + + +class Traceback(object): + """Wraps a traceback.""" + + def __init__(self, exc_type, exc_value, tb): + self.exc_type = exc_type + self.exc_value = exc_value + if not isinstance(exc_type, str): + exception_type = exc_type.__name__ + if exc_type.__module__ not in ('__builtin__', 'exceptions'): + exception_type = exc_type.__module__ + '.' + exception_type + else: + exception_type = exc_type + self.exception_type = exception_type + + # we only add frames to the list that are not hidden. This follows + # the the magic variables as defined by paste.exceptions.collector + self.frames = [] + while tb: + self.frames.append(Frame(exc_type, exc_value, tb)) + tb = tb.tb_next + + def filter_hidden_frames(self): + """Remove the frames according to the paste spec.""" + if not self.frames: + return + + new_frames = [] + hidden = False + for frame in self.frames: + hide = frame.hide + if hide in ('before', 'before_and_this'): + new_frames = [] + hidden = False + if hide == 'before_and_this': + continue + elif hide in ('reset', 'reset_and_this'): + hidden = False + if hide == 'reset_and_this': + continue + elif hide in ('after', 'after_and_this'): + hidden = True + if hide == 'after_and_this': + continue + elif hide or hidden: + continue + new_frames.append(frame) + + # if we only have one frame and that frame is from the codeop + # module, remove it. + if len(new_frames) == 1 and self.frames[0].module == 'codeop': + del self.frames[:] + + # if the last frame is missing something went terrible wrong :( + elif self.frames[-1] in new_frames: + self.frames[:] = new_frames + + def is_syntax_error(self): + """Is it a syntax error?""" + return isinstance(self.exc_value, SyntaxError) + is_syntax_error = property(is_syntax_error) + + def exception(self): + """String representation of the exception.""" + buf = traceback.format_exception_only(self.exc_type, self.exc_value) + rv = ''.join(buf).strip() + return rv.decode('utf-8', 'replace') if PY2 else rv + exception = property(exception) + + def log(self, logfile=None): + """Log the ASCII traceback into a file object.""" + if logfile is None: + logfile = sys.stderr + tb = self.plaintext.rstrip() + u'\n' + if PY2: + tb = tb.encode('utf-8', 'replace') + logfile.write(tb) + + def paste(self): + """Create a paste and return the paste id.""" + data = json.dumps({ + 'description': 'Werkzeug Internal Server Error', + 'public': False, + 'files': { + 'traceback.txt': { + 'content': self.plaintext + } + } + }).encode('utf-8') + try: + from urllib2 import urlopen + except ImportError: + from urllib.request import urlopen + rv = urlopen('https://api.github.com/gists', data=data) + resp = json.loads(rv.read().decode('utf-8')) + rv.close() + return { + 'url': resp['html_url'], + 'id': resp['id'] + } + + def render_summary(self, include_title=True): + """Render the traceback for the interactive console.""" + title = '' + frames = [] + classes = ['traceback'] + if not self.frames: + classes.append('noframe-traceback') + + if include_title: + if self.is_syntax_error: + title = u'Syntax Error' + else: + title = u'Traceback (most recent call last):' + + for frame in self.frames: + frames.append(u'%s' % ( + frame.info and u' title="%s"' % escape(frame.info) or u'', + frame.render() + )) + + if self.is_syntax_error: + description_wrapper = u'
%s
' + else: + description_wrapper = u'
%s
' + + return SUMMARY_HTML % { + 'classes': u' '.join(classes), + 'title': title and u'

%s

' % title or u'', + 'frames': u'\n'.join(frames), + 'description': description_wrapper % escape(self.exception) + } + + def render_full(self, evalex=False, secret=None, + evalex_trusted=True): + """Render the Full HTML page with the traceback info.""" + exc = escape(self.exception) + return PAGE_HTML % { + 'evalex': evalex and 'true' or 'false', + 'evalex_trusted': evalex_trusted and 'true' or 'false', + 'console': 'false', + 'title': exc, + 'exception': exc, + 'exception_type': escape(self.exception_type), + 'summary': self.render_summary(include_title=False), + 'plaintext': escape(self.plaintext), + 'plaintext_cs': re.sub('-{2,}', '-', self.plaintext), + 'traceback_id': self.id, + 'secret': secret + } + + def generate_plaintext_traceback(self): + """Like the plaintext attribute but returns a generator""" + yield u'Traceback (most recent call last):' + for frame in self.frames: + yield u' File "%s", line %s, in %s' % ( + frame.filename, + frame.lineno, + frame.function_name + ) + yield u' ' + frame.current_line.strip() + yield self.exception + + def plaintext(self): + return u'\n'.join(self.generate_plaintext_traceback()) + plaintext = cached_property(plaintext) + + id = property(lambda x: id(x)) + + +class Frame(object): + + """A single frame in a traceback.""" + + def __init__(self, exc_type, exc_value, tb): + self.lineno = tb.tb_lineno + self.function_name = tb.tb_frame.f_code.co_name + self.locals = tb.tb_frame.f_locals + self.globals = tb.tb_frame.f_globals + + fn = inspect.getsourcefile(tb) or inspect.getfile(tb) + if fn[-4:] in ('.pyo', '.pyc'): + fn = fn[:-1] + # if it's a file on the file system resolve the real filename. + if os.path.isfile(fn): + fn = os.path.realpath(fn) + self.filename = to_unicode(fn, get_filesystem_encoding()) + self.module = self.globals.get('__name__') + self.loader = self.globals.get('__loader__') + self.code = tb.tb_frame.f_code + + # support for paste's traceback extensions + self.hide = self.locals.get('__traceback_hide__', False) + info = self.locals.get('__traceback_info__') + if info is not None: + try: + info = text_type(info) + except UnicodeError: + info = str(info).decode('utf-8', 'replace') + self.info = info + + def render(self): + """Render a single frame in a traceback.""" + return FRAME_HTML % { + 'id': self.id, + 'filename': escape(self.filename), + 'lineno': self.lineno, + 'function_name': escape(self.function_name), + 'lines': self.render_line_context(), + } + + def render_line_context(self): + before, current, after = self.get_context_lines() + rv = [] + + def render_line(line, cls): + line = line.expandtabs().rstrip() + stripped_line = line.strip() + prefix = len(line) - len(stripped_line) + rv.append( + '
%s%s
' % ( + cls, ' ' * prefix, escape(stripped_line) or ' ')) + + for line in before: + render_line(line, 'before') + render_line(current, 'current') + for line in after: + render_line(line, 'after') + + return '\n'.join(rv) + + def get_annotated_lines(self): + """Helper function that returns lines with extra information.""" + lines = [Line(idx + 1, x) for idx, x in enumerate(self.sourcelines)] + + # find function definition and mark lines + if hasattr(self.code, 'co_firstlineno'): + lineno = self.code.co_firstlineno - 1 + while lineno > 0: + if _funcdef_re.match(lines[lineno].code): + break + lineno -= 1 + try: + offset = len(inspect.getblock([x.code + '\n' for x + in lines[lineno:]])) + except TokenError: + offset = 0 + for line in lines[lineno:lineno + offset]: + line.in_frame = True + + # mark current line + try: + lines[self.lineno - 1].current = True + except IndexError: + pass + + return lines + + def eval(self, code, mode='single'): + """Evaluate code in the context of the frame.""" + if isinstance(code, string_types): + if PY2 and isinstance(code, unicode): # noqa + code = UTF8_COOKIE + code.encode('utf-8') + code = compile(code, '', mode) + return eval(code, self.globals, self.locals) + + @cached_property + def sourcelines(self): + """The sourcecode of the file as list of unicode strings.""" + # get sourcecode from loader or file + source = None + if self.loader is not None: + try: + if hasattr(self.loader, 'get_source'): + source = self.loader.get_source(self.module) + elif hasattr(self.loader, 'get_source_by_code'): + source = self.loader.get_source_by_code(self.code) + except Exception: + # we munch the exception so that we don't cause troubles + # if the loader is broken. + pass + + if source is None: + try: + f = open(to_native(self.filename, get_filesystem_encoding()), + mode='rb') + except IOError: + return [] + try: + source = f.read() + finally: + f.close() + + # already unicode? return right away + if isinstance(source, text_type): + return source.splitlines() + + # yes. it should be ascii, but we don't want to reject too many + # characters in the debugger if something breaks + charset = 'utf-8' + if source.startswith(UTF8_COOKIE): + source = source[3:] + else: + for idx, match in enumerate(_line_re.finditer(source)): + match = _coding_re.search(match.group()) + if match is not None: + charset = match.group(1) + break + if idx > 1: + break + + # on broken cookies we fall back to utf-8 too + charset = to_native(charset) + try: + codecs.lookup(charset) + except LookupError: + charset = 'utf-8' + + return source.decode(charset, 'replace').splitlines() + + def get_context_lines(self, context=5): + before = self.sourcelines[self.lineno - context - 1:self.lineno - 1] + past = self.sourcelines[self.lineno:self.lineno + context] + return ( + before, + self.current_line, + past, + ) + + @property + def current_line(self): + try: + return self.sourcelines[self.lineno - 1] + except IndexError: + return u'' + + @cached_property + def console(self): + return Console(self.globals, self.locals) + + id = property(lambda x: id(x)) diff --git a/flex/lib/python3.6/site-packages/werkzeug/exceptions.py b/flex/lib/python3.6/site-packages/werkzeug/exceptions.py new file mode 100644 index 0000000..1d68185 --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/exceptions.py @@ -0,0 +1,719 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.exceptions + ~~~~~~~~~~~~~~~~~~~ + + This module implements a number of Python exceptions you can raise from + within your views to trigger a standard non-200 response. + + + Usage Example + ------------- + + :: + + from werkzeug.wrappers import BaseRequest + from werkzeug.wsgi import responder + from werkzeug.exceptions import HTTPException, NotFound + + def view(request): + raise NotFound() + + @responder + def application(environ, start_response): + request = BaseRequest(environ) + try: + return view(request) + except HTTPException as e: + return e + + + As you can see from this example those exceptions are callable WSGI + applications. Because of Python 2.4 compatibility those do not extend + from the response objects but only from the python exception class. + + As a matter of fact they are not Werkzeug response objects. However you + can get a response object by calling ``get_response()`` on a HTTP + exception. + + Keep in mind that you have to pass an environment to ``get_response()`` + because some errors fetch additional information from the WSGI + environment. + + If you want to hook in a different exception page to say, a 404 status + code, you can add a second except for a specific subclass of an error:: + + @responder + def application(environ, start_response): + request = BaseRequest(environ) + try: + return view(request) + except NotFound, e: + return not_found(request) + except HTTPException, e: + return e + + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import sys + +# Because of bootstrapping reasons we need to manually patch ourselves +# onto our parent module. +import werkzeug +werkzeug.exceptions = sys.modules[__name__] + +from werkzeug._internal import _get_environ +from werkzeug._compat import iteritems, integer_types, text_type, \ + implements_to_string + +from werkzeug.wrappers import Response + + +@implements_to_string +class HTTPException(Exception): + + """ + Baseclass for all HTTP exceptions. This exception can be called as WSGI + application to render a default error page or you can catch the subclasses + of it independently and render nicer error messages. + """ + + code = None + description = None + + def __init__(self, description=None, response=None): + Exception.__init__(self) + if description is not None: + self.description = description + self.response = response + + @classmethod + def wrap(cls, exception, name=None): + """This method returns a new subclass of the exception provided that + also is a subclass of `BadRequest`. + """ + class newcls(cls, exception): + + def __init__(self, arg=None, *args, **kwargs): + cls.__init__(self, *args, **kwargs) + exception.__init__(self, arg) + newcls.__module__ = sys._getframe(1).f_globals.get('__name__') + newcls.__name__ = name or cls.__name__ + exception.__name__ + return newcls + + @property + def name(self): + """The status name.""" + return HTTP_STATUS_CODES.get(self.code, 'Unknown Error') + + def get_description(self, environ=None): + """Get the description.""" + return u'

%s

' % escape(self.description) + + def get_body(self, environ=None): + """Get the HTML body.""" + return text_type(( + u'\n' + u'%(code)s %(name)s\n' + u'

%(name)s

\n' + u'%(description)s\n' + ) % { + 'code': self.code, + 'name': escape(self.name), + 'description': self.get_description(environ) + }) + + def get_headers(self, environ=None): + """Get a list of headers.""" + return [('Content-Type', 'text/html')] + + def get_response(self, environ=None): + """Get a response object. If one was passed to the exception + it's returned directly. + + :param environ: the optional environ for the request. This + can be used to modify the response depending + on how the request looked like. + :return: a :class:`Response` object or a subclass thereof. + """ + if self.response is not None: + return self.response + if environ is not None: + environ = _get_environ(environ) + headers = self.get_headers(environ) + return Response(self.get_body(environ), self.code, headers) + + def __call__(self, environ, start_response): + """Call the exception as WSGI application. + + :param environ: the WSGI environment. + :param start_response: the response callable provided by the WSGI + server. + """ + response = self.get_response(environ) + return response(environ, start_response) + + def __str__(self): + code = self.code if self.code is not None else '???' + return '%s %s: %s' % (code, self.name, self.description) + + def __repr__(self): + code = self.code if self.code is not None else '???' + return "<%s '%s: %s'>" % (self.__class__.__name__, code, self.name) + + +class BadRequest(HTTPException): + + """*400* `Bad Request` + + Raise if the browser sends something to the application the application + or server cannot handle. + """ + code = 400 + description = ( + 'The browser (or proxy) sent a request that this server could ' + 'not understand.' + ) + + +class ClientDisconnected(BadRequest): + + """Internal exception that is raised if Werkzeug detects a disconnected + client. Since the client is already gone at that point attempting to + send the error message to the client might not work and might ultimately + result in another exception in the server. Mainly this is here so that + it is silenced by default as far as Werkzeug is concerned. + + Since disconnections cannot be reliably detected and are unspecified + by WSGI to a large extent this might or might not be raised if a client + is gone. + + .. versionadded:: 0.8 + """ + + +class SecurityError(BadRequest): + + """Raised if something triggers a security error. This is otherwise + exactly like a bad request error. + + .. versionadded:: 0.9 + """ + + +class BadHost(BadRequest): + + """Raised if the submitted host is badly formatted. + + .. versionadded:: 0.11.2 + """ + + +class Unauthorized(HTTPException): + + """*401* `Unauthorized` + + Raise if the user is not authorized. Also used if you want to use HTTP + basic auth. + """ + code = 401 + description = ( + 'The server could not verify that you are authorized to access ' + 'the URL requested. You either supplied the wrong credentials (e.g. ' + 'a bad password), or your browser doesn\'t understand how to supply ' + 'the credentials required.' + ) + + +class Forbidden(HTTPException): + + """*403* `Forbidden` + + Raise if the user doesn't have the permission for the requested resource + but was authenticated. + """ + code = 403 + description = ( + 'You don\'t have the permission to access the requested resource. ' + 'It is either read-protected or not readable by the server.' + ) + + +class NotFound(HTTPException): + + """*404* `Not Found` + + Raise if a resource does not exist and never existed. + """ + code = 404 + description = ( + 'The requested URL was not found on the server. ' + 'If you entered the URL manually please check your spelling and ' + 'try again.' + ) + + +class MethodNotAllowed(HTTPException): + + """*405* `Method Not Allowed` + + Raise if the server used a method the resource does not handle. For + example `POST` if the resource is view only. Especially useful for REST. + + The first argument for this exception should be a list of allowed methods. + Strictly speaking the response would be invalid if you don't provide valid + methods in the header which you can do with that list. + """ + code = 405 + description = 'The method is not allowed for the requested URL.' + + def __init__(self, valid_methods=None, description=None): + """Takes an optional list of valid http methods + starting with werkzeug 0.3 the list will be mandatory.""" + HTTPException.__init__(self, description) + self.valid_methods = valid_methods + + def get_headers(self, environ): + headers = HTTPException.get_headers(self, environ) + if self.valid_methods: + headers.append(('Allow', ', '.join(self.valid_methods))) + return headers + + +class NotAcceptable(HTTPException): + + """*406* `Not Acceptable` + + Raise if the server can't return any content conforming to the + `Accept` headers of the client. + """ + code = 406 + + description = ( + 'The resource identified by the request is only capable of ' + 'generating response entities which have content characteristics ' + 'not acceptable according to the accept headers sent in the ' + 'request.' + ) + + +class RequestTimeout(HTTPException): + + """*408* `Request Timeout` + + Raise to signalize a timeout. + """ + code = 408 + description = ( + 'The server closed the network connection because the browser ' + 'didn\'t finish the request within the specified time.' + ) + + +class Conflict(HTTPException): + + """*409* `Conflict` + + Raise to signal that a request cannot be completed because it conflicts + with the current state on the server. + + .. versionadded:: 0.7 + """ + code = 409 + description = ( + 'A conflict happened while processing the request. The resource ' + 'might have been modified while the request was being processed.' + ) + + +class Gone(HTTPException): + + """*410* `Gone` + + Raise if a resource existed previously and went away without new location. + """ + code = 410 + description = ( + 'The requested URL is no longer available on this server and there ' + 'is no forwarding address. If you followed a link from a foreign ' + 'page, please contact the author of this page.' + ) + + +class LengthRequired(HTTPException): + + """*411* `Length Required` + + Raise if the browser submitted data but no ``Content-Length`` header which + is required for the kind of processing the server does. + """ + code = 411 + description = ( + 'A request with this method requires a valid Content-' + 'Length header.' + ) + + +class PreconditionFailed(HTTPException): + + """*412* `Precondition Failed` + + Status code used in combination with ``If-Match``, ``If-None-Match``, or + ``If-Unmodified-Since``. + """ + code = 412 + description = ( + 'The precondition on the request for the URL failed positive ' + 'evaluation.' + ) + + +class RequestEntityTooLarge(HTTPException): + + """*413* `Request Entity Too Large` + + The status code one should return if the data submitted exceeded a given + limit. + """ + code = 413 + description = ( + 'The data value transmitted exceeds the capacity limit.' + ) + + +class RequestURITooLarge(HTTPException): + + """*414* `Request URI Too Large` + + Like *413* but for too long URLs. + """ + code = 414 + description = ( + 'The length of the requested URL exceeds the capacity limit ' + 'for this server. The request cannot be processed.' + ) + + +class UnsupportedMediaType(HTTPException): + + """*415* `Unsupported Media Type` + + The status code returned if the server is unable to handle the media type + the client transmitted. + """ + code = 415 + description = ( + 'The server does not support the media type transmitted in ' + 'the request.' + ) + + +class RequestedRangeNotSatisfiable(HTTPException): + + """*416* `Requested Range Not Satisfiable` + + The client asked for an invalid part of the file. + + .. versionadded:: 0.7 + """ + code = 416 + description = ( + 'The server cannot provide the requested range.' + ) + + def __init__(self, length=None, units="bytes", description=None): + """Takes an optional `Content-Range` header value based on ``length`` + parameter. + """ + HTTPException.__init__(self, description) + self.length = length + self.units = units + + def get_headers(self, environ): + headers = HTTPException.get_headers(self, environ) + if self.length is not None: + headers.append( + ('Content-Range', '%s */%d' % (self.units, self.length))) + return headers + + +class ExpectationFailed(HTTPException): + + """*417* `Expectation Failed` + + The server cannot meet the requirements of the Expect request-header. + + .. versionadded:: 0.7 + """ + code = 417 + description = ( + 'The server could not meet the requirements of the Expect header' + ) + + +class ImATeapot(HTTPException): + + """*418* `I'm a teapot` + + The server should return this if it is a teapot and someone attempted + to brew coffee with it. + + .. versionadded:: 0.7 + """ + code = 418 + description = ( + 'This server is a teapot, not a coffee machine' + ) + + +class UnprocessableEntity(HTTPException): + + """*422* `Unprocessable Entity` + + Used if the request is well formed, but the instructions are otherwise + incorrect. + """ + code = 422 + description = ( + 'The request was well-formed but was unable to be followed ' + 'due to semantic errors.' + ) + + +class Locked(HTTPException): + + """*423* `Locked` + + Used if the resource that is being accessed is locked. + """ + code = 423 + description = ( + 'The resource that is being accessed is locked.' + ) + + +class PreconditionRequired(HTTPException): + + """*428* `Precondition Required` + + The server requires this request to be conditional, typically to prevent + the lost update problem, which is a race condition between two or more + clients attempting to update a resource through PUT or DELETE. By requiring + each client to include a conditional header ("If-Match" or "If-Unmodified- + Since") with the proper value retained from a recent GET request, the + server ensures that each client has at least seen the previous revision of + the resource. + """ + code = 428 + description = ( + 'This request is required to be conditional; try using "If-Match" ' + 'or "If-Unmodified-Since".' + ) + + +class TooManyRequests(HTTPException): + + """*429* `Too Many Requests` + + The server is limiting the rate at which this user receives responses, and + this request exceeds that rate. (The server may use any convenient method + to identify users and their request rates). The server may include a + "Retry-After" header to indicate how long the user should wait before + retrying. + """ + code = 429 + description = ( + 'This user has exceeded an allotted request count. Try again later.' + ) + + +class RequestHeaderFieldsTooLarge(HTTPException): + + """*431* `Request Header Fields Too Large` + + The server refuses to process the request because the header fields are too + large. One or more individual fields may be too large, or the set of all + headers is too large. + """ + code = 431 + description = ( + 'One or more header fields exceeds the maximum size.' + ) + + +class UnavailableForLegalReasons(HTTPException): + + """*451* `Unavailable For Legal Reasons` + + This status code indicates that the server is denying access to the + resource as a consequence of a legal demand. + """ + code = 451 + description = ( + 'Unavailable for legal reasons.' + ) + + +class InternalServerError(HTTPException): + + """*500* `Internal Server Error` + + Raise if an internal server error occurred. This is a good fallback if an + unknown error occurred in the dispatcher. + """ + code = 500 + description = ( + 'The server encountered an internal error and was unable to ' + 'complete your request. Either the server is overloaded or there ' + 'is an error in the application.' + ) + + +class NotImplemented(HTTPException): + + """*501* `Not Implemented` + + Raise if the application does not support the action requested by the + browser. + """ + code = 501 + description = ( + 'The server does not support the action requested by the ' + 'browser.' + ) + + +class BadGateway(HTTPException): + + """*502* `Bad Gateway` + + If you do proxying in your application you should return this status code + if you received an invalid response from the upstream server it accessed + in attempting to fulfill the request. + """ + code = 502 + description = ( + 'The proxy server received an invalid response from an upstream ' + 'server.' + ) + + +class ServiceUnavailable(HTTPException): + + """*503* `Service Unavailable` + + Status code you should return if a service is temporarily unavailable. + """ + code = 503 + description = ( + 'The server is temporarily unable to service your request due to ' + 'maintenance downtime or capacity problems. Please try again ' + 'later.' + ) + + +class GatewayTimeout(HTTPException): + + """*504* `Gateway Timeout` + + Status code you should return if a connection to an upstream server + times out. + """ + code = 504 + description = ( + 'The connection to an upstream server timed out.' + ) + + +class HTTPVersionNotSupported(HTTPException): + + """*505* `HTTP Version Not Supported` + + The server does not support the HTTP protocol version used in the request. + """ + code = 505 + description = ( + 'The server does not support the HTTP protocol version used in the ' + 'request.' + ) + + +default_exceptions = {} +__all__ = ['HTTPException'] + + +def _find_exceptions(): + for name, obj in iteritems(globals()): + try: + is_http_exception = issubclass(obj, HTTPException) + except TypeError: + is_http_exception = False + if not is_http_exception or obj.code is None: + continue + __all__.append(obj.__name__) + old_obj = default_exceptions.get(obj.code, None) + if old_obj is not None and issubclass(obj, old_obj): + continue + default_exceptions[obj.code] = obj +_find_exceptions() +del _find_exceptions + + +class Aborter(object): + + """ + When passed a dict of code -> exception items it can be used as + callable that raises exceptions. If the first argument to the + callable is an integer it will be looked up in the mapping, if it's + a WSGI application it will be raised in a proxy exception. + + The rest of the arguments are forwarded to the exception constructor. + """ + + def __init__(self, mapping=None, extra=None): + if mapping is None: + mapping = default_exceptions + self.mapping = dict(mapping) + if extra is not None: + self.mapping.update(extra) + + def __call__(self, code, *args, **kwargs): + if not args and not kwargs and not isinstance(code, integer_types): + raise HTTPException(response=code) + if code not in self.mapping: + raise LookupError('no exception for %r' % code) + raise self.mapping[code](*args, **kwargs) + + +def abort(status, *args, **kwargs): + ''' + Raises an :py:exc:`HTTPException` for the given status code or WSGI + application:: + + abort(404) # 404 Not Found + abort(Response('Hello World')) + + Can be passed a WSGI application or a status code. If a status code is + given it's looked up in the list of exceptions and will raise that + exception, if passed a WSGI application it will wrap it in a proxy WSGI + exception and raise that:: + + abort(404) + abort(Response('Hello World')) + + ''' + return _aborter(status, *args, **kwargs) + +_aborter = Aborter() + + +#: an exception that is used internally to signal both a key error and a +#: bad request. Used by a lot of the datastructures. +BadRequestKeyError = BadRequest.wrap(KeyError) + + +# imported here because of circular dependencies of werkzeug.utils +from werkzeug.utils import escape +from werkzeug.http import HTTP_STATUS_CODES diff --git a/flex/lib/python3.6/site-packages/werkzeug/filesystem.py b/flex/lib/python3.6/site-packages/werkzeug/filesystem.py new file mode 100644 index 0000000..6246746 --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/filesystem.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.filesystem + ~~~~~~~~~~~~~~~~~~~ + + Various utilities for the local filesystem. + + :copyright: (c) 2015 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" + +import codecs +import sys +import warnings + +# We do not trust traditional unixes. +has_likely_buggy_unicode_filesystem = \ + sys.platform.startswith('linux') or 'bsd' in sys.platform + + +def _is_ascii_encoding(encoding): + """ + Given an encoding this figures out if the encoding is actually ASCII (which + is something we don't actually want in most cases). This is necessary + because ASCII comes under many names such as ANSI_X3.4-1968. + """ + if encoding is None: + return False + try: + return codecs.lookup(encoding).name == 'ascii' + except LookupError: + return False + + +class BrokenFilesystemWarning(RuntimeWarning, UnicodeWarning): + '''The warning used by Werkzeug to signal a broken filesystem. Will only be + used once per runtime.''' + + +_warned_about_filesystem_encoding = False + + +def get_filesystem_encoding(): + """ + Returns the filesystem encoding that should be used. Note that this is + different from the Python understanding of the filesystem encoding which + might be deeply flawed. Do not use this value against Python's unicode APIs + because it might be different. See :ref:`filesystem-encoding` for the exact + behavior. + + The concept of a filesystem encoding in generally is not something you + should rely on. As such if you ever need to use this function except for + writing wrapper code reconsider. + """ + global _warned_about_filesystem_encoding + rv = sys.getfilesystemencoding() + if has_likely_buggy_unicode_filesystem and not rv \ + or _is_ascii_encoding(rv): + if not _warned_about_filesystem_encoding: + warnings.warn( + 'Detected a misconfigured UNIX filesystem: Will use UTF-8 as ' + 'filesystem encoding instead of {0!r}'.format(rv), + BrokenFilesystemWarning) + _warned_about_filesystem_encoding = True + return 'utf-8' + return rv diff --git a/flex/lib/python3.6/site-packages/werkzeug/formparser.py b/flex/lib/python3.6/site-packages/werkzeug/formparser.py new file mode 100644 index 0000000..c56859e --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/formparser.py @@ -0,0 +1,534 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.formparser + ~~~~~~~~~~~~~~~~~~~ + + This module implements the form parsing. It supports url-encoded forms + as well as non-nested multipart uploads. + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import re +import codecs + +# there are some platforms where SpooledTemporaryFile is not available. +# In that case we need to provide a fallback. +try: + from tempfile import SpooledTemporaryFile +except ImportError: + from tempfile import TemporaryFile + SpooledTemporaryFile = None + +from itertools import chain, repeat, tee +from functools import update_wrapper + +from werkzeug._compat import to_native, text_type, BytesIO +from werkzeug.urls import url_decode_stream +from werkzeug.wsgi import make_line_iter, \ + get_input_stream, get_content_length +from werkzeug.datastructures import Headers, FileStorage, MultiDict +from werkzeug.http import parse_options_header + + +#: an iterator that yields empty strings +_empty_string_iter = repeat('') + +#: a regular expression for multipart boundaries +_multipart_boundary_re = re.compile('^[ -~]{0,200}[!-~]$') + +#: supported http encodings that are also available in python we support +#: for multipart messages. +_supported_multipart_encodings = frozenset(['base64', 'quoted-printable']) + + +def default_stream_factory(total_content_length, filename, content_type, + content_length=None): + """The stream factory that is used per default.""" + max_size = 1024 * 500 + if SpooledTemporaryFile is not None: + return SpooledTemporaryFile(max_size=max_size, mode='wb+') + if total_content_length is None or total_content_length > max_size: + return TemporaryFile('wb+') + return BytesIO() + + +def parse_form_data(environ, stream_factory=None, charset='utf-8', + errors='replace', max_form_memory_size=None, + max_content_length=None, cls=None, + silent=True): + """Parse the form data in the environ and return it as tuple in the form + ``(stream, form, files)``. You should only call this method if the + transport method is `POST`, `PUT`, or `PATCH`. + + If the mimetype of the data transmitted is `multipart/form-data` the + files multidict will be filled with `FileStorage` objects. If the + mimetype is unknown the input stream is wrapped and returned as first + argument, else the stream is empty. + + This is a shortcut for the common usage of :class:`FormDataParser`. + + Have a look at :ref:`dealing-with-request-data` for more details. + + .. versionadded:: 0.5 + The `max_form_memory_size`, `max_content_length` and + `cls` parameters were added. + + .. versionadded:: 0.5.1 + The optional `silent` flag was added. + + :param environ: the WSGI environment to be used for parsing. + :param stream_factory: An optional callable that returns a new read and + writeable file descriptor. This callable works + the same as :meth:`~BaseResponse._get_file_stream`. + :param charset: The character set for URL and url encoded form data. + :param errors: The encoding error behavior. + :param max_form_memory_size: the maximum number of bytes to be accepted for + in-memory stored form data. If the data + exceeds the value specified an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param max_content_length: If this is provided and the transmitted data + is longer than this value an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param cls: an optional dict class to use. If this is not specified + or `None` the default :class:`MultiDict` is used. + :param silent: If set to False parsing errors will not be caught. + :return: A tuple in the form ``(stream, form, files)``. + """ + return FormDataParser(stream_factory, charset, errors, + max_form_memory_size, max_content_length, + cls, silent).parse_from_environ(environ) + + +def exhaust_stream(f): + """Helper decorator for methods that exhausts the stream on return.""" + + def wrapper(self, stream, *args, **kwargs): + try: + return f(self, stream, *args, **kwargs) + finally: + exhaust = getattr(stream, 'exhaust', None) + if exhaust is not None: + exhaust() + else: + while 1: + chunk = stream.read(1024 * 64) + if not chunk: + break + return update_wrapper(wrapper, f) + + +class FormDataParser(object): + + """This class implements parsing of form data for Werkzeug. By itself + it can parse multipart and url encoded form data. It can be subclassed + and extended but for most mimetypes it is a better idea to use the + untouched stream and expose it as separate attributes on a request + object. + + .. versionadded:: 0.8 + + :param stream_factory: An optional callable that returns a new read and + writeable file descriptor. This callable works + the same as :meth:`~BaseResponse._get_file_stream`. + :param charset: The character set for URL and url encoded form data. + :param errors: The encoding error behavior. + :param max_form_memory_size: the maximum number of bytes to be accepted for + in-memory stored form data. If the data + exceeds the value specified an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param max_content_length: If this is provided and the transmitted data + is longer than this value an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param cls: an optional dict class to use. If this is not specified + or `None` the default :class:`MultiDict` is used. + :param silent: If set to False parsing errors will not be caught. + """ + + def __init__(self, stream_factory=None, charset='utf-8', + errors='replace', max_form_memory_size=None, + max_content_length=None, cls=None, + silent=True): + if stream_factory is None: + stream_factory = default_stream_factory + self.stream_factory = stream_factory + self.charset = charset + self.errors = errors + self.max_form_memory_size = max_form_memory_size + self.max_content_length = max_content_length + if cls is None: + cls = MultiDict + self.cls = cls + self.silent = silent + + def get_parse_func(self, mimetype, options): + return self.parse_functions.get(mimetype) + + def parse_from_environ(self, environ): + """Parses the information from the environment as form data. + + :param environ: the WSGI environment to be used for parsing. + :return: A tuple in the form ``(stream, form, files)``. + """ + content_type = environ.get('CONTENT_TYPE', '') + content_length = get_content_length(environ) + mimetype, options = parse_options_header(content_type) + return self.parse(get_input_stream(environ), mimetype, + content_length, options) + + def parse(self, stream, mimetype, content_length, options=None): + """Parses the information from the given stream, mimetype, + content length and mimetype parameters. + + :param stream: an input stream + :param mimetype: the mimetype of the data + :param content_length: the content length of the incoming data + :param options: optional mimetype parameters (used for + the multipart boundary for instance) + :return: A tuple in the form ``(stream, form, files)``. + """ + if self.max_content_length is not None and \ + content_length is not None and \ + content_length > self.max_content_length: + raise exceptions.RequestEntityTooLarge() + if options is None: + options = {} + + parse_func = self.get_parse_func(mimetype, options) + if parse_func is not None: + try: + return parse_func(self, stream, mimetype, + content_length, options) + except ValueError: + if not self.silent: + raise + + return stream, self.cls(), self.cls() + + @exhaust_stream + def _parse_multipart(self, stream, mimetype, content_length, options): + parser = MultiPartParser(self.stream_factory, self.charset, self.errors, + max_form_memory_size=self.max_form_memory_size, + cls=self.cls) + boundary = options.get('boundary') + if boundary is None: + raise ValueError('Missing boundary') + if isinstance(boundary, text_type): + boundary = boundary.encode('ascii') + form, files = parser.parse(stream, boundary, content_length) + return stream, form, files + + @exhaust_stream + def _parse_urlencoded(self, stream, mimetype, content_length, options): + if self.max_form_memory_size is not None and \ + content_length is not None and \ + content_length > self.max_form_memory_size: + raise exceptions.RequestEntityTooLarge() + form = url_decode_stream(stream, self.charset, + errors=self.errors, cls=self.cls) + return stream, form, self.cls() + + #: mapping of mimetypes to parsing functions + parse_functions = { + 'multipart/form-data': _parse_multipart, + 'application/x-www-form-urlencoded': _parse_urlencoded, + 'application/x-url-encoded': _parse_urlencoded + } + + +def is_valid_multipart_boundary(boundary): + """Checks if the string given is a valid multipart boundary.""" + return _multipart_boundary_re.match(boundary) is not None + + +def _line_parse(line): + """Removes line ending characters and returns a tuple (`stripped_line`, + `is_terminated`). + """ + if line[-2:] in ['\r\n', b'\r\n']: + return line[:-2], True + elif line[-1:] in ['\r', '\n', b'\r', b'\n']: + return line[:-1], True + return line, False + + +def parse_multipart_headers(iterable): + """Parses multipart headers from an iterable that yields lines (including + the trailing newline symbol). The iterable has to be newline terminated. + + The iterable will stop at the line where the headers ended so it can be + further consumed. + + :param iterable: iterable of strings that are newline terminated + """ + result = [] + for line in iterable: + line = to_native(line) + line, line_terminated = _line_parse(line) + if not line_terminated: + raise ValueError('unexpected end of line in multipart header') + if not line: + break + elif line[0] in ' \t' and result: + key, value = result[-1] + result[-1] = (key, value + '\n ' + line[1:]) + else: + parts = line.split(':', 1) + if len(parts) == 2: + result.append((parts[0].strip(), parts[1].strip())) + + # we link the list to the headers, no need to create a copy, the + # list was not shared anyways. + return Headers(result) + + +_begin_form = 'begin_form' +_begin_file = 'begin_file' +_cont = 'cont' +_end = 'end' + + +class MultiPartParser(object): + + def __init__(self, stream_factory=None, charset='utf-8', errors='replace', + max_form_memory_size=None, cls=None, buffer_size=64 * 1024): + self.charset = charset + self.errors = errors + self.max_form_memory_size = max_form_memory_size + self.stream_factory = default_stream_factory if stream_factory is None else stream_factory + self.cls = MultiDict if cls is None else cls + + # make sure the buffer size is divisible by four so that we can base64 + # decode chunk by chunk + assert buffer_size % 4 == 0, 'buffer size has to be divisible by 4' + # also the buffer size has to be at least 1024 bytes long or long headers + # will freak out the system + assert buffer_size >= 1024, 'buffer size has to be at least 1KB' + + self.buffer_size = buffer_size + + def _fix_ie_filename(self, filename): + """Internet Explorer 6 transmits the full file name if a file is + uploaded. This function strips the full path if it thinks the + filename is Windows-like absolute. + """ + if filename[1:3] == ':\\' or filename[:2] == '\\\\': + return filename.split('\\')[-1] + return filename + + def _find_terminator(self, iterator): + """The terminator might have some additional newlines before it. + There is at least one application that sends additional newlines + before headers (the python setuptools package). + """ + for line in iterator: + if not line: + break + line = line.strip() + if line: + return line + return b'' + + def fail(self, message): + raise ValueError(message) + + def get_part_encoding(self, headers): + transfer_encoding = headers.get('content-transfer-encoding') + if transfer_encoding is not None and \ + transfer_encoding in _supported_multipart_encodings: + return transfer_encoding + + def get_part_charset(self, headers): + # Figure out input charset for current part + content_type = headers.get('content-type') + if content_type: + mimetype, ct_params = parse_options_header(content_type) + return ct_params.get('charset', self.charset) + return self.charset + + def start_file_streaming(self, filename, headers, total_content_length): + if isinstance(filename, bytes): + filename = filename.decode(self.charset, self.errors) + filename = self._fix_ie_filename(filename) + content_type = headers.get('content-type') + try: + content_length = int(headers['content-length']) + except (KeyError, ValueError): + content_length = 0 + container = self.stream_factory(total_content_length, content_type, + filename, content_length) + return filename, container + + def in_memory_threshold_reached(self, bytes): + raise exceptions.RequestEntityTooLarge() + + def validate_boundary(self, boundary): + if not boundary: + self.fail('Missing boundary') + if not is_valid_multipart_boundary(boundary): + self.fail('Invalid boundary: %s' % boundary) + if len(boundary) > self.buffer_size: # pragma: no cover + # this should never happen because we check for a minimum size + # of 1024 and boundaries may not be longer than 200. The only + # situation when this happens is for non debug builds where + # the assert is skipped. + self.fail('Boundary longer than buffer size') + + def parse_lines(self, file, boundary, content_length, cap_at_buffer=True): + """Generate parts of + ``('begin_form', (headers, name))`` + ``('begin_file', (headers, name, filename))`` + ``('cont', bytestring)`` + ``('end', None)`` + + Always obeys the grammar + parts = ( begin_form cont* end | + begin_file cont* end )* + """ + next_part = b'--' + boundary + last_part = next_part + b'--' + + iterator = chain(make_line_iter(file, limit=content_length, + buffer_size=self.buffer_size, + cap_at_buffer=cap_at_buffer), + _empty_string_iter) + + terminator = self._find_terminator(iterator) + + if terminator == last_part: + return + elif terminator != next_part: + self.fail('Expected boundary at start of multipart data') + + while terminator != last_part: + headers = parse_multipart_headers(iterator) + + disposition = headers.get('content-disposition') + if disposition is None: + self.fail('Missing Content-Disposition header') + disposition, extra = parse_options_header(disposition) + transfer_encoding = self.get_part_encoding(headers) + name = extra.get('name') + + # Accept filename* to support non-ascii filenames as per rfc2231 + filename = extra.get('filename') or extra.get('filename*') + + # if no content type is given we stream into memory. A list is + # used as a temporary container. + if filename is None: + yield _begin_form, (headers, name) + + # otherwise we parse the rest of the headers and ask the stream + # factory for something we can write in. + else: + yield _begin_file, (headers, name, filename) + + buf = b'' + for line in iterator: + if not line: + self.fail('unexpected end of stream') + + if line[:2] == b'--': + terminator = line.rstrip() + if terminator in (next_part, last_part): + break + + if transfer_encoding is not None: + if transfer_encoding == 'base64': + transfer_encoding = 'base64_codec' + try: + line = codecs.decode(line, transfer_encoding) + except Exception: + self.fail('could not decode transfer encoded chunk') + + # we have something in the buffer from the last iteration. + # this is usually a newline delimiter. + if buf: + yield _cont, buf + buf = b'' + + # If the line ends with windows CRLF we write everything except + # the last two bytes. In all other cases however we write + # everything except the last byte. If it was a newline, that's + # fine, otherwise it does not matter because we will write it + # the next iteration. this ensures we do not write the + # final newline into the stream. That way we do not have to + # truncate the stream. However we do have to make sure that + # if something else than a newline is in there we write it + # out. + if line[-2:] == b'\r\n': + buf = b'\r\n' + cutoff = -2 + else: + buf = line[-1:] + cutoff = -1 + yield _cont, line[:cutoff] + + else: # pragma: no cover + raise ValueError('unexpected end of part') + + # if we have a leftover in the buffer that is not a newline + # character we have to flush it, otherwise we will chop of + # certain values. + if buf not in (b'', b'\r', b'\n', b'\r\n'): + yield _cont, buf + + yield _end, None + + def parse_parts(self, file, boundary, content_length): + """Generate ``('file', (name, val))`` and + ``('form', (name, val))`` parts. + """ + in_memory = 0 + + for ellt, ell in self.parse_lines(file, boundary, content_length): + if ellt == _begin_file: + headers, name, filename = ell + is_file = True + guard_memory = False + filename, container = self.start_file_streaming( + filename, headers, content_length) + _write = container.write + + elif ellt == _begin_form: + headers, name = ell + is_file = False + container = [] + _write = container.append + guard_memory = self.max_form_memory_size is not None + + elif ellt == _cont: + _write(ell) + # if we write into memory and there is a memory size limit we + # count the number of bytes in memory and raise an exception if + # there is too much data in memory. + if guard_memory: + in_memory += len(ell) + if in_memory > self.max_form_memory_size: + self.in_memory_threshold_reached(in_memory) + + elif ellt == _end: + if is_file: + container.seek(0) + yield ('file', + (name, FileStorage(container, filename, name, + headers=headers))) + else: + part_charset = self.get_part_charset(headers) + yield ('form', + (name, b''.join(container).decode( + part_charset, self.errors))) + + def parse(self, file, boundary, content_length): + formstream, filestream = tee( + self.parse_parts(file, boundary, content_length), 2) + form = (p[1] for p in formstream if p[0] == 'form') + files = (p[1] for p in filestream if p[0] == 'file') + return self.cls(form), self.cls(files) + + +from werkzeug import exceptions diff --git a/flex/lib/python3.6/site-packages/werkzeug/http.py b/flex/lib/python3.6/site-packages/werkzeug/http.py new file mode 100644 index 0000000..2219722 --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/http.py @@ -0,0 +1,1158 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.http + ~~~~~~~~~~~~~ + + Werkzeug comes with a bunch of utilities that help Werkzeug to deal with + HTTP data. Most of the classes and functions provided by this module are + used by the wrappers, but they are useful on their own, too, especially if + the response and request objects are not used. + + This covers some of the more HTTP centric features of WSGI, some other + utilities such as cookie handling are documented in the `werkzeug.utils` + module. + + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import re +import warnings +from time import time, gmtime +try: + from email.utils import parsedate_tz +except ImportError: # pragma: no cover + from email.Utils import parsedate_tz +try: + from urllib.request import parse_http_list as _parse_list_header + from urllib.parse import unquote_to_bytes as _unquote +except ImportError: # pragma: no cover + from urllib2 import parse_http_list as _parse_list_header, \ + unquote as _unquote +from datetime import datetime, timedelta +from hashlib import md5 +import base64 + +from werkzeug._internal import _cookie_quote, _make_cookie_domain, \ + _cookie_parse_impl +from werkzeug._compat import to_unicode, iteritems, text_type, \ + string_types, try_coerce_native, to_bytes, PY2, \ + integer_types + + +_cookie_charset = 'latin1' +# for explanation of "media-range", etc. see Sections 5.3.{1,2} of RFC 7231 +_accept_re = re.compile( + r'''( # media-range capturing-parenthesis + [^\s;,]+ # type/subtype + (?:[ \t]*;[ \t]* # ";" + (?: # parameter non-capturing-parenthesis + [^\s;,q][^\s;,]* # token that doesn't start with "q" + | # or + q[^\s;,=][^\s;,]* # token that is more than just "q" + ) + )* # zero or more parameters + ) # end of media-range + (?:[ \t]*;[ \t]*q= # weight is a "q" parameter + (\d*(?:\.\d+)?) # qvalue capturing-parentheses + [^,]* # "extension" accept params: who cares? + )? # accept params are optional + ''', re.VERBOSE) +_token_chars = frozenset("!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + '^_`abcdefghijklmnopqrstuvwxyz|~') +_etag_re = re.compile(r'([Ww]/)?(?:"(.*?)"|(.*?))(?:\s*,\s*|$)') +_unsafe_header_chars = set('()<>@,;:\"/[]?={} \t') +_option_header_piece_re = re.compile(r''' + ;\s* + (?P + "[^"\\]*(?:\\.[^"\\]*)*" # quoted string + | + [^\s;,=*]+ # token + ) + \s* + (?: # optionally followed by =value + (?: # equals sign, possibly with encoding + \*\s*=\s* # * indicates extended notation + (?P[^\s]+?) + '(?P[^\s]*?)' + | + =\s* # basic notation + ) + (?P + "[^"\\]*(?:\\.[^"\\]*)*" # quoted string + | + [^;,]+ # token + )? + )? + \s* +''', flags=re.VERBOSE) +_option_header_start_mime_type = re.compile(r',\s*([^;,\s]+)([;,]\s*.+)?') + +_entity_headers = frozenset([ + 'allow', 'content-encoding', 'content-language', 'content-length', + 'content-location', 'content-md5', 'content-range', 'content-type', + 'expires', 'last-modified' +]) +_hop_by_hop_headers = frozenset([ + 'connection', 'keep-alive', 'proxy-authenticate', + 'proxy-authorization', 'te', 'trailer', 'transfer-encoding', + 'upgrade' +]) + + +HTTP_STATUS_CODES = { + 100: 'Continue', + 101: 'Switching Protocols', + 102: 'Processing', + 200: 'OK', + 201: 'Created', + 202: 'Accepted', + 203: 'Non Authoritative Information', + 204: 'No Content', + 205: 'Reset Content', + 206: 'Partial Content', + 207: 'Multi Status', + 226: 'IM Used', # see RFC 3229 + 300: 'Multiple Choices', + 301: 'Moved Permanently', + 302: 'Found', + 303: 'See Other', + 304: 'Not Modified', + 305: 'Use Proxy', + 307: 'Temporary Redirect', + 400: 'Bad Request', + 401: 'Unauthorized', + 402: 'Payment Required', # unused + 403: 'Forbidden', + 404: 'Not Found', + 405: 'Method Not Allowed', + 406: 'Not Acceptable', + 407: 'Proxy Authentication Required', + 408: 'Request Timeout', + 409: 'Conflict', + 410: 'Gone', + 411: 'Length Required', + 412: 'Precondition Failed', + 413: 'Request Entity Too Large', + 414: 'Request URI Too Long', + 415: 'Unsupported Media Type', + 416: 'Requested Range Not Satisfiable', + 417: 'Expectation Failed', + 418: 'I\'m a teapot', # see RFC 2324 + 422: 'Unprocessable Entity', + 423: 'Locked', + 424: 'Failed Dependency', + 426: 'Upgrade Required', + 428: 'Precondition Required', # see RFC 6585 + 429: 'Too Many Requests', + 431: 'Request Header Fields Too Large', + 449: 'Retry With', # proprietary MS extension + 451: 'Unavailable For Legal Reasons', + 500: 'Internal Server Error', + 501: 'Not Implemented', + 502: 'Bad Gateway', + 503: 'Service Unavailable', + 504: 'Gateway Timeout', + 505: 'HTTP Version Not Supported', + 507: 'Insufficient Storage', + 510: 'Not Extended' +} + + +def wsgi_to_bytes(data): + """coerce wsgi unicode represented bytes to real ones + + """ + if isinstance(data, bytes): + return data + return data.encode('latin1') # XXX: utf8 fallback? + + +def bytes_to_wsgi(data): + assert isinstance(data, bytes), 'data must be bytes' + if isinstance(data, str): + return data + else: + return data.decode('latin1') + + +def quote_header_value(value, extra_chars='', allow_token=True): + """Quote a header value if necessary. + + .. versionadded:: 0.5 + + :param value: the value to quote. + :param extra_chars: a list of extra characters to skip quoting. + :param allow_token: if this is enabled token values are returned + unchanged. + """ + if isinstance(value, bytes): + value = bytes_to_wsgi(value) + value = str(value) + if allow_token: + token_chars = _token_chars | set(extra_chars) + if set(value).issubset(token_chars): + return value + return '"%s"' % value.replace('\\', '\\\\').replace('"', '\\"') + + +def unquote_header_value(value, is_filename=False): + r"""Unquotes a header value. (Reversal of :func:`quote_header_value`). + This does not use the real unquoting but what browsers are actually + using for quoting. + + .. versionadded:: 0.5 + + :param value: the header value to unquote. + """ + if value and value[0] == value[-1] == '"': + # this is not the real unquoting, but fixing this so that the + # RFC is met will result in bugs with internet explorer and + # probably some other browsers as well. IE for example is + # uploading files with "C:\foo\bar.txt" as filename + value = value[1:-1] + + # if this is a filename and the starting characters look like + # a UNC path, then just return the value without quotes. Using the + # replace sequence below on a UNC path has the effect of turning + # the leading double slash into a single slash and then + # _fix_ie_filename() doesn't work correctly. See #458. + if not is_filename or value[:2] != '\\\\': + return value.replace('\\\\', '\\').replace('\\"', '"') + return value + + +def dump_options_header(header, options): + """The reverse function to :func:`parse_options_header`. + + :param header: the header to dump + :param options: a dict of options to append. + """ + segments = [] + if header is not None: + segments.append(header) + for key, value in iteritems(options): + if value is None: + segments.append(key) + else: + segments.append('%s=%s' % (key, quote_header_value(value))) + return '; '.join(segments) + + +def dump_header(iterable, allow_token=True): + """Dump an HTTP header again. This is the reversal of + :func:`parse_list_header`, :func:`parse_set_header` and + :func:`parse_dict_header`. This also quotes strings that include an + equals sign unless you pass it as dict of key, value pairs. + + >>> dump_header({'foo': 'bar baz'}) + 'foo="bar baz"' + >>> dump_header(('foo', 'bar baz')) + 'foo, "bar baz"' + + :param iterable: the iterable or dict of values to quote. + :param allow_token: if set to `False` tokens as values are disallowed. + See :func:`quote_header_value` for more details. + """ + if isinstance(iterable, dict): + items = [] + for key, value in iteritems(iterable): + if value is None: + items.append(key) + else: + items.append('%s=%s' % ( + key, + quote_header_value(value, allow_token=allow_token) + )) + else: + items = [quote_header_value(x, allow_token=allow_token) + for x in iterable] + return ', '.join(items) + + +def parse_list_header(value): + """Parse lists as described by RFC 2068 Section 2. + + In particular, parse comma-separated lists where the elements of + the list may include quoted-strings. A quoted-string could + contain a comma. A non-quoted string could have quotes in the + middle. Quotes are removed automatically after parsing. + + It basically works like :func:`parse_set_header` just that items + may appear multiple times and case sensitivity is preserved. + + The return value is a standard :class:`list`: + + >>> parse_list_header('token, "quoted value"') + ['token', 'quoted value'] + + To create a header from the :class:`list` again, use the + :func:`dump_header` function. + + :param value: a string with a list header. + :return: :class:`list` + """ + result = [] + for item in _parse_list_header(value): + if item[:1] == item[-1:] == '"': + item = unquote_header_value(item[1:-1]) + result.append(item) + return result + + +def parse_dict_header(value, cls=dict): + """Parse lists of key, value pairs as described by RFC 2068 Section 2 and + convert them into a python dict (or any other mapping object created from + the type with a dict like interface provided by the `cls` argument): + + >>> d = parse_dict_header('foo="is a fish", bar="as well"') + >>> type(d) is dict + True + >>> sorted(d.items()) + [('bar', 'as well'), ('foo', 'is a fish')] + + If there is no value for a key it will be `None`: + + >>> parse_dict_header('key_without_value') + {'key_without_value': None} + + To create a header from the :class:`dict` again, use the + :func:`dump_header` function. + + .. versionchanged:: 0.9 + Added support for `cls` argument. + + :param value: a string with a dict header. + :param cls: callable to use for storage of parsed results. + :return: an instance of `cls` + """ + result = cls() + if not isinstance(value, text_type): + # XXX: validate + value = bytes_to_wsgi(value) + for item in _parse_list_header(value): + if '=' not in item: + result[item] = None + continue + name, value = item.split('=', 1) + if value[:1] == value[-1:] == '"': + value = unquote_header_value(value[1:-1]) + result[name] = value + return result + + +def parse_options_header(value, multiple=False): + """Parse a ``Content-Type`` like header into a tuple with the content + type and the options: + + >>> parse_options_header('text/html; charset=utf8') + ('text/html', {'charset': 'utf8'}) + + This should not be used to parse ``Cache-Control`` like headers that use + a slightly different format. For these headers use the + :func:`parse_dict_header` function. + + .. versionadded:: 0.5 + + :param value: the header to parse. + :param multiple: Whether try to parse and return multiple MIME types + :return: (mimetype, options) or (mimetype, options, mimetype, options, …) + if multiple=True + """ + if not value: + return '', {} + + result = [] + + value = "," + value.replace("\n", ",") + while value: + match = _option_header_start_mime_type.match(value) + if not match: + break + result.append(match.group(1)) # mimetype + options = {} + # Parse options + rest = match.group(2) + while rest: + optmatch = _option_header_piece_re.match(rest) + if not optmatch: + break + option, encoding, _, option_value = optmatch.groups() + option = unquote_header_value(option) + if option_value is not None: + option_value = unquote_header_value( + option_value, + option == 'filename') + if encoding is not None: + option_value = _unquote(option_value).decode(encoding) + options[option] = option_value + rest = rest[optmatch.end():] + result.append(options) + if multiple is False: + return tuple(result) + value = rest + + return tuple(result) if result else ('', {}) + + +def parse_accept_header(value, cls=None): + """Parses an HTTP Accept-* header. This does not implement a complete + valid algorithm but one that supports at least value and quality + extraction. + + Returns a new :class:`Accept` object (basically a list of ``(value, quality)`` + tuples sorted by the quality with some additional accessor methods). + + The second parameter can be a subclass of :class:`Accept` that is created + with the parsed values and returned. + + :param value: the accept header string to be parsed. + :param cls: the wrapper class for the return value (can be + :class:`Accept` or a subclass thereof) + :return: an instance of `cls`. + """ + if cls is None: + cls = Accept + + if not value: + return cls(None) + + result = [] + for match in _accept_re.finditer(value): + quality = match.group(2) + if not quality: + quality = 1 + else: + quality = max(min(float(quality), 1), 0) + result.append((match.group(1), quality)) + return cls(result) + + +def parse_cache_control_header(value, on_update=None, cls=None): + """Parse a cache control header. The RFC differs between response and + request cache control, this method does not. It's your responsibility + to not use the wrong control statements. + + .. versionadded:: 0.5 + The `cls` was added. If not specified an immutable + :class:`~werkzeug.datastructures.RequestCacheControl` is returned. + + :param value: a cache control header to be parsed. + :param on_update: an optional callable that is called every time a value + on the :class:`~werkzeug.datastructures.CacheControl` + object is changed. + :param cls: the class for the returned object. By default + :class:`~werkzeug.datastructures.RequestCacheControl` is used. + :return: a `cls` object. + """ + if cls is None: + cls = RequestCacheControl + if not value: + return cls(None, on_update) + return cls(parse_dict_header(value), on_update) + + +def parse_set_header(value, on_update=None): + """Parse a set-like header and return a + :class:`~werkzeug.datastructures.HeaderSet` object: + + >>> hs = parse_set_header('token, "quoted value"') + + The return value is an object that treats the items case-insensitively + and keeps the order of the items: + + >>> 'TOKEN' in hs + True + >>> hs.index('quoted value') + 1 + >>> hs + HeaderSet(['token', 'quoted value']) + + To create a header from the :class:`HeaderSet` again, use the + :func:`dump_header` function. + + :param value: a set header to be parsed. + :param on_update: an optional callable that is called every time a + value on the :class:`~werkzeug.datastructures.HeaderSet` + object is changed. + :return: a :class:`~werkzeug.datastructures.HeaderSet` + """ + if not value: + return HeaderSet(None, on_update) + return HeaderSet(parse_list_header(value), on_update) + + +def parse_authorization_header(value): + """Parse an HTTP basic/digest authorization header transmitted by the web + browser. The return value is either `None` if the header was invalid or + not given, otherwise an :class:`~werkzeug.datastructures.Authorization` + object. + + :param value: the authorization header to parse. + :return: a :class:`~werkzeug.datastructures.Authorization` object or `None`. + """ + if not value: + return + value = wsgi_to_bytes(value) + try: + auth_type, auth_info = value.split(None, 1) + auth_type = auth_type.lower() + except ValueError: + return + if auth_type == b'basic': + try: + username, password = base64.b64decode(auth_info).split(b':', 1) + except Exception: + return + return Authorization('basic', {'username': bytes_to_wsgi(username), + 'password': bytes_to_wsgi(password)}) + elif auth_type == b'digest': + auth_map = parse_dict_header(auth_info) + for key in 'username', 'realm', 'nonce', 'uri', 'response': + if key not in auth_map: + return + if 'qop' in auth_map: + if not auth_map.get('nc') or not auth_map.get('cnonce'): + return + return Authorization('digest', auth_map) + + +def parse_www_authenticate_header(value, on_update=None): + """Parse an HTTP WWW-Authenticate header into a + :class:`~werkzeug.datastructures.WWWAuthenticate` object. + + :param value: a WWW-Authenticate header to parse. + :param on_update: an optional callable that is called every time a value + on the :class:`~werkzeug.datastructures.WWWAuthenticate` + object is changed. + :return: a :class:`~werkzeug.datastructures.WWWAuthenticate` object. + """ + if not value: + return WWWAuthenticate(on_update=on_update) + try: + auth_type, auth_info = value.split(None, 1) + auth_type = auth_type.lower() + except (ValueError, AttributeError): + return WWWAuthenticate(value.strip().lower(), on_update=on_update) + return WWWAuthenticate(auth_type, parse_dict_header(auth_info), + on_update) + + +def parse_if_range_header(value): + """Parses an if-range header which can be an etag or a date. Returns + a :class:`~werkzeug.datastructures.IfRange` object. + + .. versionadded:: 0.7 + """ + if not value: + return IfRange() + date = parse_date(value) + if date is not None: + return IfRange(date=date) + # drop weakness information + return IfRange(unquote_etag(value)[0]) + + +def parse_range_header(value, make_inclusive=True): + """Parses a range header into a :class:`~werkzeug.datastructures.Range` + object. If the header is missing or malformed `None` is returned. + `ranges` is a list of ``(start, stop)`` tuples where the ranges are + non-inclusive. + + .. versionadded:: 0.7 + """ + if not value or '=' not in value: + return None + + ranges = [] + last_end = 0 + units, rng = value.split('=', 1) + units = units.strip().lower() + + for item in rng.split(','): + item = item.strip() + if '-' not in item: + return None + if item.startswith('-'): + if last_end < 0: + return None + try: + begin = int(item) + except ValueError: + return None + end = None + last_end = -1 + elif '-' in item: + begin, end = item.split('-', 1) + begin = begin.strip() + end = end.strip() + if not begin.isdigit(): + return None + begin = int(begin) + if begin < last_end or last_end < 0: + return None + if end: + if not end.isdigit(): + return None + end = int(end) + 1 + if begin >= end: + return None + else: + end = None + last_end = end + ranges.append((begin, end)) + + return Range(units, ranges) + + +def parse_content_range_header(value, on_update=None): + """Parses a range header into a + :class:`~werkzeug.datastructures.ContentRange` object or `None` if + parsing is not possible. + + .. versionadded:: 0.7 + + :param value: a content range header to be parsed. + :param on_update: an optional callable that is called every time a value + on the :class:`~werkzeug.datastructures.ContentRange` + object is changed. + """ + if value is None: + return None + try: + units, rangedef = (value or '').strip().split(None, 1) + except ValueError: + return None + + if '/' not in rangedef: + return None + rng, length = rangedef.split('/', 1) + if length == '*': + length = None + elif length.isdigit(): + length = int(length) + else: + return None + + if rng == '*': + return ContentRange(units, None, None, length, on_update=on_update) + elif '-' not in rng: + return None + + start, stop = rng.split('-', 1) + try: + start = int(start) + stop = int(stop) + 1 + except ValueError: + return None + + if is_byte_range_valid(start, stop, length): + return ContentRange(units, start, stop, length, on_update=on_update) + + +def quote_etag(etag, weak=False): + """Quote an etag. + + :param etag: the etag to quote. + :param weak: set to `True` to tag it "weak". + """ + if '"' in etag: + raise ValueError('invalid etag') + etag = '"%s"' % etag + if weak: + etag = 'W/' + etag + return etag + + +def unquote_etag(etag): + """Unquote a single etag: + + >>> unquote_etag('W/"bar"') + ('bar', True) + >>> unquote_etag('"bar"') + ('bar', False) + + :param etag: the etag identifier to unquote. + :return: a ``(etag, weak)`` tuple. + """ + if not etag: + return None, None + etag = etag.strip() + weak = False + if etag.startswith(('W/', 'w/')): + weak = True + etag = etag[2:] + if etag[:1] == etag[-1:] == '"': + etag = etag[1:-1] + return etag, weak + + +def parse_etags(value): + """Parse an etag header. + + :param value: the tag header to parse + :return: an :class:`~werkzeug.datastructures.ETags` object. + """ + if not value: + return ETags() + strong = [] + weak = [] + end = len(value) + pos = 0 + while pos < end: + match = _etag_re.match(value, pos) + if match is None: + break + is_weak, quoted, raw = match.groups() + if raw == '*': + return ETags(star_tag=True) + elif quoted: + raw = quoted + if is_weak: + weak.append(raw) + else: + strong.append(raw) + pos = match.end() + return ETags(strong, weak) + + +def generate_etag(data): + """Generate an etag for some data.""" + return md5(data).hexdigest() + + +def parse_date(value): + """Parse one of the following date formats into a datetime object: + + .. sourcecode:: text + + Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 + Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 + Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format + + If parsing fails the return value is `None`. + + :param value: a string with a supported date format. + :return: a :class:`datetime.datetime` object. + """ + if value: + t = parsedate_tz(value.strip()) + if t is not None: + try: + year = t[0] + # unfortunately that function does not tell us if two digit + # years were part of the string, or if they were prefixed + # with two zeroes. So what we do is to assume that 69-99 + # refer to 1900, and everything below to 2000 + if year >= 0 and year <= 68: + year += 2000 + elif year >= 69 and year <= 99: + year += 1900 + return datetime(*((year,) + t[1:7])) - \ + timedelta(seconds=t[-1] or 0) + except (ValueError, OverflowError): + return None + + +def _dump_date(d, delim): + """Used for `http_date` and `cookie_date`.""" + if d is None: + d = gmtime() + elif isinstance(d, datetime): + d = d.utctimetuple() + elif isinstance(d, (integer_types, float)): + d = gmtime(d) + return '%s, %02d%s%s%s%s %02d:%02d:%02d GMT' % ( + ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')[d.tm_wday], + d.tm_mday, delim, + ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec')[d.tm_mon - 1], + delim, str(d.tm_year), d.tm_hour, d.tm_min, d.tm_sec + ) + + +def cookie_date(expires=None): + """Formats the time to ensure compatibility with Netscape's cookie + standard. + + Accepts a floating point number expressed in seconds since the epoch in, a + datetime object or a timetuple. All times in UTC. The :func:`parse_date` + function can be used to parse such a date. + + Outputs a string in the format ``Wdy, DD-Mon-YYYY HH:MM:SS GMT``. + + :param expires: If provided that date is used, otherwise the current. + """ + return _dump_date(expires, '-') + + +def http_date(timestamp=None): + """Formats the time to match the RFC1123 date format. + + Accepts a floating point number expressed in seconds since the epoch in, a + datetime object or a timetuple. All times in UTC. The :func:`parse_date` + function can be used to parse such a date. + + Outputs a string in the format ``Wdy, DD Mon YYYY HH:MM:SS GMT``. + + :param timestamp: If provided that date is used, otherwise the current. + """ + return _dump_date(timestamp, ' ') + + +def parse_age(value=None): + """Parses a base-10 integer count of seconds into a timedelta. + + If parsing fails, the return value is `None`. + + :param value: a string consisting of an integer represented in base-10 + :return: a :class:`datetime.timedelta` object or `None`. + """ + if not value: + return None + try: + seconds = int(value) + except ValueError: + return None + if seconds < 0: + return None + try: + return timedelta(seconds=seconds) + except OverflowError: + return None + + +def dump_age(age=None): + """Formats the duration as a base-10 integer. + + :param age: should be an integer number of seconds, + a :class:`datetime.timedelta` object, or, + if the age is unknown, `None` (default). + """ + if age is None: + return + if isinstance(age, timedelta): + # do the equivalent of Python 2.7's timedelta.total_seconds(), + # but disregarding fractional seconds + age = age.seconds + (age.days * 24 * 3600) + + age = int(age) + if age < 0: + raise ValueError('age cannot be negative') + + return str(age) + + +def is_resource_modified(environ, etag=None, data=None, last_modified=None, + ignore_if_range=True): + """Convenience method for conditional requests. + + :param environ: the WSGI environment of the request to be checked. + :param etag: the etag for the response for comparison. + :param data: or alternatively the data of the response to automatically + generate an etag using :func:`generate_etag`. + :param last_modified: an optional date of the last modification. + :param ignore_if_range: If `False`, `If-Range` header will be taken into + account. + :return: `True` if the resource was modified, otherwise `False`. + """ + if etag is None and data is not None: + etag = generate_etag(data) + elif data is not None: + raise TypeError('both data and etag given') + if environ['REQUEST_METHOD'] not in ('GET', 'HEAD'): + return False + + unmodified = False + if isinstance(last_modified, string_types): + last_modified = parse_date(last_modified) + + # ensure that microsecond is zero because the HTTP spec does not transmit + # that either and we might have some false positives. See issue #39 + if last_modified is not None: + last_modified = last_modified.replace(microsecond=0) + + if_range = None + if not ignore_if_range and 'HTTP_RANGE' in environ: + # http://tools.ietf.org/html/rfc7233#section-3.2 + # A server MUST ignore an If-Range header field received in a request + # that does not contain a Range header field. + if_range = parse_if_range_header(environ.get('HTTP_IF_RANGE')) + + if if_range is not None and if_range.date is not None: + modified_since = if_range.date + else: + modified_since = parse_date(environ.get('HTTP_IF_MODIFIED_SINCE')) + + if modified_since and last_modified and last_modified <= modified_since: + unmodified = True + + if etag: + etag, _ = unquote_etag(etag) + if if_range is not None and if_range.etag is not None: + unmodified = parse_etags(if_range.etag).contains(etag) + else: + if_none_match = parse_etags(environ.get('HTTP_IF_NONE_MATCH')) + if if_none_match: + # http://tools.ietf.org/html/rfc7232#section-3.2 + # "A recipient MUST use the weak comparison function when comparing + # entity-tags for If-None-Match" + unmodified = if_none_match.contains_weak(etag) + + # https://tools.ietf.org/html/rfc7232#section-3.1 + # "Origin server MUST use the strong comparison function when + # comparing entity-tags for If-Match" + if_match = parse_etags(environ.get('HTTP_IF_MATCH')) + if if_match: + unmodified = not if_match.is_strong(etag) + + return not unmodified + + +def remove_entity_headers(headers, allowed=('expires', 'content-location')): + """Remove all entity headers from a list or :class:`Headers` object. This + operation works in-place. `Expires` and `Content-Location` headers are + by default not removed. The reason for this is :rfc:`2616` section + 10.3.5 which specifies some entity headers that should be sent. + + .. versionchanged:: 0.5 + added `allowed` parameter. + + :param headers: a list or :class:`Headers` object. + :param allowed: a list of headers that should still be allowed even though + they are entity headers. + """ + allowed = set(x.lower() for x in allowed) + headers[:] = [(key, value) for key, value in headers if + not is_entity_header(key) or key.lower() in allowed] + + +def remove_hop_by_hop_headers(headers): + """Remove all HTTP/1.1 "Hop-by-Hop" headers from a list or + :class:`Headers` object. This operation works in-place. + + .. versionadded:: 0.5 + + :param headers: a list or :class:`Headers` object. + """ + headers[:] = [(key, value) for key, value in headers if + not is_hop_by_hop_header(key)] + + +def is_entity_header(header): + """Check if a header is an entity header. + + .. versionadded:: 0.5 + + :param header: the header to test. + :return: `True` if it's an entity header, `False` otherwise. + """ + return header.lower() in _entity_headers + + +def is_hop_by_hop_header(header): + """Check if a header is an HTTP/1.1 "Hop-by-Hop" header. + + .. versionadded:: 0.5 + + :param header: the header to test. + :return: `True` if it's an HTTP/1.1 "Hop-by-Hop" header, `False` otherwise. + """ + return header.lower() in _hop_by_hop_headers + + +def parse_cookie(header, charset='utf-8', errors='replace', cls=None): + """Parse a cookie. Either from a string or WSGI environ. + + Per default encoding errors are ignored. If you want a different behavior + you can set `errors` to ``'replace'`` or ``'strict'``. In strict mode a + :exc:`HTTPUnicodeError` is raised. + + .. versionchanged:: 0.5 + This function now returns a :class:`TypeConversionDict` instead of a + regular dict. The `cls` parameter was added. + + :param header: the header to be used to parse the cookie. Alternatively + this can be a WSGI environment. + :param charset: the charset for the cookie values. + :param errors: the error behavior for the charset decoding. + :param cls: an optional dict class to use. If this is not specified + or `None` the default :class:`TypeConversionDict` is + used. + """ + if isinstance(header, dict): + header = header.get('HTTP_COOKIE', '') + elif header is None: + header = '' + + # If the value is an unicode string it's mangled through latin1. This + # is done because on PEP 3333 on Python 3 all headers are assumed latin1 + # which however is incorrect for cookies, which are sent in page encoding. + # As a result we + if isinstance(header, text_type): + header = header.encode('latin1', 'replace') + + if cls is None: + cls = TypeConversionDict + + def _parse_pairs(): + for key, val in _cookie_parse_impl(header): + key = to_unicode(key, charset, errors, allow_none_charset=True) + val = to_unicode(val, charset, errors, allow_none_charset=True) + yield try_coerce_native(key), val + + return cls(_parse_pairs()) + + +def dump_cookie(key, value='', max_age=None, expires=None, path='/', + domain=None, secure=False, httponly=False, + charset='utf-8', sync_expires=True, max_size=4093, + samesite=None): + """Creates a new Set-Cookie header without the ``Set-Cookie`` prefix + The parameters are the same as in the cookie Morsel object in the + Python standard library but it accepts unicode data, too. + + On Python 3 the return value of this function will be a unicode + string, on Python 2 it will be a native string. In both cases the + return value is usually restricted to ascii as the vast majority of + values are properly escaped, but that is no guarantee. If a unicode + string is returned it's tunneled through latin1 as required by + PEP 3333. + + The return value is not ASCII safe if the key contains unicode + characters. This is technically against the specification but + happens in the wild. It's strongly recommended to not use + non-ASCII values for the keys. + + :param max_age: should be a number of seconds, or `None` (default) if + the cookie should last only as long as the client's + browser session. Additionally `timedelta` objects + are accepted, too. + :param expires: should be a `datetime` object or unix timestamp. + :param path: limits the cookie to a given path, per default it will + span the whole domain. + :param domain: Use this if you want to set a cross-domain cookie. For + example, ``domain=".example.com"`` will set a cookie + that is readable by the domain ``www.example.com``, + ``foo.example.com`` etc. Otherwise, a cookie will only + be readable by the domain that set it. + :param secure: The cookie will only be available via HTTPS + :param httponly: disallow JavaScript to access the cookie. This is an + extension to the cookie standard and probably not + supported by all browsers. + :param charset: the encoding for unicode values. + :param sync_expires: automatically set expires if max_age is defined + but expires not. + :param max_size: Warn if the final header value exceeds this size. The + default, 4093, should be safely `supported by most browsers + `_. Set to 0 to disable this check. + :param samesite: Limits the scope of the cookie such that it will only + be attached to requests if those requests are "same-site". + + .. _`cookie`: http://browsercookielimits.squawky.net/ + """ + key = to_bytes(key, charset) + value = to_bytes(value, charset) + + if path is not None: + path = iri_to_uri(path, charset) + domain = _make_cookie_domain(domain) + if isinstance(max_age, timedelta): + max_age = (max_age.days * 60 * 60 * 24) + max_age.seconds + if expires is not None: + if not isinstance(expires, string_types): + expires = cookie_date(expires) + elif max_age is not None and sync_expires: + expires = to_bytes(cookie_date(time() + max_age)) + + samesite = samesite.title() if samesite else None + if samesite not in ('Strict', 'Lax', None): + raise ValueError("invalid SameSite value; must be 'Strict', 'Lax' or None") + + buf = [key + b'=' + _cookie_quote(value)] + + # XXX: In theory all of these parameters that are not marked with `None` + # should be quoted. Because stdlib did not quote it before I did not + # want to introduce quoting there now. + for k, v, q in ((b'Domain', domain, True), + (b'Expires', expires, False,), + (b'Max-Age', max_age, False), + (b'Secure', secure, None), + (b'HttpOnly', httponly, None), + (b'Path', path, False), + (b'SameSite', samesite, False)): + if q is None: + if v: + buf.append(k) + continue + + if v is None: + continue + + tmp = bytearray(k) + if not isinstance(v, (bytes, bytearray)): + v = to_bytes(text_type(v), charset) + if q: + v = _cookie_quote(v) + tmp += b'=' + v + buf.append(bytes(tmp)) + + # The return value will be an incorrectly encoded latin1 header on + # Python 3 for consistency with the headers object and a bytestring + # on Python 2 because that's how the API makes more sense. + rv = b'; '.join(buf) + if not PY2: + rv = rv.decode('latin1') + + # Warn if the final value of the cookie is less than the limit. If the + # cookie is too large, then it may be silently ignored, which can be quite + # hard to debug. + cookie_size = len(rv) + + if max_size and cookie_size > max_size: + value_size = len(value) + warnings.warn( + 'The "{key}" cookie is too large: the value was {value_size} bytes' + ' but the header required {extra_size} extra bytes. The final size' + ' was {cookie_size} bytes but the limit is {max_size} bytes.' + ' Browsers may silently ignore cookies larger than this.'.format( + key=key, + value_size=value_size, + extra_size=cookie_size - value_size, + cookie_size=cookie_size, + max_size=max_size + ), + stacklevel=2 + ) + + return rv + + +def is_byte_range_valid(start, stop, length): + """Checks if a given byte content range is valid for the given length. + + .. versionadded:: 0.7 + """ + if (start is None) != (stop is None): + return False + elif start is None: + return length is None or length >= 0 + elif length is None: + return 0 <= start < stop + elif start >= stop: + return False + return 0 <= start < length + + +# circular dependency fun +from werkzeug.datastructures import Accept, HeaderSet, ETags, Authorization, \ + WWWAuthenticate, TypeConversionDict, IfRange, Range, ContentRange, \ + RequestCacheControl + + +# DEPRECATED +# backwards compatible imports +from werkzeug.datastructures import ( # noqa + MIMEAccept, CharsetAccept, LanguageAccept, Headers +) +from werkzeug.urls import iri_to_uri diff --git a/flex/lib/python3.6/site-packages/werkzeug/local.py b/flex/lib/python3.6/site-packages/werkzeug/local.py new file mode 100644 index 0000000..e6d7478 --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/local.py @@ -0,0 +1,420 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.local + ~~~~~~~~~~~~~~ + + This module implements context-local objects. + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import copy +from functools import update_wrapper +from werkzeug.wsgi import ClosingIterator +from werkzeug._compat import PY2, implements_bool + +# since each thread has its own greenlet we can just use those as identifiers +# for the context. If greenlets are not available we fall back to the +# current thread ident depending on where it is. +try: + from greenlet import getcurrent as get_ident +except ImportError: + try: + from thread import get_ident + except ImportError: + from _thread import get_ident + + +def release_local(local): + """Releases the contents of the local for the current context. + This makes it possible to use locals without a manager. + + Example:: + + >>> loc = Local() + >>> loc.foo = 42 + >>> release_local(loc) + >>> hasattr(loc, 'foo') + False + + With this function one can release :class:`Local` objects as well + as :class:`LocalStack` objects. However it is not possible to + release data held by proxies that way, one always has to retain + a reference to the underlying local object in order to be able + to release it. + + .. versionadded:: 0.6.1 + """ + local.__release_local__() + + +class Local(object): + __slots__ = ('__storage__', '__ident_func__') + + def __init__(self): + object.__setattr__(self, '__storage__', {}) + object.__setattr__(self, '__ident_func__', get_ident) + + def __iter__(self): + return iter(self.__storage__.items()) + + def __call__(self, proxy): + """Create a proxy for a name.""" + return LocalProxy(self, proxy) + + def __release_local__(self): + self.__storage__.pop(self.__ident_func__(), None) + + def __getattr__(self, name): + try: + return self.__storage__[self.__ident_func__()][name] + except KeyError: + raise AttributeError(name) + + def __setattr__(self, name, value): + ident = self.__ident_func__() + storage = self.__storage__ + try: + storage[ident][name] = value + except KeyError: + storage[ident] = {name: value} + + def __delattr__(self, name): + try: + del self.__storage__[self.__ident_func__()][name] + except KeyError: + raise AttributeError(name) + + +class LocalStack(object): + + """This class works similar to a :class:`Local` but keeps a stack + of objects instead. This is best explained with an example:: + + >>> ls = LocalStack() + >>> ls.push(42) + >>> ls.top + 42 + >>> ls.push(23) + >>> ls.top + 23 + >>> ls.pop() + 23 + >>> ls.top + 42 + + They can be force released by using a :class:`LocalManager` or with + the :func:`release_local` function but the correct way is to pop the + item from the stack after using. When the stack is empty it will + no longer be bound to the current context (and as such released). + + By calling the stack without arguments it returns a proxy that resolves to + the topmost item on the stack. + + .. versionadded:: 0.6.1 + """ + + def __init__(self): + self._local = Local() + + def __release_local__(self): + self._local.__release_local__() + + def _get__ident_func__(self): + return self._local.__ident_func__ + + def _set__ident_func__(self, value): + object.__setattr__(self._local, '__ident_func__', value) + __ident_func__ = property(_get__ident_func__, _set__ident_func__) + del _get__ident_func__, _set__ident_func__ + + def __call__(self): + def _lookup(): + rv = self.top + if rv is None: + raise RuntimeError('object unbound') + return rv + return LocalProxy(_lookup) + + def push(self, obj): + """Pushes a new item to the stack""" + rv = getattr(self._local, 'stack', None) + if rv is None: + self._local.stack = rv = [] + rv.append(obj) + return rv + + def pop(self): + """Removes the topmost item from the stack, will return the + old value or `None` if the stack was already empty. + """ + stack = getattr(self._local, 'stack', None) + if stack is None: + return None + elif len(stack) == 1: + release_local(self._local) + return stack[-1] + else: + return stack.pop() + + @property + def top(self): + """The topmost item on the stack. If the stack is empty, + `None` is returned. + """ + try: + return self._local.stack[-1] + except (AttributeError, IndexError): + return None + + +class LocalManager(object): + + """Local objects cannot manage themselves. For that you need a local + manager. You can pass a local manager multiple locals or add them later + by appending them to `manager.locals`. Every time the manager cleans up, + it will clean up all the data left in the locals for this context. + + The `ident_func` parameter can be added to override the default ident + function for the wrapped locals. + + .. versionchanged:: 0.6.1 + Instead of a manager the :func:`release_local` function can be used + as well. + + .. versionchanged:: 0.7 + `ident_func` was added. + """ + + def __init__(self, locals=None, ident_func=None): + if locals is None: + self.locals = [] + elif isinstance(locals, Local): + self.locals = [locals] + else: + self.locals = list(locals) + if ident_func is not None: + self.ident_func = ident_func + for local in self.locals: + object.__setattr__(local, '__ident_func__', ident_func) + else: + self.ident_func = get_ident + + def get_ident(self): + """Return the context identifier the local objects use internally for + this context. You cannot override this method to change the behavior + but use it to link other context local objects (such as SQLAlchemy's + scoped sessions) to the Werkzeug locals. + + .. versionchanged:: 0.7 + You can pass a different ident function to the local manager that + will then be propagated to all the locals passed to the + constructor. + """ + return self.ident_func() + + def cleanup(self): + """Manually clean up the data in the locals for this context. Call + this at the end of the request or use `make_middleware()`. + """ + for local in self.locals: + release_local(local) + + def make_middleware(self, app): + """Wrap a WSGI application so that cleaning up happens after + request end. + """ + def application(environ, start_response): + return ClosingIterator(app(environ, start_response), self.cleanup) + return application + + def middleware(self, func): + """Like `make_middleware` but for decorating functions. + + Example usage:: + + @manager.middleware + def application(environ, start_response): + ... + + The difference to `make_middleware` is that the function passed + will have all the arguments copied from the inner application + (name, docstring, module). + """ + return update_wrapper(self.make_middleware(func), func) + + def __repr__(self): + return '<%s storages: %d>' % ( + self.__class__.__name__, + len(self.locals) + ) + + +@implements_bool +class LocalProxy(object): + + """Acts as a proxy for a werkzeug local. Forwards all operations to + a proxied object. The only operations not supported for forwarding + are right handed operands and any kind of assignment. + + Example usage:: + + from werkzeug.local import Local + l = Local() + + # these are proxies + request = l('request') + user = l('user') + + + from werkzeug.local import LocalStack + _response_local = LocalStack() + + # this is a proxy + response = _response_local() + + Whenever something is bound to l.user / l.request the proxy objects + will forward all operations. If no object is bound a :exc:`RuntimeError` + will be raised. + + To create proxies to :class:`Local` or :class:`LocalStack` objects, + call the object as shown above. If you want to have a proxy to an + object looked up by a function, you can (as of Werkzeug 0.6.1) pass + a function to the :class:`LocalProxy` constructor:: + + session = LocalProxy(lambda: get_current_request().session) + + .. versionchanged:: 0.6.1 + The class can be instantiated with a callable as well now. + """ + __slots__ = ('__local', '__dict__', '__name__', '__wrapped__') + + def __init__(self, local, name=None): + object.__setattr__(self, '_LocalProxy__local', local) + object.__setattr__(self, '__name__', name) + if callable(local) and not hasattr(local, '__release_local__'): + # "local" is a callable that is not an instance of Local or + # LocalManager: mark it as a wrapped function. + object.__setattr__(self, '__wrapped__', local) + + def _get_current_object(self): + """Return the current object. This is useful if you want the real + object behind the proxy at a time for performance reasons or because + you want to pass the object into a different context. + """ + if not hasattr(self.__local, '__release_local__'): + return self.__local() + try: + return getattr(self.__local, self.__name__) + except AttributeError: + raise RuntimeError('no object bound to %s' % self.__name__) + + @property + def __dict__(self): + try: + return self._get_current_object().__dict__ + except RuntimeError: + raise AttributeError('__dict__') + + def __repr__(self): + try: + obj = self._get_current_object() + except RuntimeError: + return '<%s unbound>' % self.__class__.__name__ + return repr(obj) + + def __bool__(self): + try: + return bool(self._get_current_object()) + except RuntimeError: + return False + + def __unicode__(self): + try: + return unicode(self._get_current_object()) # noqa + except RuntimeError: + return repr(self) + + def __dir__(self): + try: + return dir(self._get_current_object()) + except RuntimeError: + return [] + + def __getattr__(self, name): + if name == '__members__': + return dir(self._get_current_object()) + return getattr(self._get_current_object(), name) + + def __setitem__(self, key, value): + self._get_current_object()[key] = value + + def __delitem__(self, key): + del self._get_current_object()[key] + + if PY2: + __getslice__ = lambda x, i, j: x._get_current_object()[i:j] + + def __setslice__(self, i, j, seq): + self._get_current_object()[i:j] = seq + + def __delslice__(self, i, j): + del self._get_current_object()[i:j] + + __setattr__ = lambda x, n, v: setattr(x._get_current_object(), n, v) + __delattr__ = lambda x, n: delattr(x._get_current_object(), n) + __str__ = lambda x: str(x._get_current_object()) + __lt__ = lambda x, o: x._get_current_object() < o + __le__ = lambda x, o: x._get_current_object() <= o + __eq__ = lambda x, o: x._get_current_object() == o + __ne__ = lambda x, o: x._get_current_object() != o + __gt__ = lambda x, o: x._get_current_object() > o + __ge__ = lambda x, o: x._get_current_object() >= o + __cmp__ = lambda x, o: cmp(x._get_current_object(), o) # noqa + __hash__ = lambda x: hash(x._get_current_object()) + __call__ = lambda x, *a, **kw: x._get_current_object()(*a, **kw) + __len__ = lambda x: len(x._get_current_object()) + __getitem__ = lambda x, i: x._get_current_object()[i] + __iter__ = lambda x: iter(x._get_current_object()) + __contains__ = lambda x, i: i in x._get_current_object() + __add__ = lambda x, o: x._get_current_object() + o + __sub__ = lambda x, o: x._get_current_object() - o + __mul__ = lambda x, o: x._get_current_object() * o + __floordiv__ = lambda x, o: x._get_current_object() // o + __mod__ = lambda x, o: x._get_current_object() % o + __divmod__ = lambda x, o: x._get_current_object().__divmod__(o) + __pow__ = lambda x, o: x._get_current_object() ** o + __lshift__ = lambda x, o: x._get_current_object() << o + __rshift__ = lambda x, o: x._get_current_object() >> o + __and__ = lambda x, o: x._get_current_object() & o + __xor__ = lambda x, o: x._get_current_object() ^ o + __or__ = lambda x, o: x._get_current_object() | o + __div__ = lambda x, o: x._get_current_object().__div__(o) + __truediv__ = lambda x, o: x._get_current_object().__truediv__(o) + __neg__ = lambda x: -(x._get_current_object()) + __pos__ = lambda x: +(x._get_current_object()) + __abs__ = lambda x: abs(x._get_current_object()) + __invert__ = lambda x: ~(x._get_current_object()) + __complex__ = lambda x: complex(x._get_current_object()) + __int__ = lambda x: int(x._get_current_object()) + __long__ = lambda x: long(x._get_current_object()) # noqa + __float__ = lambda x: float(x._get_current_object()) + __oct__ = lambda x: oct(x._get_current_object()) + __hex__ = lambda x: hex(x._get_current_object()) + __index__ = lambda x: x._get_current_object().__index__() + __coerce__ = lambda x, o: x._get_current_object().__coerce__(x, o) + __enter__ = lambda x: x._get_current_object().__enter__() + __exit__ = lambda x, *a, **kw: x._get_current_object().__exit__(*a, **kw) + __radd__ = lambda x, o: o + x._get_current_object() + __rsub__ = lambda x, o: o - x._get_current_object() + __rmul__ = lambda x, o: o * x._get_current_object() + __rdiv__ = lambda x, o: o / x._get_current_object() + if PY2: + __rtruediv__ = lambda x, o: x._get_current_object().__rtruediv__(o) + else: + __rtruediv__ = __rdiv__ + __rfloordiv__ = lambda x, o: o // x._get_current_object() + __rmod__ = lambda x, o: o % x._get_current_object() + __rdivmod__ = lambda x, o: x._get_current_object().__rdivmod__(o) + __copy__ = lambda x: copy.copy(x._get_current_object()) + __deepcopy__ = lambda x, memo: copy.deepcopy(x._get_current_object(), memo) diff --git a/flex/lib/python3.6/site-packages/werkzeug/posixemulation.py b/flex/lib/python3.6/site-packages/werkzeug/posixemulation.py new file mode 100644 index 0000000..8fd6314 --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/posixemulation.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +r""" + werkzeug.posixemulation + ~~~~~~~~~~~~~~~~~~~~~~~ + + Provides a POSIX emulation for some features that are relevant to + web applications. The main purpose is to simplify support for + systems such as Windows NT that are not 100% POSIX compatible. + + Currently this only implements a :func:`rename` function that + follows POSIX semantics. Eg: if the target file already exists it + will be replaced without asking. + + This module was introduced in 0.6.1 and is not a public interface. + It might become one in later versions of Werkzeug. + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import sys +import os +import errno +import time +import random + +from ._compat import to_unicode +from .filesystem import get_filesystem_encoding + + +can_rename_open_file = False +if os.name == 'nt': # pragma: no cover + _rename = lambda src, dst: False + _rename_atomic = lambda src, dst: False + + try: + import ctypes + + _MOVEFILE_REPLACE_EXISTING = 0x1 + _MOVEFILE_WRITE_THROUGH = 0x8 + _MoveFileEx = ctypes.windll.kernel32.MoveFileExW + + def _rename(src, dst): + src = to_unicode(src, get_filesystem_encoding()) + dst = to_unicode(dst, get_filesystem_encoding()) + if _rename_atomic(src, dst): + return True + retry = 0 + rv = False + while not rv and retry < 100: + rv = _MoveFileEx(src, dst, _MOVEFILE_REPLACE_EXISTING | + _MOVEFILE_WRITE_THROUGH) + if not rv: + time.sleep(0.001) + retry += 1 + return rv + + # new in Vista and Windows Server 2008 + _CreateTransaction = ctypes.windll.ktmw32.CreateTransaction + _CommitTransaction = ctypes.windll.ktmw32.CommitTransaction + _MoveFileTransacted = ctypes.windll.kernel32.MoveFileTransactedW + _CloseHandle = ctypes.windll.kernel32.CloseHandle + can_rename_open_file = True + + def _rename_atomic(src, dst): + ta = _CreateTransaction(None, 0, 0, 0, 0, 1000, 'Werkzeug rename') + if ta == -1: + return False + try: + retry = 0 + rv = False + while not rv and retry < 100: + rv = _MoveFileTransacted(src, dst, None, None, + _MOVEFILE_REPLACE_EXISTING | + _MOVEFILE_WRITE_THROUGH, ta) + if rv: + rv = _CommitTransaction(ta) + break + else: + time.sleep(0.001) + retry += 1 + return rv + finally: + _CloseHandle(ta) + except Exception: + pass + + def rename(src, dst): + # Try atomic or pseudo-atomic rename + if _rename(src, dst): + return + # Fall back to "move away and replace" + try: + os.rename(src, dst) + except OSError as e: + if e.errno != errno.EEXIST: + raise + old = "%s-%08x" % (dst, random.randint(0, sys.maxint)) + os.rename(dst, old) + os.rename(src, dst) + try: + os.unlink(old) + except Exception: + pass +else: + rename = os.rename + can_rename_open_file = True diff --git a/flex/lib/python3.6/site-packages/werkzeug/routing.py b/flex/lib/python3.6/site-packages/werkzeug/routing.py new file mode 100644 index 0000000..2e4e2f4 --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/routing.py @@ -0,0 +1,1792 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.routing + ~~~~~~~~~~~~~~~~ + + When it comes to combining multiple controller or view functions (however + you want to call them) you need a dispatcher. A simple way would be + applying regular expression tests on the ``PATH_INFO`` and calling + registered callback functions that return the value then. + + This module implements a much more powerful system than simple regular + expression matching because it can also convert values in the URLs and + build URLs. + + Here a simple example that creates an URL map for an application with + two subdomains (www and kb) and some URL rules: + + >>> m = Map([ + ... # Static URLs + ... Rule('/', endpoint='static/index'), + ... Rule('/about', endpoint='static/about'), + ... Rule('/help', endpoint='static/help'), + ... # Knowledge Base + ... Subdomain('kb', [ + ... Rule('/', endpoint='kb/index'), + ... Rule('/browse/', endpoint='kb/browse'), + ... Rule('/browse//', endpoint='kb/browse'), + ... Rule('/browse//', endpoint='kb/browse') + ... ]) + ... ], default_subdomain='www') + + If the application doesn't use subdomains it's perfectly fine to not set + the default subdomain and not use the `Subdomain` rule factory. The endpoint + in the rules can be anything, for example import paths or unique + identifiers. The WSGI application can use those endpoints to get the + handler for that URL. It doesn't have to be a string at all but it's + recommended. + + Now it's possible to create a URL adapter for one of the subdomains and + build URLs: + + >>> c = m.bind('example.com') + >>> c.build("kb/browse", dict(id=42)) + 'http://kb.example.com/browse/42/' + >>> c.build("kb/browse", dict()) + 'http://kb.example.com/browse/' + >>> c.build("kb/browse", dict(id=42, page=3)) + 'http://kb.example.com/browse/42/3' + >>> c.build("static/about") + '/about' + >>> c.build("static/index", force_external=True) + 'http://www.example.com/' + + >>> c = m.bind('example.com', subdomain='kb') + >>> c.build("static/about") + 'http://www.example.com/about' + + The first argument to bind is the server name *without* the subdomain. + Per default it will assume that the script is mounted on the root, but + often that's not the case so you can provide the real mount point as + second argument: + + >>> c = m.bind('example.com', '/applications/example') + + The third argument can be the subdomain, if not given the default + subdomain is used. For more details about binding have a look at the + documentation of the `MapAdapter`. + + And here is how you can match URLs: + + >>> c = m.bind('example.com') + >>> c.match("/") + ('static/index', {}) + >>> c.match("/about") + ('static/about', {}) + >>> c = m.bind('example.com', '/', 'kb') + >>> c.match("/") + ('kb/index', {}) + >>> c.match("/browse/42/23") + ('kb/browse', {'id': 42, 'page': 23}) + + If matching fails you get a `NotFound` exception, if the rule thinks + it's a good idea to redirect (for example because the URL was defined + to have a slash at the end but the request was missing that slash) it + will raise a `RequestRedirect` exception. Both are subclasses of the + `HTTPException` so you can use those errors as responses in the + application. + + If matching succeeded but the URL rule was incompatible to the given + method (for example there were only rules for `GET` and `HEAD` and + routing system tried to match a `POST` request) a `MethodNotAllowed` + exception is raised. + + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import difflib +import re +import uuid +import posixpath + +from pprint import pformat +from threading import Lock + +from werkzeug.urls import url_encode, url_quote, url_join +from werkzeug.utils import redirect, format_string +from werkzeug.exceptions import HTTPException, NotFound, MethodNotAllowed, \ + BadHost +from werkzeug._internal import _get_environ, _encode_idna +from werkzeug._compat import itervalues, iteritems, to_unicode, to_bytes, \ + text_type, string_types, native_string_result, \ + implements_to_string, wsgi_decoding_dance +from werkzeug.datastructures import ImmutableDict, MultiDict +from werkzeug.utils import cached_property + + +_rule_re = re.compile(r''' + (?P[^<]*) # static rule data + < + (?: + (?P[a-zA-Z_][a-zA-Z0-9_]*) # converter name + (?:\((?P.*?)\))? # converter arguments + \: # variable delimiter + )? + (?P[a-zA-Z_][a-zA-Z0-9_]*) # variable name + > +''', re.VERBOSE) +_simple_rule_re = re.compile(r'<([^>]+)>') +_converter_args_re = re.compile(r''' + ((?P\w+)\s*=\s*)? + (?P + True|False| + \d+.\d+| + \d+.| + \d+| + [\w\d_.]+| + [urUR]?(?P"[^"]*?"|'[^']*') + )\s*, +''', re.VERBOSE | re.UNICODE) + + +_PYTHON_CONSTANTS = { + 'None': None, + 'True': True, + 'False': False +} + + +def _pythonize(value): + if value in _PYTHON_CONSTANTS: + return _PYTHON_CONSTANTS[value] + for convert in int, float: + try: + return convert(value) + except ValueError: + pass + if value[:1] == value[-1:] and value[0] in '"\'': + value = value[1:-1] + return text_type(value) + + +def parse_converter_args(argstr): + argstr += ',' + args = [] + kwargs = {} + + for item in _converter_args_re.finditer(argstr): + value = item.group('stringval') + if value is None: + value = item.group('value') + value = _pythonize(value) + if not item.group('name'): + args.append(value) + else: + name = item.group('name') + kwargs[name] = value + + return tuple(args), kwargs + + +def parse_rule(rule): + """Parse a rule and return it as generator. Each iteration yields tuples + in the form ``(converter, arguments, variable)``. If the converter is + `None` it's a static url part, otherwise it's a dynamic one. + + :internal: + """ + pos = 0 + end = len(rule) + do_match = _rule_re.match + used_names = set() + while pos < end: + m = do_match(rule, pos) + if m is None: + break + data = m.groupdict() + if data['static']: + yield None, None, data['static'] + variable = data['variable'] + converter = data['converter'] or 'default' + if variable in used_names: + raise ValueError('variable name %r used twice.' % variable) + used_names.add(variable) + yield converter, data['args'] or None, variable + pos = m.end() + if pos < end: + remaining = rule[pos:] + if '>' in remaining or '<' in remaining: + raise ValueError('malformed url rule: %r' % rule) + yield None, None, remaining + + +class RoutingException(Exception): + + """Special exceptions that require the application to redirect, notifying + about missing urls, etc. + + :internal: + """ + + +class RequestRedirect(HTTPException, RoutingException): + + """Raise if the map requests a redirect. This is for example the case if + `strict_slashes` are activated and an url that requires a trailing slash. + + The attribute `new_url` contains the absolute destination url. + """ + code = 301 + + def __init__(self, new_url): + RoutingException.__init__(self, new_url) + self.new_url = new_url + + def get_response(self, environ): + return redirect(self.new_url, self.code) + + +class RequestSlash(RoutingException): + + """Internal exception.""" + + +class RequestAliasRedirect(RoutingException): + + """This rule is an alias and wants to redirect to the canonical URL.""" + + def __init__(self, matched_values): + self.matched_values = matched_values + + +@implements_to_string +class BuildError(RoutingException, LookupError): + + """Raised if the build system cannot find a URL for an endpoint with the + values provided. + """ + + def __init__(self, endpoint, values, method, adapter=None): + LookupError.__init__(self, endpoint, values, method) + self.endpoint = endpoint + self.values = values + self.method = method + self.adapter = adapter + + @cached_property + def suggested(self): + return self.closest_rule(self.adapter) + + def closest_rule(self, adapter): + def _score_rule(rule): + return sum([ + 0.98 * difflib.SequenceMatcher( + None, rule.endpoint, self.endpoint + ).ratio(), + 0.01 * bool(set(self.values or ()).issubset(rule.arguments)), + 0.01 * bool(rule.methods and self.method in rule.methods) + ]) + + if adapter and adapter.map._rules: + return max(adapter.map._rules, key=_score_rule) + + def __str__(self): + message = [] + message.append('Could not build url for endpoint %r' % self.endpoint) + if self.method: + message.append(' (%r)' % self.method) + if self.values: + message.append(' with values %r' % sorted(self.values.keys())) + message.append('.') + if self.suggested: + if self.endpoint == self.suggested.endpoint: + if self.method and self.method not in self.suggested.methods: + message.append(' Did you mean to use methods %r?' % sorted( + self.suggested.methods + )) + missing_values = self.suggested.arguments.union( + set(self.suggested.defaults or ()) + ) - set(self.values.keys()) + if missing_values: + message.append( + ' Did you forget to specify values %r?' % + sorted(missing_values) + ) + else: + message.append( + ' Did you mean %r instead?' % self.suggested.endpoint + ) + return u''.join(message) + + +class ValidationError(ValueError): + + """Validation error. If a rule converter raises this exception the rule + does not match the current URL and the next URL is tried. + """ + + +class RuleFactory(object): + + """As soon as you have more complex URL setups it's a good idea to use rule + factories to avoid repetitive tasks. Some of them are builtin, others can + be added by subclassing `RuleFactory` and overriding `get_rules`. + """ + + def get_rules(self, map): + """Subclasses of `RuleFactory` have to override this method and return + an iterable of rules.""" + raise NotImplementedError() + + +class Subdomain(RuleFactory): + + """All URLs provided by this factory have the subdomain set to a + specific domain. For example if you want to use the subdomain for + the current language this can be a good setup:: + + url_map = Map([ + Rule('/', endpoint='#select_language'), + Subdomain('', [ + Rule('/', endpoint='index'), + Rule('/about', endpoint='about'), + Rule('/help', endpoint='help') + ]) + ]) + + All the rules except for the ``'#select_language'`` endpoint will now + listen on a two letter long subdomain that holds the language code + for the current request. + """ + + def __init__(self, subdomain, rules): + self.subdomain = subdomain + self.rules = rules + + def get_rules(self, map): + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + rule = rule.empty() + rule.subdomain = self.subdomain + yield rule + + +class Submount(RuleFactory): + + """Like `Subdomain` but prefixes the URL rule with a given string:: + + url_map = Map([ + Rule('/', endpoint='index'), + Submount('/blog', [ + Rule('/', endpoint='blog/index'), + Rule('/entry/', endpoint='blog/show') + ]) + ]) + + Now the rule ``'blog/show'`` matches ``/blog/entry/``. + """ + + def __init__(self, path, rules): + self.path = path.rstrip('/') + self.rules = rules + + def get_rules(self, map): + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + rule = rule.empty() + rule.rule = self.path + rule.rule + yield rule + + +class EndpointPrefix(RuleFactory): + + """Prefixes all endpoints (which must be strings for this factory) with + another string. This can be useful for sub applications:: + + url_map = Map([ + Rule('/', endpoint='index'), + EndpointPrefix('blog/', [Submount('/blog', [ + Rule('/', endpoint='index'), + Rule('/entry/', endpoint='show') + ])]) + ]) + """ + + def __init__(self, prefix, rules): + self.prefix = prefix + self.rules = rules + + def get_rules(self, map): + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + rule = rule.empty() + rule.endpoint = self.prefix + rule.endpoint + yield rule + + +class RuleTemplate(object): + + """Returns copies of the rules wrapped and expands string templates in + the endpoint, rule, defaults or subdomain sections. + + Here a small example for such a rule template:: + + from werkzeug.routing import Map, Rule, RuleTemplate + + resource = RuleTemplate([ + Rule('/$name/', endpoint='$name.list'), + Rule('/$name/', endpoint='$name.show') + ]) + + url_map = Map([resource(name='user'), resource(name='page')]) + + When a rule template is called the keyword arguments are used to + replace the placeholders in all the string parameters. + """ + + def __init__(self, rules): + self.rules = list(rules) + + def __call__(self, *args, **kwargs): + return RuleTemplateFactory(self.rules, dict(*args, **kwargs)) + + +class RuleTemplateFactory(RuleFactory): + + """A factory that fills in template variables into rules. Used by + `RuleTemplate` internally. + + :internal: + """ + + def __init__(self, rules, context): + self.rules = rules + self.context = context + + def get_rules(self, map): + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + new_defaults = subdomain = None + if rule.defaults: + new_defaults = {} + for key, value in iteritems(rule.defaults): + if isinstance(value, string_types): + value = format_string(value, self.context) + new_defaults[key] = value + if rule.subdomain is not None: + subdomain = format_string(rule.subdomain, self.context) + new_endpoint = rule.endpoint + if isinstance(new_endpoint, string_types): + new_endpoint = format_string(new_endpoint, self.context) + yield Rule( + format_string(rule.rule, self.context), + new_defaults, + subdomain, + rule.methods, + rule.build_only, + new_endpoint, + rule.strict_slashes + ) + + +@implements_to_string +class Rule(RuleFactory): + + """A Rule represents one URL pattern. There are some options for `Rule` + that change the way it behaves and are passed to the `Rule` constructor. + Note that besides the rule-string all arguments *must* be keyword arguments + in order to not break the application on Werkzeug upgrades. + + `string` + Rule strings basically are just normal URL paths with placeholders in + the format ```` where the converter and the + arguments are optional. If no converter is defined the `default` + converter is used which means `string` in the normal configuration. + + URL rules that end with a slash are branch URLs, others are leaves. + If you have `strict_slashes` enabled (which is the default), all + branch URLs that are matched without a trailing slash will trigger a + redirect to the same URL with the missing slash appended. + + The converters are defined on the `Map`. + + `endpoint` + The endpoint for this rule. This can be anything. A reference to a + function, a string, a number etc. The preferred way is using a string + because the endpoint is used for URL generation. + + `defaults` + An optional dict with defaults for other rules with the same endpoint. + This is a bit tricky but useful if you want to have unique URLs:: + + url_map = Map([ + Rule('/all/', defaults={'page': 1}, endpoint='all_entries'), + Rule('/all/page/', endpoint='all_entries') + ]) + + If a user now visits ``http://example.com/all/page/1`` he will be + redirected to ``http://example.com/all/``. If `redirect_defaults` is + disabled on the `Map` instance this will only affect the URL + generation. + + `subdomain` + The subdomain rule string for this rule. If not specified the rule + only matches for the `default_subdomain` of the map. If the map is + not bound to a subdomain this feature is disabled. + + Can be useful if you want to have user profiles on different subdomains + and all subdomains are forwarded to your application:: + + url_map = Map([ + Rule('/', subdomain='', endpoint='user/homepage'), + Rule('/stats', subdomain='', endpoint='user/stats') + ]) + + `methods` + A sequence of http methods this rule applies to. If not specified, all + methods are allowed. For example this can be useful if you want different + endpoints for `POST` and `GET`. If methods are defined and the path + matches but the method matched against is not in this list or in the + list of another rule for that path the error raised is of the type + `MethodNotAllowed` rather than `NotFound`. If `GET` is present in the + list of methods and `HEAD` is not, `HEAD` is added automatically. + + .. versionchanged:: 0.6.1 + `HEAD` is now automatically added to the methods if `GET` is + present. The reason for this is that existing code often did not + work properly in servers not rewriting `HEAD` to `GET` + automatically and it was not documented how `HEAD` should be + treated. This was considered a bug in Werkzeug because of that. + + `strict_slashes` + Override the `Map` setting for `strict_slashes` only for this rule. If + not specified the `Map` setting is used. + + `build_only` + Set this to True and the rule will never match but will create a URL + that can be build. This is useful if you have resources on a subdomain + or folder that are not handled by the WSGI application (like static data) + + `redirect_to` + If given this must be either a string or callable. In case of a + callable it's called with the url adapter that triggered the match and + the values of the URL as keyword arguments and has to return the target + for the redirect, otherwise it has to be a string with placeholders in + rule syntax:: + + def foo_with_slug(adapter, id): + # ask the database for the slug for the old id. this of + # course has nothing to do with werkzeug. + return 'foo/' + Foo.get_slug_for_id(id) + + url_map = Map([ + Rule('/foo/', endpoint='foo'), + Rule('/some/old/url/', redirect_to='foo/'), + Rule('/other/old/url/', redirect_to=foo_with_slug) + ]) + + When the rule is matched the routing system will raise a + `RequestRedirect` exception with the target for the redirect. + + Keep in mind that the URL will be joined against the URL root of the + script so don't use a leading slash on the target URL unless you + really mean root of that domain. + + `alias` + If enabled this rule serves as an alias for another rule with the same + endpoint and arguments. + + `host` + If provided and the URL map has host matching enabled this can be + used to provide a match rule for the whole host. This also means + that the subdomain feature is disabled. + + .. versionadded:: 0.7 + The `alias` and `host` parameters were added. + """ + + def __init__(self, string, defaults=None, subdomain=None, methods=None, + build_only=False, endpoint=None, strict_slashes=None, + redirect_to=None, alias=False, host=None): + if not string.startswith('/'): + raise ValueError('urls must start with a leading slash') + self.rule = string + self.is_leaf = not string.endswith('/') + + self.map = None + self.strict_slashes = strict_slashes + self.subdomain = subdomain + self.host = host + self.defaults = defaults + self.build_only = build_only + self.alias = alias + if methods is None: + self.methods = None + else: + if isinstance(methods, str): + raise TypeError('param `methods` should be `Iterable[str]`, not `str`') + self.methods = set([x.upper() for x in methods]) + if 'HEAD' not in self.methods and 'GET' in self.methods: + self.methods.add('HEAD') + self.endpoint = endpoint + self.redirect_to = redirect_to + + if defaults: + self.arguments = set(map(str, defaults)) + else: + self.arguments = set() + self._trace = self._converters = self._regex = self._argument_weights = None + + def empty(self): + """ + Return an unbound copy of this rule. + + This can be useful if want to reuse an already bound URL for another + map. See ``get_empty_kwargs`` to override what keyword arguments are + provided to the new copy. + """ + return type(self)(self.rule, **self.get_empty_kwargs()) + + def get_empty_kwargs(self): + """ + Provides kwargs for instantiating empty copy with empty() + + Use this method to provide custom keyword arguments to the subclass of + ``Rule`` when calling ``some_rule.empty()``. Helpful when the subclass + has custom keyword arguments that are needed at instantiation. + + Must return a ``dict`` that will be provided as kwargs to the new + instance of ``Rule``, following the initial ``self.rule`` value which + is always provided as the first, required positional argument. + """ + defaults = None + if self.defaults: + defaults = dict(self.defaults) + return dict(defaults=defaults, subdomain=self.subdomain, + methods=self.methods, build_only=self.build_only, + endpoint=self.endpoint, strict_slashes=self.strict_slashes, + redirect_to=self.redirect_to, alias=self.alias, + host=self.host) + + def get_rules(self, map): + yield self + + def refresh(self): + """Rebinds and refreshes the URL. Call this if you modified the + rule in place. + + :internal: + """ + self.bind(self.map, rebind=True) + + def bind(self, map, rebind=False): + """Bind the url to a map and create a regular expression based on + the information from the rule itself and the defaults from the map. + + :internal: + """ + if self.map is not None and not rebind: + raise RuntimeError('url rule %r already bound to map %r' % + (self, self.map)) + self.map = map + if self.strict_slashes is None: + self.strict_slashes = map.strict_slashes + if self.subdomain is None: + self.subdomain = map.default_subdomain + self.compile() + + def get_converter(self, variable_name, converter_name, args, kwargs): + """Looks up the converter for the given parameter. + + .. versionadded:: 0.9 + """ + if converter_name not in self.map.converters: + raise LookupError('the converter %r does not exist' % converter_name) + return self.map.converters[converter_name](self.map, *args, **kwargs) + + def compile(self): + """Compiles the regular expression and stores it.""" + assert self.map is not None, 'rule not bound' + + if self.map.host_matching: + domain_rule = self.host or '' + else: + domain_rule = self.subdomain or '' + + self._trace = [] + self._converters = {} + self._static_weights = [] + self._argument_weights = [] + regex_parts = [] + + def _build_regex(rule): + index = 0 + for converter, arguments, variable in parse_rule(rule): + if converter is None: + regex_parts.append(re.escape(variable)) + self._trace.append((False, variable)) + for part in variable.split('/'): + if part: + self._static_weights.append((index, -len(part))) + else: + if arguments: + c_args, c_kwargs = parse_converter_args(arguments) + else: + c_args = () + c_kwargs = {} + convobj = self.get_converter( + variable, converter, c_args, c_kwargs) + regex_parts.append('(?P<%s>%s)' % (variable, convobj.regex)) + self._converters[variable] = convobj + self._trace.append((True, variable)) + self._argument_weights.append(convobj.weight) + self.arguments.add(str(variable)) + index = index + 1 + + _build_regex(domain_rule) + regex_parts.append('\\|') + self._trace.append((False, '|')) + _build_regex(self.is_leaf and self.rule or self.rule.rstrip('/')) + if not self.is_leaf: + self._trace.append((False, '/')) + + if self.build_only: + return + regex = r'^%s%s$' % ( + u''.join(regex_parts), + (not self.is_leaf or not self.strict_slashes) and + '(?/?)' or '' + ) + self._regex = re.compile(regex, re.UNICODE) + + def match(self, path, method=None): + """Check if the rule matches a given path. Path is a string in the + form ``"subdomain|/path"`` and is assembled by the map. If + the map is doing host matching the subdomain part will be the host + instead. + + If the rule matches a dict with the converted values is returned, + otherwise the return value is `None`. + + :internal: + """ + if not self.build_only: + m = self._regex.search(path) + if m is not None: + groups = m.groupdict() + # we have a folder like part of the url without a trailing + # slash and strict slashes enabled. raise an exception that + # tells the map to redirect to the same url but with a + # trailing slash + if self.strict_slashes and not self.is_leaf and \ + not groups.pop('__suffix__') and \ + (method is None or self.methods is None or + method in self.methods): + raise RequestSlash() + # if we are not in strict slashes mode we have to remove + # a __suffix__ + elif not self.strict_slashes: + del groups['__suffix__'] + + result = {} + for name, value in iteritems(groups): + try: + value = self._converters[name].to_python(value) + except ValidationError: + return + result[str(name)] = value + if self.defaults: + result.update(self.defaults) + + if self.alias and self.map.redirect_defaults: + raise RequestAliasRedirect(result) + + return result + + def build(self, values, append_unknown=True): + """Assembles the relative url for that rule and the subdomain. + If building doesn't work for some reasons `None` is returned. + + :internal: + """ + tmp = [] + add = tmp.append + processed = set(self.arguments) + for is_dynamic, data in self._trace: + if is_dynamic: + try: + add(self._converters[data].to_url(values[data])) + except ValidationError: + return + processed.add(data) + else: + add(url_quote(to_bytes(data, self.map.charset), safe='/:|+')) + domain_part, url = (u''.join(tmp)).split(u'|', 1) + + if append_unknown: + query_vars = MultiDict(values) + for key in processed: + if key in query_vars: + del query_vars[key] + + if query_vars: + url += u'?' + url_encode(query_vars, charset=self.map.charset, + sort=self.map.sort_parameters, + key=self.map.sort_key) + + return domain_part, url + + def provides_defaults_for(self, rule): + """Check if this rule has defaults for a given rule. + + :internal: + """ + return not self.build_only and self.defaults and \ + self.endpoint == rule.endpoint and self != rule and \ + self.arguments == rule.arguments + + def suitable_for(self, values, method=None): + """Check if the dict of values has enough data for url generation. + + :internal: + """ + # if a method was given explicitly and that method is not supported + # by this rule, this rule is not suitable. + if method is not None and self.methods is not None \ + and method not in self.methods: + return False + + defaults = self.defaults or () + + # all arguments required must be either in the defaults dict or + # the value dictionary otherwise it's not suitable + for key in self.arguments: + if key not in defaults and key not in values: + return False + + # in case defaults are given we ensure taht either the value was + # skipped or the value is the same as the default value. + if defaults: + for key, value in iteritems(defaults): + if key in values and value != values[key]: + return False + + return True + + def match_compare_key(self): + """The match compare key for sorting. + + Current implementation: + + 1. rules without any arguments come first for performance + reasons only as we expect them to match faster and some + common ones usually don't have any arguments (index pages etc.) + 2. rules with more static parts come first so the second argument + is the negative length of the number of the static weights. + 3. we order by static weights, which is a combination of index + and length + 4. The more complex rules come first so the next argument is the + negative length of the number of argument weights. + 5. lastly we order by the actual argument weights. + + :internal: + """ + return bool(self.arguments), -len(self._static_weights), self._static_weights,\ + -len(self._argument_weights), self._argument_weights + + def build_compare_key(self): + """The build compare key for sorting. + + :internal: + """ + return self.alias and 1 or 0, -len(self.arguments), \ + -len(self.defaults or ()) + + def __eq__(self, other): + return self.__class__ is other.__class__ and \ + self._trace == other._trace + + __hash__ = None + + def __ne__(self, other): + return not self.__eq__(other) + + def __str__(self): + return self.rule + + @native_string_result + def __repr__(self): + if self.map is None: + return u'<%s (unbound)>' % self.__class__.__name__ + tmp = [] + for is_dynamic, data in self._trace: + if is_dynamic: + tmp.append(u'<%s>' % data) + else: + tmp.append(data) + return u'<%s %s%s -> %s>' % ( + self.__class__.__name__, + repr((u''.join(tmp)).lstrip(u'|')).lstrip(u'u'), + self.methods is not None + and u' (%s)' % u', '.join(self.methods) + or u'', + self.endpoint + ) + + +class BaseConverter(object): + + """Base class for all converters.""" + regex = '[^/]+' + weight = 100 + + def __init__(self, map): + self.map = map + + def to_python(self, value): + return value + + def to_url(self, value): + return url_quote(value, charset=self.map.charset) + + +class UnicodeConverter(BaseConverter): + + """This converter is the default converter and accepts any string but + only one path segment. Thus the string can not include a slash. + + This is the default validator. + + Example:: + + Rule('/pages/'), + Rule('/') + + :param map: the :class:`Map`. + :param minlength: the minimum length of the string. Must be greater + or equal 1. + :param maxlength: the maximum length of the string. + :param length: the exact length of the string. + """ + + def __init__(self, map, minlength=1, maxlength=None, length=None): + BaseConverter.__init__(self, map) + if length is not None: + length = '{%d}' % int(length) + else: + if maxlength is None: + maxlength = '' + else: + maxlength = int(maxlength) + length = '{%s,%s}' % ( + int(minlength), + maxlength + ) + self.regex = '[^/]' + length + + +class AnyConverter(BaseConverter): + + """Matches one of the items provided. Items can either be Python + identifiers or strings:: + + Rule('/') + + :param map: the :class:`Map`. + :param items: this function accepts the possible items as positional + arguments. + """ + + def __init__(self, map, *items): + BaseConverter.__init__(self, map) + self.regex = '(?:%s)' % '|'.join([re.escape(x) for x in items]) + + +class PathConverter(BaseConverter): + + """Like the default :class:`UnicodeConverter`, but it also matches + slashes. This is useful for wikis and similar applications:: + + Rule('/') + Rule('//edit') + + :param map: the :class:`Map`. + """ + regex = '[^/].*?' + weight = 200 + + +class NumberConverter(BaseConverter): + + """Baseclass for `IntegerConverter` and `FloatConverter`. + + :internal: + """ + weight = 50 + + def __init__(self, map, fixed_digits=0, min=None, max=None): + BaseConverter.__init__(self, map) + self.fixed_digits = fixed_digits + self.min = min + self.max = max + + def to_python(self, value): + if (self.fixed_digits and len(value) != self.fixed_digits): + raise ValidationError() + value = self.num_convert(value) + if (self.min is not None and value < self.min) or \ + (self.max is not None and value > self.max): + raise ValidationError() + return value + + def to_url(self, value): + value = self.num_convert(value) + if self.fixed_digits: + value = ('%%0%sd' % self.fixed_digits) % value + return str(value) + + +class IntegerConverter(NumberConverter): + + """This converter only accepts integer values:: + + Rule('/page/') + + This converter does not support negative values. + + :param map: the :class:`Map`. + :param fixed_digits: the number of fixed digits in the URL. If you set + this to ``4`` for example, the application will + only match if the url looks like ``/0001/``. The + default is variable length. + :param min: the minimal value. + :param max: the maximal value. + """ + regex = r'\d+' + num_convert = int + + +class FloatConverter(NumberConverter): + + """This converter only accepts floating point values:: + + Rule('/probability/') + + This converter does not support negative values. + + :param map: the :class:`Map`. + :param min: the minimal value. + :param max: the maximal value. + """ + regex = r'\d+\.\d+' + num_convert = float + + def __init__(self, map, min=None, max=None): + NumberConverter.__init__(self, map, 0, min, max) + + +class UUIDConverter(BaseConverter): + + """This converter only accepts UUID strings:: + + Rule('/object/') + + .. versionadded:: 0.10 + + :param map: the :class:`Map`. + """ + regex = r'[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-' \ + r'[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}' + + def to_python(self, value): + return uuid.UUID(value) + + def to_url(self, value): + return str(value) + + +#: the default converter mapping for the map. +DEFAULT_CONVERTERS = { + 'default': UnicodeConverter, + 'string': UnicodeConverter, + 'any': AnyConverter, + 'path': PathConverter, + 'int': IntegerConverter, + 'float': FloatConverter, + 'uuid': UUIDConverter, +} + + +class Map(object): + + """The map class stores all the URL rules and some configuration + parameters. Some of the configuration values are only stored on the + `Map` instance since those affect all rules, others are just defaults + and can be overridden for each rule. Note that you have to specify all + arguments besides the `rules` as keyword arguments! + + :param rules: sequence of url rules for this map. + :param default_subdomain: The default subdomain for rules without a + subdomain defined. + :param charset: charset of the url. defaults to ``"utf-8"`` + :param strict_slashes: Take care of trailing slashes. + :param redirect_defaults: This will redirect to the default rule if it + wasn't visited that way. This helps creating + unique URLs. + :param converters: A dict of converters that adds additional converters + to the list of converters. If you redefine one + converter this will override the original one. + :param sort_parameters: If set to `True` the url parameters are sorted. + See `url_encode` for more details. + :param sort_key: The sort key function for `url_encode`. + :param encoding_errors: the error method to use for decoding + :param host_matching: if set to `True` it enables the host matching + feature and disables the subdomain one. If + enabled the `host` parameter to rules is used + instead of the `subdomain` one. + + .. versionadded:: 0.5 + `sort_parameters` and `sort_key` was added. + + .. versionadded:: 0.7 + `encoding_errors` and `host_matching` was added. + """ + + #: .. versionadded:: 0.6 + #: a dict of default converters to be used. + default_converters = ImmutableDict(DEFAULT_CONVERTERS) + + def __init__(self, rules=None, default_subdomain='', charset='utf-8', + strict_slashes=True, redirect_defaults=True, + converters=None, sort_parameters=False, sort_key=None, + encoding_errors='replace', host_matching=False): + self._rules = [] + self._rules_by_endpoint = {} + self._remap = True + self._remap_lock = Lock() + + self.default_subdomain = default_subdomain + self.charset = charset + self.encoding_errors = encoding_errors + self.strict_slashes = strict_slashes + self.redirect_defaults = redirect_defaults + self.host_matching = host_matching + + self.converters = self.default_converters.copy() + if converters: + self.converters.update(converters) + + self.sort_parameters = sort_parameters + self.sort_key = sort_key + + for rulefactory in rules or (): + self.add(rulefactory) + + def is_endpoint_expecting(self, endpoint, *arguments): + """Iterate over all rules and check if the endpoint expects + the arguments provided. This is for example useful if you have + some URLs that expect a language code and others that do not and + you want to wrap the builder a bit so that the current language + code is automatically added if not provided but endpoints expect + it. + + :param endpoint: the endpoint to check. + :param arguments: this function accepts one or more arguments + as positional arguments. Each one of them is + checked. + """ + self.update() + arguments = set(arguments) + for rule in self._rules_by_endpoint[endpoint]: + if arguments.issubset(rule.arguments): + return True + return False + + def iter_rules(self, endpoint=None): + """Iterate over all rules or the rules of an endpoint. + + :param endpoint: if provided only the rules for that endpoint + are returned. + :return: an iterator + """ + self.update() + if endpoint is not None: + return iter(self._rules_by_endpoint[endpoint]) + return iter(self._rules) + + def add(self, rulefactory): + """Add a new rule or factory to the map and bind it. Requires that the + rule is not bound to another map. + + :param rulefactory: a :class:`Rule` or :class:`RuleFactory` + """ + for rule in rulefactory.get_rules(self): + rule.bind(self) + self._rules.append(rule) + self._rules_by_endpoint.setdefault(rule.endpoint, []).append(rule) + self._remap = True + + def bind(self, server_name, script_name=None, subdomain=None, + url_scheme='http', default_method='GET', path_info=None, + query_args=None): + """Return a new :class:`MapAdapter` with the details specified to the + call. Note that `script_name` will default to ``'/'`` if not further + specified or `None`. The `server_name` at least is a requirement + because the HTTP RFC requires absolute URLs for redirects and so all + redirect exceptions raised by Werkzeug will contain the full canonical + URL. + + If no path_info is passed to :meth:`match` it will use the default path + info passed to bind. While this doesn't really make sense for + manual bind calls, it's useful if you bind a map to a WSGI + environment which already contains the path info. + + `subdomain` will default to the `default_subdomain` for this map if + no defined. If there is no `default_subdomain` you cannot use the + subdomain feature. + + .. versionadded:: 0.7 + `query_args` added + + .. versionadded:: 0.8 + `query_args` can now also be a string. + """ + server_name = server_name.lower() + if self.host_matching: + if subdomain is not None: + raise RuntimeError('host matching enabled and a ' + 'subdomain was provided') + elif subdomain is None: + subdomain = self.default_subdomain + if script_name is None: + script_name = '/' + try: + server_name = _encode_idna(server_name) + except UnicodeError: + raise BadHost() + return MapAdapter(self, server_name, script_name, subdomain, + url_scheme, path_info, default_method, query_args) + + def bind_to_environ(self, environ, server_name=None, subdomain=None): + """Like :meth:`bind` but you can pass it an WSGI environment and it + will fetch the information from that dictionary. Note that because of + limitations in the protocol there is no way to get the current + subdomain and real `server_name` from the environment. If you don't + provide it, Werkzeug will use `SERVER_NAME` and `SERVER_PORT` (or + `HTTP_HOST` if provided) as used `server_name` with disabled subdomain + feature. + + If `subdomain` is `None` but an environment and a server name is + provided it will calculate the current subdomain automatically. + Example: `server_name` is ``'example.com'`` and the `SERVER_NAME` + in the wsgi `environ` is ``'staging.dev.example.com'`` the calculated + subdomain will be ``'staging.dev'``. + + If the object passed as environ has an environ attribute, the value of + this attribute is used instead. This allows you to pass request + objects. Additionally `PATH_INFO` added as a default of the + :class:`MapAdapter` so that you don't have to pass the path info to + the match method. + + .. versionchanged:: 0.5 + previously this method accepted a bogus `calculate_subdomain` + parameter that did not have any effect. It was removed because + of that. + + .. versionchanged:: 0.8 + This will no longer raise a ValueError when an unexpected server + name was passed. + + :param environ: a WSGI environment. + :param server_name: an optional server name hint (see above). + :param subdomain: optionally the current subdomain (see above). + """ + environ = _get_environ(environ) + + if 'HTTP_HOST' in environ: + wsgi_server_name = environ['HTTP_HOST'] + + if environ['wsgi.url_scheme'] == 'http' \ + and wsgi_server_name.endswith(':80'): + wsgi_server_name = wsgi_server_name[:-3] + elif environ['wsgi.url_scheme'] == 'https' \ + and wsgi_server_name.endswith(':443'): + wsgi_server_name = wsgi_server_name[:-4] + else: + wsgi_server_name = environ['SERVER_NAME'] + + if (environ['wsgi.url_scheme'], environ['SERVER_PORT']) not \ + in (('https', '443'), ('http', '80')): + wsgi_server_name += ':' + environ['SERVER_PORT'] + + wsgi_server_name = wsgi_server_name.lower() + + if server_name is None: + server_name = wsgi_server_name + else: + server_name = server_name.lower() + + if subdomain is None and not self.host_matching: + cur_server_name = wsgi_server_name.split('.') + real_server_name = server_name.split('.') + offset = -len(real_server_name) + if cur_server_name[offset:] != real_server_name: + # This can happen even with valid configs if the server was + # accesssed directly by IP address under some situations. + # Instead of raising an exception like in Werkzeug 0.7 or + # earlier we go by an invalid subdomain which will result + # in a 404 error on matching. + subdomain = '' + else: + subdomain = '.'.join(filter(None, cur_server_name[:offset])) + + def _get_wsgi_string(name): + val = environ.get(name) + if val is not None: + return wsgi_decoding_dance(val, self.charset) + + script_name = _get_wsgi_string('SCRIPT_NAME') + path_info = _get_wsgi_string('PATH_INFO') + query_args = _get_wsgi_string('QUERY_STRING') + return Map.bind(self, server_name, script_name, + subdomain, environ['wsgi.url_scheme'], + environ['REQUEST_METHOD'], path_info, + query_args=query_args) + + def update(self): + """Called before matching and building to keep the compiled rules + in the correct order after things changed. + """ + if not self._remap: + return + + with self._remap_lock: + if not self._remap: + return + + self._rules.sort(key=lambda x: x.match_compare_key()) + for rules in itervalues(self._rules_by_endpoint): + rules.sort(key=lambda x: x.build_compare_key()) + self._remap = False + + def __repr__(self): + rules = self.iter_rules() + return '%s(%s)' % (self.__class__.__name__, pformat(list(rules))) + + +class MapAdapter(object): + + """Returned by :meth:`Map.bind` or :meth:`Map.bind_to_environ` and does + the URL matching and building based on runtime information. + """ + + def __init__(self, map, server_name, script_name, subdomain, + url_scheme, path_info, default_method, query_args=None): + self.map = map + self.server_name = to_unicode(server_name) + script_name = to_unicode(script_name) + if not script_name.endswith(u'/'): + script_name += u'/' + self.script_name = script_name + self.subdomain = to_unicode(subdomain) + self.url_scheme = to_unicode(url_scheme) + self.path_info = to_unicode(path_info) + self.default_method = to_unicode(default_method) + self.query_args = query_args + + def dispatch(self, view_func, path_info=None, method=None, + catch_http_exceptions=False): + """Does the complete dispatching process. `view_func` is called with + the endpoint and a dict with the values for the view. It should + look up the view function, call it, and return a response object + or WSGI application. http exceptions are not caught by default + so that applications can display nicer error messages by just + catching them by hand. If you want to stick with the default + error messages you can pass it ``catch_http_exceptions=True`` and + it will catch the http exceptions. + + Here a small example for the dispatch usage:: + + from werkzeug.wrappers import Request, Response + from werkzeug.wsgi import responder + from werkzeug.routing import Map, Rule + + def on_index(request): + return Response('Hello from the index') + + url_map = Map([Rule('/', endpoint='index')]) + views = {'index': on_index} + + @responder + def application(environ, start_response): + request = Request(environ) + urls = url_map.bind_to_environ(environ) + return urls.dispatch(lambda e, v: views[e](request, **v), + catch_http_exceptions=True) + + Keep in mind that this method might return exception objects, too, so + use :class:`Response.force_type` to get a response object. + + :param view_func: a function that is called with the endpoint as + first argument and the value dict as second. Has + to dispatch to the actual view function with this + information. (see above) + :param path_info: the path info to use for matching. Overrides the + path info specified on binding. + :param method: the HTTP method used for matching. Overrides the + method specified on binding. + :param catch_http_exceptions: set to `True` to catch any of the + werkzeug :class:`HTTPException`\s. + """ + try: + try: + endpoint, args = self.match(path_info, method) + except RequestRedirect as e: + return e + return view_func(endpoint, args) + except HTTPException as e: + if catch_http_exceptions: + return e + raise + + def match(self, path_info=None, method=None, return_rule=False, + query_args=None): + """The usage is simple: you just pass the match method the current + path info as well as the method (which defaults to `GET`). The + following things can then happen: + + - you receive a `NotFound` exception that indicates that no URL is + matching. A `NotFound` exception is also a WSGI application you + can call to get a default page not found page (happens to be the + same object as `werkzeug.exceptions.NotFound`) + + - you receive a `MethodNotAllowed` exception that indicates that there + is a match for this URL but not for the current request method. + This is useful for RESTful applications. + + - you receive a `RequestRedirect` exception with a `new_url` + attribute. This exception is used to notify you about a request + Werkzeug requests from your WSGI application. This is for example the + case if you request ``/foo`` although the correct URL is ``/foo/`` + You can use the `RequestRedirect` instance as response-like object + similar to all other subclasses of `HTTPException`. + + - you get a tuple in the form ``(endpoint, arguments)`` if there is + a match (unless `return_rule` is True, in which case you get a tuple + in the form ``(rule, arguments)``) + + If the path info is not passed to the match method the default path + info of the map is used (defaults to the root URL if not defined + explicitly). + + All of the exceptions raised are subclasses of `HTTPException` so they + can be used as WSGI responses. They will all render generic error or + redirect pages. + + Here is a small example for matching: + + >>> m = Map([ + ... Rule('/', endpoint='index'), + ... Rule('/downloads/', endpoint='downloads/index'), + ... Rule('/downloads/', endpoint='downloads/show') + ... ]) + >>> urls = m.bind("example.com", "/") + >>> urls.match("/", "GET") + ('index', {}) + >>> urls.match("/downloads/42") + ('downloads/show', {'id': 42}) + + And here is what happens on redirect and missing URLs: + + >>> urls.match("/downloads") + Traceback (most recent call last): + ... + RequestRedirect: http://example.com/downloads/ + >>> urls.match("/missing") + Traceback (most recent call last): + ... + NotFound: 404 Not Found + + :param path_info: the path info to use for matching. Overrides the + path info specified on binding. + :param method: the HTTP method used for matching. Overrides the + method specified on binding. + :param return_rule: return the rule that matched instead of just the + endpoint (defaults to `False`). + :param query_args: optional query arguments that are used for + automatic redirects as string or dictionary. It's + currently not possible to use the query arguments + for URL matching. + + .. versionadded:: 0.6 + `return_rule` was added. + + .. versionadded:: 0.7 + `query_args` was added. + + .. versionchanged:: 0.8 + `query_args` can now also be a string. + """ + self.map.update() + if path_info is None: + path_info = self.path_info + else: + path_info = to_unicode(path_info, self.map.charset) + if query_args is None: + query_args = self.query_args + method = (method or self.default_method).upper() + + path = u'%s|%s' % ( + self.map.host_matching and self.server_name or self.subdomain, + path_info and '/%s' % path_info.lstrip('/') + ) + + have_match_for = set() + for rule in self.map._rules: + try: + rv = rule.match(path, method) + except RequestSlash: + raise RequestRedirect(self.make_redirect_url( + url_quote(path_info, self.map.charset, + safe='/:|+') + '/', query_args)) + except RequestAliasRedirect as e: + raise RequestRedirect(self.make_alias_redirect_url( + path, rule.endpoint, e.matched_values, method, query_args)) + if rv is None: + continue + if rule.methods is not None and method not in rule.methods: + have_match_for.update(rule.methods) + continue + + if self.map.redirect_defaults: + redirect_url = self.get_default_redirect(rule, method, rv, + query_args) + if redirect_url is not None: + raise RequestRedirect(redirect_url) + + if rule.redirect_to is not None: + if isinstance(rule.redirect_to, string_types): + def _handle_match(match): + value = rv[match.group(1)] + return rule._converters[match.group(1)].to_url(value) + redirect_url = _simple_rule_re.sub(_handle_match, + rule.redirect_to) + else: + redirect_url = rule.redirect_to(self, **rv) + raise RequestRedirect(str(url_join('%s://%s%s%s' % ( + self.url_scheme or 'http', + self.subdomain and self.subdomain + '.' or '', + self.server_name, + self.script_name + ), redirect_url))) + + if return_rule: + return rule, rv + else: + return rule.endpoint, rv + + if have_match_for: + raise MethodNotAllowed(valid_methods=list(have_match_for)) + raise NotFound() + + def test(self, path_info=None, method=None): + """Test if a rule would match. Works like `match` but returns `True` + if the URL matches, or `False` if it does not exist. + + :param path_info: the path info to use for matching. Overrides the + path info specified on binding. + :param method: the HTTP method used for matching. Overrides the + method specified on binding. + """ + try: + self.match(path_info, method) + except RequestRedirect: + pass + except HTTPException: + return False + return True + + def allowed_methods(self, path_info=None): + """Returns the valid methods that match for a given path. + + .. versionadded:: 0.7 + """ + try: + self.match(path_info, method='--') + except MethodNotAllowed as e: + return e.valid_methods + except HTTPException as e: + pass + return [] + + def get_host(self, domain_part): + """Figures out the full host name for the given domain part. The + domain part is a subdomain in case host matching is disabled or + a full host name. + """ + if self.map.host_matching: + if domain_part is None: + return self.server_name + return to_unicode(domain_part, 'ascii') + subdomain = domain_part + if subdomain is None: + subdomain = self.subdomain + else: + subdomain = to_unicode(subdomain, 'ascii') + return (subdomain and subdomain + u'.' or u'') + self.server_name + + def get_default_redirect(self, rule, method, values, query_args): + """A helper that returns the URL to redirect to if it finds one. + This is used for default redirecting only. + + :internal: + """ + assert self.map.redirect_defaults + for r in self.map._rules_by_endpoint[rule.endpoint]: + # every rule that comes after this one, including ourself + # has a lower priority for the defaults. We order the ones + # with the highest priority up for building. + if r is rule: + break + if r.provides_defaults_for(rule) and \ + r.suitable_for(values, method): + values.update(r.defaults) + domain_part, path = r.build(values) + return self.make_redirect_url( + path, query_args, domain_part=domain_part) + + def encode_query_args(self, query_args): + if not isinstance(query_args, string_types): + query_args = url_encode(query_args, self.map.charset) + return query_args + + def make_redirect_url(self, path_info, query_args=None, domain_part=None): + """Creates a redirect URL. + + :internal: + """ + suffix = '' + if query_args: + suffix = '?' + self.encode_query_args(query_args) + return str('%s://%s/%s%s' % ( + self.url_scheme or 'http', + self.get_host(domain_part), + posixpath.join(self.script_name[:-1].lstrip('/'), + path_info.lstrip('/')), + suffix + )) + + def make_alias_redirect_url(self, path, endpoint, values, method, query_args): + """Internally called to make an alias redirect URL.""" + url = self.build(endpoint, values, method, append_unknown=False, + force_external=True) + if query_args: + url += '?' + self.encode_query_args(query_args) + assert url != path, 'detected invalid alias setting. No canonical ' \ + 'URL found' + return url + + def _partial_build(self, endpoint, values, method, append_unknown): + """Helper for :meth:`build`. Returns subdomain and path for the + rule that accepts this endpoint, values and method. + + :internal: + """ + # in case the method is none, try with the default method first + if method is None: + rv = self._partial_build(endpoint, values, self.default_method, + append_unknown) + if rv is not None: + return rv + + # default method did not match or a specific method is passed, + # check all and go with first result. + for rule in self.map._rules_by_endpoint.get(endpoint, ()): + if rule.suitable_for(values, method): + rv = rule.build(values, append_unknown) + if rv is not None: + return rv + + def build(self, endpoint, values=None, method=None, force_external=False, + append_unknown=True): + """Building URLs works pretty much the other way round. Instead of + `match` you call `build` and pass it the endpoint and a dict of + arguments for the placeholders. + + The `build` function also accepts an argument called `force_external` + which, if you set it to `True` will force external URLs. Per default + external URLs (include the server name) will only be used if the + target URL is on a different subdomain. + + >>> m = Map([ + ... Rule('/', endpoint='index'), + ... Rule('/downloads/', endpoint='downloads/index'), + ... Rule('/downloads/', endpoint='downloads/show') + ... ]) + >>> urls = m.bind("example.com", "/") + >>> urls.build("index", {}) + '/' + >>> urls.build("downloads/show", {'id': 42}) + '/downloads/42' + >>> urls.build("downloads/show", {'id': 42}, force_external=True) + 'http://example.com/downloads/42' + + Because URLs cannot contain non ASCII data you will always get + bytestrings back. Non ASCII characters are urlencoded with the + charset defined on the map instance. + + Additional values are converted to unicode and appended to the URL as + URL querystring parameters: + + >>> urls.build("index", {'q': 'My Searchstring'}) + '/?q=My+Searchstring' + + When processing those additional values, lists are furthermore + interpreted as multiple values (as per + :py:class:`werkzeug.datastructures.MultiDict`): + + >>> urls.build("index", {'q': ['a', 'b', 'c']}) + '/?q=a&q=b&q=c' + + If a rule does not exist when building a `BuildError` exception is + raised. + + The build method accepts an argument called `method` which allows you + to specify the method you want to have an URL built for if you have + different methods for the same endpoint specified. + + .. versionadded:: 0.6 + the `append_unknown` parameter was added. + + :param endpoint: the endpoint of the URL to build. + :param values: the values for the URL to build. Unhandled values are + appended to the URL as query parameters. + :param method: the HTTP method for the rule if there are different + URLs for different methods on the same endpoint. + :param force_external: enforce full canonical external URLs. If the URL + scheme is not provided, this will generate + a protocol-relative URL. + :param append_unknown: unknown parameters are appended to the generated + URL as query string argument. Disable this + if you want the builder to ignore those. + """ + self.map.update() + if values: + if isinstance(values, MultiDict): + valueiter = iteritems(values, multi=True) + else: + valueiter = iteritems(values) + values = dict((k, v) for k, v in valueiter if v is not None) + else: + values = {} + + rv = self._partial_build(endpoint, values, method, append_unknown) + if rv is None: + raise BuildError(endpoint, values, method, self) + domain_part, path = rv + + host = self.get_host(domain_part) + + # shortcut this. + if not force_external and ( + (self.map.host_matching and host == self.server_name) or + (not self.map.host_matching and domain_part == self.subdomain) + ): + return str(url_join(self.script_name, './' + path.lstrip('/'))) + return str('%s//%s%s/%s' % ( + self.url_scheme + ':' if self.url_scheme else '', + host, + self.script_name[:-1], + path.lstrip('/') + )) diff --git a/flex/lib/python3.6/site-packages/werkzeug/script.py b/flex/lib/python3.6/site-packages/werkzeug/script.py new file mode 100644 index 0000000..cfff3c1 --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/script.py @@ -0,0 +1,318 @@ +# -*- coding: utf-8 -*- +r''' + werkzeug.script + ~~~~~~~~~~~~~~~ + + .. admonition:: Deprecated Functionality + + ``werkzeug.script`` is deprecated without replacement functionality. + Python's command line support improved greatly with :mod:`argparse` + and a bunch of alternative modules. + + Most of the time you have recurring tasks while writing an application + such as starting up an interactive python interpreter with some prefilled + imports, starting the development server, initializing the database or + something similar. + + For that purpose werkzeug provides the `werkzeug.script` module which + helps you writing such scripts. + + + Basic Usage + ----------- + + The following snippet is roughly the same in every werkzeug script:: + + #!/usr/bin/env python + # -*- coding: utf-8 -*- + from werkzeug import script + + # actions go here + + if __name__ == '__main__': + script.run() + + Starting this script now does nothing because no actions are defined. + An action is a function in the same module starting with ``"action_"`` + which takes a number of arguments where every argument has a default. The + type of the default value specifies the type of the argument. + + Arguments can then be passed by position or using ``--name=value`` from + the shell. + + Because a runserver and shell command is pretty common there are two + factory functions that create such commands:: + + def make_app(): + from yourapplication import YourApplication + return YourApplication(...) + + action_runserver = script.make_runserver(make_app, use_reloader=True) + action_shell = script.make_shell(lambda: {'app': make_app()}) + + + Using The Scripts + ----------------- + + The script from above can be used like this from the shell now: + + .. sourcecode:: text + + $ ./manage.py --help + $ ./manage.py runserver localhost 8080 --debugger --no-reloader + $ ./manage.py runserver -p 4000 + $ ./manage.py shell + + As you can see it's possible to pass parameters as positional arguments + or as named parameters, pretty much like Python function calls. + + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +''' +from __future__ import print_function + +import sys +import inspect +import getopt +from os.path import basename +from werkzeug._compat import iteritems + + +argument_types = { + bool: 'boolean', + str: 'string', + int: 'integer', + float: 'float' +} + + +converters = { + 'boolean': lambda x: x.lower() in ('1', 'true', 'yes', 'on'), + 'string': str, + 'integer': int, + 'float': float +} + + +def run(namespace=None, action_prefix='action_', args=None): + """Run the script. Participating actions are looked up in the caller's + namespace if no namespace is given, otherwise in the dict provided. + Only items that start with action_prefix are processed as actions. If + you want to use all items in the namespace provided as actions set + action_prefix to an empty string. + + :param namespace: An optional dict where the functions are looked up in. + By default the local namespace of the caller is used. + :param action_prefix: The prefix for the functions. Everything else + is ignored. + :param args: the arguments for the function. If not specified + :data:`sys.argv` without the first argument is used. + """ + if namespace is None: + namespace = sys._getframe(1).f_locals + actions = find_actions(namespace, action_prefix) + + if args is None: + args = sys.argv[1:] + if not args or args[0] in ('-h', '--help'): + return print_usage(actions) + elif args[0] not in actions: + fail('Unknown action \'%s\'' % args[0]) + + arguments = {} + types = {} + key_to_arg = {} + long_options = [] + formatstring = '' + func, doc, arg_def = actions[args.pop(0)] + for idx, (arg, shortcut, default, option_type) in enumerate(arg_def): + real_arg = arg.replace('-', '_') + if shortcut: + formatstring += shortcut + if not isinstance(default, bool): + formatstring += ':' + key_to_arg['-' + shortcut] = real_arg + long_options.append(isinstance(default, bool) and arg or arg + '=') + key_to_arg['--' + arg] = real_arg + key_to_arg[idx] = real_arg + types[real_arg] = option_type + arguments[real_arg] = default + + try: + optlist, posargs = getopt.gnu_getopt(args, formatstring, long_options) + except getopt.GetoptError as e: + fail(str(e)) + + specified_arguments = set() + for key, value in enumerate(posargs): + try: + arg = key_to_arg[key] + except IndexError: + fail('Too many parameters') + specified_arguments.add(arg) + try: + arguments[arg] = converters[types[arg]](value) + except ValueError: + fail('Invalid value for argument %s (%s): %s' % (key, arg, value)) + + for key, value in optlist: + arg = key_to_arg[key] + if arg in specified_arguments: + fail('Argument \'%s\' is specified twice' % arg) + if types[arg] == 'boolean': + if arg.startswith('no_'): + value = 'no' + else: + value = 'yes' + try: + arguments[arg] = converters[types[arg]](value) + except ValueError: + fail('Invalid value for \'%s\': %s' % (key, value)) + + newargs = {} + for k, v in iteritems(arguments): + newargs[k.startswith('no_') and k[3:] or k] = v + arguments = newargs + return func(**arguments) + + +def fail(message, code=-1): + """Fail with an error.""" + print('Error: %s' % message, file=sys.stderr) + sys.exit(code) + + +def find_actions(namespace, action_prefix): + """Find all the actions in the namespace.""" + actions = {} + for key, value in iteritems(namespace): + if key.startswith(action_prefix): + actions[key[len(action_prefix):]] = analyse_action(value) + return actions + + +def print_usage(actions): + """Print the usage information. (Help screen)""" + actions = sorted(iteritems(actions)) + print('usage: %s []' % basename(sys.argv[0])) + print(' %s --help' % basename(sys.argv[0])) + print() + print('actions:') + for name, (func, doc, arguments) in actions: + print(' %s:' % name) + for line in doc.splitlines(): + print(' %s' % line) + if arguments: + print() + for arg, shortcut, default, argtype in arguments: + if isinstance(default, bool): + print(' %s' % ( + (shortcut and '-%s, ' % shortcut or '') + '--' + arg + )) + else: + print(' %-30s%-10s%s' % ( + (shortcut and '-%s, ' % shortcut or '') + '--' + arg, + argtype, default + )) + print() + + +def analyse_action(func): + """Analyse a function.""" + description = inspect.getdoc(func) or 'undocumented action' + arguments = [] + args, varargs, kwargs, defaults = inspect.getargspec(func) + if varargs or kwargs: + raise TypeError('variable length arguments for action not allowed.') + if len(args) != len(defaults or ()): + raise TypeError('not all arguments have proper definitions') + + for idx, (arg, definition) in enumerate(zip(args, defaults or ())): + if arg.startswith('_'): + raise TypeError('arguments may not start with an underscore') + if not isinstance(definition, tuple): + shortcut = None + default = definition + else: + shortcut, default = definition + argument_type = argument_types[type(default)] + if isinstance(default, bool) and default is True: + arg = 'no-' + arg + arguments.append((arg.replace('_', '-'), shortcut, + default, argument_type)) + return func, description, arguments + + +def make_shell(init_func=None, banner=None, use_ipython=True): + """Returns an action callback that spawns a new interactive + python shell. + + :param init_func: an optional initialization function that is + called before the shell is started. The return + value of this function is the initial namespace. + :param banner: the banner that is displayed before the shell. If + not specified a generic banner is used instead. + :param use_ipython: if set to `True` ipython is used if available. + """ + if banner is None: + banner = 'Interactive Werkzeug Shell' + if init_func is None: + init_func = dict + + def action(ipython=use_ipython): + """Start a new interactive python session.""" + namespace = init_func() + if ipython: + try: + try: + from IPython.frontend.terminal.embed import InteractiveShellEmbed + sh = InteractiveShellEmbed(banner1=banner) + except ImportError: + from IPython.Shell import IPShellEmbed + sh = IPShellEmbed(banner=banner) + except ImportError: + pass + else: + sh(global_ns={}, local_ns=namespace) + return + from code import interact + interact(banner, local=namespace) + return action + + +def make_runserver(app_factory, hostname='localhost', port=5000, + use_reloader=False, use_debugger=False, use_evalex=True, + threaded=False, processes=1, static_files=None, + extra_files=None, ssl_context=None): + """Returns an action callback that spawns a new development server. + + .. versionadded:: 0.5 + `static_files` and `extra_files` was added. + + ..versionadded:: 0.6.1 + `ssl_context` was added. + + :param app_factory: a function that returns a new WSGI application. + :param hostname: the default hostname the server should listen on. + :param port: the default port of the server. + :param use_reloader: the default setting for the reloader. + :param use_evalex: the default setting for the evalex flag of the debugger. + :param threaded: the default threading setting. + :param processes: the default number of processes to start. + :param static_files: optional dict of static files. + :param extra_files: optional list of extra files to track for reloading. + :param ssl_context: optional SSL context for running server in HTTPS mode. + """ + def action(hostname=('h', hostname), port=('p', port), + reloader=use_reloader, debugger=use_debugger, + evalex=use_evalex, threaded=threaded, processes=processes): + """Start a new development server.""" + from werkzeug.serving import run_simple + app = app_factory() + run_simple(hostname, port, app, + use_reloader=reloader, use_debugger=debugger, + use_evalex=evalex, extra_files=extra_files, + reloader_interval=1, threaded=threaded, processes=processes, + static_files=static_files, ssl_context=ssl_context) + return action diff --git a/flex/lib/python3.6/site-packages/werkzeug/security.py b/flex/lib/python3.6/site-packages/werkzeug/security.py new file mode 100644 index 0000000..d4c5c9f --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/security.py @@ -0,0 +1,270 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.security + ~~~~~~~~~~~~~~~~~ + + Security related helpers such as secure password hashing tools. + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import os +import hmac +import hashlib +import posixpath +import codecs +from struct import Struct +from random import SystemRandom +from operator import xor +from itertools import starmap + +from werkzeug._compat import range_type, PY2, text_type, izip, to_bytes, \ + string_types, to_native + + +SALT_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' +DEFAULT_PBKDF2_ITERATIONS = 50000 + + +_pack_int = Struct('>I').pack +_builtin_safe_str_cmp = getattr(hmac, 'compare_digest', None) +_sys_rng = SystemRandom() +_os_alt_seps = list(sep for sep in [os.path.sep, os.path.altsep] + if sep not in (None, '/')) + + +def _find_hashlib_algorithms(): + algos = getattr(hashlib, 'algorithms', None) + if algos is None: + algos = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512') + rv = {} + for algo in algos: + func = getattr(hashlib, algo, None) + if func is not None: + rv[algo] = func + return rv +_hash_funcs = _find_hashlib_algorithms() + + +def pbkdf2_hex(data, salt, iterations=DEFAULT_PBKDF2_ITERATIONS, + keylen=None, hashfunc=None): + """Like :func:`pbkdf2_bin`, but returns a hex-encoded string. + + .. versionadded:: 0.9 + + :param data: the data to derive. + :param salt: the salt for the derivation. + :param iterations: the number of iterations. + :param keylen: the length of the resulting key. If not provided, + the digest size will be used. + :param hashfunc: the hash function to use. This can either be the + string name of a known hash function, or a function + from the hashlib module. Defaults to sha256. + """ + rv = pbkdf2_bin(data, salt, iterations, keylen, hashfunc) + return to_native(codecs.encode(rv, 'hex_codec')) + + +_has_native_pbkdf2 = hasattr(hashlib, 'pbkdf2_hmac') + + +def pbkdf2_bin(data, salt, iterations=DEFAULT_PBKDF2_ITERATIONS, + keylen=None, hashfunc=None): + """Returns a binary digest for the PBKDF2 hash algorithm of `data` + with the given `salt`. It iterates `iterations` times and produces a + key of `keylen` bytes. By default, SHA-256 is used as hash function; + a different hashlib `hashfunc` can be provided. + + .. versionadded:: 0.9 + + :param data: the data to derive. + :param salt: the salt for the derivation. + :param iterations: the number of iterations. + :param keylen: the length of the resulting key. If not provided + the digest size will be used. + :param hashfunc: the hash function to use. This can either be the + string name of a known hash function or a function + from the hashlib module. Defaults to sha256. + """ + if isinstance(hashfunc, string_types): + hashfunc = _hash_funcs[hashfunc] + elif not hashfunc: + hashfunc = hashlib.sha256 + data = to_bytes(data) + salt = to_bytes(salt) + + # If we're on Python with pbkdf2_hmac we can try to use it for + # compatible digests. + if _has_native_pbkdf2: + _test_hash = hashfunc() + if hasattr(_test_hash, 'name') and \ + _test_hash.name in _hash_funcs: + return hashlib.pbkdf2_hmac(_test_hash.name, + data, salt, iterations, + keylen) + + mac = hmac.HMAC(data, None, hashfunc) + if not keylen: + keylen = mac.digest_size + + def _pseudorandom(x, mac=mac): + h = mac.copy() + h.update(x) + return bytearray(h.digest()) + buf = bytearray() + for block in range_type(1, -(-keylen // mac.digest_size) + 1): + rv = u = _pseudorandom(salt + _pack_int(block)) + for i in range_type(iterations - 1): + u = _pseudorandom(bytes(u)) + rv = bytearray(starmap(xor, izip(rv, u))) + buf.extend(rv) + return bytes(buf[:keylen]) + + +def safe_str_cmp(a, b): + """This function compares strings in somewhat constant time. This + requires that the length of at least one string is known in advance. + + Returns `True` if the two strings are equal, or `False` if they are not. + + .. versionadded:: 0.7 + """ + if isinstance(a, text_type): + a = a.encode('utf-8') + if isinstance(b, text_type): + b = b.encode('utf-8') + + if _builtin_safe_str_cmp is not None: + return _builtin_safe_str_cmp(a, b) + + if len(a) != len(b): + return False + + rv = 0 + if PY2: + for x, y in izip(a, b): + rv |= ord(x) ^ ord(y) + else: + for x, y in izip(a, b): + rv |= x ^ y + + return rv == 0 + + +def gen_salt(length): + """Generate a random string of SALT_CHARS with specified ``length``.""" + if length <= 0: + raise ValueError('Salt length must be positive') + return ''.join(_sys_rng.choice(SALT_CHARS) for _ in range_type(length)) + + +def _hash_internal(method, salt, password): + """Internal password hash helper. Supports plaintext without salt, + unsalted and salted passwords. In case salted passwords are used + hmac is used. + """ + if method == 'plain': + return password, method + + if isinstance(password, text_type): + password = password.encode('utf-8') + + if method.startswith('pbkdf2:'): + args = method[7:].split(':') + if len(args) not in (1, 2): + raise ValueError('Invalid number of arguments for PBKDF2') + method = args.pop(0) + iterations = args and int(args[0] or 0) or DEFAULT_PBKDF2_ITERATIONS + is_pbkdf2 = True + actual_method = 'pbkdf2:%s:%d' % (method, iterations) + else: + is_pbkdf2 = False + actual_method = method + + hash_func = _hash_funcs.get(method) + if hash_func is None: + raise TypeError('invalid method %r' % method) + + if is_pbkdf2: + if not salt: + raise ValueError('Salt is required for PBKDF2') + rv = pbkdf2_hex(password, salt, iterations, + hashfunc=hash_func) + elif salt: + if isinstance(salt, text_type): + salt = salt.encode('utf-8') + rv = hmac.HMAC(salt, password, hash_func).hexdigest() + else: + h = hash_func() + h.update(password) + rv = h.hexdigest() + return rv, actual_method + + +def generate_password_hash(password, method='pbkdf2:sha256', salt_length=8): + """Hash a password with the given method and salt with a string of + the given length. The format of the string returned includes the method + that was used so that :func:`check_password_hash` can check the hash. + + The format for the hashed string looks like this:: + + method$salt$hash + + This method can **not** generate unsalted passwords but it is possible + to set param method='plain' in order to enforce plaintext passwords. + If a salt is used, hmac is used internally to salt the password. + + If PBKDF2 is wanted it can be enabled by setting the method to + ``pbkdf2:method:iterations`` where iterations is optional:: + + pbkdf2:sha256:80000$salt$hash + pbkdf2:sha256$salt$hash + + :param password: the password to hash. + :param method: the hash method to use (one that hashlib supports). Can + optionally be in the format ``pbkdf2:[:iterations]`` + to enable PBKDF2. + :param salt_length: the length of the salt in letters. + """ + salt = method != 'plain' and gen_salt(salt_length) or '' + h, actual_method = _hash_internal(method, salt, password) + return '%s$%s$%s' % (actual_method, salt, h) + + +def check_password_hash(pwhash, password): + """check a password against a given salted and hashed password value. + In order to support unsalted legacy passwords this method supports + plain text passwords, md5 and sha1 hashes (both salted and unsalted). + + Returns `True` if the password matched, `False` otherwise. + + :param pwhash: a hashed string like returned by + :func:`generate_password_hash`. + :param password: the plaintext password to compare against the hash. + """ + if pwhash.count('$') < 2: + return False + method, salt, hashval = pwhash.split('$', 2) + return safe_str_cmp(_hash_internal(method, salt, password)[0], hashval) + + +def safe_join(directory, *pathnames): + """Safely join `directory` and one or more untrusted `pathnames`. If this + cannot be done, this function returns ``None``. + + :param directory: the base directory. + :param pathnames: the untrusted pathnames relative to that directory. + """ + parts = [directory] + for filename in pathnames: + if filename != '': + filename = posixpath.normpath(filename) + for sep in _os_alt_seps: + if sep in filename: + return None + if os.path.isabs(filename) or \ + filename == '..' or \ + filename.startswith('../'): + return None + parts.append(filename) + return posixpath.join(*parts) diff --git a/flex/lib/python3.6/site-packages/werkzeug/serving.py b/flex/lib/python3.6/site-packages/werkzeug/serving.py new file mode 100644 index 0000000..902f1aa --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/serving.py @@ -0,0 +1,862 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.serving + ~~~~~~~~~~~~~~~~ + + There are many ways to serve a WSGI application. While you're developing + it you usually don't want a full blown webserver like Apache but a simple + standalone one. From Python 2.5 onwards there is the `wsgiref`_ server in + the standard library. If you're using older versions of Python you can + download the package from the cheeseshop. + + However there are some caveats. Sourcecode won't reload itself when + changed and each time you kill the server using ``^C`` you get an + `KeyboardInterrupt` error. While the latter is easy to solve the first + one can be a pain in the ass in some situations. + + The easiest way is creating a small ``start-myproject.py`` that runs the + application:: + + #!/usr/bin/env python + # -*- coding: utf-8 -*- + from myproject import make_app + from werkzeug.serving import run_simple + + app = make_app(...) + run_simple('localhost', 8080, app, use_reloader=True) + + You can also pass it a `extra_files` keyword argument with a list of + additional files (like configuration files) you want to observe. + + For bigger applications you should consider using `click` + (http://click.pocoo.org) instead of a simple start file. + + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +from __future__ import with_statement + +import io +import os +import socket +import sys +import signal + + +can_fork = hasattr(os, "fork") + + +try: + import termcolor +except ImportError: + termcolor = None + +try: + import ssl +except ImportError: + class _SslDummy(object): + def __getattr__(self, name): + raise RuntimeError('SSL support unavailable') + ssl = _SslDummy() + + +def _get_openssl_crypto_module(): + try: + from OpenSSL import crypto + except ImportError: + raise TypeError('Using ad-hoc certificates requires the pyOpenSSL ' + 'library.') + else: + return crypto + + +try: + import SocketServer as socketserver + from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler +except ImportError: + import socketserver + from http.server import HTTPServer, BaseHTTPRequestHandler + +ThreadingMixIn = socketserver.ThreadingMixIn + +if can_fork: + ForkingMixIn = socketserver.ForkingMixIn +else: + class ForkingMixIn(object): + pass + +# important: do not use relative imports here or python -m will break +import werkzeug +from werkzeug._internal import _log +from werkzeug._compat import PY2, WIN, reraise, wsgi_encoding_dance +from werkzeug.urls import url_parse, url_unquote +from werkzeug.exceptions import InternalServerError + + +LISTEN_QUEUE = 128 +can_open_by_fd = not WIN and hasattr(socket, 'fromfd') + + +class DechunkedInput(io.RawIOBase): + """An input stream that handles Transfer-Encoding 'chunked'""" + + def __init__(self, rfile): + self._rfile = rfile + self._done = False + self._len = 0 + + def readable(self): + return True + + def read_chunk_len(self): + try: + line = self._rfile.readline().decode('latin1') + _len = int(line.strip(), 16) + except ValueError: + raise IOError('Invalid chunk header') + if _len < 0: + raise IOError('Negative chunk length not allowed') + return _len + + def readinto(self, buf): + read = 0 + while not self._done and read < len(buf): + if self._len == 0: + # This is the first chunk or we fully consumed the previous + # one. Read the next length of the next chunk + self._len = self.read_chunk_len() + + if self._len == 0: + # Found the final chunk of size 0. The stream is now exhausted, + # but there is still a final newline that should be consumed + self._done = True + + if self._len > 0: + # There is data (left) in this chunk, so append it to the + # buffer. If this operation fully consumes the chunk, this will + # reset self._len to 0. + n = min(len(buf), self._len) + buf[read:read + n] = self._rfile.read(n) + self._len -= n + read += n + + if self._len == 0: + # Skip the terminating newline of a chunk that has been fully + # consumed. This also applies to the 0-sized final chunk + terminator = self._rfile.readline() + if terminator not in (b'\n', b'\r\n', b'\r'): + raise IOError('Missing chunk terminating newline') + + return read + + +class WSGIRequestHandler(BaseHTTPRequestHandler, object): + + """A request handler that implements WSGI dispatching.""" + + @property + def server_version(self): + return 'Werkzeug/' + werkzeug.__version__ + + def make_environ(self): + request_url = url_parse(self.path) + + def shutdown_server(): + self.server.shutdown_signal = True + + url_scheme = self.server.ssl_context is None and 'http' or 'https' + path_info = url_unquote(request_url.path) + + environ = { + 'wsgi.version': (1, 0), + 'wsgi.url_scheme': url_scheme, + 'wsgi.input': self.rfile, + 'wsgi.errors': sys.stderr, + 'wsgi.multithread': self.server.multithread, + 'wsgi.multiprocess': self.server.multiprocess, + 'wsgi.run_once': False, + 'werkzeug.server.shutdown': shutdown_server, + 'SERVER_SOFTWARE': self.server_version, + 'REQUEST_METHOD': self.command, + 'SCRIPT_NAME': '', + 'PATH_INFO': wsgi_encoding_dance(path_info), + 'QUERY_STRING': wsgi_encoding_dance(request_url.query), + 'REMOTE_ADDR': self.address_string(), + 'REMOTE_PORT': self.port_integer(), + 'SERVER_NAME': self.server.server_address[0], + 'SERVER_PORT': str(self.server.server_address[1]), + 'SERVER_PROTOCOL': self.request_version + } + + for key, value in self.headers.items(): + key = key.upper().replace('-', '_') + if key not in ('CONTENT_TYPE', 'CONTENT_LENGTH'): + key = 'HTTP_' + key + environ[key] = value + + if environ.get('HTTP_TRANSFER_ENCODING', '').strip().lower() == 'chunked': + environ['wsgi.input_terminated'] = True + environ['wsgi.input'] = DechunkedInput(environ['wsgi.input']) + + if request_url.scheme and request_url.netloc: + environ['HTTP_HOST'] = request_url.netloc + + return environ + + def run_wsgi(self): + if self.headers.get('Expect', '').lower().strip() == '100-continue': + self.wfile.write(b'HTTP/1.1 100 Continue\r\n\r\n') + + self.environ = environ = self.make_environ() + headers_set = [] + headers_sent = [] + + def write(data): + assert headers_set, 'write() before start_response' + if not headers_sent: + status, response_headers = headers_sent[:] = headers_set + try: + code, msg = status.split(None, 1) + except ValueError: + code, msg = status, "" + code = int(code) + self.send_response(code, msg) + header_keys = set() + for key, value in response_headers: + self.send_header(key, value) + key = key.lower() + header_keys.add(key) + if not ('content-length' in header_keys or + environ['REQUEST_METHOD'] == 'HEAD' or + code < 200 or code in (204, 304)): + self.close_connection = True + self.send_header('Connection', 'close') + if 'server' not in header_keys: + self.send_header('Server', self.version_string()) + if 'date' not in header_keys: + self.send_header('Date', self.date_time_string()) + self.end_headers() + + assert isinstance(data, bytes), 'applications must write bytes' + self.wfile.write(data) + self.wfile.flush() + + def start_response(status, response_headers, exc_info=None): + if exc_info: + try: + if headers_sent: + reraise(*exc_info) + finally: + exc_info = None + elif headers_set: + raise AssertionError('Headers already set') + headers_set[:] = [status, response_headers] + return write + + def execute(app): + application_iter = app(environ, start_response) + try: + for data in application_iter: + write(data) + if not headers_sent: + write(b'') + finally: + if hasattr(application_iter, 'close'): + application_iter.close() + application_iter = None + + try: + execute(self.server.app) + except (socket.error, socket.timeout) as e: + self.connection_dropped(e, environ) + except Exception: + if self.server.passthrough_errors: + raise + from werkzeug.debug.tbtools import get_current_traceback + traceback = get_current_traceback(ignore_system_exceptions=True) + try: + # if we haven't yet sent the headers but they are set + # we roll back to be able to set them again. + if not headers_sent: + del headers_set[:] + execute(InternalServerError()) + except Exception: + pass + self.server.log('error', 'Error on request:\n%s', + traceback.plaintext) + + def handle(self): + """Handles a request ignoring dropped connections.""" + rv = None + try: + rv = BaseHTTPRequestHandler.handle(self) + except (socket.error, socket.timeout) as e: + self.connection_dropped(e) + except Exception: + if self.server.ssl_context is None or not is_ssl_error(): + raise + if self.server.shutdown_signal: + self.initiate_shutdown() + return rv + + def initiate_shutdown(self): + """A horrible, horrible way to kill the server for Python 2.6 and + later. It's the best we can do. + """ + # Windows does not provide SIGKILL, go with SIGTERM then. + sig = getattr(signal, 'SIGKILL', signal.SIGTERM) + # reloader active + if os.environ.get('WERKZEUG_RUN_MAIN') == 'true': + os.kill(os.getpid(), sig) + # python 2.7 + self.server._BaseServer__shutdown_request = True + # python 2.6 + self.server._BaseServer__serving = False + + def connection_dropped(self, error, environ=None): + """Called if the connection was closed by the client. By default + nothing happens. + """ + + def handle_one_request(self): + """Handle a single HTTP request.""" + self.raw_requestline = self.rfile.readline() + if not self.raw_requestline: + self.close_connection = 1 + elif self.parse_request(): + return self.run_wsgi() + + def send_response(self, code, message=None): + """Send the response header and log the response code.""" + self.log_request(code) + if message is None: + message = code in self.responses and self.responses[code][0] or '' + if self.request_version != 'HTTP/0.9': + hdr = "%s %d %s\r\n" % (self.protocol_version, code, message) + self.wfile.write(hdr.encode('ascii')) + + def version_string(self): + return BaseHTTPRequestHandler.version_string(self).strip() + + def address_string(self): + if getattr(self, 'environ', None): + return self.environ['REMOTE_ADDR'] + else: + return self.client_address[0] + + def port_integer(self): + return self.client_address[1] + + def log_request(self, code='-', size='-'): + msg = self.requestline + code = str(code) + + if termcolor: + color = termcolor.colored + + if code[0] == '1': # 1xx - Informational + msg = color(msg, attrs=['bold']) + elif code[0] == '2': # 2xx - Success + msg = color(msg, color='white') + elif code == '304': # 304 - Resource Not Modified + msg = color(msg, color='cyan') + elif code[0] == '3': # 3xx - Redirection + msg = color(msg, color='green') + elif code == '404': # 404 - Resource Not Found + msg = color(msg, color='yellow') + elif code[0] == '4': # 4xx - Client Error + msg = color(msg, color='red', attrs=['bold']) + else: # 5xx, or any other response + msg = color(msg, color='magenta', attrs=['bold']) + + self.log('info', '"%s" %s %s', msg, code, size) + + def log_error(self, *args): + self.log('error', *args) + + def log_message(self, format, *args): + self.log('info', format, *args) + + def log(self, type, message, *args): + _log(type, '%s - - [%s] %s\n' % (self.address_string(), + self.log_date_time_string(), + message % args)) + + +#: backwards compatible name if someone is subclassing it +BaseRequestHandler = WSGIRequestHandler + + +def generate_adhoc_ssl_pair(cn=None): + from random import random + crypto = _get_openssl_crypto_module() + + # pretty damn sure that this is not actually accepted by anyone + if cn is None: + cn = '*' + + cert = crypto.X509() + cert.set_serial_number(int(random() * sys.maxsize)) + cert.gmtime_adj_notBefore(0) + cert.gmtime_adj_notAfter(60 * 60 * 24 * 365) + + subject = cert.get_subject() + subject.CN = cn + subject.O = 'Dummy Certificate' # noqa: E741 + + issuer = cert.get_issuer() + issuer.CN = 'Untrusted Authority' + issuer.O = 'Self-Signed' # noqa: E741 + + pkey = crypto.PKey() + pkey.generate_key(crypto.TYPE_RSA, 2048) + cert.set_pubkey(pkey) + cert.sign(pkey, 'sha256') + + return cert, pkey + + +def make_ssl_devcert(base_path, host=None, cn=None): + """Creates an SSL key for development. This should be used instead of + the ``'adhoc'`` key which generates a new cert on each server start. + It accepts a path for where it should store the key and cert and + either a host or CN. If a host is given it will use the CN + ``*.host/CN=host``. + + For more information see :func:`run_simple`. + + .. versionadded:: 0.9 + + :param base_path: the path to the certificate and key. The extension + ``.crt`` is added for the certificate, ``.key`` is + added for the key. + :param host: the name of the host. This can be used as an alternative + for the `cn`. + :param cn: the `CN` to use. + """ + from OpenSSL import crypto + if host is not None: + cn = '*.%s/CN=%s' % (host, host) + cert, pkey = generate_adhoc_ssl_pair(cn=cn) + + cert_file = base_path + '.crt' + pkey_file = base_path + '.key' + + with open(cert_file, 'wb') as f: + f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) + with open(pkey_file, 'wb') as f: + f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey)) + + return cert_file, pkey_file + + +def generate_adhoc_ssl_context(): + """Generates an adhoc SSL context for the development server.""" + crypto = _get_openssl_crypto_module() + import tempfile + import atexit + + cert, pkey = generate_adhoc_ssl_pair() + cert_handle, cert_file = tempfile.mkstemp() + pkey_handle, pkey_file = tempfile.mkstemp() + atexit.register(os.remove, pkey_file) + atexit.register(os.remove, cert_file) + + os.write(cert_handle, crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) + os.write(pkey_handle, crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey)) + os.close(cert_handle) + os.close(pkey_handle) + ctx = load_ssl_context(cert_file, pkey_file) + return ctx + + +def load_ssl_context(cert_file, pkey_file=None, protocol=None): + """Loads SSL context from cert/private key files and optional protocol. + Many parameters are directly taken from the API of + :py:class:`ssl.SSLContext`. + + :param cert_file: Path of the certificate to use. + :param pkey_file: Path of the private key to use. If not given, the key + will be obtained from the certificate file. + :param protocol: One of the ``PROTOCOL_*`` constants in the stdlib ``ssl`` + module. Defaults to ``PROTOCOL_SSLv23``. + """ + if protocol is None: + protocol = ssl.PROTOCOL_SSLv23 + ctx = _SSLContext(protocol) + ctx.load_cert_chain(cert_file, pkey_file) + return ctx + + +class _SSLContext(object): + + '''A dummy class with a small subset of Python3's ``ssl.SSLContext``, only + intended to be used with and by Werkzeug.''' + + def __init__(self, protocol): + self._protocol = protocol + self._certfile = None + self._keyfile = None + self._password = None + + def load_cert_chain(self, certfile, keyfile=None, password=None): + self._certfile = certfile + self._keyfile = keyfile or certfile + self._password = password + + def wrap_socket(self, sock, **kwargs): + return ssl.wrap_socket(sock, keyfile=self._keyfile, + certfile=self._certfile, + ssl_version=self._protocol, **kwargs) + + +def is_ssl_error(error=None): + """Checks if the given error (or the current one) is an SSL error.""" + exc_types = (ssl.SSLError,) + try: + from OpenSSL.SSL import Error + exc_types += (Error,) + except ImportError: + pass + + if error is None: + error = sys.exc_info()[1] + return isinstance(error, exc_types) + + +def select_ip_version(host, port): + """Returns AF_INET4 or AF_INET6 depending on where to connect to.""" + # disabled due to problems with current ipv6 implementations + # and various operating systems. Probably this code also is + # not supposed to work, but I can't come up with any other + # ways to implement this. + # try: + # info = socket.getaddrinfo(host, port, socket.AF_UNSPEC, + # socket.SOCK_STREAM, 0, + # socket.AI_PASSIVE) + # if info: + # return info[0][0] + # except socket.gaierror: + # pass + if ':' in host and hasattr(socket, 'AF_INET6'): + return socket.AF_INET6 + return socket.AF_INET + + +def get_sockaddr(host, port, family): + """Returns a fully qualified socket address, that can properly used by + socket.bind""" + try: + res = socket.getaddrinfo(host, port, family, + socket.SOCK_STREAM, socket.SOL_TCP) + except socket.gaierror: + return (host, port) + return res[0][4] + + +class BaseWSGIServer(HTTPServer, object): + + """Simple single-threaded, single-process WSGI server.""" + multithread = False + multiprocess = False + request_queue_size = LISTEN_QUEUE + + def __init__(self, host, port, app, handler=None, + passthrough_errors=False, ssl_context=None, fd=None): + if handler is None: + handler = WSGIRequestHandler + + self.address_family = select_ip_version(host, port) + + if fd is not None: + real_sock = socket.fromfd(fd, self.address_family, + socket.SOCK_STREAM) + port = 0 + HTTPServer.__init__(self, get_sockaddr(host, int(port), + self.address_family), handler) + self.app = app + self.passthrough_errors = passthrough_errors + self.shutdown_signal = False + self.host = host + self.port = self.socket.getsockname()[1] + + # Patch in the original socket. + if fd is not None: + self.socket.close() + self.socket = real_sock + self.server_address = self.socket.getsockname() + + if ssl_context is not None: + if isinstance(ssl_context, tuple): + ssl_context = load_ssl_context(*ssl_context) + if ssl_context == 'adhoc': + ssl_context = generate_adhoc_ssl_context() + # If we are on Python 2 the return value from socket.fromfd + # is an internal socket object but what we need for ssl wrap + # is the wrapper around it :( + sock = self.socket + if PY2 and not isinstance(sock, socket.socket): + sock = socket.socket(sock.family, sock.type, sock.proto, sock) + self.socket = ssl_context.wrap_socket(sock, server_side=True) + self.ssl_context = ssl_context + else: + self.ssl_context = None + + def log(self, type, message, *args): + _log(type, message, *args) + + def serve_forever(self): + self.shutdown_signal = False + try: + HTTPServer.serve_forever(self) + except KeyboardInterrupt: + pass + finally: + self.server_close() + + def handle_error(self, request, client_address): + if self.passthrough_errors: + raise + return HTTPServer.handle_error(self, request, client_address) + + def get_request(self): + con, info = self.socket.accept() + return con, info + + +class ThreadedWSGIServer(ThreadingMixIn, BaseWSGIServer): + + """A WSGI server that does threading.""" + multithread = True + daemon_threads = True + + +class ForkingWSGIServer(ForkingMixIn, BaseWSGIServer): + + """A WSGI server that does forking.""" + multiprocess = True + + def __init__(self, host, port, app, processes=40, handler=None, + passthrough_errors=False, ssl_context=None, fd=None): + if not can_fork: + raise ValueError('Your platform does not support forking.') + BaseWSGIServer.__init__(self, host, port, app, handler, + passthrough_errors, ssl_context, fd) + self.max_children = processes + + +def make_server(host=None, port=None, app=None, threaded=False, processes=1, + request_handler=None, passthrough_errors=False, + ssl_context=None, fd=None): + """Create a new server instance that is either threaded, or forks + or just processes one request after another. + """ + if threaded and processes > 1: + raise ValueError("cannot have a multithreaded and " + "multi process server.") + elif threaded: + return ThreadedWSGIServer(host, port, app, request_handler, + passthrough_errors, ssl_context, fd=fd) + elif processes > 1: + return ForkingWSGIServer(host, port, app, processes, request_handler, + passthrough_errors, ssl_context, fd=fd) + else: + return BaseWSGIServer(host, port, app, request_handler, + passthrough_errors, ssl_context, fd=fd) + + +def is_running_from_reloader(): + """Checks if the application is running from within the Werkzeug + reloader subprocess. + + .. versionadded:: 0.10 + """ + return os.environ.get('WERKZEUG_RUN_MAIN') == 'true' + + +def run_simple(hostname, port, application, use_reloader=False, + use_debugger=False, use_evalex=True, + extra_files=None, reloader_interval=1, + reloader_type='auto', threaded=False, + processes=1, request_handler=None, static_files=None, + passthrough_errors=False, ssl_context=None): + """Start a WSGI application. Optional features include a reloader, + multithreading and fork support. + + This function has a command-line interface too:: + + python -m werkzeug.serving --help + + .. versionadded:: 0.5 + `static_files` was added to simplify serving of static files as well + as `passthrough_errors`. + + .. versionadded:: 0.6 + support for SSL was added. + + .. versionadded:: 0.8 + Added support for automatically loading a SSL context from certificate + file and private key. + + .. versionadded:: 0.9 + Added command-line interface. + + .. versionadded:: 0.10 + Improved the reloader and added support for changing the backend + through the `reloader_type` parameter. See :ref:`reloader` + for more information. + + :param hostname: The host for the application. eg: ``'localhost'`` + :param port: The port for the server. eg: ``8080`` + :param application: the WSGI application to execute + :param use_reloader: should the server automatically restart the python + process if modules were changed? + :param use_debugger: should the werkzeug debugging system be used? + :param use_evalex: should the exception evaluation feature be enabled? + :param extra_files: a list of files the reloader should watch + additionally to the modules. For example configuration + files. + :param reloader_interval: the interval for the reloader in seconds. + :param reloader_type: the type of reloader to use. The default is + auto detection. Valid values are ``'stat'`` and + ``'watchdog'``. See :ref:`reloader` for more + information. + :param threaded: should the process handle each request in a separate + thread? + :param processes: if greater than 1 then handle each request in a new process + up to this maximum number of concurrent processes. + :param request_handler: optional parameter that can be used to replace + the default one. You can use this to replace it + with a different + :class:`~BaseHTTPServer.BaseHTTPRequestHandler` + subclass. + :param static_files: a list or dict of paths for static files. This works + exactly like :class:`SharedDataMiddleware`, it's actually + just wrapping the application in that middleware before + serving. + :param passthrough_errors: set this to `True` to disable the error catching. + This means that the server will die on errors but + it can be useful to hook debuggers in (pdb etc.) + :param ssl_context: an SSL context for the connection. Either an + :class:`ssl.SSLContext`, a tuple in the form + ``(cert_file, pkey_file)``, the string ``'adhoc'`` if + the server should automatically create one, or ``None`` + to disable SSL (which is the default). + """ + if not isinstance(port, int): + raise TypeError('port must be an integer') + if use_debugger: + from werkzeug.debug import DebuggedApplication + application = DebuggedApplication(application, use_evalex) + if static_files: + from werkzeug.wsgi import SharedDataMiddleware + application = SharedDataMiddleware(application, static_files) + + def log_startup(sock): + display_hostname = hostname not in ('', '*') and hostname or 'localhost' + if ':' in display_hostname: + display_hostname = '[%s]' % display_hostname + quit_msg = '(Press CTRL+C to quit)' + port = sock.getsockname()[1] + _log('info', ' * Running on %s://%s:%d/ %s', + ssl_context is None and 'http' or 'https', + display_hostname, port, quit_msg) + + def inner(): + try: + fd = int(os.environ['WERKZEUG_SERVER_FD']) + except (LookupError, ValueError): + fd = None + srv = make_server(hostname, port, application, threaded, + processes, request_handler, + passthrough_errors, ssl_context, + fd=fd) + if fd is None: + log_startup(srv.socket) + srv.serve_forever() + + if use_reloader: + # If we're not running already in the subprocess that is the + # reloader we want to open up a socket early to make sure the + # port is actually available. + if os.environ.get('WERKZEUG_RUN_MAIN') != 'true': + if port == 0 and not can_open_by_fd: + raise ValueError('Cannot bind to a random port with enabled ' + 'reloader if the Python interpreter does ' + 'not support socket opening by fd.') + + # Create and destroy a socket so that any exceptions are + # raised before we spawn a separate Python interpreter and + # lose this ability. + address_family = select_ip_version(hostname, port) + s = socket.socket(address_family, socket.SOCK_STREAM) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind(get_sockaddr(hostname, port, address_family)) + if hasattr(s, 'set_inheritable'): + s.set_inheritable(True) + + # If we can open the socket by file descriptor, then we can just + # reuse this one and our socket will survive the restarts. + if can_open_by_fd: + os.environ['WERKZEUG_SERVER_FD'] = str(s.fileno()) + s.listen(LISTEN_QUEUE) + log_startup(s) + else: + s.close() + + # Do not use relative imports, otherwise "python -m werkzeug.serving" + # breaks. + from werkzeug._reloader import run_with_reloader + run_with_reloader(inner, extra_files, reloader_interval, + reloader_type) + else: + inner() + + +def run_with_reloader(*args, **kwargs): + # People keep using undocumented APIs. Do not use this function + # please, we do not guarantee that it continues working. + from werkzeug._reloader import run_with_reloader + return run_with_reloader(*args, **kwargs) + + +def main(): + '''A simple command-line interface for :py:func:`run_simple`.''' + + # in contrast to argparse, this works at least under Python < 2.7 + import optparse + from werkzeug.utils import import_string + + parser = optparse.OptionParser( + usage='Usage: %prog [options] app_module:app_object') + parser.add_option('-b', '--bind', dest='address', + help='The hostname:port the app should listen on.') + parser.add_option('-d', '--debug', dest='use_debugger', + action='store_true', default=False, + help='Use Werkzeug\'s debugger.') + parser.add_option('-r', '--reload', dest='use_reloader', + action='store_true', default=False, + help='Reload Python process if modules change.') + options, args = parser.parse_args() + + hostname, port = None, None + if options.address: + address = options.address.split(':') + hostname = address[0] + if len(address) > 1: + port = address[1] + + if len(args) != 1: + sys.stdout.write('No application supplied, or too much. See --help\n') + sys.exit(1) + app = import_string(args[0]) + + run_simple( + hostname=(hostname or '127.0.0.1'), port=int(port or 5000), + application=app, use_reloader=options.use_reloader, + use_debugger=options.use_debugger + ) + +if __name__ == '__main__': + main() diff --git a/flex/lib/python3.6/site-packages/werkzeug/test.py b/flex/lib/python3.6/site-packages/werkzeug/test.py new file mode 100644 index 0000000..acd2179 --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/test.py @@ -0,0 +1,948 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.test + ~~~~~~~~~~~~~ + + This module implements a client to WSGI applications for testing. + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import sys +import mimetypes +from time import time +from random import random +from itertools import chain +from tempfile import TemporaryFile +from io import BytesIO + +try: + from urllib2 import Request as U2Request +except ImportError: + from urllib.request import Request as U2Request +try: + from http.cookiejar import CookieJar +except ImportError: # Py2 + from cookielib import CookieJar + +from werkzeug._compat import iterlists, iteritems, itervalues, to_bytes, \ + string_types, text_type, reraise, wsgi_encoding_dance, \ + make_literal_wrapper +from werkzeug._internal import _empty_stream, _get_environ +from werkzeug.wrappers import BaseRequest +from werkzeug.urls import url_encode, url_fix, iri_to_uri, url_unquote, \ + url_unparse, url_parse +from werkzeug.wsgi import get_host, get_current_url, ClosingIterator +from werkzeug.utils import dump_cookie, get_content_type +from werkzeug.datastructures import FileMultiDict, MultiDict, \ + CombinedMultiDict, Headers, FileStorage, CallbackDict +from werkzeug.http import dump_options_header, parse_options_header + + +def stream_encode_multipart(values, use_tempfile=True, threshold=1024 * 500, + boundary=None, charset='utf-8'): + """Encode a dict of values (either strings or file descriptors or + :class:`FileStorage` objects.) into a multipart encoded string stored + in a file descriptor. + """ + if boundary is None: + boundary = '---------------WerkzeugFormPart_%s%s' % (time(), random()) + _closure = [BytesIO(), 0, False] + + if use_tempfile: + def write_binary(string): + stream, total_length, on_disk = _closure + if on_disk: + stream.write(string) + else: + length = len(string) + if length + _closure[1] <= threshold: + stream.write(string) + else: + new_stream = TemporaryFile('wb+') + new_stream.write(stream.getvalue()) + new_stream.write(string) + _closure[0] = new_stream + _closure[2] = True + _closure[1] = total_length + length + else: + write_binary = _closure[0].write + + def write(string): + write_binary(string.encode(charset)) + + if not isinstance(values, MultiDict): + values = MultiDict(values) + + for key, values in iterlists(values): + for value in values: + write('--%s\r\nContent-Disposition: form-data; name="%s"' % + (boundary, key)) + reader = getattr(value, 'read', None) + if reader is not None: + filename = getattr(value, 'filename', + getattr(value, 'name', None)) + content_type = getattr(value, 'content_type', None) + if content_type is None: + content_type = filename and \ + mimetypes.guess_type(filename)[0] or \ + 'application/octet-stream' + if filename is not None: + write('; filename="%s"\r\n' % filename) + else: + write('\r\n') + write('Content-Type: %s\r\n\r\n' % content_type) + while 1: + chunk = reader(16384) + if not chunk: + break + write_binary(chunk) + else: + if not isinstance(value, string_types): + value = str(value) + + value = to_bytes(value, charset) + write('\r\n\r\n') + write_binary(value) + write('\r\n') + write('--%s--\r\n' % boundary) + + length = int(_closure[0].tell()) + _closure[0].seek(0) + return _closure[0], length, boundary + + +def encode_multipart(values, boundary=None, charset='utf-8'): + """Like `stream_encode_multipart` but returns a tuple in the form + (``boundary``, ``data``) where data is a bytestring. + """ + stream, length, boundary = stream_encode_multipart( + values, use_tempfile=False, boundary=boundary, charset=charset) + return boundary, stream.read() + + +def File(fd, filename=None, mimetype=None): + """Backwards compat.""" + from warnings import warn + warn(DeprecationWarning('werkzeug.test.File is deprecated, use the ' + 'EnvironBuilder or FileStorage instead')) + return FileStorage(fd, filename=filename, content_type=mimetype) + + +class _TestCookieHeaders(object): + + """A headers adapter for cookielib + """ + + def __init__(self, headers): + self.headers = headers + + def getheaders(self, name): + headers = [] + name = name.lower() + for k, v in self.headers: + if k.lower() == name: + headers.append(v) + return headers + + def get_all(self, name, default=None): + rv = [] + for k, v in self.headers: + if k.lower() == name.lower(): + rv.append(v) + return rv or default or [] + + +class _TestCookieResponse(object): + + """Something that looks like a httplib.HTTPResponse, but is actually just an + adapter for our test responses to make them available for cookielib. + """ + + def __init__(self, headers): + self.headers = _TestCookieHeaders(headers) + + def info(self): + return self.headers + + +class _TestCookieJar(CookieJar): + + """A cookielib.CookieJar modified to inject and read cookie headers from + and to wsgi environments, and wsgi application responses. + """ + + def inject_wsgi(self, environ): + """Inject the cookies as client headers into the server's wsgi + environment. + """ + cvals = [] + for cookie in self: + cvals.append('%s=%s' % (cookie.name, cookie.value)) + if cvals: + environ['HTTP_COOKIE'] = '; '.join(cvals) + + def extract_wsgi(self, environ, headers): + """Extract the server's set-cookie headers as cookies into the + cookie jar. + """ + self.extract_cookies( + _TestCookieResponse(headers), + U2Request(get_current_url(environ)), + ) + + +def _iter_data(data): + """Iterates over a `dict` or :class:`MultiDict` yielding all keys and + values. + This is used to iterate over the data passed to the + :class:`EnvironBuilder`. + """ + if isinstance(data, MultiDict): + for key, values in iterlists(data): + for value in values: + yield key, value + else: + for key, values in iteritems(data): + if isinstance(values, list): + for value in values: + yield key, value + else: + yield key, values + + +class EnvironBuilder(object): + + """This class can be used to conveniently create a WSGI environment + for testing purposes. It can be used to quickly create WSGI environments + or request objects from arbitrary data. + + The signature of this class is also used in some other places as of + Werkzeug 0.5 (:func:`create_environ`, :meth:`BaseResponse.from_values`, + :meth:`Client.open`). Because of this most of the functionality is + available through the constructor alone. + + Files and regular form data can be manipulated independently of each + other with the :attr:`form` and :attr:`files` attributes, but are + passed with the same argument to the constructor: `data`. + + `data` can be any of these values: + + - a `str` or `bytes` object: The object is converted into an + :attr:`input_stream`, the :attr:`content_length` is set and you have to + provide a :attr:`content_type`. + - a `dict` or :class:`MultiDict`: The keys have to be strings. The values + have to be either any of the following objects, or a list of any of the + following objects: + + - a :class:`file`-like object: These are converted into + :class:`FileStorage` objects automatically. + - a `tuple`: The :meth:`~FileMultiDict.add_file` method is called + with the key and the unpacked `tuple` items as positional + arguments. + - a `str`: The string is set as form data for the associated key. + - a file-like object: The object content is loaded in memory and then + handled like a regular `str` or a `bytes`. + + .. versionadded:: 0.6 + `path` and `base_url` can now be unicode strings that are encoded using + the :func:`iri_to_uri` function. + + :param path: the path of the request. In the WSGI environment this will + end up as `PATH_INFO`. If the `query_string` is not defined + and there is a question mark in the `path` everything after + it is used as query string. + :param base_url: the base URL is a URL that is used to extract the WSGI + URL scheme, host (server name + server port) and the + script root (`SCRIPT_NAME`). + :param query_string: an optional string or dict with URL parameters. + :param method: the HTTP method to use, defaults to `GET`. + :param input_stream: an optional input stream. Do not specify this and + `data`. As soon as an input stream is set you can't + modify :attr:`args` and :attr:`files` unless you + set the :attr:`input_stream` to `None` again. + :param content_type: The content type for the request. As of 0.5 you + don't have to provide this when specifying files + and form data via `data`. + :param content_length: The content length for the request. You don't + have to specify this when providing data via + `data`. + :param errors_stream: an optional error stream that is used for + `wsgi.errors`. Defaults to :data:`stderr`. + :param multithread: controls `wsgi.multithread`. Defaults to `False`. + :param multiprocess: controls `wsgi.multiprocess`. Defaults to `False`. + :param run_once: controls `wsgi.run_once`. Defaults to `False`. + :param headers: an optional list or :class:`Headers` object of headers. + :param data: a string or dict of form data or a file-object. + See explanation above. + :param environ_base: an optional dict of environment defaults. + :param environ_overrides: an optional dict of environment overrides. + :param charset: the charset used to encode unicode data. + """ + + #: the server protocol to use. defaults to HTTP/1.1 + server_protocol = 'HTTP/1.1' + + #: the wsgi version to use. defaults to (1, 0) + wsgi_version = (1, 0) + + #: the default request class for :meth:`get_request` + request_class = BaseRequest + + def __init__(self, path='/', base_url=None, query_string=None, + method='GET', input_stream=None, content_type=None, + content_length=None, errors_stream=None, multithread=False, + multiprocess=False, run_once=False, headers=None, data=None, + environ_base=None, environ_overrides=None, charset='utf-8', + mimetype=None): + path_s = make_literal_wrapper(path) + if query_string is None and path_s('?') in path: + path, query_string = path.split(path_s('?'), 1) + self.charset = charset + self.path = iri_to_uri(path) + if base_url is not None: + base_url = url_fix(iri_to_uri(base_url, charset), charset) + self.base_url = base_url + if isinstance(query_string, (bytes, text_type)): + self.query_string = query_string + else: + if query_string is None: + query_string = MultiDict() + elif not isinstance(query_string, MultiDict): + query_string = MultiDict(query_string) + self.args = query_string + self.method = method + if headers is None: + headers = Headers() + elif not isinstance(headers, Headers): + headers = Headers(headers) + self.headers = headers + if content_type is not None: + self.content_type = content_type + if errors_stream is None: + errors_stream = sys.stderr + self.errors_stream = errors_stream + self.multithread = multithread + self.multiprocess = multiprocess + self.run_once = run_once + self.environ_base = environ_base + self.environ_overrides = environ_overrides + self.input_stream = input_stream + self.content_length = content_length + self.closed = False + + if data: + if input_stream is not None: + raise TypeError('can\'t provide input stream and data') + if hasattr(data, 'read'): + data = data.read() + if isinstance(data, text_type): + data = data.encode(self.charset) + if isinstance(data, bytes): + self.input_stream = BytesIO(data) + if self.content_length is None: + self.content_length = len(data) + else: + for key, value in _iter_data(data): + if isinstance(value, (tuple, dict)) or \ + hasattr(value, 'read'): + self._add_file_from_data(key, value) + else: + self.form.setlistdefault(key).append(value) + + if mimetype is not None: + self.mimetype = mimetype + + def _add_file_from_data(self, key, value): + """Called in the EnvironBuilder to add files from the data dict.""" + if isinstance(value, tuple): + self.files.add_file(key, *value) + elif isinstance(value, dict): + from warnings import warn + warn(DeprecationWarning('it\'s no longer possible to pass dicts ' + 'as `data`. Use tuples or FileStorage ' + 'objects instead'), stacklevel=2) + value = dict(value) + mimetype = value.pop('mimetype', None) + if mimetype is not None: + value['content_type'] = mimetype + self.files.add_file(key, **value) + else: + self.files.add_file(key, value) + + def _get_base_url(self): + return url_unparse((self.url_scheme, self.host, + self.script_root, '', '')).rstrip('/') + '/' + + def _set_base_url(self, value): + if value is None: + scheme = 'http' + netloc = 'localhost' + script_root = '' + else: + scheme, netloc, script_root, qs, anchor = url_parse(value) + if qs or anchor: + raise ValueError('base url must not contain a query string ' + 'or fragment') + self.script_root = script_root.rstrip('/') + self.host = netloc + self.url_scheme = scheme + + base_url = property(_get_base_url, _set_base_url, doc=''' + The base URL is a URL that is used to extract the WSGI + URL scheme, host (server name + server port) and the + script root (`SCRIPT_NAME`).''') + del _get_base_url, _set_base_url + + def _get_content_type(self): + ct = self.headers.get('Content-Type') + if ct is None and not self._input_stream: + if self._files: + return 'multipart/form-data' + elif self._form: + return 'application/x-www-form-urlencoded' + return None + return ct + + def _set_content_type(self, value): + if value is None: + self.headers.pop('Content-Type', None) + else: + self.headers['Content-Type'] = value + + content_type = property(_get_content_type, _set_content_type, doc=''' + The content type for the request. Reflected from and to the + :attr:`headers`. Do not set if you set :attr:`files` or + :attr:`form` for auto detection.''') + del _get_content_type, _set_content_type + + def _get_content_length(self): + return self.headers.get('Content-Length', type=int) + + def _get_mimetype(self): + ct = self.content_type + if ct: + return ct.split(';')[0].strip() + + def _set_mimetype(self, value): + self.content_type = get_content_type(value, self.charset) + + def _get_mimetype_params(self): + def on_update(d): + self.headers['Content-Type'] = \ + dump_options_header(self.mimetype, d) + d = parse_options_header(self.headers.get('content-type', ''))[1] + return CallbackDict(d, on_update) + + mimetype = property(_get_mimetype, _set_mimetype, doc=''' + The mimetype (content type without charset etc.) + + .. versionadded:: 0.14 + ''') + mimetype_params = property(_get_mimetype_params, doc=''' + The mimetype parameters as dict. For example if the content + type is ``text/html; charset=utf-8`` the params would be + ``{'charset': 'utf-8'}``. + + .. versionadded:: 0.14 + ''') + del _get_mimetype, _set_mimetype, _get_mimetype_params + + def _set_content_length(self, value): + if value is None: + self.headers.pop('Content-Length', None) + else: + self.headers['Content-Length'] = str(value) + + content_length = property(_get_content_length, _set_content_length, doc=''' + The content length as integer. Reflected from and to the + :attr:`headers`. Do not set if you set :attr:`files` or + :attr:`form` for auto detection.''') + del _get_content_length, _set_content_length + + def form_property(name, storage, doc): + key = '_' + name + + def getter(self): + if self._input_stream is not None: + raise AttributeError('an input stream is defined') + rv = getattr(self, key) + if rv is None: + rv = storage() + setattr(self, key, rv) + + return rv + + def setter(self, value): + self._input_stream = None + setattr(self, key, value) + return property(getter, setter, doc=doc) + + form = form_property('form', MultiDict, doc=''' + A :class:`MultiDict` of form values.''') + files = form_property('files', FileMultiDict, doc=''' + A :class:`FileMultiDict` of uploaded files. You can use the + :meth:`~FileMultiDict.add_file` method to add new files to the + dict.''') + del form_property + + def _get_input_stream(self): + return self._input_stream + + def _set_input_stream(self, value): + self._input_stream = value + self._form = self._files = None + + input_stream = property(_get_input_stream, _set_input_stream, doc=''' + An optional input stream. If you set this it will clear + :attr:`form` and :attr:`files`.''') + del _get_input_stream, _set_input_stream + + def _get_query_string(self): + if self._query_string is None: + if self._args is not None: + return url_encode(self._args, charset=self.charset) + return '' + return self._query_string + + def _set_query_string(self, value): + self._query_string = value + self._args = None + + query_string = property(_get_query_string, _set_query_string, doc=''' + The query string. If you set this to a string :attr:`args` will + no longer be available.''') + del _get_query_string, _set_query_string + + def _get_args(self): + if self._query_string is not None: + raise AttributeError('a query string is defined') + if self._args is None: + self._args = MultiDict() + return self._args + + def _set_args(self, value): + self._query_string = None + self._args = value + + args = property(_get_args, _set_args, doc=''' + The URL arguments as :class:`MultiDict`.''') + del _get_args, _set_args + + @property + def server_name(self): + """The server name (read-only, use :attr:`host` to set)""" + return self.host.split(':', 1)[0] + + @property + def server_port(self): + """The server port as integer (read-only, use :attr:`host` to set)""" + pieces = self.host.split(':', 1) + if len(pieces) == 2 and pieces[1].isdigit(): + return int(pieces[1]) + elif self.url_scheme == 'https': + return 443 + return 80 + + def __del__(self): + try: + self.close() + except Exception: + pass + + def close(self): + """Closes all files. If you put real :class:`file` objects into the + :attr:`files` dict you can call this method to automatically close + them all in one go. + """ + if self.closed: + return + try: + files = itervalues(self.files) + except AttributeError: + files = () + for f in files: + try: + f.close() + except Exception: + pass + self.closed = True + + def get_environ(self): + """Return the built environ.""" + input_stream = self.input_stream + content_length = self.content_length + + mimetype = self.mimetype + content_type = self.content_type + + if input_stream is not None: + start_pos = input_stream.tell() + input_stream.seek(0, 2) + end_pos = input_stream.tell() + input_stream.seek(start_pos) + content_length = end_pos - start_pos + elif mimetype == 'multipart/form-data': + values = CombinedMultiDict([self.form, self.files]) + input_stream, content_length, boundary = \ + stream_encode_multipart(values, charset=self.charset) + content_type = mimetype + '; boundary="%s"' % boundary + elif mimetype == 'application/x-www-form-urlencoded': + # XXX: py2v3 review + values = url_encode(self.form, charset=self.charset) + values = values.encode('ascii') + content_length = len(values) + input_stream = BytesIO(values) + else: + input_stream = _empty_stream + + result = {} + if self.environ_base: + result.update(self.environ_base) + + def _path_encode(x): + return wsgi_encoding_dance(url_unquote(x, self.charset), self.charset) + + qs = wsgi_encoding_dance(self.query_string) + + result.update({ + 'REQUEST_METHOD': self.method, + 'SCRIPT_NAME': _path_encode(self.script_root), + 'PATH_INFO': _path_encode(self.path), + 'QUERY_STRING': qs, + 'SERVER_NAME': self.server_name, + 'SERVER_PORT': str(self.server_port), + 'HTTP_HOST': self.host, + 'SERVER_PROTOCOL': self.server_protocol, + 'CONTENT_TYPE': content_type or '', + 'CONTENT_LENGTH': str(content_length or '0'), + 'wsgi.version': self.wsgi_version, + 'wsgi.url_scheme': self.url_scheme, + 'wsgi.input': input_stream, + 'wsgi.errors': self.errors_stream, + 'wsgi.multithread': self.multithread, + 'wsgi.multiprocess': self.multiprocess, + 'wsgi.run_once': self.run_once + }) + for key, value in self.headers.to_wsgi_list(): + result['HTTP_%s' % key.upper().replace('-', '_')] = value + if self.environ_overrides: + result.update(self.environ_overrides) + return result + + def get_request(self, cls=None): + """Returns a request with the data. If the request class is not + specified :attr:`request_class` is used. + + :param cls: The request wrapper to use. + """ + if cls is None: + cls = self.request_class + return cls(self.get_environ()) + + +class ClientRedirectError(Exception): + + """ + If a redirect loop is detected when using follow_redirects=True with + the :cls:`Client`, then this exception is raised. + """ + + +class Client(object): + + """This class allows to send requests to a wrapped application. + + The response wrapper can be a class or factory function that takes + three arguments: app_iter, status and headers. The default response + wrapper just returns a tuple. + + Example:: + + class ClientResponse(BaseResponse): + ... + + client = Client(MyApplication(), response_wrapper=ClientResponse) + + The use_cookies parameter indicates whether cookies should be stored and + sent for subsequent requests. This is True by default, but passing False + will disable this behaviour. + + If you want to request some subdomain of your application you may set + `allow_subdomain_redirects` to `True` as if not no external redirects + are allowed. + + .. versionadded:: 0.5 + `use_cookies` is new in this version. Older versions did not provide + builtin cookie support. + + .. versionadded:: 0.14 + The `mimetype` parameter was added. + """ + + def __init__(self, application, response_wrapper=None, use_cookies=True, + allow_subdomain_redirects=False): + self.application = application + self.response_wrapper = response_wrapper + if use_cookies: + self.cookie_jar = _TestCookieJar() + else: + self.cookie_jar = None + self.allow_subdomain_redirects = allow_subdomain_redirects + + def set_cookie(self, server_name, key, value='', max_age=None, + expires=None, path='/', domain=None, secure=None, + httponly=False, charset='utf-8'): + """Sets a cookie in the client's cookie jar. The server name + is required and has to match the one that is also passed to + the open call. + """ + assert self.cookie_jar is not None, 'cookies disabled' + header = dump_cookie(key, value, max_age, expires, path, domain, + secure, httponly, charset) + environ = create_environ(path, base_url='http://' + server_name) + headers = [('Set-Cookie', header)] + self.cookie_jar.extract_wsgi(environ, headers) + + def delete_cookie(self, server_name, key, path='/', domain=None): + """Deletes a cookie in the test client.""" + self.set_cookie(server_name, key, expires=0, max_age=0, + path=path, domain=domain) + + def run_wsgi_app(self, environ, buffered=False): + """Runs the wrapped WSGI app with the given environment.""" + if self.cookie_jar is not None: + self.cookie_jar.inject_wsgi(environ) + rv = run_wsgi_app(self.application, environ, buffered=buffered) + if self.cookie_jar is not None: + self.cookie_jar.extract_wsgi(environ, rv[2]) + return rv + + def resolve_redirect(self, response, new_location, environ, buffered=False): + """Resolves a single redirect and triggers the request again + directly on this redirect client. + """ + scheme, netloc, script_root, qs, anchor = url_parse(new_location) + base_url = url_unparse((scheme, netloc, '', '', '')).rstrip('/') + '/' + + cur_server_name = netloc.split(':', 1)[0].split('.') + real_server_name = get_host(environ).rsplit(':', 1)[0].split('.') + if cur_server_name == ['']: + # this is a local redirect having autocorrect_location_header=False + cur_server_name = real_server_name + base_url = EnvironBuilder(environ).base_url + + if self.allow_subdomain_redirects: + allowed = cur_server_name[-len(real_server_name):] == real_server_name + else: + allowed = cur_server_name == real_server_name + + if not allowed: + raise RuntimeError('%r does not support redirect to ' + 'external targets' % self.__class__) + + status_code = int(response[1].split(None, 1)[0]) + if status_code == 307: + method = environ['REQUEST_METHOD'] + else: + method = 'GET' + + # For redirect handling we temporarily disable the response + # wrapper. This is not threadsafe but not a real concern + # since the test client must not be shared anyways. + old_response_wrapper = self.response_wrapper + self.response_wrapper = None + try: + return self.open(path=script_root, base_url=base_url, + query_string=qs, as_tuple=True, + buffered=buffered, method=method) + finally: + self.response_wrapper = old_response_wrapper + + def open(self, *args, **kwargs): + """Takes the same arguments as the :class:`EnvironBuilder` class with + some additions: You can provide a :class:`EnvironBuilder` or a WSGI + environment as only argument instead of the :class:`EnvironBuilder` + arguments and two optional keyword arguments (`as_tuple`, `buffered`) + that change the type of the return value or the way the application is + executed. + + .. versionchanged:: 0.5 + If a dict is provided as file in the dict for the `data` parameter + the content type has to be called `content_type` now instead of + `mimetype`. This change was made for consistency with + :class:`werkzeug.FileWrapper`. + + The `follow_redirects` parameter was added to :func:`open`. + + Additional parameters: + + :param as_tuple: Returns a tuple in the form ``(environ, result)`` + :param buffered: Set this to True to buffer the application run. + This will automatically close the application for + you as well. + :param follow_redirects: Set this to True if the `Client` should + follow HTTP redirects. + """ + as_tuple = kwargs.pop('as_tuple', False) + buffered = kwargs.pop('buffered', False) + follow_redirects = kwargs.pop('follow_redirects', False) + environ = None + if not kwargs and len(args) == 1: + if isinstance(args[0], EnvironBuilder): + environ = args[0].get_environ() + elif isinstance(args[0], dict): + environ = args[0] + if environ is None: + builder = EnvironBuilder(*args, **kwargs) + try: + environ = builder.get_environ() + finally: + builder.close() + + response = self.run_wsgi_app(environ, buffered=buffered) + + # handle redirects + redirect_chain = [] + while 1: + status_code = int(response[1].split(None, 1)[0]) + if status_code not in (301, 302, 303, 305, 307) \ + or not follow_redirects: + break + new_location = response[2]['location'] + new_redirect_entry = (new_location, status_code) + if new_redirect_entry in redirect_chain: + raise ClientRedirectError('loop detected') + redirect_chain.append(new_redirect_entry) + environ, response = self.resolve_redirect(response, new_location, + environ, + buffered=buffered) + + if self.response_wrapper is not None: + response = self.response_wrapper(*response) + if as_tuple: + return environ, response + return response + + def get(self, *args, **kw): + """Like open but method is enforced to GET.""" + kw['method'] = 'GET' + return self.open(*args, **kw) + + def patch(self, *args, **kw): + """Like open but method is enforced to PATCH.""" + kw['method'] = 'PATCH' + return self.open(*args, **kw) + + def post(self, *args, **kw): + """Like open but method is enforced to POST.""" + kw['method'] = 'POST' + return self.open(*args, **kw) + + def head(self, *args, **kw): + """Like open but method is enforced to HEAD.""" + kw['method'] = 'HEAD' + return self.open(*args, **kw) + + def put(self, *args, **kw): + """Like open but method is enforced to PUT.""" + kw['method'] = 'PUT' + return self.open(*args, **kw) + + def delete(self, *args, **kw): + """Like open but method is enforced to DELETE.""" + kw['method'] = 'DELETE' + return self.open(*args, **kw) + + def options(self, *args, **kw): + """Like open but method is enforced to OPTIONS.""" + kw['method'] = 'OPTIONS' + return self.open(*args, **kw) + + def trace(self, *args, **kw): + """Like open but method is enforced to TRACE.""" + kw['method'] = 'TRACE' + return self.open(*args, **kw) + + def __repr__(self): + return '<%s %r>' % ( + self.__class__.__name__, + self.application + ) + + +def create_environ(*args, **kwargs): + """Create a new WSGI environ dict based on the values passed. The first + parameter should be the path of the request which defaults to '/'. The + second one can either be an absolute path (in that case the host is + localhost:80) or a full path to the request with scheme, netloc port and + the path to the script. + + This accepts the same arguments as the :class:`EnvironBuilder` + constructor. + + .. versionchanged:: 0.5 + This function is now a thin wrapper over :class:`EnvironBuilder` which + was added in 0.5. The `headers`, `environ_base`, `environ_overrides` + and `charset` parameters were added. + """ + builder = EnvironBuilder(*args, **kwargs) + try: + return builder.get_environ() + finally: + builder.close() + + +def run_wsgi_app(app, environ, buffered=False): + """Return a tuple in the form (app_iter, status, headers) of the + application output. This works best if you pass it an application that + returns an iterator all the time. + + Sometimes applications may use the `write()` callable returned + by the `start_response` function. This tries to resolve such edge + cases automatically. But if you don't get the expected output you + should set `buffered` to `True` which enforces buffering. + + If passed an invalid WSGI application the behavior of this function is + undefined. Never pass non-conforming WSGI applications to this function. + + :param app: the application to execute. + :param buffered: set to `True` to enforce buffering. + :return: tuple in the form ``(app_iter, status, headers)`` + """ + environ = _get_environ(environ) + response = [] + buffer = [] + + def start_response(status, headers, exc_info=None): + if exc_info is not None: + reraise(*exc_info) + response[:] = [status, headers] + return buffer.append + + app_rv = app(environ, start_response) + close_func = getattr(app_rv, 'close', None) + app_iter = iter(app_rv) + + # when buffering we emit the close call early and convert the + # application iterator into a regular list + if buffered: + try: + app_iter = list(app_iter) + finally: + if close_func is not None: + close_func() + + # otherwise we iterate the application iter until we have a response, chain + # the already received data with the already collected data and wrap it in + # a new `ClosingIterator` if we need to restore a `close` callable from the + # original return value. + else: + while not response: + buffer.append(next(app_iter)) + if buffer: + app_iter = chain(buffer, app_iter) + if close_func is not None and app_iter is not app_rv: + app_iter = ClosingIterator(app_iter, close_func) + + return app_iter, response[0], Headers(response[1]) diff --git a/flex/lib/python3.6/site-packages/werkzeug/testapp.py b/flex/lib/python3.6/site-packages/werkzeug/testapp.py new file mode 100644 index 0000000..595555a --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/testapp.py @@ -0,0 +1,230 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.testapp + ~~~~~~~~~~~~~~~~ + + Provide a small test application that can be used to test a WSGI server + and check it for WSGI compliance. + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import os +import sys +import werkzeug +from textwrap import wrap +from werkzeug.wrappers import BaseRequest as Request, BaseResponse as Response +from werkzeug.utils import escape +import base64 + +logo = Response(base64.b64decode(''' +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 +='''), mimetype='image/png') + + +TEMPLATE = u'''\ + +WSGI Information + +
+ +

WSGI Information

+

+ This page displays all available information about the WSGI server and + the underlying Python interpreter. +

Python Interpreter

+ + + + + + +
Python Version + %(python_version)s +
Platform + %(platform)s [%(os)s] +
API Version + %(api_version)s +
Byteorder + %(byteorder)s +
Werkzeug Version + %(werkzeug_version)s +
+

WSGI Environment

+ %(wsgi_env)s
+

Installed Eggs

+

+ The following python packages were installed on the system as + Python eggs: +

    %(python_eggs)s
+

System Path

+

+ The following paths are the current contents of the load path. The + following entries are looked up for Python packages. Note that not + all items in this path are folders. Gray and underlined items are + entries pointing to invalid resources or used by custom import hooks + such as the zip importer. +

+ Items with a bright background were expanded for display from a relative + path. If you encounter such paths in the output you might want to check + your setup as relative paths are usually problematic in multithreaded + environments. +

    %(sys_path)s
+
+''' + + +def iter_sys_path(): + if os.name == 'posix': + def strip(x): + prefix = os.path.expanduser('~') + if x.startswith(prefix): + x = '~' + x[len(prefix):] + return x + else: + strip = lambda x: x + + cwd = os.path.abspath(os.getcwd()) + for item in sys.path: + path = os.path.join(cwd, item or os.path.curdir) + yield strip(os.path.normpath(path)), \ + not os.path.isdir(path), path != item + + +def render_testapp(req): + try: + import pkg_resources + except ImportError: + eggs = () + else: + eggs = sorted(pkg_resources.working_set, + key=lambda x: x.project_name.lower()) + python_eggs = [] + for egg in eggs: + try: + version = egg.version + except (ValueError, AttributeError): + version = 'unknown' + python_eggs.append('
  • %s [%s]' % ( + escape(egg.project_name), + escape(version) + )) + + wsgi_env = [] + sorted_environ = sorted(req.environ.items(), + key=lambda x: repr(x[0]).lower()) + for key, value in sorted_environ: + wsgi_env.append('%s%s' % ( + escape(str(key)), + ' '.join(wrap(escape(repr(value)))) + )) + + sys_path = [] + for item, virtual, expanded in iter_sys_path(): + class_ = [] + if virtual: + class_.append('virtual') + if expanded: + class_.append('exp') + sys_path.append('%s' % ( + class_ and ' class="%s"' % ' '.join(class_) or '', + escape(item) + )) + + return (TEMPLATE % { + 'python_version': '
    '.join(escape(sys.version).splitlines()), + 'platform': escape(sys.platform), + 'os': escape(os.name), + 'api_version': sys.api_version, + 'byteorder': sys.byteorder, + 'werkzeug_version': werkzeug.__version__, + 'python_eggs': '\n'.join(python_eggs), + 'wsgi_env': '\n'.join(wsgi_env), + 'sys_path': '\n'.join(sys_path) + }).encode('utf-8') + + +def test_app(environ, start_response): + """Simple test application that dumps the environment. You can use + it to check if Werkzeug is working properly: + + .. sourcecode:: pycon + + >>> from werkzeug.serving import run_simple + >>> from werkzeug.testapp import test_app + >>> run_simple('localhost', 3000, test_app) + * Running on http://localhost:3000/ + + The application displays important information from the WSGI environment, + the Python interpreter and the installed libraries. + """ + req = Request(environ, populate_request=False) + if req.args.get('resource') == 'logo': + response = logo + else: + response = Response(render_testapp(req), mimetype='text/html') + return response(environ, start_response) + + +if __name__ == '__main__': + from werkzeug.serving import run_simple + run_simple('localhost', 5000, test_app, use_reloader=True) diff --git a/flex/lib/python3.6/site-packages/werkzeug/urls.py b/flex/lib/python3.6/site-packages/werkzeug/urls.py new file mode 100644 index 0000000..5bd9a40 --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/urls.py @@ -0,0 +1,1007 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.urls + ~~~~~~~~~~~~~ + + ``werkzeug.urls`` used to provide several wrapper functions for Python 2 + urlparse, whose main purpose were to work around the behavior of the Py2 + stdlib and its lack of unicode support. While this was already a somewhat + inconvenient situation, it got even more complicated because Python 3's + ``urllib.parse`` actually does handle unicode properly. In other words, + this module would wrap two libraries with completely different behavior. So + now this module contains a 2-and-3-compatible backport of Python 3's + ``urllib.parse``, which is mostly API-compatible. + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import os +import re +from werkzeug._compat import text_type, PY2, to_unicode, \ + to_native, implements_to_string, try_coerce_native, \ + normalize_string_tuple, make_literal_wrapper, \ + fix_tuple_repr +from werkzeug._internal import _encode_idna, _decode_idna +from werkzeug.datastructures import MultiDict, iter_multi_items +from collections import namedtuple + + +# A regular expression for what a valid schema looks like +_scheme_re = re.compile(r'^[a-zA-Z0-9+-.]+$') + +# Characters that are safe in any part of an URL. +_always_safe = (b'abcdefghijklmnopqrstuvwxyz' + b'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.-+') + +_hexdigits = '0123456789ABCDEFabcdef' +_hextobyte = dict( + ((a + b).encode(), int(a + b, 16)) + for a in _hexdigits for b in _hexdigits +) +_bytetohex = [ + ('%%%02X' % char).encode('ascii') for char in range(256) +] + + +_URLTuple = fix_tuple_repr(namedtuple( + '_URLTuple', + ['scheme', 'netloc', 'path', 'query', 'fragment'] +)) + + +class BaseURL(_URLTuple): + + '''Superclass of :py:class:`URL` and :py:class:`BytesURL`.''' + __slots__ = () + + def replace(self, **kwargs): + """Return an URL with the same values, except for those parameters + given new values by whichever keyword arguments are specified.""" + return self._replace(**kwargs) + + @property + def host(self): + """The host part of the URL if available, otherwise `None`. The + host is either the hostname or the IP address mentioned in the + URL. It will not contain the port. + """ + return self._split_host()[0] + + @property + def ascii_host(self): + """Works exactly like :attr:`host` but will return a result that + is restricted to ASCII. If it finds a netloc that is not ASCII + it will attempt to idna decode it. This is useful for socket + operations when the URL might include internationalized characters. + """ + rv = self.host + if rv is not None and isinstance(rv, text_type): + try: + rv = _encode_idna(rv) + except UnicodeError: + rv = rv.encode('ascii', 'ignore') + return to_native(rv, 'ascii', 'ignore') + + @property + def port(self): + """The port in the URL as an integer if it was present, `None` + otherwise. This does not fill in default ports. + """ + try: + rv = int(to_native(self._split_host()[1])) + if 0 <= rv <= 65535: + return rv + except (ValueError, TypeError): + pass + + @property + def auth(self): + """The authentication part in the URL if available, `None` + otherwise. + """ + return self._split_netloc()[0] + + @property + def username(self): + """The username if it was part of the URL, `None` otherwise. + This undergoes URL decoding and will always be a unicode string. + """ + rv = self._split_auth()[0] + if rv is not None: + return _url_unquote_legacy(rv) + + @property + def raw_username(self): + """The username if it was part of the URL, `None` otherwise. + Unlike :attr:`username` this one is not being decoded. + """ + return self._split_auth()[0] + + @property + def password(self): + """The password if it was part of the URL, `None` otherwise. + This undergoes URL decoding and will always be a unicode string. + """ + rv = self._split_auth()[1] + if rv is not None: + return _url_unquote_legacy(rv) + + @property + def raw_password(self): + """The password if it was part of the URL, `None` otherwise. + Unlike :attr:`password` this one is not being decoded. + """ + return self._split_auth()[1] + + def decode_query(self, *args, **kwargs): + """Decodes the query part of the URL. Ths is a shortcut for + calling :func:`url_decode` on the query argument. The arguments and + keyword arguments are forwarded to :func:`url_decode` unchanged. + """ + return url_decode(self.query, *args, **kwargs) + + def join(self, *args, **kwargs): + """Joins this URL with another one. This is just a convenience + function for calling into :meth:`url_join` and then parsing the + return value again. + """ + return url_parse(url_join(self, *args, **kwargs)) + + def to_url(self): + """Returns a URL string or bytes depending on the type of the + information stored. This is just a convenience function + for calling :meth:`url_unparse` for this URL. + """ + return url_unparse(self) + + def decode_netloc(self): + """Decodes the netloc part into a string.""" + rv = _decode_idna(self.host or '') + + if ':' in rv: + rv = '[%s]' % rv + port = self.port + if port is not None: + rv = '%s:%d' % (rv, port) + auth = ':'.join(filter(None, [ + _url_unquote_legacy(self.raw_username or '', '/:%@'), + _url_unquote_legacy(self.raw_password or '', '/:%@'), + ])) + if auth: + rv = '%s@%s' % (auth, rv) + return rv + + def to_uri_tuple(self): + """Returns a :class:`BytesURL` tuple that holds a URI. This will + encode all the information in the URL properly to ASCII using the + rules a web browser would follow. + + It's usually more interesting to directly call :meth:`iri_to_uri` which + will return a string. + """ + return url_parse(iri_to_uri(self).encode('ascii')) + + def to_iri_tuple(self): + """Returns a :class:`URL` tuple that holds a IRI. This will try + to decode as much information as possible in the URL without + losing information similar to how a web browser does it for the + URL bar. + + It's usually more interesting to directly call :meth:`uri_to_iri` which + will return a string. + """ + return url_parse(uri_to_iri(self)) + + def get_file_location(self, pathformat=None): + """Returns a tuple with the location of the file in the form + ``(server, location)``. If the netloc is empty in the URL or + points to localhost, it's represented as ``None``. + + The `pathformat` by default is autodetection but needs to be set + when working with URLs of a specific system. The supported values + are ``'windows'`` when working with Windows or DOS paths and + ``'posix'`` when working with posix paths. + + If the URL does not point to to a local file, the server and location + are both represented as ``None``. + + :param pathformat: The expected format of the path component. + Currently ``'windows'`` and ``'posix'`` are + supported. Defaults to ``None`` which is + autodetect. + """ + if self.scheme != 'file': + return None, None + + path = url_unquote(self.path) + host = self.netloc or None + + if pathformat is None: + if os.name == 'nt': + pathformat = 'windows' + else: + pathformat = 'posix' + + if pathformat == 'windows': + if path[:1] == '/' and path[1:2].isalpha() and path[2:3] in '|:': + path = path[1:2] + ':' + path[3:] + windows_share = path[:3] in ('\\' * 3, '/' * 3) + import ntpath + path = ntpath.normpath(path) + # Windows shared drives are represented as ``\\host\\directory``. + # That results in a URL like ``file://///host/directory``, and a + # path like ``///host/directory``. We need to special-case this + # because the path contains the hostname. + if windows_share and host is None: + parts = path.lstrip('\\').split('\\', 1) + if len(parts) == 2: + host, path = parts + else: + host = parts[0] + path = '' + elif pathformat == 'posix': + import posixpath + path = posixpath.normpath(path) + else: + raise TypeError('Invalid path format %s' % repr(pathformat)) + + if host in ('127.0.0.1', '::1', 'localhost'): + host = None + + return host, path + + def _split_netloc(self): + if self._at in self.netloc: + return self.netloc.split(self._at, 1) + return None, self.netloc + + def _split_auth(self): + auth = self._split_netloc()[0] + if not auth: + return None, None + if self._colon not in auth: + return auth, None + return auth.split(self._colon, 1) + + def _split_host(self): + rv = self._split_netloc()[1] + if not rv: + return None, None + + if not rv.startswith(self._lbracket): + if self._colon in rv: + return rv.split(self._colon, 1) + return rv, None + + idx = rv.find(self._rbracket) + if idx < 0: + return rv, None + + host = rv[1:idx] + rest = rv[idx + 1:] + if rest.startswith(self._colon): + return host, rest[1:] + return host, None + + +@implements_to_string +class URL(BaseURL): + + """Represents a parsed URL. This behaves like a regular tuple but + also has some extra attributes that give further insight into the + URL. + """ + __slots__ = () + _at = '@' + _colon = ':' + _lbracket = '[' + _rbracket = ']' + + def __str__(self): + return self.to_url() + + def encode_netloc(self): + """Encodes the netloc part to an ASCII safe URL as bytes.""" + rv = self.ascii_host or '' + if ':' in rv: + rv = '[%s]' % rv + port = self.port + if port is not None: + rv = '%s:%d' % (rv, port) + auth = ':'.join(filter(None, [ + url_quote(self.raw_username or '', 'utf-8', 'strict', '/:%'), + url_quote(self.raw_password or '', 'utf-8', 'strict', '/:%'), + ])) + if auth: + rv = '%s@%s' % (auth, rv) + return to_native(rv) + + def encode(self, charset='utf-8', errors='replace'): + """Encodes the URL to a tuple made out of bytes. The charset is + only being used for the path, query and fragment. + """ + return BytesURL( + self.scheme.encode('ascii'), + self.encode_netloc(), + self.path.encode(charset, errors), + self.query.encode(charset, errors), + self.fragment.encode(charset, errors) + ) + + +class BytesURL(BaseURL): + + """Represents a parsed URL in bytes.""" + __slots__ = () + _at = b'@' + _colon = b':' + _lbracket = b'[' + _rbracket = b']' + + def __str__(self): + return self.to_url().decode('utf-8', 'replace') + + def encode_netloc(self): + """Returns the netloc unchanged as bytes.""" + return self.netloc + + def decode(self, charset='utf-8', errors='replace'): + """Decodes the URL to a tuple made out of strings. The charset is + only being used for the path, query and fragment. + """ + return URL( + self.scheme.decode('ascii'), + self.decode_netloc(), + self.path.decode(charset, errors), + self.query.decode(charset, errors), + self.fragment.decode(charset, errors) + ) + + +def _unquote_to_bytes(string, unsafe=''): + if isinstance(string, text_type): + string = string.encode('utf-8') + if isinstance(unsafe, text_type): + unsafe = unsafe.encode('utf-8') + unsafe = frozenset(bytearray(unsafe)) + bits = iter(string.split(b'%')) + result = bytearray(next(bits, b'')) + for item in bits: + try: + char = _hextobyte[item[:2]] + if char in unsafe: + raise KeyError() + result.append(char) + result.extend(item[2:]) + except KeyError: + result.extend(b'%') + result.extend(item) + return bytes(result) + + +def _url_encode_impl(obj, charset, encode_keys, sort, key): + iterable = iter_multi_items(obj) + if sort: + iterable = sorted(iterable, key=key) + for key, value in iterable: + if value is None: + continue + if not isinstance(key, bytes): + key = text_type(key).encode(charset) + if not isinstance(value, bytes): + value = text_type(value).encode(charset) + yield url_quote_plus(key) + '=' + url_quote_plus(value) + + +def _url_unquote_legacy(value, unsafe=''): + try: + return url_unquote(value, charset='utf-8', + errors='strict', unsafe=unsafe) + except UnicodeError: + return url_unquote(value, charset='latin1', unsafe=unsafe) + + +def url_parse(url, scheme=None, allow_fragments=True): + """Parses a URL from a string into a :class:`URL` tuple. If the URL + is lacking a scheme it can be provided as second argument. Otherwise, + it is ignored. Optionally fragments can be stripped from the URL + by setting `allow_fragments` to `False`. + + The inverse of this function is :func:`url_unparse`. + + :param url: the URL to parse. + :param scheme: the default schema to use if the URL is schemaless. + :param allow_fragments: if set to `False` a fragment will be removed + from the URL. + """ + s = make_literal_wrapper(url) + is_text_based = isinstance(url, text_type) + + if scheme is None: + scheme = s('') + netloc = query = fragment = s('') + i = url.find(s(':')) + if i > 0 and _scheme_re.match(to_native(url[:i], errors='replace')): + # make sure "iri" is not actually a port number (in which case + # "scheme" is really part of the path) + rest = url[i + 1:] + if not rest or any(c not in s('0123456789') for c in rest): + # not a port number + scheme, url = url[:i].lower(), rest + + if url[:2] == s('//'): + delim = len(url) + for c in s('/?#'): + wdelim = url.find(c, 2) + if wdelim >= 0: + delim = min(delim, wdelim) + netloc, url = url[2:delim], url[delim:] + if (s('[') in netloc and s(']') not in netloc) or \ + (s(']') in netloc and s('[') not in netloc): + raise ValueError('Invalid IPv6 URL') + + if allow_fragments and s('#') in url: + url, fragment = url.split(s('#'), 1) + if s('?') in url: + url, query = url.split(s('?'), 1) + + result_type = is_text_based and URL or BytesURL + return result_type(scheme, netloc, url, query, fragment) + + +def url_quote(string, charset='utf-8', errors='strict', safe='/:', unsafe=''): + """URL encode a single string with a given encoding. + + :param s: the string to quote. + :param charset: the charset to be used. + :param safe: an optional sequence of safe characters. + :param unsafe: an optional sequence of unsafe characters. + + .. versionadded:: 0.9.2 + The `unsafe` parameter was added. + """ + if not isinstance(string, (text_type, bytes, bytearray)): + string = text_type(string) + if isinstance(string, text_type): + string = string.encode(charset, errors) + if isinstance(safe, text_type): + safe = safe.encode(charset, errors) + if isinstance(unsafe, text_type): + unsafe = unsafe.encode(charset, errors) + safe = frozenset(bytearray(safe) + _always_safe) - frozenset(bytearray(unsafe)) + rv = bytearray() + for char in bytearray(string): + if char in safe: + rv.append(char) + else: + rv.extend(_bytetohex[char]) + return to_native(bytes(rv)) + + +def url_quote_plus(string, charset='utf-8', errors='strict', safe=''): + """URL encode a single string with the given encoding and convert + whitespace to "+". + + :param s: The string to quote. + :param charset: The charset to be used. + :param safe: An optional sequence of safe characters. + """ + return url_quote(string, charset, errors, safe + ' ', '+').replace(' ', '+') + + +def url_unparse(components): + """The reverse operation to :meth:`url_parse`. This accepts arbitrary + as well as :class:`URL` tuples and returns a URL as a string. + + :param components: the parsed URL as tuple which should be converted + into a URL string. + """ + scheme, netloc, path, query, fragment = \ + normalize_string_tuple(components) + s = make_literal_wrapper(scheme) + url = s('') + + # We generally treat file:///x and file:/x the same which is also + # what browsers seem to do. This also allows us to ignore a schema + # register for netloc utilization or having to differenciate between + # empty and missing netloc. + if netloc or (scheme and path.startswith(s('/'))): + if path and path[:1] != s('/'): + path = s('/') + path + url = s('//') + (netloc or s('')) + path + elif path: + url += path + if scheme: + url = scheme + s(':') + url + if query: + url = url + s('?') + query + if fragment: + url = url + s('#') + fragment + return url + + +def url_unquote(string, charset='utf-8', errors='replace', unsafe=''): + """URL decode a single string with a given encoding. If the charset + is set to `None` no unicode decoding is performed and raw bytes + are returned. + + :param s: the string to unquote. + :param charset: the charset of the query string. If set to `None` + no unicode decoding will take place. + :param errors: the error handling for the charset decoding. + """ + rv = _unquote_to_bytes(string, unsafe) + if charset is not None: + rv = rv.decode(charset, errors) + return rv + + +def url_unquote_plus(s, charset='utf-8', errors='replace'): + """URL decode a single string with the given `charset` and decode "+" to + whitespace. + + Per default encoding errors are ignored. If you want a different behavior + you can set `errors` to ``'replace'`` or ``'strict'``. In strict mode a + :exc:`HTTPUnicodeError` is raised. + + :param s: The string to unquote. + :param charset: the charset of the query string. If set to `None` + no unicode decoding will take place. + :param errors: The error handling for the `charset` decoding. + """ + if isinstance(s, text_type): + s = s.replace(u'+', u' ') + else: + s = s.replace(b'+', b' ') + return url_unquote(s, charset, errors) + + +def url_fix(s, charset='utf-8'): + r"""Sometimes you get an URL by a user that just isn't a real URL because + it contains unsafe characters like ' ' and so on. This function can fix + some of the problems in a similar way browsers handle data entered by the + user: + + >>> url_fix(u'http://de.wikipedia.org/wiki/Elf (Begriffskl\xe4rung)') + 'http://de.wikipedia.org/wiki/Elf%20(Begriffskl%C3%A4rung)' + + :param s: the string with the URL to fix. + :param charset: The target charset for the URL if the url was given as + unicode string. + """ + # First step is to switch to unicode processing and to convert + # backslashes (which are invalid in URLs anyways) to slashes. This is + # consistent with what Chrome does. + s = to_unicode(s, charset, 'replace').replace('\\', '/') + + # For the specific case that we look like a malformed windows URL + # we want to fix this up manually: + if s.startswith('file://') and s[7:8].isalpha() and s[8:10] in (':/', '|/'): + s = 'file:///' + s[7:] + + url = url_parse(s) + path = url_quote(url.path, charset, safe='/%+$!*\'(),') + qs = url_quote_plus(url.query, charset, safe=':&%=+$!*\'(),') + anchor = url_quote_plus(url.fragment, charset, safe=':&%=+$!*\'(),') + return to_native(url_unparse((url.scheme, url.encode_netloc(), + path, qs, anchor))) + + +def uri_to_iri(uri, charset='utf-8', errors='replace'): + r""" + Converts a URI in a given charset to a IRI. + + Examples for URI versus IRI: + + >>> uri_to_iri(b'http://xn--n3h.net/') + u'http://\u2603.net/' + >>> uri_to_iri(b'http://%C3%BCser:p%C3%A4ssword@xn--n3h.net/p%C3%A5th') + u'http://\xfcser:p\xe4ssword@\u2603.net/p\xe5th' + + Query strings are left unchanged: + + >>> uri_to_iri('/?foo=24&x=%26%2f') + u'/?foo=24&x=%26%2f' + + .. versionadded:: 0.6 + + :param uri: The URI to convert. + :param charset: The charset of the URI. + :param errors: The error handling on decode. + """ + if isinstance(uri, tuple): + uri = url_unparse(uri) + uri = url_parse(to_unicode(uri, charset)) + path = url_unquote(uri.path, charset, errors, '%/;?') + query = url_unquote(uri.query, charset, errors, '%;/?:@&=+,$#') + fragment = url_unquote(uri.fragment, charset, errors, '%;/?:@&=+,$#') + return url_unparse((uri.scheme, uri.decode_netloc(), + path, query, fragment)) + + +def iri_to_uri(iri, charset='utf-8', errors='strict', safe_conversion=False): + r""" + Converts any unicode based IRI to an acceptable ASCII URI. Werkzeug always + uses utf-8 URLs internally because this is what browsers and HTTP do as + well. In some places where it accepts an URL it also accepts a unicode IRI + and converts it into a URI. + + Examples for IRI versus URI: + + >>> iri_to_uri(u'http://☃.net/') + 'http://xn--n3h.net/' + >>> iri_to_uri(u'http://üser:pässword@☃.net/påth') + 'http://%C3%BCser:p%C3%A4ssword@xn--n3h.net/p%C3%A5th' + + There is a general problem with IRI and URI conversion with some + protocols that appear in the wild that are in violation of the URI + specification. In places where Werkzeug goes through a forced IRI to + URI conversion it will set the `safe_conversion` flag which will + not perform a conversion if the end result is already ASCII. This + can mean that the return value is not an entirely correct URI but + it will not destroy such invalid URLs in the process. + + As an example consider the following two IRIs:: + + magnet:?xt=uri:whatever + itms-services://?action=download-manifest + + The internal representation after parsing of those URLs is the same + and there is no way to reconstruct the original one. If safe + conversion is enabled however this function becomes a noop for both of + those strings as they both can be considered URIs. + + .. versionadded:: 0.6 + + .. versionchanged:: 0.9.6 + The `safe_conversion` parameter was added. + + :param iri: The IRI to convert. + :param charset: The charset for the URI. + :param safe_conversion: indicates if a safe conversion should take place. + For more information see the explanation above. + """ + if isinstance(iri, tuple): + iri = url_unparse(iri) + + if safe_conversion: + try: + native_iri = to_native(iri) + ascii_iri = to_native(iri).encode('ascii') + if ascii_iri.split() == [ascii_iri]: + return native_iri + except UnicodeError: + pass + + iri = url_parse(to_unicode(iri, charset, errors)) + + netloc = iri.encode_netloc() + path = url_quote(iri.path, charset, errors, '/:~+%') + query = url_quote(iri.query, charset, errors, '%&[]:;$*()+,!?*/=') + fragment = url_quote(iri.fragment, charset, errors, '=%&[]:;$()+,!?*/') + + return to_native(url_unparse((iri.scheme, netloc, + path, query, fragment))) + + +def url_decode(s, charset='utf-8', decode_keys=False, include_empty=True, + errors='replace', separator='&', cls=None): + """ + Parse a querystring and return it as :class:`MultiDict`. There is a + difference in key decoding on different Python versions. On Python 3 + keys will always be fully decoded whereas on Python 2, keys will + remain bytestrings if they fit into ASCII. On 2.x keys can be forced + to be unicode by setting `decode_keys` to `True`. + + If the charset is set to `None` no unicode decoding will happen and + raw bytes will be returned. + + Per default a missing value for a key will default to an empty key. If + you don't want that behavior you can set `include_empty` to `False`. + + Per default encoding errors are ignored. If you want a different behavior + you can set `errors` to ``'replace'`` or ``'strict'``. In strict mode a + `HTTPUnicodeError` is raised. + + .. versionchanged:: 0.5 + In previous versions ";" and "&" could be used for url decoding. + This changed in 0.5 where only "&" is supported. If you want to + use ";" instead a different `separator` can be provided. + + The `cls` parameter was added. + + :param s: a string with the query string to decode. + :param charset: the charset of the query string. If set to `None` + no unicode decoding will take place. + :param decode_keys: Used on Python 2.x to control whether keys should + be forced to be unicode objects. If set to `True` + then keys will be unicode in all cases. Otherwise, + they remain `str` if they fit into ASCII. + :param include_empty: Set to `False` if you don't want empty values to + appear in the dict. + :param errors: the decoding error behavior. + :param separator: the pair separator to be used, defaults to ``&`` + :param cls: an optional dict class to use. If this is not specified + or `None` the default :class:`MultiDict` is used. + """ + if cls is None: + cls = MultiDict + if isinstance(s, text_type) and not isinstance(separator, text_type): + separator = separator.decode(charset or 'ascii') + elif isinstance(s, bytes) and not isinstance(separator, bytes): + separator = separator.encode(charset or 'ascii') + return cls(_url_decode_impl(s.split(separator), charset, decode_keys, + include_empty, errors)) + + +def url_decode_stream(stream, charset='utf-8', decode_keys=False, + include_empty=True, errors='replace', separator='&', + cls=None, limit=None, return_iterator=False): + """Works like :func:`url_decode` but decodes a stream. The behavior + of stream and limit follows functions like + :func:`~werkzeug.wsgi.make_line_iter`. The generator of pairs is + directly fed to the `cls` so you can consume the data while it's + parsed. + + .. versionadded:: 0.8 + + :param stream: a stream with the encoded querystring + :param charset: the charset of the query string. If set to `None` + no unicode decoding will take place. + :param decode_keys: Used on Python 2.x to control whether keys should + be forced to be unicode objects. If set to `True`, + keys will be unicode in all cases. Otherwise, they + remain `str` if they fit into ASCII. + :param include_empty: Set to `False` if you don't want empty values to + appear in the dict. + :param errors: the decoding error behavior. + :param separator: the pair separator to be used, defaults to ``&`` + :param cls: an optional dict class to use. If this is not specified + or `None` the default :class:`MultiDict` is used. + :param limit: the content length of the URL data. Not necessary if + a limited stream is provided. + :param return_iterator: if set to `True` the `cls` argument is ignored + and an iterator over all decoded pairs is + returned + """ + from werkzeug.wsgi import make_chunk_iter + if return_iterator: + cls = lambda x: x + elif cls is None: + cls = MultiDict + pair_iter = make_chunk_iter(stream, separator, limit) + return cls(_url_decode_impl(pair_iter, charset, decode_keys, + include_empty, errors)) + + +def _url_decode_impl(pair_iter, charset, decode_keys, include_empty, errors): + for pair in pair_iter: + if not pair: + continue + s = make_literal_wrapper(pair) + equal = s('=') + if equal in pair: + key, value = pair.split(equal, 1) + else: + if not include_empty: + continue + key = pair + value = s('') + key = url_unquote_plus(key, charset, errors) + if charset is not None and PY2 and not decode_keys: + key = try_coerce_native(key) + yield key, url_unquote_plus(value, charset, errors) + + +def url_encode(obj, charset='utf-8', encode_keys=False, sort=False, key=None, + separator=b'&'): + """URL encode a dict/`MultiDict`. If a value is `None` it will not appear + in the result string. Per default only values are encoded into the target + charset strings. If `encode_keys` is set to ``True`` unicode keys are + supported too. + + If `sort` is set to `True` the items are sorted by `key` or the default + sorting algorithm. + + .. versionadded:: 0.5 + `sort`, `key`, and `separator` were added. + + :param obj: the object to encode into a query string. + :param charset: the charset of the query string. + :param encode_keys: set to `True` if you have unicode keys. (Ignored on + Python 3.x) + :param sort: set to `True` if you want parameters to be sorted by `key`. + :param separator: the separator to be used for the pairs. + :param key: an optional function to be used for sorting. For more details + check out the :func:`sorted` documentation. + """ + separator = to_native(separator, 'ascii') + return separator.join(_url_encode_impl(obj, charset, encode_keys, sort, key)) + + +def url_encode_stream(obj, stream=None, charset='utf-8', encode_keys=False, + sort=False, key=None, separator=b'&'): + """Like :meth:`url_encode` but writes the results to a stream + object. If the stream is `None` a generator over all encoded + pairs is returned. + + .. versionadded:: 0.8 + + :param obj: the object to encode into a query string. + :param stream: a stream to write the encoded object into or `None` if + an iterator over the encoded pairs should be returned. In + that case the separator argument is ignored. + :param charset: the charset of the query string. + :param encode_keys: set to `True` if you have unicode keys. (Ignored on + Python 3.x) + :param sort: set to `True` if you want parameters to be sorted by `key`. + :param separator: the separator to be used for the pairs. + :param key: an optional function to be used for sorting. For more details + check out the :func:`sorted` documentation. + """ + separator = to_native(separator, 'ascii') + gen = _url_encode_impl(obj, charset, encode_keys, sort, key) + if stream is None: + return gen + for idx, chunk in enumerate(gen): + if idx: + stream.write(separator) + stream.write(chunk) + + +def url_join(base, url, allow_fragments=True): + """Join a base URL and a possibly relative URL to form an absolute + interpretation of the latter. + + :param base: the base URL for the join operation. + :param url: the URL to join. + :param allow_fragments: indicates whether fragments should be allowed. + """ + if isinstance(base, tuple): + base = url_unparse(base) + if isinstance(url, tuple): + url = url_unparse(url) + + base, url = normalize_string_tuple((base, url)) + s = make_literal_wrapper(base) + + if not base: + return url + if not url: + return base + + bscheme, bnetloc, bpath, bquery, bfragment = \ + url_parse(base, allow_fragments=allow_fragments) + scheme, netloc, path, query, fragment = \ + url_parse(url, bscheme, allow_fragments) + if scheme != bscheme: + return url + if netloc: + return url_unparse((scheme, netloc, path, query, fragment)) + netloc = bnetloc + + if path[:1] == s('/'): + segments = path.split(s('/')) + elif not path: + segments = bpath.split(s('/')) + if not query: + query = bquery + else: + segments = bpath.split(s('/'))[:-1] + path.split(s('/')) + + # If the rightmost part is "./" we want to keep the slash but + # remove the dot. + if segments[-1] == s('.'): + segments[-1] = s('') + + # Resolve ".." and "." + segments = [segment for segment in segments if segment != s('.')] + while 1: + i = 1 + n = len(segments) - 1 + while i < n: + if segments[i] == s('..') and \ + segments[i - 1] not in (s(''), s('..')): + del segments[i - 1:i + 1] + break + i += 1 + else: + break + + # Remove trailing ".." if the URL is absolute + unwanted_marker = [s(''), s('..')] + while segments[:2] == unwanted_marker: + del segments[1] + + path = s('/').join(segments) + return url_unparse((scheme, netloc, path, query, fragment)) + + +class Href(object): + + """Implements a callable that constructs URLs with the given base. The + function can be called with any number of positional and keyword + arguments which than are used to assemble the URL. Works with URLs + and posix paths. + + Positional arguments are appended as individual segments to + the path of the URL: + + >>> href = Href('/foo') + >>> href('bar', 23) + '/foo/bar/23' + >>> href('foo', bar=23) + '/foo/foo?bar=23' + + If any of the arguments (positional or keyword) evaluates to `None` it + will be skipped. If no keyword arguments are given the last argument + can be a :class:`dict` or :class:`MultiDict` (or any other dict subclass), + otherwise the keyword arguments are used for the query parameters, cutting + off the first trailing underscore of the parameter name: + + >>> href(is_=42) + '/foo?is=42' + >>> href({'foo': 'bar'}) + '/foo?foo=bar' + + Combining of both methods is not allowed: + + >>> href({'foo': 'bar'}, bar=42) + Traceback (most recent call last): + ... + TypeError: keyword arguments and query-dicts can't be combined + + Accessing attributes on the href object creates a new href object with + the attribute name as prefix: + + >>> bar_href = href.bar + >>> bar_href("blub") + '/foo/bar/blub' + + If `sort` is set to `True` the items are sorted by `key` or the default + sorting algorithm: + + >>> href = Href("/", sort=True) + >>> href(a=1, b=2, c=3) + '/?a=1&b=2&c=3' + + .. versionadded:: 0.5 + `sort` and `key` were added. + """ + + def __init__(self, base='./', charset='utf-8', sort=False, key=None): + if not base: + base = './' + self.base = base + self.charset = charset + self.sort = sort + self.key = key + + def __getattr__(self, name): + if name[:2] == '__': + raise AttributeError(name) + base = self.base + if base[-1:] != '/': + base += '/' + return Href(url_join(base, name), self.charset, self.sort, self.key) + + def __call__(self, *path, **query): + if path and isinstance(path[-1], dict): + if query: + raise TypeError('keyword arguments and query-dicts ' + 'can\'t be combined') + query, path = path[-1], path[:-1] + elif query: + query = dict([(k.endswith('_') and k[:-1] or k, v) + for k, v in query.items()]) + path = '/'.join([to_unicode(url_quote(x, self.charset), 'ascii') + for x in path if x is not None]).lstrip('/') + rv = self.base + if path: + if not rv.endswith('/'): + rv += '/' + rv = url_join(rv, './' + path) + if query: + rv += '?' + to_unicode(url_encode(query, self.charset, sort=self.sort, + key=self.key), 'ascii') + return to_native(rv) diff --git a/flex/lib/python3.6/site-packages/werkzeug/useragents.py b/flex/lib/python3.6/site-packages/werkzeug/useragents.py new file mode 100644 index 0000000..4d7d41f --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/useragents.py @@ -0,0 +1,212 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.useragents + ~~~~~~~~~~~~~~~~~~~ + + This module provides a helper to inspect user agent strings. This module + is far from complete but should work for most of the currently available + browsers. + + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import re + + +class UserAgentParser(object): + + """A simple user agent parser. Used by the `UserAgent`.""" + + platforms = ( + ('cros', 'chromeos'), + ('iphone|ios', 'iphone'), + ('ipad', 'ipad'), + (r'darwin|mac|os\s*x', 'macos'), + ('win', 'windows'), + (r'android', 'android'), + ('netbsd', 'netbsd'), + ('openbsd', 'openbsd'), + ('freebsd', 'freebsd'), + ('dragonfly', 'dragonflybsd'), + ('(sun|i86)os', 'solaris'), + (r'x11|lin(\b|ux)?', 'linux'), + (r'nintendo\s+wii', 'wii'), + ('irix', 'irix'), + ('hp-?ux', 'hpux'), + ('aix', 'aix'), + ('sco|unix_sv', 'sco'), + ('bsd', 'bsd'), + ('amiga', 'amiga'), + ('blackberry|playbook', 'blackberry'), + ('symbian', 'symbian') + ) + browsers = ( + ('googlebot', 'google'), + ('msnbot', 'msn'), + ('yahoo', 'yahoo'), + ('ask jeeves', 'ask'), + (r'aol|america\s+online\s+browser', 'aol'), + ('opera', 'opera'), + ('edge', 'edge'), + ('chrome', 'chrome'), + ('seamonkey', 'seamonkey'), + ('firefox|firebird|phoenix|iceweasel', 'firefox'), + ('galeon', 'galeon'), + ('safari|version', 'safari'), + ('webkit', 'webkit'), + ('camino', 'camino'), + ('konqueror', 'konqueror'), + ('k-meleon', 'kmeleon'), + ('netscape', 'netscape'), + (r'msie|microsoft\s+internet\s+explorer|trident/.+? rv:', 'msie'), + ('lynx', 'lynx'), + ('links', 'links'), + ('Baiduspider', 'baidu'), + ('bingbot', 'bing'), + ('mozilla', 'mozilla') + ) + + _browser_version_re = r'(?:%s)[/\sa-z(]*(\d+[.\da-z]+)?' + _language_re = re.compile( + r'(?:;\s*|\s+)(\b\w{2}\b(?:-\b\w{2}\b)?)\s*;|' + r'(?:\(|\[|;)\s*(\b\w{2}\b(?:-\b\w{2}\b)?)\s*(?:\]|\)|;)' + ) + + def __init__(self): + self.platforms = [(b, re.compile(a, re.I)) for a, b in self.platforms] + self.browsers = [(b, re.compile(self._browser_version_re % a, re.I)) + for a, b in self.browsers] + + def __call__(self, user_agent): + for platform, regex in self.platforms: + match = regex.search(user_agent) + if match is not None: + break + else: + platform = None + for browser, regex in self.browsers: + match = regex.search(user_agent) + if match is not None: + version = match.group(1) + break + else: + browser = version = None + match = self._language_re.search(user_agent) + if match is not None: + language = match.group(1) or match.group(2) + else: + language = None + return platform, browser, version, language + + +class UserAgent(object): + + """Represents a user agent. Pass it a WSGI environment or a user agent + string and you can inspect some of the details from the user agent + string via the attributes. The following attributes exist: + + .. attribute:: string + + the raw user agent string + + .. attribute:: platform + + the browser platform. The following platforms are currently + recognized: + + - `aix` + - `amiga` + - `android` + - `blackberry` + - `bsd` + - `chromeos` + - `dragonflybsd` + - `freebsd` + - `hpux` + - `ipad` + - `iphone` + - `irix` + - `linux` + - `macos` + - `netbsd` + - `openbsd` + - `sco` + - `solaris` + - `symbian` + - `wii` + - `windows` + + .. attribute:: browser + + the name of the browser. The following browsers are currently + recognized: + + - `aol` * + - `ask` * + - `baidu` * + - `bing` * + - `camino` + - `chrome` + - `firefox` + - `galeon` + - `google` * + - `kmeleon` + - `konqueror` + - `links` + - `lynx` + - `mozilla` + - `msie` + - `msn` + - `netscape` + - `opera` + - `safari` + - `seamonkey` + - `webkit` + - `yahoo` * + + (Browsers marked with a star (``*``) are crawlers.) + + .. attribute:: version + + the version of the browser + + .. attribute:: language + + the language of the browser + """ + + _parser = UserAgentParser() + + def __init__(self, environ_or_string): + if isinstance(environ_or_string, dict): + environ_or_string = environ_or_string.get('HTTP_USER_AGENT', '') + self.string = environ_or_string + self.platform, self.browser, self.version, self.language = \ + self._parser(environ_or_string) + + def to_header(self): + return self.string + + def __str__(self): + return self.string + + def __nonzero__(self): + return bool(self.browser) + + __bool__ = __nonzero__ + + def __repr__(self): + return '<%s %r/%s>' % ( + self.__class__.__name__, + self.browser, + self.version + ) + + +# conceptionally this belongs in this module but because we want to lazily +# load the user agent module (which happens in wrappers.py) we have to import +# it afterwards. The class itself has the module set to this module so +# pickle, inspect and similar modules treat the object as if it was really +# implemented here. +from werkzeug.wrappers import UserAgentMixin # noqa diff --git a/flex/lib/python3.6/site-packages/werkzeug/utils.py b/flex/lib/python3.6/site-packages/werkzeug/utils.py new file mode 100644 index 0000000..918e7e5 --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/utils.py @@ -0,0 +1,628 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.utils + ~~~~~~~~~~~~~~ + + This module implements various utilities for WSGI applications. Most of + them are used by the request and response wrappers but especially for + middleware development it makes sense to use them without the wrappers. + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import re +import os +import sys +import pkgutil +try: + from html.entities import name2codepoint +except ImportError: + from htmlentitydefs import name2codepoint + +from werkzeug._compat import unichr, text_type, string_types, iteritems, \ + reraise, PY2 +from werkzeug._internal import _DictAccessorProperty, \ + _parse_signature, _missing + + +_format_re = re.compile(r'\$(?:(%s)|\{(%s)\})' % (('[a-zA-Z_][a-zA-Z0-9_]*',) * 2)) +_entity_re = re.compile(r'&([^;]+);') +_filename_ascii_strip_re = re.compile(r'[^A-Za-z0-9_.-]') +_windows_device_files = ('CON', 'AUX', 'COM1', 'COM2', 'COM3', 'COM4', 'LPT1', + 'LPT2', 'LPT3', 'PRN', 'NUL') + + +class cached_property(property): + + """A decorator that converts a function into a lazy property. The + function wrapped is called the first time to retrieve the result + and then that calculated result is used the next time you access + the value:: + + class Foo(object): + + @cached_property + def foo(self): + # calculate something important here + return 42 + + The class has to have a `__dict__` in order for this property to + work. + """ + + # implementation detail: A subclass of python's builtin property + # decorator, we override __get__ to check for a cached value. If one + # choses to invoke __get__ by hand the property will still work as + # expected because the lookup logic is replicated in __get__ for + # manual invocation. + + def __init__(self, func, name=None, doc=None): + self.__name__ = name or func.__name__ + self.__module__ = func.__module__ + self.__doc__ = doc or func.__doc__ + self.func = func + + def __set__(self, obj, value): + obj.__dict__[self.__name__] = value + + def __get__(self, obj, type=None): + if obj is None: + return self + value = obj.__dict__.get(self.__name__, _missing) + if value is _missing: + value = self.func(obj) + obj.__dict__[self.__name__] = value + return value + + +class environ_property(_DictAccessorProperty): + + """Maps request attributes to environment variables. This works not only + for the Werzeug request object, but also any other class with an + environ attribute: + + >>> class Test(object): + ... environ = {'key': 'value'} + ... test = environ_property('key') + >>> var = Test() + >>> var.test + 'value' + + If you pass it a second value it's used as default if the key does not + exist, the third one can be a converter that takes a value and converts + it. If it raises :exc:`ValueError` or :exc:`TypeError` the default value + is used. If no default value is provided `None` is used. + + Per default the property is read only. You have to explicitly enable it + by passing ``read_only=False`` to the constructor. + """ + + read_only = True + + def lookup(self, obj): + return obj.environ + + +class header_property(_DictAccessorProperty): + + """Like `environ_property` but for headers.""" + + def lookup(self, obj): + return obj.headers + + +class HTMLBuilder(object): + + """Helper object for HTML generation. + + Per default there are two instances of that class. The `html` one, and + the `xhtml` one for those two dialects. The class uses keyword parameters + and positional parameters to generate small snippets of HTML. + + Keyword parameters are converted to XML/SGML attributes, positional + arguments are used as children. Because Python accepts positional + arguments before keyword arguments it's a good idea to use a list with the + star-syntax for some children: + + >>> html.p(class_='foo', *[html.a('foo', href='foo.html'), ' ', + ... html.a('bar', href='bar.html')]) + u'

    foo bar

    ' + + This class works around some browser limitations and can not be used for + arbitrary SGML/XML generation. For that purpose lxml and similar + libraries exist. + + Calling the builder escapes the string passed: + + >>> html.p(html("")) + u'

    <foo>

    ' + """ + + _entity_re = re.compile(r'&([^;]+);') + _entities = name2codepoint.copy() + _entities['apos'] = 39 + _empty_elements = set([ + 'area', 'base', 'basefont', 'br', 'col', 'command', 'embed', 'frame', + 'hr', 'img', 'input', 'keygen', 'isindex', 'link', 'meta', 'param', + 'source', 'wbr' + ]) + _boolean_attributes = set([ + 'selected', 'checked', 'compact', 'declare', 'defer', 'disabled', + 'ismap', 'multiple', 'nohref', 'noresize', 'noshade', 'nowrap' + ]) + _plaintext_elements = set(['textarea']) + _c_like_cdata = set(['script', 'style']) + + def __init__(self, dialect): + self._dialect = dialect + + def __call__(self, s): + return escape(s) + + def __getattr__(self, tag): + if tag[:2] == '__': + raise AttributeError(tag) + + def proxy(*children, **arguments): + buffer = '<' + tag + for key, value in iteritems(arguments): + if value is None: + continue + if key[-1] == '_': + key = key[:-1] + if key in self._boolean_attributes: + if not value: + continue + if self._dialect == 'xhtml': + value = '="' + key + '"' + else: + value = '' + else: + value = '="' + escape(value) + '"' + buffer += ' ' + key + value + if not children and tag in self._empty_elements: + if self._dialect == 'xhtml': + buffer += ' />' + else: + buffer += '>' + return buffer + buffer += '>' + + children_as_string = ''.join([text_type(x) for x in children + if x is not None]) + + if children_as_string: + if tag in self._plaintext_elements: + children_as_string = escape(children_as_string) + elif tag in self._c_like_cdata and self._dialect == 'xhtml': + children_as_string = '/**/' + buffer += children_as_string + '' + return buffer + return proxy + + def __repr__(self): + return '<%s for %r>' % ( + self.__class__.__name__, + self._dialect + ) + + +html = HTMLBuilder('html') +xhtml = HTMLBuilder('xhtml') + + +def get_content_type(mimetype, charset): + """Returns the full content type string with charset for a mimetype. + + If the mimetype represents text the charset will be appended as charset + parameter, otherwise the mimetype is returned unchanged. + + :param mimetype: the mimetype to be used as content type. + :param charset: the charset to be appended in case it was a text mimetype. + :return: the content type. + """ + if mimetype.startswith('text/') or \ + mimetype == 'application/xml' or \ + (mimetype.startswith('application/') and + mimetype.endswith('+xml')): + mimetype += '; charset=' + charset + return mimetype + + +def format_string(string, context): + """String-template format a string: + + >>> format_string('$foo and ${foo}s', dict(foo=42)) + '42 and 42s' + + This does not do any attribute lookup etc. For more advanced string + formattings have a look at the `werkzeug.template` module. + + :param string: the format string. + :param context: a dict with the variables to insert. + """ + def lookup_arg(match): + x = context[match.group(1) or match.group(2)] + if not isinstance(x, string_types): + x = type(string)(x) + return x + return _format_re.sub(lookup_arg, string) + + +def secure_filename(filename): + r"""Pass it a filename and it will return a secure version of it. This + filename can then safely be stored on a regular file system and passed + to :func:`os.path.join`. The filename returned is an ASCII only string + for maximum portability. + + On windows systems the function also makes sure that the file is not + named after one of the special device files. + + >>> secure_filename("My cool movie.mov") + 'My_cool_movie.mov' + >>> secure_filename("../../../etc/passwd") + 'etc_passwd' + >>> secure_filename(u'i contain cool \xfcml\xe4uts.txt') + 'i_contain_cool_umlauts.txt' + + The function might return an empty filename. It's your responsibility + to ensure that the filename is unique and that you generate random + filename if the function returned an empty one. + + .. versionadded:: 0.5 + + :param filename: the filename to secure + """ + if isinstance(filename, text_type): + from unicodedata import normalize + filename = normalize('NFKD', filename).encode('ascii', 'ignore') + if not PY2: + filename = filename.decode('ascii') + for sep in os.path.sep, os.path.altsep: + if sep: + filename = filename.replace(sep, ' ') + filename = str(_filename_ascii_strip_re.sub('', '_'.join( + filename.split()))).strip('._') + + # on nt a couple of special files are present in each folder. We + # have to ensure that the target file is not such a filename. In + # this case we prepend an underline + if os.name == 'nt' and filename and \ + filename.split('.')[0].upper() in _windows_device_files: + filename = '_' + filename + + return filename + + +def escape(s, quote=None): + """Replace special characters "&", "<", ">" and (") to HTML-safe sequences. + + There is a special handling for `None` which escapes to an empty string. + + .. versionchanged:: 0.9 + `quote` is now implicitly on. + + :param s: the string to escape. + :param quote: ignored. + """ + if s is None: + return '' + elif hasattr(s, '__html__'): + return text_type(s.__html__()) + elif not isinstance(s, string_types): + s = text_type(s) + if quote is not None: + from warnings import warn + warn(DeprecationWarning('quote parameter is implicit now'), stacklevel=2) + s = s.replace('&', '&').replace('<', '<') \ + .replace('>', '>').replace('"', """) + return s + + +def unescape(s): + """The reverse function of `escape`. This unescapes all the HTML + entities, not only the XML entities inserted by `escape`. + + :param s: the string to unescape. + """ + def handle_match(m): + name = m.group(1) + if name in HTMLBuilder._entities: + return unichr(HTMLBuilder._entities[name]) + try: + if name[:2] in ('#x', '#X'): + return unichr(int(name[2:], 16)) + elif name.startswith('#'): + return unichr(int(name[1:])) + except ValueError: + pass + return u'' + return _entity_re.sub(handle_match, s) + + +def redirect(location, code=302, Response=None): + """Returns a response object (a WSGI application) that, if called, + redirects the client to the target location. Supported codes are 301, + 302, 303, 305, and 307. 300 is not supported because it's not a real + redirect and 304 because it's the answer for a request with a request + with defined If-Modified-Since headers. + + .. versionadded:: 0.6 + The location can now be a unicode string that is encoded using + the :func:`iri_to_uri` function. + + .. versionadded:: 0.10 + The class used for the Response object can now be passed in. + + :param location: the location the response should redirect to. + :param code: the redirect status code. defaults to 302. + :param class Response: a Response class to use when instantiating a + response. The default is :class:`werkzeug.wrappers.Response` if + unspecified. + """ + if Response is None: + from werkzeug.wrappers import Response + + display_location = escape(location) + if isinstance(location, text_type): + # Safe conversion is necessary here as we might redirect + # to a broken URI scheme (for instance itms-services). + from werkzeug.urls import iri_to_uri + location = iri_to_uri(location, safe_conversion=True) + response = Response( + '\n' + 'Redirecting...\n' + '

    Redirecting...

    \n' + '

    You should be redirected automatically to target URL: ' + '%s. If not click the link.' % + (escape(location), display_location), code, mimetype='text/html') + response.headers['Location'] = location + return response + + +def append_slash_redirect(environ, code=301): + """Redirects to the same URL but with a slash appended. The behavior + of this function is undefined if the path ends with a slash already. + + :param environ: the WSGI environment for the request that triggers + the redirect. + :param code: the status code for the redirect. + """ + new_path = environ['PATH_INFO'].strip('/') + '/' + query_string = environ.get('QUERY_STRING') + if query_string: + new_path += '?' + query_string + return redirect(new_path, code) + + +def import_string(import_name, silent=False): + """Imports an object based on a string. This is useful if you want to + use import paths as endpoints or something similar. An import path can + be specified either in dotted notation (``xml.sax.saxutils.escape``) + or with a colon as object delimiter (``xml.sax.saxutils:escape``). + + If `silent` is True the return value will be `None` if the import fails. + + :param import_name: the dotted name for the object to import. + :param silent: if set to `True` import errors are ignored and + `None` is returned instead. + :return: imported object + """ + # force the import name to automatically convert to strings + # __import__ is not able to handle unicode strings in the fromlist + # if the module is a package + import_name = str(import_name).replace(':', '.') + try: + try: + __import__(import_name) + except ImportError: + if '.' not in import_name: + raise + else: + return sys.modules[import_name] + + module_name, obj_name = import_name.rsplit('.', 1) + try: + module = __import__(module_name, None, None, [obj_name]) + except ImportError: + # support importing modules not yet set up by the parent module + # (or package for that matter) + module = import_string(module_name) + + try: + return getattr(module, obj_name) + except AttributeError as e: + raise ImportError(e) + + except ImportError as e: + if not silent: + reraise( + ImportStringError, + ImportStringError(import_name, e), + sys.exc_info()[2]) + + +def find_modules(import_path, include_packages=False, recursive=False): + """Finds all the modules below a package. This can be useful to + automatically import all views / controllers so that their metaclasses / + function decorators have a chance to register themselves on the + application. + + Packages are not returned unless `include_packages` is `True`. This can + also recursively list modules but in that case it will import all the + packages to get the correct load path of that module. + + :param import_path: the dotted name for the package to find child modules. + :param include_packages: set to `True` if packages should be returned, too. + :param recursive: set to `True` if recursion should happen. + :return: generator + """ + module = import_string(import_path) + path = getattr(module, '__path__', None) + if path is None: + raise ValueError('%r is not a package' % import_path) + basename = module.__name__ + '.' + for importer, modname, ispkg in pkgutil.iter_modules(path): + modname = basename + modname + if ispkg: + if include_packages: + yield modname + if recursive: + for item in find_modules(modname, include_packages, True): + yield item + else: + yield modname + + +def validate_arguments(func, args, kwargs, drop_extra=True): + """Checks if the function accepts the arguments and keyword arguments. + Returns a new ``(args, kwargs)`` tuple that can safely be passed to + the function without causing a `TypeError` because the function signature + is incompatible. If `drop_extra` is set to `True` (which is the default) + any extra positional or keyword arguments are dropped automatically. + + The exception raised provides three attributes: + + `missing` + A set of argument names that the function expected but where + missing. + + `extra` + A dict of keyword arguments that the function can not handle but + where provided. + + `extra_positional` + A list of values that where given by positional argument but the + function cannot accept. + + This can be useful for decorators that forward user submitted data to + a view function:: + + from werkzeug.utils import ArgumentValidationError, validate_arguments + + def sanitize(f): + def proxy(request): + data = request.values.to_dict() + try: + args, kwargs = validate_arguments(f, (request,), data) + except ArgumentValidationError: + raise BadRequest('The browser failed to transmit all ' + 'the data expected.') + return f(*args, **kwargs) + return proxy + + :param func: the function the validation is performed against. + :param args: a tuple of positional arguments. + :param kwargs: a dict of keyword arguments. + :param drop_extra: set to `False` if you don't want extra arguments + to be silently dropped. + :return: tuple in the form ``(args, kwargs)``. + """ + parser = _parse_signature(func) + args, kwargs, missing, extra, extra_positional = parser(args, kwargs)[:5] + if missing: + raise ArgumentValidationError(tuple(missing)) + elif (extra or extra_positional) and not drop_extra: + raise ArgumentValidationError(None, extra, extra_positional) + return tuple(args), kwargs + + +def bind_arguments(func, args, kwargs): + """Bind the arguments provided into a dict. When passed a function, + a tuple of arguments and a dict of keyword arguments `bind_arguments` + returns a dict of names as the function would see it. This can be useful + to implement a cache decorator that uses the function arguments to build + the cache key based on the values of the arguments. + + :param func: the function the arguments should be bound for. + :param args: tuple of positional arguments. + :param kwargs: a dict of keyword arguments. + :return: a :class:`dict` of bound keyword arguments. + """ + args, kwargs, missing, extra, extra_positional, \ + arg_spec, vararg_var, kwarg_var = _parse_signature(func)(args, kwargs) + values = {} + for (name, has_default, default), value in zip(arg_spec, args): + values[name] = value + if vararg_var is not None: + values[vararg_var] = tuple(extra_positional) + elif extra_positional: + raise TypeError('too many positional arguments') + if kwarg_var is not None: + multikw = set(extra) & set([x[0] for x in arg_spec]) + if multikw: + raise TypeError('got multiple values for keyword argument ' + + repr(next(iter(multikw)))) + values[kwarg_var] = extra + elif extra: + raise TypeError('got unexpected keyword argument ' + + repr(next(iter(extra)))) + return values + + +class ArgumentValidationError(ValueError): + + """Raised if :func:`validate_arguments` fails to validate""" + + def __init__(self, missing=None, extra=None, extra_positional=None): + self.missing = set(missing or ()) + self.extra = extra or {} + self.extra_positional = extra_positional or [] + ValueError.__init__(self, 'function arguments invalid. (' + '%d missing, %d additional)' % ( + len(self.missing), + len(self.extra) + len(self.extra_positional) + )) + + +class ImportStringError(ImportError): + + """Provides information about a failed :func:`import_string` attempt.""" + + #: String in dotted notation that failed to be imported. + import_name = None + #: Wrapped exception. + exception = None + + def __init__(self, import_name, exception): + self.import_name = import_name + self.exception = exception + + msg = ( + 'import_string() failed for %r. Possible reasons are:\n\n' + '- missing __init__.py in a package;\n' + '- package or module path not included in sys.path;\n' + '- duplicated package or module name taking precedence in ' + 'sys.path;\n' + '- missing module, class, function or variable;\n\n' + 'Debugged import:\n\n%s\n\n' + 'Original exception:\n\n%s: %s') + + name = '' + tracked = [] + for part in import_name.replace(':', '.').split('.'): + name += (name and '.') + part + imported = import_string(name, silent=True) + if imported: + tracked.append((name, getattr(imported, '__file__', None))) + else: + track = ['- %r found in %r.' % (n, i) for n, i in tracked] + track.append('- %r not found.' % name) + msg = msg % (import_name, '\n'.join(track), + exception.__class__.__name__, str(exception)) + break + + ImportError.__init__(self, msg) + + def __repr__(self): + return '<%s(%r, %r)>' % (self.__class__.__name__, self.import_name, + self.exception) + + +# DEPRECATED +# these objects were previously in this module as well. we import +# them here for backwards compatibility with old pickles. +from werkzeug.datastructures import ( # noqa + MultiDict, CombinedMultiDict, Headers, EnvironHeaders) +from werkzeug.http import parse_cookie, dump_cookie # noqa diff --git a/flex/lib/python3.6/site-packages/werkzeug/websocket.py b/flex/lib/python3.6/site-packages/werkzeug/websocket.py new file mode 100644 index 0000000..764698b --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/websocket.py @@ -0,0 +1,337 @@ +import re +import errno +import socket +import struct +import collections + +from base64 import b64decode, b64encode +from hashlib import sha1 + + +WS_KEY = b'258EAFA5-E914-47DA-95CA-C5AB0DC85B11' + + +def pack_message(message): + """Pack the message inside ``00`` and ``FF`` + As per the dataframing section (5.3) for the websocket spec + """ + if isinstance(message, unicode): + message = message.encode('utf-8') + elif not isinstance(message, str): + message = str(message) + packed = "\x00%s\xFF" % message + return packed + + +def encode_hybi(buf, opcode, base64=False): + """ Encode a HyBi style WebSocket frame. + Optional opcode: + 0x0 - continuation + 0x1 - text frame (base64 encode buf) + 0x2 - binary frame (use raw buf) + 0x8 - connection close + 0x9 - ping + 0xA - pong + """ + if base64: + buf = b64encode(buf) + b1 = 0x80 | (opcode & 0x0f) # FIN + opcode + payload_len = len(buf) + if payload_len <= 125: + header = struct.pack('>BB', b1, payload_len) + elif payload_len > 125 and payload_len < 65536: + header = struct.pack('>BBH', b1, 126, payload_len) + elif payload_len >= 65536: + header = struct.pack('>BBQ', b1, 127, payload_len) + return header + buf, len(header), 0 + + +def decode_hybi(buf, base64=False): + """Decode HyBi style WebSocket packets.""" + f = {'fin' : 0, + 'opcode' : 0, + 'mask' : 0, + 'hlen' : 2, + 'length' : 0, + 'payload' : None, + 'left' : 0, + 'close_code' : None, + 'close_reason' : None} + + blen = len(buf) + f['left'] = blen + + if blen < f['hlen']: + return f # Incomplete frame header + + b1, b2 = struct.unpack_from(">BB", buf) + f['opcode'] = b1 & 0x0f + f['fin'] = (b1 & 0x80) >> 7 + has_mask = (b2 & 0x80) >> 7 + + f['length'] = b2 & 0x7f + + if f['length'] == 126: + f['hlen'] = 4 + if blen < f['hlen']: + return f # Incomplete frame header + (f['length'],) = struct.unpack_from('>xxH', buf) + elif f['length'] == 127: + f['hlen'] = 10 + if blen < f['hlen']: + return f # Incomplete frame header + (f['length'],) = struct.unpack_from('>xxQ', buf) + + full_len = f['hlen'] + has_mask * 4 + f['length'] + + if blen < full_len: # Incomplete frame + return f # Incomplete frame header + + # Number of bytes that are part of the next frame(s) + f['left'] = blen - full_len + + # Process 1 frame + if has_mask: + # unmask payload + f['mask'] = buf[f['hlen']:f['hlen']+4] + b = c = '' + if f['length'] >= 4: + data = struct.unpack('= 2: + f['close_code'] = struct.unpack_from(">H", f['payload']) + if f['length'] > 3: + f['close_reason'] = f['payload'][2:] + + return f + + +class WebSocketWSGI(object): + + def __init__(self, handler): + self.handler = handler + + def verify_client(self, ws): + pass + + def __call__(self, environ, start_response): + if not (environ.get('HTTP_CONNECTION').find('Upgrade') != -1 and + environ['HTTP_UPGRADE'].lower() == 'websocket'): + # need to check a few more things here for true compliance + start_response('400 Bad Request', [('Connection','close')]) + return [] + + sock = environ['gunicorn.socket'] + + ws = WebSocket(sock, environ) + + handshake_reply = ("HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n") + + path = environ['PATH_INFO'] + key = environ.get('HTTP_SEC_WEBSOCKET_KEY') + if key: + ws_key = b64decode(key) + if len(ws_key) != 16: + start_response('400 Bad Request', [('Connection','close')]) + return [] + + protocols = [] + subprotocols = environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL') + ws_protocols = [] + if subprotocols: + for s in subprotocols.split(','): + s = s.strip() + if s in protocols: + ws_protocols.append(s) + if ws_protocols: + handshake_reply += 'Sec-WebSocket-Protocol: %s\r\n' % ', '.join(ws_protocols) + + exts = [] + extensions = environ.get('HTTP_SEC_WEBSOCKET_EXTENSIONS') + ws_extensions = [] + if extensions: + for ext in extensions.split(','): + ext = ext.strip() + if ext in exts: + ws_extensions.append(ext) + if ws_extensions: + handshake_reply += 'Sec-WebSocket-Extensions: %s\r\n' % ', '.join(ws_extensions) + + handshake_reply += ( + "Sec-WebSocket-Origin: %s\r\n" + "Sec-WebSocket-Location: ws://%s%s\r\n" + "Sec-WebSocket-Version: %s\r\n" + "Sec-WebSocket-Accept: %s\r\n\r\n" + % ( + environ.get('HTTP_ORIGIN'), + environ.get('HTTP_HOST'), + path, + ws.version, + b64encode(sha1(key + WS_KEY).digest()) + )) + + else: + + handshake_reply += ( + "WebSocket-Origin: %s\r\n" + "WebSocket-Location: ws://%s%s\r\n\r\n" % ( + environ.get('HTTP_ORIGIN'), + environ.get('HTTP_HOST'), + path)) + + sock.sendall(handshake_reply) + + try: + self.handler(ws) + except socket.error as e: + if e[0] != errno.EPIPE: + raise + + # use this undocumented feature of grainbows to ensure that it + # doesn't barf on the fact that we didn't call start_response + return ALREADY_HANDLED + + +class WebSocket(object): + + def __init__(self, sock, environ, version=76): + self._socket = sock + try: + version = int(environ.get('HTTP_SEC_WEBSOCKET_VERSION')) + except (ValueError, TypeError): + version = 76 + self.version = version + self.closed = False + self.accepted = False + self._buf = b'' + self._msgs = collections.deque() + + def _parse_messages(self): + """ Parses for messages in the buffer *buf*. It is assumed that + the buffer contains the start character for a message, but that it + may contain only part of the rest of the message. + Returns an array of messages, and the buffer remainder that + didn't contain any full messages.""" + msgs = [] + end_idx = 0 + buf = self._buf + while buf: + if self.version in (7, 8, 13): + frame = decode_hybi(buf, base64=False) + + if frame['payload'] == None: + break + else: + if frame['opcode'] == 0x8: # connection close + self.closed = True + break + else: + msgs.append(frame['payload']); + if frame['left']: + buf = buf[-frame['left']:] + else: + buf = b'' + + else: + frame_type = ord(buf[0]) + if frame_type == 0: + # Normal message. + end_idx = buf.find("\xFF") + if end_idx == -1: #pragma NO COVER + break + msgs.append(buf[1:end_idx].decode('utf-8', 'replace')) + buf = buf[end_idx+1:] + elif frame_type == 255: + # Closing handshake. + assert ord(buf[1]) == 0, "Unexpected closing handshake: %r" % buf + self.closed = True + break + else: + raise ValueError("Don't understand how to parse this type of message: %r" % buf) + self._buf = buf + return msgs + + def send(self, message): + """Send a message to the browser. + *message* should be convertable to a string; unicode objects should be + encodable as utf-8. Raises socket.error with errno of 32 + (broken pipe) if the socket has already been closed by the client. + """ + if self.version in (7, 8, 13): + packed, lenhead, lentail = encode_hybi( + message, opcode=0x01, base64=False) + else: + packed = pack_message(message) + self._socket.sendall(packed) + + def wait(self): + """Waits for and deserializes messages. + Returns a single message; the oldest not yet processed. If the client + has already closed the connection, returns None. This is different + from normal socket behavior because the empty string is a valid + websocket message.""" + while not self._msgs: + # Websocket might be closed already. + if self.closed: + return None + # no parsed messages, must mean buf needs more data + delta = self._socket.recv(8096) + if delta == '': + return None + self._buf += delta + msgs = self._parse_messages() + self._msgs.extend(msgs) + return self._msgs.popleft() + + def _send_closing_frame(self, ignore_send_errors=False): + """Sends the closing frame to the client, if required.""" + if self.version in (7, 8, 13) and not self.closed: + msg = '' + #if code != None: + # msg = struct.pack(">H%ds" % (len(reason)), code) + + buf, h, t = encode_hybi(msg, opcode=0x08, base64=False) + self._socket.sendall(buf) + self.closed = True + + elif self.version == 76 and not self.closed: + try: + self._socket.sendall("\xff\x00") + except socket.error: + # Sometimes, like when the remote side cuts off the connection, + # we don't care about this. + if not ignore_send_errors: #pragma NO COVER + raise + self.closed = True + + def close(self): + """Forcibly close the websocket; generally it is preferable to + return from the handler method.""" + self._send_closing_frame() + self._socket.shutdown(True) + self._socket.close() diff --git a/flex/lib/python3.6/site-packages/werkzeug/wrappers.py b/flex/lib/python3.6/site-packages/werkzeug/wrappers.py new file mode 100644 index 0000000..92dfa5d --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/wrappers.py @@ -0,0 +1,2028 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.wrappers + ~~~~~~~~~~~~~~~~~ + + The wrappers are simple request and response objects which you can + subclass to do whatever you want them to do. The request object contains + the information transmitted by the client (webbrowser) and the response + object contains all the information sent back to the browser. + + An important detail is that the request object is created with the WSGI + environ and will act as high-level proxy whereas the response object is an + actual WSGI application. + + Like everything else in Werkzeug these objects will work correctly with + unicode data. Incoming form data parsed by the response object will be + decoded into an unicode object if possible and if it makes sense. + + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +from functools import update_wrapper +from datetime import datetime, timedelta +from warnings import warn + +from werkzeug.http import HTTP_STATUS_CODES, \ + parse_accept_header, parse_cache_control_header, parse_etags, \ + parse_date, generate_etag, is_resource_modified, unquote_etag, \ + quote_etag, parse_set_header, parse_authorization_header, \ + parse_www_authenticate_header, remove_entity_headers, \ + parse_options_header, dump_options_header, http_date, \ + parse_if_range_header, parse_cookie, dump_cookie, \ + parse_range_header, parse_content_range_header, dump_header, \ + parse_age, dump_age +from werkzeug.urls import url_decode, iri_to_uri, url_join +from werkzeug.formparser import FormDataParser, default_stream_factory +from werkzeug.utils import cached_property, environ_property, \ + header_property, get_content_type +from werkzeug.wsgi import get_current_url, get_host, \ + ClosingIterator, get_input_stream, get_content_length, _RangeWrapper +from werkzeug.datastructures import MultiDict, CombinedMultiDict, Headers, \ + EnvironHeaders, ImmutableMultiDict, ImmutableTypeConversionDict, \ + ImmutableList, MIMEAccept, CharsetAccept, LanguageAccept, \ + ResponseCacheControl, RequestCacheControl, CallbackDict, \ + ContentRange, iter_multi_items +from werkzeug._internal import _get_environ +from werkzeug._compat import to_bytes, string_types, text_type, \ + integer_types, wsgi_decoding_dance, wsgi_get_bytes, \ + to_unicode, to_native, BytesIO + + +def _run_wsgi_app(*args): + """This function replaces itself to ensure that the test module is not + imported unless required. DO NOT USE! + """ + global _run_wsgi_app + from werkzeug.test import run_wsgi_app as _run_wsgi_app + return _run_wsgi_app(*args) + + +def _warn_if_string(iterable): + """Helper for the response objects to check if the iterable returned + to the WSGI server is not a string. + """ + if isinstance(iterable, string_types): + warn(Warning('response iterable was set to a string. This appears ' + 'to work but means that the server will send the ' + 'data to the client char, by char. This is almost ' + 'never intended behavior, use response.data to assign ' + 'strings to the response object.'), stacklevel=2) + + +def _assert_not_shallow(request): + if request.shallow: + raise RuntimeError('A shallow request tried to consume ' + 'form data. If you really want to do ' + 'that, set `shallow` to False.') + + +def _iter_encoded(iterable, charset): + for item in iterable: + if isinstance(item, text_type): + yield item.encode(charset) + else: + yield item + + +def _clean_accept_ranges(accept_ranges): + if accept_ranges is True: + return "bytes" + elif accept_ranges is False: + return "none" + elif isinstance(accept_ranges, text_type): + return to_native(accept_ranges) + raise ValueError("Invalid accept_ranges value") + + +class BaseRequest(object): + + """Very basic request object. This does not implement advanced stuff like + entity tag parsing or cache controls. The request object is created with + the WSGI environment as first argument and will add itself to the WSGI + environment as ``'werkzeug.request'`` unless it's created with + `populate_request` set to False. + + There are a couple of mixins available that add additional functionality + to the request object, there is also a class called `Request` which + subclasses `BaseRequest` and all the important mixins. + + It's a good idea to create a custom subclass of the :class:`BaseRequest` + and add missing functionality either via mixins or direct implementation. + Here an example for such subclasses:: + + from werkzeug.wrappers import BaseRequest, ETagRequestMixin + + class Request(BaseRequest, ETagRequestMixin): + pass + + Request objects are **read only**. As of 0.5 modifications are not + allowed in any place. Unlike the lower level parsing functions the + request object will use immutable objects everywhere possible. + + Per default the request object will assume all the text data is `utf-8` + encoded. Please refer to `the unicode chapter `_ for more + details about customizing the behavior. + + Per default the request object will be added to the WSGI + environment as `werkzeug.request` to support the debugging system. + If you don't want that, set `populate_request` to `False`. + + If `shallow` is `True` the environment is initialized as shallow + object around the environ. Every operation that would modify the + environ in any way (such as consuming form data) raises an exception + unless the `shallow` attribute is explicitly set to `False`. This + is useful for middlewares where you don't want to consume the form + data by accident. A shallow request is not populated to the WSGI + environment. + + .. versionchanged:: 0.5 + read-only mode was enforced by using immutables classes for all + data. + """ + + #: the charset for the request, defaults to utf-8 + charset = 'utf-8' + + #: the error handling procedure for errors, defaults to 'replace' + encoding_errors = 'replace' + + #: the maximum content length. This is forwarded to the form data + #: parsing function (:func:`parse_form_data`). When set and the + #: :attr:`form` or :attr:`files` attribute is accessed and the + #: parsing fails because more than the specified value is transmitted + #: a :exc:`~werkzeug.exceptions.RequestEntityTooLarge` exception is raised. + #: + #: Have a look at :ref:`dealing-with-request-data` for more details. + #: + #: .. versionadded:: 0.5 + max_content_length = None + + #: the maximum form field size. This is forwarded to the form data + #: parsing function (:func:`parse_form_data`). When set and the + #: :attr:`form` or :attr:`files` attribute is accessed and the + #: data in memory for post data is longer than the specified value a + #: :exc:`~werkzeug.exceptions.RequestEntityTooLarge` exception is raised. + #: + #: Have a look at :ref:`dealing-with-request-data` for more details. + #: + #: .. versionadded:: 0.5 + max_form_memory_size = None + + #: the class to use for `args` and `form`. The default is an + #: :class:`~werkzeug.datastructures.ImmutableMultiDict` which supports + #: multiple values per key. alternatively it makes sense to use an + #: :class:`~werkzeug.datastructures.ImmutableOrderedMultiDict` which + #: preserves order or a :class:`~werkzeug.datastructures.ImmutableDict` + #: which is the fastest but only remembers the last key. It is also + #: possible to use mutable structures, but this is not recommended. + #: + #: .. versionadded:: 0.6 + parameter_storage_class = ImmutableMultiDict + + #: the type to be used for list values from the incoming WSGI environment. + #: By default an :class:`~werkzeug.datastructures.ImmutableList` is used + #: (for example for :attr:`access_list`). + #: + #: .. versionadded:: 0.6 + list_storage_class = ImmutableList + + #: the type to be used for dict values from the incoming WSGI environment. + #: By default an + #: :class:`~werkzeug.datastructures.ImmutableTypeConversionDict` is used + #: (for example for :attr:`cookies`). + #: + #: .. versionadded:: 0.6 + dict_storage_class = ImmutableTypeConversionDict + + #: The form data parser that shoud be used. Can be replaced to customize + #: the form date parsing. + form_data_parser_class = FormDataParser + + #: Optionally a list of hosts that is trusted by this request. By default + #: all hosts are trusted which means that whatever the client sends the + #: host is will be accepted. + #: + #: This is the recommended setup as a webserver should manually be set up + #: to only route correct hosts to the application, and remove the + #: `X-Forwarded-Host` header if it is not being used (see + #: :func:`werkzeug.wsgi.get_host`). + #: + #: .. versionadded:: 0.9 + trusted_hosts = None + + #: Indicates whether the data descriptor should be allowed to read and + #: buffer up the input stream. By default it's enabled. + #: + #: .. versionadded:: 0.9 + disable_data_descriptor = False + + def __init__(self, environ, populate_request=True, shallow=False): + self.environ = environ + if populate_request and not shallow: + self.environ['werkzeug.request'] = self + self.shallow = shallow + + def __repr__(self): + # make sure the __repr__ even works if the request was created + # from an invalid WSGI environment. If we display the request + # in a debug session we don't want the repr to blow up. + args = [] + try: + args.append("'%s'" % to_native(self.url, self.url_charset)) + args.append('[%s]' % self.method) + except Exception: + args.append('(invalid WSGI environ)') + + return '<%s %s>' % ( + self.__class__.__name__, + ' '.join(args) + ) + + @property + def url_charset(self): + """The charset that is assumed for URLs. Defaults to the value + of :attr:`charset`. + + .. versionadded:: 0.6 + """ + return self.charset + + @classmethod + def from_values(cls, *args, **kwargs): + """Create a new request object based on the values provided. If + environ is given missing values are filled from there. This method is + useful for small scripts when you need to simulate a request from an URL. + Do not use this method for unittesting, there is a full featured client + object (:class:`Client`) that allows to create multipart requests, + support for cookies etc. + + This accepts the same options as the + :class:`~werkzeug.test.EnvironBuilder`. + + .. versionchanged:: 0.5 + This method now accepts the same arguments as + :class:`~werkzeug.test.EnvironBuilder`. Because of this the + `environ` parameter is now called `environ_overrides`. + + :return: request object + """ + from werkzeug.test import EnvironBuilder + charset = kwargs.pop('charset', cls.charset) + kwargs['charset'] = charset + builder = EnvironBuilder(*args, **kwargs) + try: + return builder.get_request(cls) + finally: + builder.close() + + @classmethod + def application(cls, f): + """Decorate a function as responder that accepts the request as first + argument. This works like the :func:`responder` decorator but the + function is passed the request object as first argument and the + request object will be closed automatically:: + + @Request.application + def my_wsgi_app(request): + return Response('Hello World!') + + As of Werkzeug 0.14 HTTP exceptions are automatically caught and + converted to responses instead of failing. + + :param f: the WSGI callable to decorate + :return: a new WSGI callable + """ + #: return a callable that wraps the -2nd argument with the request + #: and calls the function with all the arguments up to that one and + #: the request. The return value is then called with the latest + #: two arguments. This makes it possible to use this decorator for + #: both methods and standalone WSGI functions. + from werkzeug.exceptions import HTTPException + + def application(*args): + request = cls(args[-2]) + with request: + try: + resp = f(*args[:-2] + (request,)) + except HTTPException as e: + resp = e.get_response(args[-2]) + return resp(*args[-2:]) + + return update_wrapper(application, f) + + def _get_file_stream(self, total_content_length, content_type, filename=None, + content_length=None): + """Called to get a stream for the file upload. + + This must provide a file-like class with `read()`, `readline()` + and `seek()` methods that is both writeable and readable. + + The default implementation returns a temporary file if the total + content length is higher than 500KB. Because many browsers do not + provide a content length for the files only the total content + length matters. + + :param total_content_length: the total content length of all the + data in the request combined. This value + is guaranteed to be there. + :param content_type: the mimetype of the uploaded file. + :param filename: the filename of the uploaded file. May be `None`. + :param content_length: the length of this file. This value is usually + not provided because webbrowsers do not provide + this value. + """ + return default_stream_factory( + total_content_length=total_content_length, + content_type=content_type, + filename=filename, + content_length=content_length) + + @property + def want_form_data_parsed(self): + """Returns True if the request method carries content. As of + Werkzeug 0.9 this will be the case if a content type is transmitted. + + .. versionadded:: 0.8 + """ + return bool(self.environ.get('CONTENT_TYPE')) + + def make_form_data_parser(self): + """Creates the form data parser. Instantiates the + :attr:`form_data_parser_class` with some parameters. + + .. versionadded:: 0.8 + """ + return self.form_data_parser_class(self._get_file_stream, + self.charset, + self.encoding_errors, + self.max_form_memory_size, + self.max_content_length, + self.parameter_storage_class) + + def _load_form_data(self): + """Method used internally to retrieve submitted data. After calling + this sets `form` and `files` on the request object to multi dicts + filled with the incoming form data. As a matter of fact the input + stream will be empty afterwards. You can also call this method to + force the parsing of the form data. + + .. versionadded:: 0.8 + """ + # abort early if we have already consumed the stream + if 'form' in self.__dict__: + return + + _assert_not_shallow(self) + + if self.want_form_data_parsed: + content_type = self.environ.get('CONTENT_TYPE', '') + content_length = get_content_length(self.environ) + mimetype, options = parse_options_header(content_type) + parser = self.make_form_data_parser() + data = parser.parse(self._get_stream_for_parsing(), + mimetype, content_length, options) + else: + data = (self.stream, self.parameter_storage_class(), + self.parameter_storage_class()) + + # inject the values into the instance dict so that we bypass + # our cached_property non-data descriptor. + d = self.__dict__ + d['stream'], d['form'], d['files'] = data + + def _get_stream_for_parsing(self): + """This is the same as accessing :attr:`stream` with the difference + that if it finds cached data from calling :meth:`get_data` first it + will create a new stream out of the cached data. + + .. versionadded:: 0.9.3 + """ + cached_data = getattr(self, '_cached_data', None) + if cached_data is not None: + return BytesIO(cached_data) + return self.stream + + def close(self): + """Closes associated resources of this request object. This + closes all file handles explicitly. You can also use the request + object in a with statement which will automatically close it. + + .. versionadded:: 0.9 + """ + files = self.__dict__.get('files') + for key, value in iter_multi_items(files or ()): + value.close() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, tb): + self.close() + + @cached_property + def stream(self): + """ + If the incoming form data was not encoded with a known mimetype + the data is stored unmodified in this stream for consumption. Most + of the time it is a better idea to use :attr:`data` which will give + you that data as a string. The stream only returns the data once. + + Unlike :attr:`input_stream` this stream is properly guarded that you + can't accidentally read past the length of the input. Werkzeug will + internally always refer to this stream to read data which makes it + possible to wrap this object with a stream that does filtering. + + .. versionchanged:: 0.9 + This stream is now always available but might be consumed by the + form parser later on. Previously the stream was only set if no + parsing happened. + """ + _assert_not_shallow(self) + return get_input_stream(self.environ) + + input_stream = environ_property('wsgi.input', """ + The WSGI input stream. + + In general it's a bad idea to use this one because you can easily read past + the boundary. Use the :attr:`stream` instead. + """) + + @cached_property + def args(self): + """The parsed URL parameters (the part in the URL after the question + mark). + + By default an + :class:`~werkzeug.datastructures.ImmutableMultiDict` + is returned from this function. This can be changed by setting + :attr:`parameter_storage_class` to a different type. This might + be necessary if the order of the form data is important. + """ + return url_decode(wsgi_get_bytes(self.environ.get('QUERY_STRING', '')), + self.url_charset, errors=self.encoding_errors, + cls=self.parameter_storage_class) + + @cached_property + def data(self): + """ + Contains the incoming request data as string in case it came with + a mimetype Werkzeug does not handle. + """ + + if self.disable_data_descriptor: + raise AttributeError('data descriptor is disabled') + # XXX: this should eventually be deprecated. + + # We trigger form data parsing first which means that the descriptor + # will not cache the data that would otherwise be .form or .files + # data. This restores the behavior that was there in Werkzeug + # before 0.9. New code should use :meth:`get_data` explicitly as + # this will make behavior explicit. + return self.get_data(parse_form_data=True) + + def get_data(self, cache=True, as_text=False, parse_form_data=False): + """This reads the buffered incoming data from the client into one + bytestring. By default this is cached but that behavior can be + changed by setting `cache` to `False`. + + Usually it's a bad idea to call this method without checking the + content length first as a client could send dozens of megabytes or more + to cause memory problems on the server. + + Note that if the form data was already parsed this method will not + return anything as form data parsing does not cache the data like + this method does. To implicitly invoke form data parsing function + set `parse_form_data` to `True`. When this is done the return value + of this method will be an empty string if the form parser handles + the data. This generally is not necessary as if the whole data is + cached (which is the default) the form parser will used the cached + data to parse the form data. Please be generally aware of checking + the content length first in any case before calling this method + to avoid exhausting server memory. + + If `as_text` is set to `True` the return value will be a decoded + unicode string. + + .. versionadded:: 0.9 + """ + rv = getattr(self, '_cached_data', None) + if rv is None: + if parse_form_data: + self._load_form_data() + rv = self.stream.read() + if cache: + self._cached_data = rv + if as_text: + rv = rv.decode(self.charset, self.encoding_errors) + return rv + + @cached_property + def form(self): + """The form parameters. By default an + :class:`~werkzeug.datastructures.ImmutableMultiDict` + is returned from this function. This can be changed by setting + :attr:`parameter_storage_class` to a different type. This might + be necessary if the order of the form data is important. + + Please keep in mind that file uploads will not end up here, but instead + in the :attr:`files` attribute. + + .. versionchanged:: 0.9 + + Previous to Werkzeug 0.9 this would only contain form data for POST + and PUT requests. + """ + self._load_form_data() + return self.form + + @cached_property + def values(self): + """A :class:`werkzeug.datastructures.CombinedMultiDict` that combines + :attr:`args` and :attr:`form`.""" + args = [] + for d in self.args, self.form: + if not isinstance(d, MultiDict): + d = MultiDict(d) + args.append(d) + return CombinedMultiDict(args) + + @cached_property + def files(self): + """:class:`~werkzeug.datastructures.MultiDict` object containing + all uploaded files. Each key in :attr:`files` is the name from the + ````. Each value in :attr:`files` is a + Werkzeug :class:`~werkzeug.datastructures.FileStorage` object. + + It basically behaves like a standard file object you know from Python, + with the difference that it also has a + :meth:`~werkzeug.datastructures.FileStorage.save` function that can + store the file on the filesystem. + + Note that :attr:`files` will only contain data if the request method was + POST, PUT or PATCH and the ``

    `` that posted to the request had + ``enctype="multipart/form-data"``. It will be empty otherwise. + + See the :class:`~werkzeug.datastructures.MultiDict` / + :class:`~werkzeug.datastructures.FileStorage` documentation for + more details about the used data structure. + """ + self._load_form_data() + return self.files + + @cached_property + def cookies(self): + """A :class:`dict` with the contents of all cookies transmitted with + the request.""" + return parse_cookie(self.environ, self.charset, + self.encoding_errors, + cls=self.dict_storage_class) + + @cached_property + def headers(self): + """The headers from the WSGI environ as immutable + :class:`~werkzeug.datastructures.EnvironHeaders`. + """ + return EnvironHeaders(self.environ) + + @cached_property + def path(self): + """Requested path as unicode. This works a bit like the regular path + info in the WSGI environment but will always include a leading slash, + even if the URL root is accessed. + """ + raw_path = wsgi_decoding_dance(self.environ.get('PATH_INFO') or '', + self.charset, self.encoding_errors) + return '/' + raw_path.lstrip('/') + + @cached_property + def full_path(self): + """Requested path as unicode, including the query string.""" + return self.path + u'?' + to_unicode(self.query_string, self.url_charset) + + @cached_property + def script_root(self): + """The root path of the script without the trailing slash.""" + raw_path = wsgi_decoding_dance(self.environ.get('SCRIPT_NAME') or '', + self.charset, self.encoding_errors) + return raw_path.rstrip('/') + + @cached_property + def url(self): + """The reconstructed current URL as IRI. + See also: :attr:`trusted_hosts`. + """ + return get_current_url(self.environ, + trusted_hosts=self.trusted_hosts) + + @cached_property + def base_url(self): + """Like :attr:`url` but without the querystring + See also: :attr:`trusted_hosts`. + """ + return get_current_url(self.environ, strip_querystring=True, + trusted_hosts=self.trusted_hosts) + + @cached_property + def url_root(self): + """The full URL root (with hostname), this is the application + root as IRI. + See also: :attr:`trusted_hosts`. + """ + return get_current_url(self.environ, True, + trusted_hosts=self.trusted_hosts) + + @cached_property + def host_url(self): + """Just the host with scheme as IRI. + See also: :attr:`trusted_hosts`. + """ + return get_current_url(self.environ, host_only=True, + trusted_hosts=self.trusted_hosts) + + @cached_property + def host(self): + """Just the host including the port if available. + See also: :attr:`trusted_hosts`. + """ + return get_host(self.environ, trusted_hosts=self.trusted_hosts) + + query_string = environ_property( + 'QUERY_STRING', '', read_only=True, + load_func=wsgi_get_bytes, doc='The URL parameters as raw bytestring.') + method = environ_property( + 'REQUEST_METHOD', 'GET', read_only=True, + load_func=lambda x: x.upper(), + doc="The request method. (For example ``'GET'`` or ``'POST'``).") + + @cached_property + def access_route(self): + """If a forwarded header exists this is a list of all ip addresses + from the client ip to the last proxy server. + """ + if 'HTTP_X_FORWARDED_FOR' in self.environ: + addr = self.environ['HTTP_X_FORWARDED_FOR'].split(',') + return self.list_storage_class([x.strip() for x in addr]) + elif 'REMOTE_ADDR' in self.environ: + return self.list_storage_class([self.environ['REMOTE_ADDR']]) + return self.list_storage_class() + + @property + def remote_addr(self): + """The remote address of the client.""" + return self.environ.get('REMOTE_ADDR') + + remote_user = environ_property('REMOTE_USER', doc=''' + If the server supports user authentication, and the script is + protected, this attribute contains the username the user has + authenticated as.''') + + scheme = environ_property('wsgi.url_scheme', doc=''' + URL scheme (http or https). + + .. versionadded:: 0.7''') + + @property + def is_xhr(self): + """True if the request was triggered via a JavaScript XMLHttpRequest. + This only works with libraries that support the ``X-Requested-With`` + header and set it to "XMLHttpRequest". Libraries that do that are + prototype, jQuery and Mochikit and probably some more. + + .. deprecated:: 0.13 + ``X-Requested-With`` is not standard and is unreliable. + """ + warn(DeprecationWarning( + 'Request.is_xhr is deprecated. Given that the X-Requested-With ' + 'header is not a part of any spec, it is not reliable' + ), stacklevel=2) + return self.environ.get( + 'HTTP_X_REQUESTED_WITH', '' + ).lower() == 'xmlhttprequest' + + is_secure = property(lambda x: x.environ['wsgi.url_scheme'] == 'https', + doc='`True` if the request is secure.') + is_multithread = environ_property('wsgi.multithread', doc=''' + boolean that is `True` if the application is served by + a multithreaded WSGI server.''') + is_multiprocess = environ_property('wsgi.multiprocess', doc=''' + boolean that is `True` if the application is served by + a WSGI server that spawns multiple processes.''') + is_run_once = environ_property('wsgi.run_once', doc=''' + boolean that is `True` if the application will be executed only + once in a process lifetime. This is the case for CGI for example, + but it's not guaranteed that the execution only happens one time.''') + + +class BaseResponse(object): + + """Base response class. The most important fact about a response object + is that it's a regular WSGI application. It's initialized with a couple + of response parameters (headers, body, status code etc.) and will start a + valid WSGI response when called with the environ and start response + callable. + + Because it's a WSGI application itself processing usually ends before the + actual response is sent to the server. This helps debugging systems + because they can catch all the exceptions before responses are started. + + Here a small example WSGI application that takes advantage of the + response objects:: + + from werkzeug.wrappers import BaseResponse as Response + + def index(): + return Response('Index page') + + def application(environ, start_response): + path = environ.get('PATH_INFO') or '/' + if path == '/': + response = index() + else: + response = Response('Not Found', status=404) + return response(environ, start_response) + + Like :class:`BaseRequest` which object is lacking a lot of functionality + implemented in mixins. This gives you a better control about the actual + API of your response objects, so you can create subclasses and add custom + functionality. A full featured response object is available as + :class:`Response` which implements a couple of useful mixins. + + To enforce a new type of already existing responses you can use the + :meth:`force_type` method. This is useful if you're working with different + subclasses of response objects and you want to post process them with a + known interface. + + Per default the response object will assume all the text data is `utf-8` + encoded. Please refer to `the unicode chapter `_ for more + details about customizing the behavior. + + Response can be any kind of iterable or string. If it's a string it's + considered being an iterable with one item which is the string passed. + Headers can be a list of tuples or a + :class:`~werkzeug.datastructures.Headers` object. + + Special note for `mimetype` and `content_type`: For most mime types + `mimetype` and `content_type` work the same, the difference affects + only 'text' mimetypes. If the mimetype passed with `mimetype` is a + mimetype starting with `text/`, the charset parameter of the response + object is appended to it. In contrast the `content_type` parameter is + always added as header unmodified. + + .. versionchanged:: 0.5 + the `direct_passthrough` parameter was added. + + :param response: a string or response iterable. + :param status: a string with a status or an integer with the status code. + :param headers: a list of headers or a + :class:`~werkzeug.datastructures.Headers` object. + :param mimetype: the mimetype for the response. See notice above. + :param content_type: the content type for the response. See notice above. + :param direct_passthrough: if set to `True` :meth:`iter_encoded` is not + called before iteration which makes it + possible to pass special iterators through + unchanged (see :func:`wrap_file` for more + details.) + """ + + #: the charset of the response. + charset = 'utf-8' + + #: the default status if none is provided. + default_status = 200 + + #: the default mimetype if none is provided. + default_mimetype = 'text/plain' + + #: if set to `False` accessing properties on the response object will + #: not try to consume the response iterator and convert it into a list. + #: + #: .. versionadded:: 0.6.2 + #: + #: That attribute was previously called `implicit_seqence_conversion`. + #: (Notice the typo). If you did use this feature, you have to adapt + #: your code to the name change. + implicit_sequence_conversion = True + + #: Should this response object correct the location header to be RFC + #: conformant? This is true by default. + #: + #: .. versionadded:: 0.8 + autocorrect_location_header = True + + #: Should this response object automatically set the content-length + #: header if possible? This is true by default. + #: + #: .. versionadded:: 0.8 + automatically_set_content_length = True + + #: Warn if a cookie header exceeds this size. The default, 4093, should be + #: safely `supported by most browsers `_. A cookie larger than + #: this size will still be sent, but it may be ignored or handled + #: incorrectly by some browsers. Set to 0 to disable this check. + #: + #: .. versionadded:: 0.13 + #: + #: .. _`cookie`: http://browsercookielimits.squawky.net/ + max_cookie_size = 4093 + + def __init__(self, response=None, status=None, headers=None, + mimetype=None, content_type=None, direct_passthrough=False): + if isinstance(headers, Headers): + self.headers = headers + elif not headers: + self.headers = Headers() + else: + self.headers = Headers(headers) + + if content_type is None: + if mimetype is None and 'content-type' not in self.headers: + mimetype = self.default_mimetype + if mimetype is not None: + mimetype = get_content_type(mimetype, self.charset) + content_type = mimetype + if content_type is not None: + self.headers['Content-Type'] = content_type + if status is None: + status = self.default_status + if isinstance(status, integer_types): + self.status_code = status + else: + self.status = status + + self.direct_passthrough = direct_passthrough + self._on_close = [] + + # we set the response after the headers so that if a class changes + # the charset attribute, the data is set in the correct charset. + if response is None: + self.response = [] + elif isinstance(response, (text_type, bytes, bytearray)): + self.set_data(response) + else: + self.response = response + + def call_on_close(self, func): + """Adds a function to the internal list of functions that should + be called as part of closing down the response. Since 0.7 this + function also returns the function that was passed so that this + can be used as a decorator. + + .. versionadded:: 0.6 + """ + self._on_close.append(func) + return func + + def __repr__(self): + if self.is_sequence: + body_info = '%d bytes' % sum(map(len, self.iter_encoded())) + else: + body_info = 'streamed' if self.is_streamed else 'likely-streamed' + return '<%s %s [%s]>' % ( + self.__class__.__name__, + body_info, + self.status + ) + + @classmethod + def force_type(cls, response, environ=None): + """Enforce that the WSGI response is a response object of the current + type. Werkzeug will use the :class:`BaseResponse` internally in many + situations like the exceptions. If you call :meth:`get_response` on an + exception you will get back a regular :class:`BaseResponse` object, even + if you are using a custom subclass. + + This method can enforce a given response type, and it will also + convert arbitrary WSGI callables into response objects if an environ + is provided:: + + # convert a Werkzeug response object into an instance of the + # MyResponseClass subclass. + response = MyResponseClass.force_type(response) + + # convert any WSGI application into a response object + response = MyResponseClass.force_type(response, environ) + + This is especially useful if you want to post-process responses in + the main dispatcher and use functionality provided by your subclass. + + Keep in mind that this will modify response objects in place if + possible! + + :param response: a response object or wsgi application. + :param environ: a WSGI environment object. + :return: a response object. + """ + if not isinstance(response, BaseResponse): + if environ is None: + raise TypeError('cannot convert WSGI application into ' + 'response objects without an environ') + response = BaseResponse(*_run_wsgi_app(response, environ)) + response.__class__ = cls + return response + + @classmethod + def from_app(cls, app, environ, buffered=False): + """Create a new response object from an application output. This + works best if you pass it an application that returns a generator all + the time. Sometimes applications may use the `write()` callable + returned by the `start_response` function. This tries to resolve such + edge cases automatically. But if you don't get the expected output + you should set `buffered` to `True` which enforces buffering. + + :param app: the WSGI application to execute. + :param environ: the WSGI environment to execute against. + :param buffered: set to `True` to enforce buffering. + :return: a response object. + """ + return cls(*_run_wsgi_app(app, environ, buffered)) + + def _get_status_code(self): + return self._status_code + + def _set_status_code(self, code): + self._status_code = code + try: + self._status = '%d %s' % (code, HTTP_STATUS_CODES[code].upper()) + except KeyError: + self._status = '%d UNKNOWN' % code + status_code = property(_get_status_code, _set_status_code, + doc='The HTTP Status code as number') + del _get_status_code, _set_status_code + + def _get_status(self): + return self._status + + def _set_status(self, value): + try: + self._status = to_native(value) + except AttributeError: + raise TypeError('Invalid status argument') + + try: + self._status_code = int(self._status.split(None, 1)[0]) + except ValueError: + self._status_code = 0 + self._status = '0 %s' % self._status + except IndexError: + raise ValueError('Empty status argument') + status = property(_get_status, _set_status, doc='The HTTP Status code') + del _get_status, _set_status + + def get_data(self, as_text=False): + """The string representation of the request body. Whenever you call + this property the request iterable is encoded and flattened. This + can lead to unwanted behavior if you stream big data. + + This behavior can be disabled by setting + :attr:`implicit_sequence_conversion` to `False`. + + If `as_text` is set to `True` the return value will be a decoded + unicode string. + + .. versionadded:: 0.9 + """ + self._ensure_sequence() + rv = b''.join(self.iter_encoded()) + if as_text: + rv = rv.decode(self.charset) + return rv + + def set_data(self, value): + """Sets a new string as response. The value set must either by a + unicode or bytestring. If a unicode string is set it's encoded + automatically to the charset of the response (utf-8 by default). + + .. versionadded:: 0.9 + """ + # if an unicode string is set, it's encoded directly so that we + # can set the content length + if isinstance(value, text_type): + value = value.encode(self.charset) + else: + value = bytes(value) + self.response = [value] + if self.automatically_set_content_length: + self.headers['Content-Length'] = str(len(value)) + + data = property(get_data, set_data, doc=''' + A descriptor that calls :meth:`get_data` and :meth:`set_data`. This + should not be used and will eventually get deprecated. + ''') + + def calculate_content_length(self): + """Returns the content length if available or `None` otherwise.""" + try: + self._ensure_sequence() + except RuntimeError: + return None + return sum(len(x) for x in self.iter_encoded()) + + def _ensure_sequence(self, mutable=False): + """This method can be called by methods that need a sequence. If + `mutable` is true, it will also ensure that the response sequence + is a standard Python list. + + .. versionadded:: 0.6 + """ + if self.is_sequence: + # if we need a mutable object, we ensure it's a list. + if mutable and not isinstance(self.response, list): + self.response = list(self.response) + return + if self.direct_passthrough: + raise RuntimeError('Attempted implicit sequence conversion ' + 'but the response object is in direct ' + 'passthrough mode.') + if not self.implicit_sequence_conversion: + raise RuntimeError('The response object required the iterable ' + 'to be a sequence, but the implicit ' + 'conversion was disabled. Call ' + 'make_sequence() yourself.') + self.make_sequence() + + def make_sequence(self): + """Converts the response iterator in a list. By default this happens + automatically if required. If `implicit_sequence_conversion` is + disabled, this method is not automatically called and some properties + might raise exceptions. This also encodes all the items. + + .. versionadded:: 0.6 + """ + if not self.is_sequence: + # if we consume an iterable we have to ensure that the close + # method of the iterable is called if available when we tear + # down the response + close = getattr(self.response, 'close', None) + self.response = list(self.iter_encoded()) + if close is not None: + self.call_on_close(close) + + def iter_encoded(self): + """Iter the response encoded with the encoding of the response. + If the response object is invoked as WSGI application the return + value of this method is used as application iterator unless + :attr:`direct_passthrough` was activated. + """ + if __debug__: + _warn_if_string(self.response) + # Encode in a separate function so that self.response is fetched + # early. This allows us to wrap the response with the return + # value from get_app_iter or iter_encoded. + return _iter_encoded(self.response, self.charset) + + def set_cookie(self, key, value='', max_age=None, expires=None, + path='/', domain=None, secure=False, httponly=False, + samesite=None): + """Sets a cookie. The parameters are the same as in the cookie `Morsel` + object in the Python standard library but it accepts unicode data, too. + + A warning is raised if the size of the cookie header exceeds + :attr:`max_cookie_size`, but the header will still be set. + + :param key: the key (name) of the cookie to be set. + :param value: the value of the cookie. + :param max_age: should be a number of seconds, or `None` (default) if + the cookie should last only as long as the client's + browser session. + :param expires: should be a `datetime` object or UNIX timestamp. + :param path: limits the cookie to a given path, per default it will + span the whole domain. + :param domain: if you want to set a cross-domain cookie. For example, + ``domain=".example.com"`` will set a cookie that is + readable by the domain ``www.example.com``, + ``foo.example.com`` etc. Otherwise, a cookie will only + be readable by the domain that set it. + :param secure: If `True`, the cookie will only be available via HTTPS + :param httponly: disallow JavaScript to access the cookie. This is an + extension to the cookie standard and probably not + supported by all browsers. + :param samesite: Limits the scope of the cookie such that it will only + be attached to requests if those requests are + "same-site". + """ + self.headers.add('Set-Cookie', dump_cookie( + key, + value=value, + max_age=max_age, + expires=expires, + path=path, + domain=domain, + secure=secure, + httponly=httponly, + charset=self.charset, + max_size=self.max_cookie_size, + samesite=samesite + )) + + def delete_cookie(self, key, path='/', domain=None): + """Delete a cookie. Fails silently if key doesn't exist. + + :param key: the key (name) of the cookie to be deleted. + :param path: if the cookie that should be deleted was limited to a + path, the path has to be defined here. + :param domain: if the cookie that should be deleted was limited to a + domain, that domain has to be defined here. + """ + self.set_cookie(key, expires=0, max_age=0, path=path, domain=domain) + + @property + def is_streamed(self): + """If the response is streamed (the response is not an iterable with + a length information) this property is `True`. In this case streamed + means that there is no information about the number of iterations. + This is usually `True` if a generator is passed to the response object. + + This is useful for checking before applying some sort of post + filtering that should not take place for streamed responses. + """ + try: + len(self.response) + except (TypeError, AttributeError): + return True + return False + + @property + def is_sequence(self): + """If the iterator is buffered, this property will be `True`. A + response object will consider an iterator to be buffered if the + response attribute is a list or tuple. + + .. versionadded:: 0.6 + """ + return isinstance(self.response, (tuple, list)) + + def close(self): + """Close the wrapped response if possible. You can also use the object + in a with statement which will automatically close it. + + .. versionadded:: 0.9 + Can now be used in a with statement. + """ + if hasattr(self.response, 'close'): + self.response.close() + for func in self._on_close: + func() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, tb): + self.close() + + def freeze(self): + """Call this method if you want to make your response object ready for + being pickled. This buffers the generator if there is one. It will + also set the `Content-Length` header to the length of the body. + + .. versionchanged:: 0.6 + The `Content-Length` header is now set. + """ + # we explicitly set the length to a list of the *encoded* response + # iterator. Even if the implicit sequence conversion is disabled. + self.response = list(self.iter_encoded()) + self.headers['Content-Length'] = str(sum(map(len, self.response))) + + def get_wsgi_headers(self, environ): + """This is automatically called right before the response is started + and returns headers modified for the given environment. It returns a + copy of the headers from the response with some modifications applied + if necessary. + + For example the location header (if present) is joined with the root + URL of the environment. Also the content length is automatically set + to zero here for certain status codes. + + .. versionchanged:: 0.6 + Previously that function was called `fix_headers` and modified + the response object in place. Also since 0.6, IRIs in location + and content-location headers are handled properly. + + Also starting with 0.6, Werkzeug will attempt to set the content + length if it is able to figure it out on its own. This is the + case if all the strings in the response iterable are already + encoded and the iterable is buffered. + + :param environ: the WSGI environment of the request. + :return: returns a new :class:`~werkzeug.datastructures.Headers` + object. + """ + headers = Headers(self.headers) + location = None + content_location = None + content_length = None + status = self.status_code + + # iterate over the headers to find all values in one go. Because + # get_wsgi_headers is used each response that gives us a tiny + # speedup. + for key, value in headers: + ikey = key.lower() + if ikey == u'location': + location = value + elif ikey == u'content-location': + content_location = value + elif ikey == u'content-length': + content_length = value + + # make sure the location header is an absolute URL + if location is not None: + old_location = location + if isinstance(location, text_type): + # Safe conversion is necessary here as we might redirect + # to a broken URI scheme (for instance itms-services). + location = iri_to_uri(location, safe_conversion=True) + + if self.autocorrect_location_header: + current_url = get_current_url(environ, root_only=True) + if isinstance(current_url, text_type): + current_url = iri_to_uri(current_url) + location = url_join(current_url, location) + if location != old_location: + headers['Location'] = location + + # make sure the content location is a URL + if content_location is not None and \ + isinstance(content_location, text_type): + headers['Content-Location'] = iri_to_uri(content_location) + + if status in (304, 412): + remove_entity_headers(headers) + + # if we can determine the content length automatically, we + # should try to do that. But only if this does not involve + # flattening the iterator or encoding of unicode strings in + # the response. We however should not do that if we have a 304 + # response. + if self.automatically_set_content_length and \ + self.is_sequence and content_length is None and \ + status not in (204, 304) and \ + not (100 <= status < 200): + try: + content_length = sum(len(to_bytes(x, 'ascii')) + for x in self.response) + except UnicodeError: + # aha, something non-bytestringy in there, too bad, we + # can't safely figure out the length of the response. + pass + else: + headers['Content-Length'] = str(content_length) + + return headers + + def get_app_iter(self, environ): + """Returns the application iterator for the given environ. Depending + on the request method and the current status code the return value + might be an empty response rather than the one from the response. + + If the request method is `HEAD` or the status code is in a range + where the HTTP specification requires an empty response, an empty + iterable is returned. + + .. versionadded:: 0.6 + + :param environ: the WSGI environment of the request. + :return: a response iterable. + """ + status = self.status_code + if environ['REQUEST_METHOD'] == 'HEAD' or \ + 100 <= status < 200 or status in (204, 304, 412): + iterable = () + elif self.direct_passthrough: + if __debug__: + _warn_if_string(self.response) + return self.response + else: + iterable = self.iter_encoded() + return ClosingIterator(iterable, self.close) + + def get_wsgi_response(self, environ): + """Returns the final WSGI response as tuple. The first item in + the tuple is the application iterator, the second the status and + the third the list of headers. The response returned is created + specially for the given environment. For example if the request + method in the WSGI environment is ``'HEAD'`` the response will + be empty and only the headers and status code will be present. + + .. versionadded:: 0.6 + + :param environ: the WSGI environment of the request. + :return: an ``(app_iter, status, headers)`` tuple. + """ + headers = self.get_wsgi_headers(environ) + app_iter = self.get_app_iter(environ) + return app_iter, self.status, headers.to_wsgi_list() + + def __call__(self, environ, start_response): + """Process this response as WSGI application. + + :param environ: the WSGI environment. + :param start_response: the response callable provided by the WSGI + server. + :return: an application iterator + """ + app_iter, status, headers = self.get_wsgi_response(environ) + start_response(status, headers) + return app_iter + + +class AcceptMixin(object): + + """A mixin for classes with an :attr:`~BaseResponse.environ` attribute + to get all the HTTP accept headers as + :class:`~werkzeug.datastructures.Accept` objects (or subclasses + thereof). + """ + + @cached_property + def accept_mimetypes(self): + """List of mimetypes this client supports as + :class:`~werkzeug.datastructures.MIMEAccept` object. + """ + return parse_accept_header(self.environ.get('HTTP_ACCEPT'), MIMEAccept) + + @cached_property + def accept_charsets(self): + """List of charsets this client supports as + :class:`~werkzeug.datastructures.CharsetAccept` object. + """ + return parse_accept_header(self.environ.get('HTTP_ACCEPT_CHARSET'), + CharsetAccept) + + @cached_property + def accept_encodings(self): + """List of encodings this client accepts. Encodings in a HTTP term + are compression encodings such as gzip. For charsets have a look at + :attr:`accept_charset`. + """ + return parse_accept_header(self.environ.get('HTTP_ACCEPT_ENCODING')) + + @cached_property + def accept_languages(self): + """List of languages this client accepts as + :class:`~werkzeug.datastructures.LanguageAccept` object. + + .. versionchanged 0.5 + In previous versions this was a regular + :class:`~werkzeug.datastructures.Accept` object. + """ + return parse_accept_header(self.environ.get('HTTP_ACCEPT_LANGUAGE'), + LanguageAccept) + + +class ETagRequestMixin(object): + + """Add entity tag and cache descriptors to a request object or object with + a WSGI environment available as :attr:`~BaseRequest.environ`. This not + only provides access to etags but also to the cache control header. + """ + + @cached_property + def cache_control(self): + """A :class:`~werkzeug.datastructures.RequestCacheControl` object + for the incoming cache control headers. + """ + cache_control = self.environ.get('HTTP_CACHE_CONTROL') + return parse_cache_control_header(cache_control, None, + RequestCacheControl) + + @cached_property + def if_match(self): + """An object containing all the etags in the `If-Match` header. + + :rtype: :class:`~werkzeug.datastructures.ETags` + """ + return parse_etags(self.environ.get('HTTP_IF_MATCH')) + + @cached_property + def if_none_match(self): + """An object containing all the etags in the `If-None-Match` header. + + :rtype: :class:`~werkzeug.datastructures.ETags` + """ + return parse_etags(self.environ.get('HTTP_IF_NONE_MATCH')) + + @cached_property + def if_modified_since(self): + """The parsed `If-Modified-Since` header as datetime object.""" + return parse_date(self.environ.get('HTTP_IF_MODIFIED_SINCE')) + + @cached_property + def if_unmodified_since(self): + """The parsed `If-Unmodified-Since` header as datetime object.""" + return parse_date(self.environ.get('HTTP_IF_UNMODIFIED_SINCE')) + + @cached_property + def if_range(self): + """The parsed `If-Range` header. + + .. versionadded:: 0.7 + + :rtype: :class:`~werkzeug.datastructures.IfRange` + """ + return parse_if_range_header(self.environ.get('HTTP_IF_RANGE')) + + @cached_property + def range(self): + """The parsed `Range` header. + + .. versionadded:: 0.7 + + :rtype: :class:`~werkzeug.datastructures.Range` + """ + return parse_range_header(self.environ.get('HTTP_RANGE')) + + +class UserAgentMixin(object): + + """Adds a `user_agent` attribute to the request object which contains the + parsed user agent of the browser that triggered the request as a + :class:`~werkzeug.useragents.UserAgent` object. + """ + + @cached_property + def user_agent(self): + """The current user agent.""" + from werkzeug.useragents import UserAgent + return UserAgent(self.environ) + + +class AuthorizationMixin(object): + + """Adds an :attr:`authorization` property that represents the parsed + value of the `Authorization` header as + :class:`~werkzeug.datastructures.Authorization` object. + """ + + @cached_property + def authorization(self): + """The `Authorization` object in parsed form.""" + header = self.environ.get('HTTP_AUTHORIZATION') + return parse_authorization_header(header) + + +class StreamOnlyMixin(object): + + """If mixed in before the request object this will change the bahavior + of it to disable handling of form parsing. This disables the + :attr:`files`, :attr:`form` attributes and will just provide a + :attr:`stream` attribute that however is always available. + + .. versionadded:: 0.9 + """ + + disable_data_descriptor = True + want_form_data_parsed = False + + +class ETagResponseMixin(object): + + """Adds extra functionality to a response object for etag and cache + handling. This mixin requires an object with at least a `headers` + object that implements a dict like interface similar to + :class:`~werkzeug.datastructures.Headers`. + + If you want the :meth:`freeze` method to automatically add an etag, you + have to mixin this method before the response base class. The default + response class does not do that. + """ + + @property + def cache_control(self): + """The Cache-Control general-header field is used to specify + directives that MUST be obeyed by all caching mechanisms along the + request/response chain. + """ + def on_update(cache_control): + if not cache_control and 'cache-control' in self.headers: + del self.headers['cache-control'] + elif cache_control: + self.headers['Cache-Control'] = cache_control.to_header() + return parse_cache_control_header(self.headers.get('cache-control'), + on_update, + ResponseCacheControl) + + def _wrap_response(self, start, length): + """Wrap existing Response in case of Range Request context.""" + if self.status_code == 206: + self.response = _RangeWrapper(self.response, start, length) + + def _is_range_request_processable(self, environ): + """Return ``True`` if `Range` header is present and if underlying + resource is considered unchanged when compared with `If-Range` header. + """ + return ( + 'HTTP_IF_RANGE' not in environ + or not is_resource_modified( + environ, self.headers.get('etag'), None, + self.headers.get('last-modified'), ignore_if_range=False + ) + ) and 'HTTP_RANGE' in environ + + def _process_range_request(self, environ, complete_length=None, accept_ranges=None): + """Handle Range Request related headers (RFC7233). If `Accept-Ranges` + header is valid, and Range Request is processable, we set the headers + as described by the RFC, and wrap the underlying response in a + RangeWrapper. + + Returns ``True`` if Range Request can be fulfilled, ``False`` otherwise. + + :raises: :class:`~werkzeug.exceptions.RequestedRangeNotSatisfiable` + if `Range` header could not be parsed or satisfied. + """ + from werkzeug.exceptions import RequestedRangeNotSatisfiable + if accept_ranges is None: + return False + self.headers['Accept-Ranges'] = accept_ranges + if not self._is_range_request_processable(environ) or complete_length is None: + return False + parsed_range = parse_range_header(environ.get('HTTP_RANGE')) + if parsed_range is None: + raise RequestedRangeNotSatisfiable(complete_length) + range_tuple = parsed_range.range_for_length(complete_length) + content_range_header = parsed_range.to_content_range_header(complete_length) + if range_tuple is None or content_range_header is None: + raise RequestedRangeNotSatisfiable(complete_length) + content_length = range_tuple[1] - range_tuple[0] + # Be sure not to send 206 response + # if requested range is the full content. + if content_length != complete_length: + self.headers['Content-Length'] = content_length + self.content_range = content_range_header + self.status_code = 206 + self._wrap_response(range_tuple[0], content_length) + return True + return False + + def make_conditional(self, request_or_environ, accept_ranges=False, + complete_length=None): + """Make the response conditional to the request. This method works + best if an etag was defined for the response already. The `add_etag` + method can be used to do that. If called without etag just the date + header is set. + + This does nothing if the request method in the request or environ is + anything but GET or HEAD. + + For optimal performance when handling range requests, it's recommended + that your response data object implements `seekable`, `seek` and `tell` + methods as described by :py:class:`io.IOBase`. Objects returned by + :meth:`~werkzeug.wsgi.wrap_file` automatically implement those methods. + + It does not remove the body of the response because that's something + the :meth:`__call__` function does for us automatically. + + Returns self so that you can do ``return resp.make_conditional(req)`` + but modifies the object in-place. + + :param request_or_environ: a request object or WSGI environment to be + used to make the response conditional + against. + :param accept_ranges: This parameter dictates the value of + `Accept-Ranges` header. If ``False`` (default), + the header is not set. If ``True``, it will be set + to ``"bytes"``. If ``None``, it will be set to + ``"none"``. If it's a string, it will use this + value. + :param complete_length: Will be used only in valid Range Requests. + It will set `Content-Range` complete length + value and compute `Content-Length` real value. + This parameter is mandatory for successful + Range Requests completion. + :raises: :class:`~werkzeug.exceptions.RequestedRangeNotSatisfiable` + if `Range` header could not be parsed or satisfied. + """ + environ = _get_environ(request_or_environ) + if environ['REQUEST_METHOD'] in ('GET', 'HEAD'): + # if the date is not in the headers, add it now. We however + # will not override an already existing header. Unfortunately + # this header will be overriden by many WSGI servers including + # wsgiref. + if 'date' not in self.headers: + self.headers['Date'] = http_date() + accept_ranges = _clean_accept_ranges(accept_ranges) + is206 = self._process_range_request(environ, complete_length, accept_ranges) + if not is206 and not is_resource_modified( + environ, self.headers.get('etag'), None, + self.headers.get('last-modified') + ): + if parse_etags(environ.get('HTTP_IF_MATCH')): + self.status_code = 412 + else: + self.status_code = 304 + if self.automatically_set_content_length and 'content-length' not in self.headers: + length = self.calculate_content_length() + if length is not None: + self.headers['Content-Length'] = length + return self + + def add_etag(self, overwrite=False, weak=False): + """Add an etag for the current response if there is none yet.""" + if overwrite or 'etag' not in self.headers: + self.set_etag(generate_etag(self.get_data()), weak) + + def set_etag(self, etag, weak=False): + """Set the etag, and override the old one if there was one.""" + self.headers['ETag'] = quote_etag(etag, weak) + + def get_etag(self): + """Return a tuple in the form ``(etag, is_weak)``. If there is no + ETag the return value is ``(None, None)``. + """ + return unquote_etag(self.headers.get('ETag')) + + def freeze(self, no_etag=False): + """Call this method if you want to make your response object ready for + pickeling. This buffers the generator if there is one. This also + sets the etag unless `no_etag` is set to `True`. + """ + if not no_etag: + self.add_etag() + super(ETagResponseMixin, self).freeze() + + accept_ranges = header_property('Accept-Ranges', doc=''' + The `Accept-Ranges` header. Even though the name would indicate + that multiple values are supported, it must be one string token only. + + The values ``'bytes'`` and ``'none'`` are common. + + .. versionadded:: 0.7''') + + def _get_content_range(self): + def on_update(rng): + if not rng: + del self.headers['content-range'] + else: + self.headers['Content-Range'] = rng.to_header() + rv = parse_content_range_header(self.headers.get('content-range'), + on_update) + # always provide a content range object to make the descriptor + # more user friendly. It provides an unset() method that can be + # used to remove the header quickly. + if rv is None: + rv = ContentRange(None, None, None, on_update=on_update) + return rv + + def _set_content_range(self, value): + if not value: + del self.headers['content-range'] + elif isinstance(value, string_types): + self.headers['Content-Range'] = value + else: + self.headers['Content-Range'] = value.to_header() + content_range = property(_get_content_range, _set_content_range, doc=''' + The `Content-Range` header as + :class:`~werkzeug.datastructures.ContentRange` object. Even if the + header is not set it wil provide such an object for easier + manipulation. + + .. versionadded:: 0.7''') + del _get_content_range, _set_content_range + + +class ResponseStream(object): + + """A file descriptor like object used by the :class:`ResponseStreamMixin` to + represent the body of the stream. It directly pushes into the response + iterable of the response object. + """ + + mode = 'wb+' + + def __init__(self, response): + self.response = response + self.closed = False + + def write(self, value): + if self.closed: + raise ValueError('I/O operation on closed file') + self.response._ensure_sequence(mutable=True) + self.response.response.append(value) + self.response.headers.pop('Content-Length', None) + return len(value) + + def writelines(self, seq): + for item in seq: + self.write(item) + + def close(self): + self.closed = True + + def flush(self): + if self.closed: + raise ValueError('I/O operation on closed file') + + def isatty(self): + if self.closed: + raise ValueError('I/O operation on closed file') + return False + + def tell(self): + self.response._ensure_sequence() + return sum(map(len, self.response.response)) + + @property + def encoding(self): + return self.response.charset + + +class ResponseStreamMixin(object): + + """Mixin for :class:`BaseRequest` subclasses. Classes that inherit from + this mixin will automatically get a :attr:`stream` property that provides + a write-only interface to the response iterable. + """ + + @cached_property + def stream(self): + """The response iterable as write-only stream.""" + return ResponseStream(self) + + +class CommonRequestDescriptorsMixin(object): + + """A mixin for :class:`BaseRequest` subclasses. Request objects that + mix this class in will automatically get descriptors for a couple of + HTTP headers with automatic type conversion. + + .. versionadded:: 0.5 + """ + + content_type = environ_property('CONTENT_TYPE', doc=''' + The Content-Type entity-header field indicates the media type of + the entity-body sent to the recipient or, in the case of the HEAD + method, the media type that would have been sent had the request + been a GET.''') + + @cached_property + def content_length(self): + """The Content-Length entity-header field indicates the size of the + entity-body in bytes or, in the case of the HEAD method, the size of + the entity-body that would have been sent had the request been a + GET. + """ + return get_content_length(self.environ) + + content_encoding = environ_property('HTTP_CONTENT_ENCODING', doc=''' + The Content-Encoding entity-header field is used as a modifier to the + media-type. When present, its value indicates what additional content + codings have been applied to the entity-body, and thus what decoding + mechanisms must be applied in order to obtain the media-type + referenced by the Content-Type header field. + + .. versionadded:: 0.9''') + content_md5 = environ_property('HTTP_CONTENT_MD5', doc=''' + The Content-MD5 entity-header field, as defined in RFC 1864, is an + MD5 digest of the entity-body for the purpose of providing an + end-to-end message integrity check (MIC) of the entity-body. (Note: + a MIC is good for detecting accidental modification of the + entity-body in transit, but is not proof against malicious attacks.) + + .. versionadded:: 0.9''') + referrer = environ_property('HTTP_REFERER', doc=''' + The Referer[sic] request-header field allows the client to specify, + for the server's benefit, the address (URI) of the resource from which + the Request-URI was obtained (the "referrer", although the header + field is misspelled).''') + date = environ_property('HTTP_DATE', None, parse_date, doc=''' + The Date general-header field represents the date and time at which + the message was originated, having the same semantics as orig-date + in RFC 822.''') + max_forwards = environ_property('HTTP_MAX_FORWARDS', None, int, doc=''' + The Max-Forwards request-header field provides a mechanism with the + TRACE and OPTIONS methods to limit the number of proxies or gateways + that can forward the request to the next inbound server.''') + + def _parse_content_type(self): + if not hasattr(self, '_parsed_content_type'): + self._parsed_content_type = \ + parse_options_header(self.environ.get('CONTENT_TYPE', '')) + + @property + def mimetype(self): + """Like :attr:`content_type`, but without parameters (eg, without + charset, type etc.) and always lowercase. For example if the content + type is ``text/HTML; charset=utf-8`` the mimetype would be + ``'text/html'``. + """ + self._parse_content_type() + return self._parsed_content_type[0].lower() + + @property + def mimetype_params(self): + """The mimetype parameters as dict. For example if the content + type is ``text/html; charset=utf-8`` the params would be + ``{'charset': 'utf-8'}``. + """ + self._parse_content_type() + return self._parsed_content_type[1] + + @cached_property + def pragma(self): + """The Pragma general-header field is used to include + implementation-specific directives that might apply to any recipient + along the request/response chain. All pragma directives specify + optional behavior from the viewpoint of the protocol; however, some + systems MAY require that behavior be consistent with the directives. + """ + return parse_set_header(self.environ.get('HTTP_PRAGMA', '')) + + +class CommonResponseDescriptorsMixin(object): + + """A mixin for :class:`BaseResponse` subclasses. Response objects that + mix this class in will automatically get descriptors for a couple of + HTTP headers with automatic type conversion. + """ + + def _get_mimetype(self): + ct = self.headers.get('content-type') + if ct: + return ct.split(';')[0].strip() + + def _set_mimetype(self, value): + self.headers['Content-Type'] = get_content_type(value, self.charset) + + def _get_mimetype_params(self): + def on_update(d): + self.headers['Content-Type'] = \ + dump_options_header(self.mimetype, d) + d = parse_options_header(self.headers.get('content-type', ''))[1] + return CallbackDict(d, on_update) + + mimetype = property(_get_mimetype, _set_mimetype, doc=''' + The mimetype (content type without charset etc.)''') + mimetype_params = property(_get_mimetype_params, doc=''' + The mimetype parameters as dict. For example if the content + type is ``text/html; charset=utf-8`` the params would be + ``{'charset': 'utf-8'}``. + + .. versionadded:: 0.5 + ''') + location = header_property('Location', doc=''' + The Location response-header field is used to redirect the recipient + to a location other than the Request-URI for completion of the request + or identification of a new resource.''') + age = header_property('Age', None, parse_age, dump_age, doc=''' + The Age response-header field conveys the sender's estimate of the + amount of time since the response (or its revalidation) was + generated at the origin server. + + Age values are non-negative decimal integers, representing time in + seconds.''') + content_type = header_property('Content-Type', doc=''' + The Content-Type entity-header field indicates the media type of the + entity-body sent to the recipient or, in the case of the HEAD method, + the media type that would have been sent had the request been a GET. + ''') + content_length = header_property('Content-Length', None, int, str, doc=''' + The Content-Length entity-header field indicates the size of the + entity-body, in decimal number of OCTETs, sent to the recipient or, + in the case of the HEAD method, the size of the entity-body that would + have been sent had the request been a GET.''') + content_location = header_property('Content-Location', doc=''' + The Content-Location entity-header field MAY be used to supply the + resource location for the entity enclosed in the message when that + entity is accessible from a location separate from the requested + resource's URI.''') + content_encoding = header_property('Content-Encoding', doc=''' + The Content-Encoding entity-header field is used as a modifier to the + media-type. When present, its value indicates what additional content + codings have been applied to the entity-body, and thus what decoding + mechanisms must be applied in order to obtain the media-type + referenced by the Content-Type header field.''') + content_md5 = header_property('Content-MD5', doc=''' + The Content-MD5 entity-header field, as defined in RFC 1864, is an + MD5 digest of the entity-body for the purpose of providing an + end-to-end message integrity check (MIC) of the entity-body. (Note: + a MIC is good for detecting accidental modification of the + entity-body in transit, but is not proof against malicious attacks.) + ''') + date = header_property('Date', None, parse_date, http_date, doc=''' + The Date general-header field represents the date and time at which + the message was originated, having the same semantics as orig-date + in RFC 822.''') + expires = header_property('Expires', None, parse_date, http_date, doc=''' + The Expires entity-header field gives the date/time after which the + response is considered stale. A stale cache entry may not normally be + returned by a cache.''') + last_modified = header_property('Last-Modified', None, parse_date, + http_date, doc=''' + The Last-Modified entity-header field indicates the date and time at + which the origin server believes the variant was last modified.''') + + def _get_retry_after(self): + value = self.headers.get('retry-after') + if value is None: + return + elif value.isdigit(): + return datetime.utcnow() + timedelta(seconds=int(value)) + return parse_date(value) + + def _set_retry_after(self, value): + if value is None: + if 'retry-after' in self.headers: + del self.headers['retry-after'] + return + elif isinstance(value, datetime): + value = http_date(value) + else: + value = str(value) + self.headers['Retry-After'] = value + + retry_after = property(_get_retry_after, _set_retry_after, doc=''' + The Retry-After response-header field can be used with a 503 (Service + Unavailable) response to indicate how long the service is expected + to be unavailable to the requesting client. + + Time in seconds until expiration or date.''') + + def _set_property(name, doc=None): + def fget(self): + def on_update(header_set): + if not header_set and name in self.headers: + del self.headers[name] + elif header_set: + self.headers[name] = header_set.to_header() + return parse_set_header(self.headers.get(name), on_update) + + def fset(self, value): + if not value: + del self.headers[name] + elif isinstance(value, string_types): + self.headers[name] = value + else: + self.headers[name] = dump_header(value) + return property(fget, fset, doc=doc) + + vary = _set_property('Vary', doc=''' + The Vary field value indicates the set of request-header fields that + fully determines, while the response is fresh, whether a cache is + permitted to use the response to reply to a subsequent request + without revalidation.''') + content_language = _set_property('Content-Language', doc=''' + The Content-Language entity-header field describes the natural + language(s) of the intended audience for the enclosed entity. Note + that this might not be equivalent to all the languages used within + the entity-body.''') + allow = _set_property('Allow', doc=''' + The Allow entity-header field lists the set of methods supported + by the resource identified by the Request-URI. The purpose of this + field is strictly to inform the recipient of valid methods + associated with the resource. An Allow header field MUST be + present in a 405 (Method Not Allowed) response.''') + + del _set_property, _get_mimetype, _set_mimetype, _get_retry_after, \ + _set_retry_after + + +class WWWAuthenticateMixin(object): + + """Adds a :attr:`www_authenticate` property to a response object.""" + + @property + def www_authenticate(self): + """The `WWW-Authenticate` header in a parsed form.""" + def on_update(www_auth): + if not www_auth and 'www-authenticate' in self.headers: + del self.headers['www-authenticate'] + elif www_auth: + self.headers['WWW-Authenticate'] = www_auth.to_header() + header = self.headers.get('www-authenticate') + return parse_www_authenticate_header(header, on_update) + + +class Request(BaseRequest, AcceptMixin, ETagRequestMixin, + UserAgentMixin, AuthorizationMixin, + CommonRequestDescriptorsMixin): + + """Full featured request object implementing the following mixins: + + - :class:`AcceptMixin` for accept header parsing + - :class:`ETagRequestMixin` for etag and cache control handling + - :class:`UserAgentMixin` for user agent introspection + - :class:`AuthorizationMixin` for http auth handling + - :class:`CommonRequestDescriptorsMixin` for common headers + """ + + +class PlainRequest(StreamOnlyMixin, Request): + + """A request object without special form parsing capabilities. + + .. versionadded:: 0.9 + """ + + +class Response(BaseResponse, ETagResponseMixin, ResponseStreamMixin, + CommonResponseDescriptorsMixin, + WWWAuthenticateMixin): + + """Full featured response object implementing the following mixins: + + - :class:`ETagResponseMixin` for etag and cache control handling + - :class:`ResponseStreamMixin` to add support for the `stream` property + - :class:`CommonResponseDescriptorsMixin` for various HTTP descriptors + - :class:`WWWAuthenticateMixin` for HTTP authentication support + """ diff --git a/flex/lib/python3.6/site-packages/werkzeug/wsgi.py b/flex/lib/python3.6/site-packages/werkzeug/wsgi.py new file mode 100644 index 0000000..c30021a --- /dev/null +++ b/flex/lib/python3.6/site-packages/werkzeug/wsgi.py @@ -0,0 +1,1364 @@ +# -*- coding: utf-8 -*- +""" + werkzeug.wsgi + ~~~~~~~~~~~~~ + + This module implements WSGI related helpers. + + :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import io +try: + import httplib +except ImportError: + from http import client as httplib +import mimetypes +import os +import posixpath +import re +import socket +from datetime import datetime +from functools import partial, update_wrapper +from itertools import chain +from time import mktime, time +from zlib import adler32 + +from werkzeug._compat import BytesIO, PY2, implements_iterator, iteritems, \ + make_literal_wrapper, string_types, text_type, to_bytes, to_unicode, \ + try_coerce_native, wsgi_get_bytes +from werkzeug._internal import _empty_stream, _encode_idna +from werkzeug.filesystem import get_filesystem_encoding +from werkzeug.http import http_date, is_resource_modified, \ + is_hop_by_hop_header +from werkzeug.urls import uri_to_iri, url_join, url_parse, url_quote +from werkzeug.datastructures import EnvironHeaders + + +def responder(f): + """Marks a function as responder. Decorate a function with it and it + will automatically call the return value as WSGI application. + + Example:: + + @responder + def application(environ, start_response): + return Response('Hello World!') + """ + return update_wrapper(lambda *a: f(*a)(*a[-2:]), f) + + +def get_current_url(environ, root_only=False, strip_querystring=False, + host_only=False, trusted_hosts=None): + """A handy helper function that recreates the full URL as IRI for the + current request or parts of it. Here's an example: + + >>> from werkzeug.test import create_environ + >>> env = create_environ("/?param=foo", "http://localhost/script") + >>> get_current_url(env) + 'http://localhost/script/?param=foo' + >>> get_current_url(env, root_only=True) + 'http://localhost/script/' + >>> get_current_url(env, host_only=True) + 'http://localhost/' + >>> get_current_url(env, strip_querystring=True) + 'http://localhost/script/' + + This optionally it verifies that the host is in a list of trusted hosts. + If the host is not in there it will raise a + :exc:`~werkzeug.exceptions.SecurityError`. + + Note that the string returned might contain unicode characters as the + representation is an IRI not an URI. If you need an ASCII only + representation you can use the :func:`~werkzeug.urls.iri_to_uri` + function: + + >>> from werkzeug.urls import iri_to_uri + >>> iri_to_uri(get_current_url(env)) + 'http://localhost/script/?param=foo' + + :param environ: the WSGI environment to get the current URL from. + :param root_only: set `True` if you only want the root URL. + :param strip_querystring: set to `True` if you don't want the querystring. + :param host_only: set to `True` if the host URL should be returned. + :param trusted_hosts: a list of trusted hosts, see :func:`host_is_trusted` + for more information. + """ + tmp = [environ['wsgi.url_scheme'], '://', get_host(environ, trusted_hosts)] + cat = tmp.append + if host_only: + return uri_to_iri(''.join(tmp) + '/') + cat(url_quote(wsgi_get_bytes(environ.get('SCRIPT_NAME', ''))).rstrip('/')) + cat('/') + if not root_only: + cat(url_quote(wsgi_get_bytes(environ.get('PATH_INFO', '')).lstrip(b'/'))) + if not strip_querystring: + qs = get_query_string(environ) + if qs: + cat('?' + qs) + return uri_to_iri(''.join(tmp)) + + +def host_is_trusted(hostname, trusted_list): + """Checks if a host is trusted against a list. This also takes care + of port normalization. + + .. versionadded:: 0.9 + + :param hostname: the hostname to check + :param trusted_list: a list of hostnames to check against. If a + hostname starts with a dot it will match against + all subdomains as well. + """ + if not hostname: + return False + + if isinstance(trusted_list, string_types): + trusted_list = [trusted_list] + + def _normalize(hostname): + if ':' in hostname: + hostname = hostname.rsplit(':', 1)[0] + return _encode_idna(hostname) + + try: + hostname = _normalize(hostname) + except UnicodeError: + return False + for ref in trusted_list: + if ref.startswith('.'): + ref = ref[1:] + suffix_match = True + else: + suffix_match = False + try: + ref = _normalize(ref) + except UnicodeError: + return False + if ref == hostname: + return True + if suffix_match and hostname.endswith(b'.' + ref): + return True + return False + + +def get_host(environ, trusted_hosts=None): + """Return the real host for the given WSGI environment. This first checks + the `X-Forwarded-Host` header, then the normal `Host` header, and finally + the `SERVER_NAME` environment variable (using the first one it finds). + + Optionally it verifies that the host is in a list of trusted hosts. + If the host is not in there it will raise a + :exc:`~werkzeug.exceptions.SecurityError`. + + :param environ: the WSGI environment to get the host of. + :param trusted_hosts: a list of trusted hosts, see :func:`host_is_trusted` + for more information. + """ + if 'HTTP_X_FORWARDED_HOST' in environ: + rv = environ['HTTP_X_FORWARDED_HOST'].split(',', 1)[0].strip() + elif 'HTTP_HOST' in environ: + rv = environ['HTTP_HOST'] + else: + rv = environ['SERVER_NAME'] + if (environ['wsgi.url_scheme'], environ['SERVER_PORT']) not \ + in (('https', '443'), ('http', '80')): + rv += ':' + environ['SERVER_PORT'] + if trusted_hosts is not None: + if not host_is_trusted(rv, trusted_hosts): + from werkzeug.exceptions import SecurityError + raise SecurityError('Host "%s" is not trusted' % rv) + return rv + + +def get_content_length(environ): + """Returns the content length from the WSGI environment as + integer. If it's not available or chunked transfer encoding is used, + ``None`` is returned. + + .. versionadded:: 0.9 + + :param environ: the WSGI environ to fetch the content length from. + """ + if environ.get('HTTP_TRANSFER_ENCODING', '') == 'chunked': + return None + + content_length = environ.get('CONTENT_LENGTH') + if content_length is not None: + try: + return max(0, int(content_length)) + except (ValueError, TypeError): + pass + + +def get_input_stream(environ, safe_fallback=True): + """Returns the input stream from the WSGI environment and wraps it + in the most sensible way possible. The stream returned is not the + raw WSGI stream in most cases but one that is safe to read from + without taking into account the content length. + + If content length is not set, the stream will be empty for safety reasons. + If the WSGI server supports chunked or infinite streams, it should set + the ``wsgi.input_terminated`` value in the WSGI environ to indicate that. + + .. versionadded:: 0.9 + + :param environ: the WSGI environ to fetch the stream from. + :param safe_fallback: use an empty stream as a safe fallback when the + content length is not set. Disabling this allows infinite streams, + which can be a denial-of-service risk. + """ + stream = environ['wsgi.input'] + content_length = get_content_length(environ) + + # A wsgi extension that tells us if the input is terminated. In + # that case we return the stream unchanged as we know we can safely + # read it until the end. + if environ.get('wsgi.input_terminated'): + return stream + + # If the request doesn't specify a content length, returning the stream is + # potentially dangerous because it could be infinite, malicious or not. If + # safe_fallback is true, return an empty stream instead for safety. + if content_length is None: + return safe_fallback and _empty_stream or stream + + # Otherwise limit the stream to the content length + return LimitedStream(stream, content_length) + + +def get_query_string(environ): + """Returns the `QUERY_STRING` from the WSGI environment. This also takes + care about the WSGI decoding dance on Python 3 environments as a + native string. The string returned will be restricted to ASCII + characters. + + .. versionadded:: 0.9 + + :param environ: the WSGI environment object to get the query string from. + """ + qs = wsgi_get_bytes(environ.get('QUERY_STRING', '')) + # QUERY_STRING really should be ascii safe but some browsers + # will send us some unicode stuff (I am looking at you IE). + # In that case we want to urllib quote it badly. + return try_coerce_native(url_quote(qs, safe=':&%=+$!*\'(),')) + + +def get_path_info(environ, charset='utf-8', errors='replace'): + """Returns the `PATH_INFO` from the WSGI environment and properly + decodes it. This also takes care about the WSGI decoding dance + on Python 3 environments. if the `charset` is set to `None` a + bytestring is returned. + + .. versionadded:: 0.9 + + :param environ: the WSGI environment object to get the path from. + :param charset: the charset for the path info, or `None` if no + decoding should be performed. + :param errors: the decoding error handling. + """ + path = wsgi_get_bytes(environ.get('PATH_INFO', '')) + return to_unicode(path, charset, errors, allow_none_charset=True) + + +def get_script_name(environ, charset='utf-8', errors='replace'): + """Returns the `SCRIPT_NAME` from the WSGI environment and properly + decodes it. This also takes care about the WSGI decoding dance + on Python 3 environments. if the `charset` is set to `None` a + bytestring is returned. + + .. versionadded:: 0.9 + + :param environ: the WSGI environment object to get the path from. + :param charset: the charset for the path, or `None` if no + decoding should be performed. + :param errors: the decoding error handling. + """ + path = wsgi_get_bytes(environ.get('SCRIPT_NAME', '')) + return to_unicode(path, charset, errors, allow_none_charset=True) + + +def pop_path_info(environ, charset='utf-8', errors='replace'): + """Removes and returns the next segment of `PATH_INFO`, pushing it onto + `SCRIPT_NAME`. Returns `None` if there is nothing left on `PATH_INFO`. + + If the `charset` is set to `None` a bytestring is returned. + + If there are empty segments (``'/foo//bar``) these are ignored but + properly pushed to the `SCRIPT_NAME`: + + >>> env = {'SCRIPT_NAME': '/foo', 'PATH_INFO': '/a/b'} + >>> pop_path_info(env) + 'a' + >>> env['SCRIPT_NAME'] + '/foo/a' + >>> pop_path_info(env) + 'b' + >>> env['SCRIPT_NAME'] + '/foo/a/b' + + .. versionadded:: 0.5 + + .. versionchanged:: 0.9 + The path is now decoded and a charset and encoding + parameter can be provided. + + :param environ: the WSGI environment that is modified. + """ + path = environ.get('PATH_INFO') + if not path: + return None + + script_name = environ.get('SCRIPT_NAME', '') + + # shift multiple leading slashes over + old_path = path + path = path.lstrip('/') + if path != old_path: + script_name += '/' * (len(old_path) - len(path)) + + if '/' not in path: + environ['PATH_INFO'] = '' + environ['SCRIPT_NAME'] = script_name + path + rv = wsgi_get_bytes(path) + else: + segment, path = path.split('/', 1) + environ['PATH_INFO'] = '/' + path + environ['SCRIPT_NAME'] = script_name + segment + rv = wsgi_get_bytes(segment) + + return to_unicode(rv, charset, errors, allow_none_charset=True) + + +def peek_path_info(environ, charset='utf-8', errors='replace'): + """Returns the next segment on the `PATH_INFO` or `None` if there + is none. Works like :func:`pop_path_info` without modifying the + environment: + + >>> env = {'SCRIPT_NAME': '/foo', 'PATH_INFO': '/a/b'} + >>> peek_path_info(env) + 'a' + >>> peek_path_info(env) + 'a' + + If the `charset` is set to `None` a bytestring is returned. + + .. versionadded:: 0.5 + + .. versionchanged:: 0.9 + The path is now decoded and a charset and encoding + parameter can be provided. + + :param environ: the WSGI environment that is checked. + """ + segments = environ.get('PATH_INFO', '').lstrip('/').split('/', 1) + if segments: + return to_unicode(wsgi_get_bytes(segments[0]), + charset, errors, allow_none_charset=True) + + +def extract_path_info(environ_or_baseurl, path_or_url, charset='utf-8', + errors='replace', collapse_http_schemes=True): + """Extracts the path info from the given URL (or WSGI environment) and + path. The path info returned is a unicode string, not a bytestring + suitable for a WSGI environment. The URLs might also be IRIs. + + If the path info could not be determined, `None` is returned. + + Some examples: + + >>> extract_path_info('http://example.com/app', '/app/hello') + u'/hello' + >>> extract_path_info('http://example.com/app', + ... 'https://example.com/app/hello') + u'/hello' + >>> extract_path_info('http://example.com/app', + ... 'https://example.com/app/hello', + ... collapse_http_schemes=False) is None + True + + Instead of providing a base URL you can also pass a WSGI environment. + + .. versionadded:: 0.6 + + :param environ_or_baseurl: a WSGI environment dict, a base URL or + base IRI. This is the root of the + application. + :param path_or_url: an absolute path from the server root, a + relative path (in which case it's the path info) + or a full URL. Also accepts IRIs and unicode + parameters. + :param charset: the charset for byte data in URLs + :param errors: the error handling on decode + :param collapse_http_schemes: if set to `False` the algorithm does + not assume that http and https on the + same server point to the same + resource. + """ + def _normalize_netloc(scheme, netloc): + parts = netloc.split(u'@', 1)[-1].split(u':', 1) + if len(parts) == 2: + netloc, port = parts + if (scheme == u'http' and port == u'80') or \ + (scheme == u'https' and port == u'443'): + port = None + else: + netloc = parts[0] + port = None + if port is not None: + netloc += u':' + port + return netloc + + # make sure whatever we are working on is a IRI and parse it + path = uri_to_iri(path_or_url, charset, errors) + if isinstance(environ_or_baseurl, dict): + environ_or_baseurl = get_current_url(environ_or_baseurl, + root_only=True) + base_iri = uri_to_iri(environ_or_baseurl, charset, errors) + base_scheme, base_netloc, base_path = url_parse(base_iri)[:3] + cur_scheme, cur_netloc, cur_path, = \ + url_parse(url_join(base_iri, path))[:3] + + # normalize the network location + base_netloc = _normalize_netloc(base_scheme, base_netloc) + cur_netloc = _normalize_netloc(cur_scheme, cur_netloc) + + # is that IRI even on a known HTTP scheme? + if collapse_http_schemes: + for scheme in base_scheme, cur_scheme: + if scheme not in (u'http', u'https'): + return None + else: + if not (base_scheme in (u'http', u'https') and + base_scheme == cur_scheme): + return None + + # are the netlocs compatible? + if base_netloc != cur_netloc: + return None + + # are we below the application path? + base_path = base_path.rstrip(u'/') + if not cur_path.startswith(base_path): + return None + + return u'/' + cur_path[len(base_path):].lstrip(u'/') + + +class ProxyMiddleware(object): + """This middleware routes some requests to the provided WSGI app and + proxies some requests to an external server. This is not something that + can generally be done on the WSGI layer and some HTTP requests will not + tunnel through correctly (for instance websocket requests cannot be + proxied through WSGI). As a result this is only really useful for some + basic requests that can be forwarded. + + Example configuration:: + + app = ProxyMiddleware(app, { + '/static/': { + 'target': 'http://127.0.0.1:5001/', + } + }) + + For each host options can be specified. The following options are + supported: + + ``target``: + the target URL to dispatch to + ``remove_prefix``: + if set to `True` the prefix is chopped off the URL before + dispatching it to the server. + ``host``: + When set to ``''`` which is the default the host header is + automatically rewritten to the URL of the target. If set to `None` + then the host header is unmodified from the client request. Any + other value overwrites the host header with that value. + ``headers``: + An optional dictionary of headers that should be sent with the + request to the target host. + ``ssl_context``: + In case this is an HTTPS target host then an SSL context can be + provided here (:class:`ssl.SSLContext`). This can be used for instance + to disable SSL verification. + + In this case everything below ``'/static/'`` is proxied to the server on + port 5001. The host header is automatically rewritten and so are request + URLs (eg: the leading `/static/` prefix here gets chopped off). + + .. versionadded:: 0.14 + """ + + def __init__(self, app, targets, chunk_size=2 << 13, timeout=10): + def _set_defaults(opts): + opts.setdefault('remove_prefix', False) + opts.setdefault('host', '') + opts.setdefault('headers', {}) + opts.setdefault('ssl_context', None) + return opts + self.app = app + self.targets = dict(('/%s/' % k.strip('/'), _set_defaults(v)) + for k, v in iteritems(targets)) + self.chunk_size = chunk_size + self.timeout = timeout + + def proxy_to(self, opts, path, prefix): + target = url_parse(opts['target']) + + def application(environ, start_response): + headers = list(EnvironHeaders(environ).items()) + headers[:] = [(k, v) for k, v in headers + if not is_hop_by_hop_header(k) and + k.lower() not in ('content-length', 'host')] + headers.append(('Connection', 'close')) + if opts['host'] == '': + headers.append(('Host', target.ascii_host)) + elif opts['host'] is None: + headers.append(('Host', environ['HTTP_HOST'])) + else: + headers.append(('Host', opts['host'])) + headers.extend(opts['headers'].items()) + + remote_path = path + if opts['remove_prefix']: + remote_path = '%s/%s' % ( + target.path.rstrip('/'), + remote_path[len(prefix):].lstrip('/') + ) + + content_length = environ.get('CONTENT_LENGTH') + chunked = False + if content_length not in ('', None): + headers.append(('Content-Length', content_length)) + elif content_length is not None: + headers.append(('Transfer-Encoding', 'chunked')) + chunked = True + + try: + if target.scheme == 'http': + con = httplib.HTTPConnection( + target.ascii_host, target.port or 80, + timeout=self.timeout) + elif target.scheme == 'https': + con = httplib.HTTPSConnection( + target.ascii_host, target.port or 443, + timeout=self.timeout, + context=opts['ssl_context']) + con.connect() + con.putrequest(environ['REQUEST_METHOD'], url_quote(remote_path), + skip_host=True) + + for k, v in headers: + if k.lower() == 'connection': + v = 'close' + con.putheader(k, v) + con.endheaders() + + stream = get_input_stream(environ) + while 1: + data = stream.read(self.chunk_size) + if not data: + break + if chunked: + con.send(b'%x\r\n%s\r\n' % (len(data), data)) + else: + con.send(data) + + resp = con.getresponse() + except socket.error: + from werkzeug.exceptions import BadGateway + return BadGateway()(environ, start_response) + + start_response('%d %s' % (resp.status, resp.reason), + [(k.title(), v) for k, v in resp.getheaders() + if not is_hop_by_hop_header(k)]) + + def read(): + while 1: + try: + data = resp.read(self.chunk_size) + except socket.error: + break + if not data: + break + yield data + return read() + return application + + def __call__(self, environ, start_response): + path = environ['PATH_INFO'] + app = self.app + for prefix, opts in iteritems(self.targets): + if path.startswith(prefix): + app = self.proxy_to(opts, path, prefix) + break + return app(environ, start_response) + + +class SharedDataMiddleware(object): + + """A WSGI middleware that provides static content for development + environments or simple server setups. Usage is quite simple:: + + import os + from werkzeug.wsgi import SharedDataMiddleware + + app = SharedDataMiddleware(app, { + '/shared': os.path.join(os.path.dirname(__file__), 'shared') + }) + + The contents of the folder ``./shared`` will now be available on + ``http://example.com/shared/``. This is pretty useful during development + because a standalone media server is not required. One can also mount + files on the root folder and still continue to use the application because + the shared data middleware forwards all unhandled requests to the + application, even if the requests are below one of the shared folders. + + If `pkg_resources` is available you can also tell the middleware to serve + files from package data:: + + app = SharedDataMiddleware(app, { + '/shared': ('myapplication', 'shared_files') + }) + + This will then serve the ``shared_files`` folder in the `myapplication` + Python package. + + The optional `disallow` parameter can be a list of :func:`~fnmatch.fnmatch` + rules for files that are not accessible from the web. If `cache` is set to + `False` no caching headers are sent. + + Currently the middleware does not support non ASCII filenames. If the + encoding on the file system happens to be the encoding of the URI it may + work but this could also be by accident. We strongly suggest using ASCII + only file names for static files. + + The middleware will guess the mimetype using the Python `mimetype` + module. If it's unable to figure out the charset it will fall back + to `fallback_mimetype`. + + .. versionchanged:: 0.5 + The cache timeout is configurable now. + + .. versionadded:: 0.6 + The `fallback_mimetype` parameter was added. + + :param app: the application to wrap. If you don't want to wrap an + application you can pass it :exc:`NotFound`. + :param exports: a list or dict of exported files and folders. + :param disallow: a list of :func:`~fnmatch.fnmatch` rules. + :param fallback_mimetype: the fallback mimetype for unknown files. + :param cache: enable or disable caching headers. + :param cache_timeout: the cache timeout in seconds for the headers. + """ + + def __init__(self, app, exports, disallow=None, cache=True, + cache_timeout=60 * 60 * 12, fallback_mimetype='text/plain'): + self.app = app + self.exports = [] + self.cache = cache + self.cache_timeout = cache_timeout + if hasattr(exports, 'items'): + exports = iteritems(exports) + for key, value in exports: + if isinstance(value, tuple): + loader = self.get_package_loader(*value) + elif isinstance(value, string_types): + if os.path.isfile(value): + loader = self.get_file_loader(value) + else: + loader = self.get_directory_loader(value) + else: + raise TypeError('unknown def %r' % value) + self.exports.append((key, loader)) + if disallow is not None: + from fnmatch import fnmatch + self.is_allowed = lambda x: not fnmatch(x, disallow) + self.fallback_mimetype = fallback_mimetype + + def is_allowed(self, filename): + """Subclasses can override this method to disallow the access to + certain files. However by providing `disallow` in the constructor + this method is overwritten. + """ + return True + + def _opener(self, filename): + return lambda: ( + open(filename, 'rb'), + datetime.utcfromtimestamp(os.path.getmtime(filename)), + int(os.path.getsize(filename)) + ) + + def get_file_loader(self, filename): + return lambda x: (os.path.basename(filename), self._opener(filename)) + + def get_package_loader(self, package, package_path): + from pkg_resources import DefaultProvider, ResourceManager, \ + get_provider + loadtime = datetime.utcnow() + provider = get_provider(package) + manager = ResourceManager() + filesystem_bound = isinstance(provider, DefaultProvider) + + def loader(path): + if path is None: + return None, None + path = posixpath.join(package_path, path) + if not provider.has_resource(path): + return None, None + basename = posixpath.basename(path) + if filesystem_bound: + return basename, self._opener( + provider.get_resource_filename(manager, path)) + s = provider.get_resource_string(manager, path) + return basename, lambda: ( + BytesIO(s), + loadtime, + len(s) + ) + return loader + + def get_directory_loader(self, directory): + def loader(path): + if path is not None: + path = os.path.join(directory, path) + else: + path = directory + if os.path.isfile(path): + return os.path.basename(path), self._opener(path) + return None, None + return loader + + def generate_etag(self, mtime, file_size, real_filename): + if not isinstance(real_filename, bytes): + real_filename = real_filename.encode(get_filesystem_encoding()) + return 'wzsdm-%d-%s-%s' % ( + mktime(mtime.timetuple()), + file_size, + adler32(real_filename) & 0xffffffff + ) + + def __call__(self, environ, start_response): + cleaned_path = get_path_info(environ) + if PY2: + cleaned_path = cleaned_path.encode(get_filesystem_encoding()) + # sanitize the path for non unix systems + cleaned_path = cleaned_path.strip('/') + for sep in os.sep, os.altsep: + if sep and sep != '/': + cleaned_path = cleaned_path.replace(sep, '/') + path = '/' + '/'.join(x for x in cleaned_path.split('/') + if x and x != '..') + file_loader = None + for search_path, loader in self.exports: + if search_path == path: + real_filename, file_loader = loader(None) + if file_loader is not None: + break + if not search_path.endswith('/'): + search_path += '/' + if path.startswith(search_path): + real_filename, file_loader = loader(path[len(search_path):]) + if file_loader is not None: + break + if file_loader is None or not self.is_allowed(real_filename): + return self.app(environ, start_response) + + guessed_type = mimetypes.guess_type(real_filename) + mime_type = guessed_type[0] or self.fallback_mimetype + f, mtime, file_size = file_loader() + + headers = [('Date', http_date())] + if self.cache: + timeout = self.cache_timeout + etag = self.generate_etag(mtime, file_size, real_filename) + headers += [ + ('Etag', '"%s"' % etag), + ('Cache-Control', 'max-age=%d, public' % timeout) + ] + if not is_resource_modified(environ, etag, last_modified=mtime): + f.close() + start_response('304 Not Modified', headers) + return [] + headers.append(('Expires', http_date(time() + timeout))) + else: + headers.append(('Cache-Control', 'public')) + + headers.extend(( + ('Content-Type', mime_type), + ('Content-Length', str(file_size)), + ('Last-Modified', http_date(mtime)) + )) + start_response('200 OK', headers) + return wrap_file(environ, f) + + +class DispatcherMiddleware(object): + + """Allows one to mount middlewares or applications in a WSGI application. + This is useful if you want to combine multiple WSGI applications:: + + app = DispatcherMiddleware(app, { + '/app2': app2, + '/app3': app3 + }) + """ + + def __init__(self, app, mounts=None): + self.app = app + self.mounts = mounts or {} + + def __call__(self, environ, start_response): + script = environ.get('PATH_INFO', '') + path_info = '' + while '/' in script: + if script in self.mounts: + app = self.mounts[script] + break + script, last_item = script.rsplit('/', 1) + path_info = '/%s%s' % (last_item, path_info) + else: + app = self.mounts.get(script, self.app) + original_script_name = environ.get('SCRIPT_NAME', '') + environ['SCRIPT_NAME'] = original_script_name + script + environ['PATH_INFO'] = path_info + return app(environ, start_response) + + +@implements_iterator +class ClosingIterator(object): + + """The WSGI specification requires that all middlewares and gateways + respect the `close` callback of an iterator. Because it is useful to add + another close action to a returned iterator and adding a custom iterator + is a boring task this class can be used for that:: + + return ClosingIterator(app(environ, start_response), [cleanup_session, + cleanup_locals]) + + If there is just one close function it can be passed instead of the list. + + A closing iterator is not needed if the application uses response objects + and finishes the processing if the response is started:: + + try: + return response(environ, start_response) + finally: + cleanup_session() + cleanup_locals() + """ + + def __init__(self, iterable, callbacks=None): + iterator = iter(iterable) + self._next = partial(next, iterator) + if callbacks is None: + callbacks = [] + elif callable(callbacks): + callbacks = [callbacks] + else: + callbacks = list(callbacks) + iterable_close = getattr(iterator, 'close', None) + if iterable_close: + callbacks.insert(0, iterable_close) + self._callbacks = callbacks + + def __iter__(self): + return self + + def __next__(self): + return self._next() + + def close(self): + for callback in self._callbacks: + callback() + + +def wrap_file(environ, file, buffer_size=8192): + """Wraps a file. This uses the WSGI server's file wrapper if available + or otherwise the generic :class:`FileWrapper`. + + .. versionadded:: 0.5 + + If the file wrapper from the WSGI server is used it's important to not + iterate over it from inside the application but to pass it through + unchanged. If you want to pass out a file wrapper inside a response + object you have to set :attr:`~BaseResponse.direct_passthrough` to `True`. + + More information about file wrappers are available in :pep:`333`. + + :param file: a :class:`file`-like object with a :meth:`~file.read` method. + :param buffer_size: number of bytes for one iteration. + """ + return environ.get('wsgi.file_wrapper', FileWrapper)(file, buffer_size) + + +@implements_iterator +class FileWrapper(object): + + """This class can be used to convert a :class:`file`-like object into + an iterable. It yields `buffer_size` blocks until the file is fully + read. + + You should not use this class directly but rather use the + :func:`wrap_file` function that uses the WSGI server's file wrapper + support if it's available. + + .. versionadded:: 0.5 + + If you're using this object together with a :class:`BaseResponse` you have + to use the `direct_passthrough` mode. + + :param file: a :class:`file`-like object with a :meth:`~file.read` method. + :param buffer_size: number of bytes for one iteration. + """ + + def __init__(self, file, buffer_size=8192): + self.file = file + self.buffer_size = buffer_size + + def close(self): + if hasattr(self.file, 'close'): + self.file.close() + + def seekable(self): + if hasattr(self.file, 'seekable'): + return self.file.seekable() + if hasattr(self.file, 'seek'): + return True + return False + + def seek(self, *args): + if hasattr(self.file, 'seek'): + self.file.seek(*args) + + def tell(self): + if hasattr(self.file, 'tell'): + return self.file.tell() + return None + + def __iter__(self): + return self + + def __next__(self): + data = self.file.read(self.buffer_size) + if data: + return data + raise StopIteration() + + +@implements_iterator +class _RangeWrapper(object): + # private for now, but should we make it public in the future ? + + """This class can be used to convert an iterable object into + an iterable that will only yield a piece of the underlying content. + It yields blocks until the underlying stream range is fully read. + The yielded blocks will have a size that can't exceed the original + iterator defined block size, but that can be smaller. + + If you're using this object together with a :class:`BaseResponse` you have + to use the `direct_passthrough` mode. + + :param iterable: an iterable object with a :meth:`__next__` method. + :param start_byte: byte from which read will start. + :param byte_range: how many bytes to read. + """ + + def __init__(self, iterable, start_byte=0, byte_range=None): + self.iterable = iter(iterable) + self.byte_range = byte_range + self.start_byte = start_byte + self.end_byte = None + if byte_range is not None: + self.end_byte = self.start_byte + self.byte_range + self.read_length = 0 + self.seekable = hasattr(iterable, 'seekable') and iterable.seekable() + self.end_reached = False + + def __iter__(self): + return self + + def _next_chunk(self): + try: + chunk = next(self.iterable) + self.read_length += len(chunk) + return chunk + except StopIteration: + self.end_reached = True + raise + + def _first_iteration(self): + chunk = None + if self.seekable: + self.iterable.seek(self.start_byte) + self.read_length = self.iterable.tell() + contextual_read_length = self.read_length + else: + while self.read_length <= self.start_byte: + chunk = self._next_chunk() + if chunk is not None: + chunk = chunk[self.start_byte - self.read_length:] + contextual_read_length = self.start_byte + return chunk, contextual_read_length + + def _next(self): + if self.end_reached: + raise StopIteration() + chunk = None + contextual_read_length = self.read_length + if self.read_length == 0: + chunk, contextual_read_length = self._first_iteration() + if chunk is None: + chunk = self._next_chunk() + if self.end_byte is not None and self.read_length >= self.end_byte: + self.end_reached = True + return chunk[:self.end_byte - contextual_read_length] + return chunk + + def __next__(self): + chunk = self._next() + if chunk: + return chunk + self.end_reached = True + raise StopIteration() + + def close(self): + if hasattr(self.iterable, 'close'): + self.iterable.close() + + +def _make_chunk_iter(stream, limit, buffer_size): + """Helper for the line and chunk iter functions.""" + if isinstance(stream, (bytes, bytearray, text_type)): + raise TypeError('Passed a string or byte object instead of ' + 'true iterator or stream.') + if not hasattr(stream, 'read'): + for item in stream: + if item: + yield item + return + if not isinstance(stream, LimitedStream) and limit is not None: + stream = LimitedStream(stream, limit) + _read = stream.read + while 1: + item = _read(buffer_size) + if not item: + break + yield item + + +def make_line_iter(stream, limit=None, buffer_size=10 * 1024, + cap_at_buffer=False): + """Safely iterates line-based over an input stream. If the input stream + is not a :class:`LimitedStream` the `limit` parameter is mandatory. + + This uses the stream's :meth:`~file.read` method internally as opposite + to the :meth:`~file.readline` method that is unsafe and can only be used + in violation of the WSGI specification. The same problem applies to the + `__iter__` function of the input stream which calls :meth:`~file.readline` + without arguments. + + If you need line-by-line processing it's strongly recommended to iterate + over the input stream using this helper function. + + .. versionchanged:: 0.8 + This function now ensures that the limit was reached. + + .. versionadded:: 0.9 + added support for iterators as input stream. + + .. versionadded:: 0.11.10 + added support for the `cap_at_buffer` parameter. + + :param stream: the stream or iterate to iterate over. + :param limit: the limit in bytes for the stream. (Usually + content length. Not necessary if the `stream` + is a :class:`LimitedStream`. + :param buffer_size: The optional buffer size. + :param cap_at_buffer: if this is set chunks are split if they are longer + than the buffer size. Internally this is implemented + that the buffer size might be exhausted by a factor + of two however. + """ + _iter = _make_chunk_iter(stream, limit, buffer_size) + + first_item = next(_iter, '') + if not first_item: + return + + s = make_literal_wrapper(first_item) + empty = s('') + cr = s('\r') + lf = s('\n') + crlf = s('\r\n') + + _iter = chain((first_item,), _iter) + + def _iter_basic_lines(): + _join = empty.join + buffer = [] + while 1: + new_data = next(_iter, '') + if not new_data: + break + new_buf = [] + buf_size = 0 + for item in chain(buffer, new_data.splitlines(True)): + new_buf.append(item) + buf_size += len(item) + if item and item[-1:] in crlf: + yield _join(new_buf) + new_buf = [] + elif cap_at_buffer and buf_size >= buffer_size: + rv = _join(new_buf) + while len(rv) >= buffer_size: + yield rv[:buffer_size] + rv = rv[buffer_size:] + new_buf = [rv] + buffer = new_buf + if buffer: + yield _join(buffer) + + # This hackery is necessary to merge 'foo\r' and '\n' into one item + # of 'foo\r\n' if we were unlucky and we hit a chunk boundary. + previous = empty + for item in _iter_basic_lines(): + if item == lf and previous[-1:] == cr: + previous += item + item = empty + if previous: + yield previous + previous = item + if previous: + yield previous + + +def make_chunk_iter(stream, separator, limit=None, buffer_size=10 * 1024, + cap_at_buffer=False): + """Works like :func:`make_line_iter` but accepts a separator + which divides chunks. If you want newline based processing + you should use :func:`make_line_iter` instead as it + supports arbitrary newline markers. + + .. versionadded:: 0.8 + + .. versionadded:: 0.9 + added support for iterators as input stream. + + .. versionadded:: 0.11.10 + added support for the `cap_at_buffer` parameter. + + :param stream: the stream or iterate to iterate over. + :param separator: the separator that divides chunks. + :param limit: the limit in bytes for the stream. (Usually + content length. Not necessary if the `stream` + is otherwise already limited). + :param buffer_size: The optional buffer size. + :param cap_at_buffer: if this is set chunks are split if they are longer + than the buffer size. Internally this is implemented + that the buffer size might be exhausted by a factor + of two however. + """ + _iter = _make_chunk_iter(stream, limit, buffer_size) + + first_item = next(_iter, '') + if not first_item: + return + + _iter = chain((first_item,), _iter) + if isinstance(first_item, text_type): + separator = to_unicode(separator) + _split = re.compile(r'(%s)' % re.escape(separator)).split + _join = u''.join + else: + separator = to_bytes(separator) + _split = re.compile(b'(' + re.escape(separator) + b')').split + _join = b''.join + + buffer = [] + while 1: + new_data = next(_iter, '') + if not new_data: + break + chunks = _split(new_data) + new_buf = [] + buf_size = 0 + for item in chain(buffer, chunks): + if item == separator: + yield _join(new_buf) + new_buf = [] + buf_size = 0 + else: + buf_size += len(item) + new_buf.append(item) + + if cap_at_buffer and buf_size >= buffer_size: + rv = _join(new_buf) + while len(rv) >= buffer_size: + yield rv[:buffer_size] + rv = rv[buffer_size:] + new_buf = [rv] + buf_size = len(rv) + + buffer = new_buf + if buffer: + yield _join(buffer) + + +@implements_iterator +class LimitedStream(io.IOBase): + + """Wraps a stream so that it doesn't read more than n bytes. If the + stream is exhausted and the caller tries to get more bytes from it + :func:`on_exhausted` is called which by default returns an empty + string. The return value of that function is forwarded + to the reader function. So if it returns an empty string + :meth:`read` will return an empty string as well. + + The limit however must never be higher than what the stream can + output. Otherwise :meth:`readlines` will try to read past the + limit. + + .. admonition:: Note on WSGI compliance + + calls to :meth:`readline` and :meth:`readlines` are not + WSGI compliant because it passes a size argument to the + readline methods. Unfortunately the WSGI PEP is not safely + implementable without a size argument to :meth:`readline` + because there is no EOF marker in the stream. As a result + of that the use of :meth:`readline` is discouraged. + + For the same reason iterating over the :class:`LimitedStream` + is not portable. It internally calls :meth:`readline`. + + We strongly suggest using :meth:`read` only or using the + :func:`make_line_iter` which safely iterates line-based + over a WSGI input stream. + + :param stream: the stream to wrap. + :param limit: the limit for the stream, must not be longer than + what the string can provide if the stream does not + end with `EOF` (like `wsgi.input`) + """ + + def __init__(self, stream, limit): + self._read = stream.read + self._readline = stream.readline + self._pos = 0 + self.limit = limit + + def __iter__(self): + return self + + @property + def is_exhausted(self): + """If the stream is exhausted this attribute is `True`.""" + return self._pos >= self.limit + + def on_exhausted(self): + """This is called when the stream tries to read past the limit. + The return value of this function is returned from the reading + function. + """ + # Read null bytes from the stream so that we get the + # correct end of stream marker. + return self._read(0) + + def on_disconnect(self): + """What should happen if a disconnect is detected? The return + value of this function is returned from read functions in case + the client went away. By default a + :exc:`~werkzeug.exceptions.ClientDisconnected` exception is raised. + """ + from werkzeug.exceptions import ClientDisconnected + raise ClientDisconnected() + + def exhaust(self, chunk_size=1024 * 64): + """Exhaust the stream. This consumes all the data left until the + limit is reached. + + :param chunk_size: the size for a chunk. It will read the chunk + until the stream is exhausted and throw away + the results. + """ + to_read = self.limit - self._pos + chunk = chunk_size + while to_read > 0: + chunk = min(to_read, chunk) + self.read(chunk) + to_read -= chunk + + def read(self, size=None): + """Read `size` bytes or if size is not provided everything is read. + + :param size: the number of bytes read. + """ + if self._pos >= self.limit: + return self.on_exhausted() + if size is None or size == -1: # -1 is for consistence with file + size = self.limit + to_read = min(self.limit - self._pos, size) + try: + read = self._read(to_read) + except (IOError, ValueError): + return self.on_disconnect() + if to_read and len(read) != to_read: + return self.on_disconnect() + self._pos += len(read) + return read + + def readline(self, size=None): + """Reads one line from the stream.""" + if self._pos >= self.limit: + return self.on_exhausted() + if size is None: + size = self.limit - self._pos + else: + size = min(size, self.limit - self._pos) + try: + line = self._readline(size) + except (ValueError, IOError): + return self.on_disconnect() + if size and not line: + return self.on_disconnect() + self._pos += len(line) + return line + + def readlines(self, size=None): + """Reads a file into a list of strings. It calls :meth:`readline` + until the file is read to the end. It does support the optional + `size` argument if the underlaying stream supports it for + `readline`. + """ + last_pos = self._pos + result = [] + if size is not None: + end = min(self.limit, last_pos + size) + else: + end = self.limit + while 1: + if size is not None: + size -= last_pos - self._pos + if self._pos >= end: + break + result.append(self.readline(size)) + if size is not None: + last_pos = self._pos + return result + + def tell(self): + """Returns the position of the stream. + + .. versionadded:: 0.9 + """ + return self._pos + + def __next__(self): + line = self.readline() + if not line: + raise StopIteration() + return line + + def readable(self): + return True diff --git a/flex/lib/python3.6/site-packages/wheel/__pycache__/__init__.cpython-36.pyc b/flex/lib/python3.6/site-packages/wheel/__pycache__/__init__.cpython-36.pyc index 85073d27e0f31ccf337cddd4b1cd79a02a86f65b..4a6d061596ac12a849037c8e9895beb295dc8a02 100644 GIT binary patch delta 96 zcmX@Zc!H75n3tE!W79-7f4_MB(BjmhV*TvIqLPfv?1IvqoYb5|eV5eY?2`Nf{fxxq w?3Bc^%wm1FoYV^aG!T)KnWSG(S(1^TXRK$YUz}Nzs#^e5mYAMeJaM@y09@iC%K!iX delta 100 zcmX@Xc!rV9n3tE!aOOld|Da_3f}+f_#FA9~vcw|&wEUcu)S_bjv?6`uY{R^wLK91a zl&X{}%VHCYY!k~|OEVJ#AV|;C5795kEYM9V&CE&BEl5vGE-Ozn&@azOP0g9OSQP+e Ch9QCg diff --git a/flex/lib/python3.6/site-packages/wheel/__pycache__/archive.cpython-36.pyc b/flex/lib/python3.6/site-packages/wheel/__pycache__/archive.cpython-36.pyc index 355c8be4adb9470f7976cf06fd6edd38609b0a8c..ed1952e2440988c5ec3ab8d39c12ad01c9dba70b 100644 GIT binary patch delta 106 zcmbO%&@aGd%*)H=v1udQGDg2R{m|mnqGJ8*#G;an%bP{j?%|<7~scqCyi( zgOsY2D$8OMi)<6iTuU<(10YDx(+|-v$SlxJD$UGE(Je?%OD-!veb9ad*2j>lak^ zMHId0!4D9^NJnKs^|;pp?j35m){=F{O{d+&&)ueFJSeg zrL8+O@yMEDIpz}@RmxN$Brz>0hoUh>p^7BbQ8lDRqC!yehgzg|SrzIP+9|XmitH1j zU0N^__PDA9Rn}-ll*gn1RdvbIltx6DwiR>V+ZMRv8xCZN$#Pp%@wQWDBuPHmt4RS7 z%o$$`+D#@CYvwo-*-`#utOfaV7SnB+*_JJQX;{@HMe!OY!yMMS%`TUi{N9A4SszntWVtSlZM8>%e9V*@LJsY_B8(uweg004590 z^Fw$FcM>wGhl<>mqQ@9|!WlQSDXgDz`2DA`eg@BrE69i*FTO{}jNZHHwS^4nzOn{0 z8HFiF5gCFdhftvNtdZCj;x}gVSSR}<{H-%e*%%Z%v&bA&IZMbSoOJHBzQT>)!7XQ@ zbpp$mFzc)%FTh%^kR?#dx08N-tbB^_*`KbsoBM!g9E9z{Xg*>`mZ8uUFS^Q0!_0i$ zNor7X@2J|nLIg*qkr2~lg~g#%a9PJN{Q;VVt%(nLDZ+KZekP7pDx>}gYw<=UEy$KJ z_T~R}tE^D=6Wgn!{?02SAt`10g!S82$Reav z*6+vn$hwf*93!nGNa^ZluF8=x8^8yE;4s-FGK0(^{m3BnR^BZAf#olx5gA5i5ga`G fh=gIE`xNPg5qG8en+X=()u}ismW3ohj;H4jNZly{ delta 1036 zcmYk*Ur19?7y$5{ZBEmqY3j^>sQr;?dbhbsEepzupeLCLQjI%zw%xpLx9?sj&a#NI zB7*2ZQDlE~B|(HW%9jet{yy|i!szrCSoF|CJ%vPczD497eti4Rch3FJIrp9pp9$L< zb91xZ=Wf{+SlUC921;Bus1%n$3dPhQ1zie()Y#*W!d`E)E0_o-nsskekGHwEd9~Li ze&ML(lQc!E5A-Q&uwDy?y5s#Jm((AjR88%&bmkJy?%1n@@9i&zSMxR(@GPZQQ~hxY zJW~!RenSp(_B-zf8D!t{OUOWK;o?He3Q-l+4OvzF+{DdMBVlf6;EVp{v_7D!65woW zQMFihPm#auh{|JM-n1F}vz8+KHZAvW%qt~r2{ z4k3pH+|ok_y6jjKRKOn#=oI2K2>aRP;^l;=o)-Tii=tRvDCn~Ia3gO^np!3>rz34h zH?j>G6z~jPQxyX`G0}nSKt_;@Y*T4V2~OvhUOf!^Fgbv%N8;>kshfkQs-E0P%~p*Q@+x(5=^G14rgqo( z%$2vrxX(%W0zC$XUu;@;md$G|$)=r>`;jQ(8NEH?DBuIeS=}*hzyM0&F8;Lwm4grv zA=r@_=BceFQ>>$QgY6?GzOeJP<+g_yzGL@m+sHIC*QsQd#p=A|N-9}5NyHuPtiR^C zCu*Do)?#T1Qi{y6B@JIIPKc13A&|(_BeG}J>ee|TITv$lpP{JmlT}I$Hf#sJF`u;Z zzyqw#>IcQ35bJl^VLOhc7v6}`PeE4>(C!!n{hDkKA!#8aJ diff --git a/flex/lib/python3.6/site-packages/wheel/__pycache__/metadata.cpython-36.pyc b/flex/lib/python3.6/site-packages/wheel/__pycache__/metadata.cpython-36.pyc index fab53767ded643b1f63a10fe6f274156dd333885..68593a2d8d944899e6056b120939e0a3f8a3875e 100644 GIT binary patch delta 242 zcmX@@eB7DMn3tE!W79^q6U=_``k}?CMaBBriA5zDnb`%UIXS60iTW<7#n~nK1^O9@ z$=NB1WtqkLZaJwH`e`5{Co@UEpt2+*KhIdtOusm@BvrQns4Ou(wRp1vOFO?%6nknx zd|GBs>Mb@PBR8=iYVuBDImW2TH-tYjwr)NpqRz##@t{Wu`IC-7F<5#>hBtv!R?XBinoi28N;qlUw8+7#B@GDu0o2 g<>cuKdO)Se6e2}iL6Y4dA`e7N0TFX2nMTI7o z1}Rl3RhGpj7TG42xt3-o20)OWryrtUkXfLcRGOKSqFa!jmRwezW}si5k(!#bS%#&Z z-|!ZDYC(KjW=`rYHXtK6u>dGgQIKC$QhbXwy(qu5pvZ)QfuTqRLt&`f&fhF1E5^vU zV6(2AFC*JRkU@(kH^@6ME}48#{vzY*$&(fIfJzT3M2dERB>O-_9*CF@BIZvvP@E0` Dm+e^S diff --git a/flex/lib/python3.6/site-packages/wheel/__pycache__/pep425tags.cpython-36.pyc b/flex/lib/python3.6/site-packages/wheel/__pycache__/pep425tags.cpython-36.pyc index 616e1f45ed997e1b3d5b7b0d932d9c1c4103431c..51713cdb3288b0d818e4c9afab6ccfb1e24ee4c8 100644 GIT binary patch delta 827 zcmY+C&rj4q6vubkZrSYuvS3{K6H=iWS$n0WWZdsQ$V-Y4IA^PL}W-t1RCRLojOhqe6Wv-zIY zx&2rQkamMZyzMojmhTIn+lxXr;xMwe`9{O#JD#+ce6ee95`1snj`rg1FsMz<*wTx| zWP~=pC8YYvz84+s>0V;pgD`lQx*YXQ`@~8r*54v^L$D#`8HcE=*$1V;OeRyskU2y~ zx3o@XX)t*3Ci|SRi36jp#Y){c1D%M(YVzGy;BADifL`@3x5CQmN4}(f=blZct^!#J zRR$MMHMEnuf~aFij7-9sj@r-9n`IopW!&UqKN(gqQp2%<>R3lqH5gatt&vB=I7rx3 z!q)1TJG&I>t2mS5KWzamhZ4aiq-RZ#x*aA z*qjXATKi~e0p&Wz->2+j-I~E*;b6X9=>5aw>m@M63uB7* zPd6J?hv&wZ?$gv6u#UTwSVmNPfSQzKfd^Y6F?ke;z=b}V?%uKkrr3>fL1M}fV&Nu+@5vbGvPoV9t)>7Ti)xpX+rf|Mg@H_pvK2+XC)~Bj=kaC; zO(##Obp4;VtI(Mv1nRP5U^NnENoLzn*Cf={QP)Sds^a3<>>V=p5YiTCq_Tv64H}{$ T)d^{X=19>UVKx0=zlxJ5Y2v<3 delta 791 zcmY+C&rcIk5XbwrKWw*vtw<_urKv4HmO!_))ld^66L{bo_^?-@pme`jCgLV9{2H)G$KoI${&eMe_;P7W_D}8p@#q1uT$Adl~g%##sQ>nIEA@FwbN1 z^uufD2v!hmdlO^l9id*r6%YSu8E8995=sQ`XA7kAge*Ulvw0D8ZLMKKnL;-RRfOwOtMQ-fWi97@`&M2QS*=@ zFvK8Gp!#01IsWP5+!T!l&VlE6K!FW}G7cHeV&fBOid-d35xjHNxDrc8SJ20fbsg^T ztyof{PDI48x@`mSZ7DGk?%}&KZOeTUce{?$G7Wv(X=$CN4Q&yjkPRI}|1+2wDnCo0 zI}`zI)rGqxgDA@`)cI-bEo*QmKD)9;c@qS0yb`G(;otDHG*)FL$S;*bP{j?%|<7~scqCyi( zgOsY2D$8OMi)<6iTuU<(10YDx(+|-v$SlxJD$UGE(Je?%OD-!;o<&&TMTqK&AkeLQg%ORM1h%U{*{sHbO+c zXPf$^a*G-xay!Qml@GZd28-F?uQCGK1?&MJXs(fo&jnZAzA9~5HcwF~C+3w-Rb5<<@$wV$XlEN+p$nS76yL}@^()E delta 438 zcmYL_%S!@L6vn+}gG@d{X%Qir}mP`d6Rq7d}hSS0E^oE&ZD%=o}%ixw@tD>tp& zwusra?9Z70Aqd(;tM0ML3-`x4-}yc`oQKR~Mks_rVt)1_e37#TH9;RX9fb~?K-D`# zR=}nz&_Xxg2TLmDET~cB55G0O#J|7$-P7p=JIZKC=+oxCt5oHdIf7{Oy zAVCqzt`@EnqO!NhWuVU0lmIGAMu8Y?8r3LDaE1CBs90kh4iFsEVW>}JQ{eQM=bULDICh!|R6v5UbzW0f?ZXd|qpADn;d(r>xi#w!s9I2y9ucrD@y pi`&@nr`^YIiN@aJ7Qag)k=(lGR?jc%Z3kMITI`Q&fyHKt-Vfd>Z}k8G
  • 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 S`{Su2se|bp{=*#E{r>?oQ1pfX literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/flask/__pycache__/blueprints.cpython-36.pyc b/flex/lib/python3.6/site-packages/flask/__pycache__/blueprints.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba0f4e17f9a1cc3b567faaa9b19739b3fce91899 GIT binary patch literal 19967 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 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/flask/__pycache__/ctx.cpython-36.pyc b/flex/lib/python3.6/site-packages/flask/__pycache__/ctx.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..99b65d71494d77f08f555ca1b1609ffef52ff892 GIT binary patch literal 12681 zcmdT~&2QXhekM7i8EQ0=jOY`IBYdAj!4-Z&ptozx$(9d{G0Yb$Uv*_5J&lr$2D zoV?^n)s^w3+61?E(sr!CNbU{8IX-%D~nET>y+ zFO@wU4*Bx^_)48cV}8NIG^z=VWnGbRl9b}mfzKIwp(k}x^t~L`E7^w?tE*$yUo!gJ!zvv`E;C%St&fS&Acb$z`Io((Vjvu66Crp~PUqIBx zO2Zs3^n1RS2JW8ndc8p5%KQhbs}Ju!Z3n%y6Gy)=(Xe3+Pq>_Jkfbga=_aYy-We{q zcxLn)t&ZbDwgR`;PqqSo@=}a3e6%}z`_T`+e|N=w`02w>-8-wFe02Yjd-szEtHY`a zl-EguHs_cBm2h$spX37^0t1F&v@G9jm7ubcU;fH$m4lfLlV*YQiofVreH&+0t?-te zsd_e3bxl-v9P_``>)lD8-Vft-FH8oC5`-JWa^!V`Vbu>dyndMejiHX?`CtCQ<(}&7 zLh_e)J#~2_4*ftSmp9bqH+HT@>WgdFulNIha6P&9&d#;#-Ro~%yMn*X=<@32UZ;0y zz26D_OV>Kr-|T#`zH?cuFFQg#P1wvl26>gUwQw-Z!HLPWHZjAaSNB_Jeqg1>j;&5% zmFBi}U>=%}xneojEA|b&>e6u5O<>ubC=X_T zK1l@!!?ex1_1p~6&(Sk{f&BIGwIoP0QU8y#IE}Hn++0R4P047~Ra>Npru^nd455Y- zm;g*+r=rDS$|M?=EPq(;q(OIT>BG9~(nDZoiR(7dLq7VqrbZuc*QOWpkKYsHr=l1t zNE;!?RC*SsR>Gv{X{Bu9x);$^KK9w?#@20$aVOUOn|LyXIXr^{_{PqxdfCU>wzXY4 z1G7lW+cO7-%*a|99J`@Ij}<@|8wk{t_c6Exo$W1`ytPvk1zUOnBA$uhvPOT zLH|)Fd7!N-nu@ z6rBmBQlZ}8LGE{-2JL$ zHufbus37UZ$PRh-k@mr;M?BZ_l7!g^DQc><<3+x+Ib+?m&?qv z&%}K`==r|86?llA7xGC@^}?R=TTR_G`E2QvOZVb<>2v2@XX&A*kVY}BrHS74bF$F< z@rnDH5SBg&!Z3E8#47Z^v!qv>YeI5vrj8EgIudsbDN})-mf~&)!Yj19=LuAZWjL)v zJeyAfn!5*qBYvb_)DCC`(GI=KgCyIr@>1MI C5Lm^3DNepFWB5?LP=@yjXAR6rk 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 L^jor#|Lp$(HS5rX literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/flask/__pycache__/globals.cpython-36.pyc b/flex/lib/python3.6/site-packages/flask/__pycache__/globals.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..deded8dbcbf4d7168766ee02463212aeee5f664e GIT binary patch literal 1764 zcmb_dUvJws5SL{6pAtK1SL|UJ24YV&u-a*x4off$+tL6VPy|J7V1Ql(TBL2pl&Bo3 zBo4AYH2X691p6ohw7u(rV&hecLGWNS@Be-~H}LJ@56R-+oQwtmS!sdK)do z`PbO>TNKQTJ?67O`dJVMzMVH@BMaj&YsO7nhjEKF<2Gxt_Rn72VI9`RvCAU1g=56S z8!z5+a+^1KbmPZ890T5A+cyEO`t_>kRy%IhWqr5WWjkYUuzU4;M6k^y)yv^rswtJ) zX@1&lkyE|oGm&#msFcJkI9Zz$H9h62(Ws(^P~fBhbt%x!C})1B zoV@z}==fxOOlAs5rf`484HZ%kqrZ@3Z{Sz$f`SoL4uUFrrBW)#hNjDU{ug$NXBVi$GuV|p~mp6Fr3-QOU=ow%rRcX zFNImH`N=tFoJBMzH5K1YCa>S^G$iCm<+_x{5ywr?5^1y+x)uRevA{BTkjfg z;?3M%d#7QYSLmbF9ZJ~2W!%6G2mX68brZZInGIzRE$>5lfSRgZmr2#uTx&enl|Mfj zJgC}9f>oL%Ro7h_N=XeCYTUozu)N~sd?@YB1-3T9en!A1#{qJg0UIgUJ)miY1s-qJ zcdrEm53TwGD;`;K$EKS(N;_X>ij|UoWmWnk6k)LK?{>pZ*yyzJ>9kxm^!>j74|pE$ A8UO$Q literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/flask/__pycache__/helpers.cpython-36.pyc b/flex/lib/python3.6/site-packages/flask/__pycache__/helpers.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e06b93e3c1d999c619c3c5a91a4f988b81e33ab GIT binary patch literal 31277 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�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 literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/flask/__pycache__/logging.cpython-36.pyc b/flex/lib/python3.6/site-packages/flask/__pycache__/logging.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cc831737625056ced1a497cd56aafc59d548a060 GIT binary patch literal 3391 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 phI>%L zlPfC{f*$I;NRNGjUi%gW_S!?ySLmr9xx0!KlmbUXayT4*^9}d@)>iw^-^1Y7mgD^8 zth7z&kJ0rX5ZnnI?gs9BpL@I(dy`sFa~62$?=g-J6QDl-RLAb~ejqbId|ATxv2X4M`#wJ3iEEF$8GgY-3l*j1$7KCsD7s>Uw zZxZ{~4Qkv4Ty^DP@hmj9rkQ`!pP=hDMCQD4-+0#^Y~3>)wn?9}u{gK59@KJQi+Gs( z5)tGzo`k?;DL;#h#XQ0y5k*N#Jsm(Aey7+pVwSmJCD z-rzOv18cu1l%QS|NPvRzQ55Jc^bPbj`exAism=}3ZDoA2J=bwghwqrE$yBazF;oHo z6Gn!}2nj)WO=eMcLBLU>abL?RQw)*Jgc^b%SYjCgYm*sxDz?4M?E5yx;D z#f38_mu`eoU?FOQ$$55Rwu)Gb9wDbvXM&+@hJ+_(erW(>bIctQWlJ~qfLBwU5wOTm z+QiG$Xj)VvlN?@9Ld6kL;kzghbD4Frn#4ab;O|0!st$GDc#t4_L0M1Lv643_1wAP} zs3{*~JE8il)^Qu|Vt4ws=u+6>rLj=xLfJ3b$X&CmD#4O?81r_4vfmKruBproaPv)ESZ|cn_7>`EDw+ zXd<4Otd!Tvec-6`#&~A_-@jU&nzVjoVl3;WyLKzH8e-KpV_~jmuVi2-0kuvKyxe8E zH=ezJMC)P9CIikMeT*F%-C0MjS~hjLrOX4P%=bqb%+!_<+eVn0HgAjMc{5C;6k!&$ zd88}7d%-kSA{5aT-W7_+G1yuk-p<4XC^Hqsb6Rc_oMuVTSsks!Z+T!V-emJ8y3J&( z?tAT8%WrwNU0armu5lfs^bQpQ6iV>Lt${!c)x=?Cu-H-Jaw>Foh`gx`hP&0o5G2zV znAxvpP(cdxIONGpE^dyJ4DO4~;&mv}EK20!1D2);KNGJr9I|5HU0Fz{*74d@lBPIo z2j2g1vo(oPB}p}65IGZ`3g;LU=8hPts@%eaUSgSvQ@Lk{a+>YCFx7}U;*3Cw}?Y{r}4;ssw`~Uy| literal 0 HcmV?d00001 diff --git a/flex/lib/python3.6/site-packages/flask/__pycache__/templating.cpython-36.pyc b/flex/lib/python3.6/site-packages/flask/__pycache__/templating.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..25831fbcce0ee3a9ddeedaa181665089813acc40 GIT binary patch literal 4977 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 qlT', + endpoint='static', + view_func=self.send_static_file) + + #: The click command line context for this application. Commands + #: registered here show up in the :command:`flask` command once the + #: application has been discovered. The default commands are + #: provided by Flask itself and can be overridden. + #: + #: This is an instance of a :class:`click.Group` object. + self.cli = cli.AppGroup(self.name) + + def _get_error_handlers(self): + from warnings import warn + warn(DeprecationWarning('error_handlers is deprecated, use the ' + 'new error_handler_spec attribute instead.'), stacklevel=1) + return self._error_handlers + def _set_error_handlers(self, value): + self._error_handlers = value + self.error_handler_spec[None] = value + error_handlers = property(_get_error_handlers, _set_error_handlers) + del _get_error_handlers, _set_error_handlers + + @locked_cached_property + def name(self): + """The name of the application. This is usually the import name + with the difference that it's guessed from the run file if the + import name is main. This name is used as a display name when + Flask needs the name of the application. It can be set and overridden + to change the value. + + .. versionadded:: 0.8 + """ + if self.import_name == '__main__': + fn = getattr(sys.modules['__main__'], '__file__', None) + if fn is None: + return '__main__' + return os.path.splitext(os.path.basename(fn))[0] + return self.import_name + + @property + def propagate_exceptions(self): + """Returns the value of the ``PROPAGATE_EXCEPTIONS`` configuration + value in case it's set, otherwise a sensible default is returned. + + .. versionadded:: 0.7 + """ + rv = self.config['PROPAGATE_EXCEPTIONS'] + if rv is not None: + return rv + return self.testing or self.debug + + @property + def preserve_context_on_exception(self): + """Returns the value of the ``PRESERVE_CONTEXT_ON_EXCEPTION`` + configuration value in case it's set, otherwise a sensible default + is returned. + + .. versionadded:: 0.7 + """ + rv = self.config['PRESERVE_CONTEXT_ON_EXCEPTION'] + if rv is not None: + return rv + return self.debug + + @property + def logger(self): + """A :class:`logging.Logger` object for this application. The + default configuration is to log to stderr if the application is + in debug mode. This logger can be used to (surprise) log messages. + Here some examples:: + + app.logger.debug('A value for debugging') + app.logger.warning('A warning occurred (%d apples)', 42) + app.logger.error('An error occurred') + + .. versionadded:: 0.3 + """ + if self._logger and self._logger.name == self.logger_name: + return self._logger + with _logger_lock: + if self._logger and self._logger.name == self.logger_name: + return self._logger + from flask.logging import create_logger + self._logger = rv = create_logger(self) + return rv + + @locked_cached_property + def jinja_env(self): + """The Jinja2 environment used to load templates.""" + return self.create_jinja_environment() + + @property + def got_first_request(self): + """This attribute is set to ``True`` if the application started + handling the first request. + + .. versionadded:: 0.8 + """ + return self._got_first_request + + def make_config(self, instance_relative=False): + """Used to create the config attribute by the Flask constructor. + The `instance_relative` parameter is passed in from the constructor + of Flask (there named `instance_relative_config`) and indicates if + the config should be relative to the instance path or the root path + of the application. + + .. versionadded:: 0.8 + """ + root_path = self.root_path + if instance_relative: + root_path = self.instance_path + return self.config_class(root_path, self.default_config) + + def auto_find_instance_path(self): + """Tries to locate the instance path if it was not provided to the + constructor of the application class. It will basically calculate + the path to a folder named ``instance`` next to your main file or + the package. + + .. versionadded:: 0.8 + """ + prefix, package_path = find_package(self.import_name) + if prefix is None: + return os.path.join(package_path, 'instance') + return os.path.join(prefix, 'var', self.name + '-instance') + + def open_instance_resource(self, resource, mode='rb'): + """Opens a resource from the application's instance folder + (:attr:`instance_path`). Otherwise works like + :meth:`open_resource`. Instance resources can also be opened for + writing. + + :param resource: the name of the resource. To access resources within + subfolders use forward slashes as separator. + :param mode: resource file opening mode, default is 'rb'. + """ + return open(os.path.join(self.instance_path, resource), mode) + + def create_jinja_environment(self): + """Creates the Jinja2 environment based on :attr:`jinja_options` + and :meth:`select_jinja_autoescape`. Since 0.7 this also adds + the Jinja2 globals and filters after initialization. Override + this function to customize the behavior. + + .. versionadded:: 0.5 + .. versionchanged:: 0.11 + ``Environment.auto_reload`` set in accordance with + ``TEMPLATES_AUTO_RELOAD`` configuration option. + """ + options = dict(self.jinja_options) + if 'autoescape' not in options: + options['autoescape'] = self.select_jinja_autoescape + if 'auto_reload' not in options: + if self.config['TEMPLATES_AUTO_RELOAD'] is not None: + options['auto_reload'] = self.config['TEMPLATES_AUTO_RELOAD'] + else: + options['auto_reload'] = self.debug + rv = self.jinja_environment(self, **options) + rv.globals.update( + url_for=url_for, + get_flashed_messages=get_flashed_messages, + config=self.config, + # request, session and g are normally added with the + # context processor for efficiency reasons but for imported + # templates we also want the proxies in there. + request=request, + session=session, + g=g + ) + rv.filters['tojson'] = json.tojson_filter + return rv + + def create_global_jinja_loader(self): + """Creates the loader for the Jinja2 environment. Can be used to + override just the loader and keeping the rest unchanged. It's + discouraged to override this function. Instead one should override + the :meth:`jinja_loader` function instead. + + The global loader dispatches between the loaders of the application + and the individual blueprints. + + .. versionadded:: 0.7 + """ + return DispatchingJinjaLoader(self) + + def init_jinja_globals(self): + """Deprecated. Used to initialize the Jinja2 globals. + + .. versionadded:: 0.5 + .. versionchanged:: 0.7 + This method is deprecated with 0.7. Override + :meth:`create_jinja_environment` instead. + """ + + def select_jinja_autoescape(self, filename): + """Returns ``True`` if autoescaping should be active for the given + template name. If no template name is given, returns `True`. + + .. versionadded:: 0.5 + """ + if filename is None: + return True + return filename.endswith(('.html', '.htm', '.xml', '.xhtml')) + + def update_template_context(self, context): + """Update the template context with some commonly used variables. + This injects request, session, config and g into the template + context as well as everything template context processors want + to inject. Note that the as of Flask 0.6, the original values + in the context will not be overridden if a context processor + decides to return a value with the same key. + + :param context: the context as a dictionary that is updated in place + to add extra variables. + """ + funcs = self.template_context_processors[None] + reqctx = _request_ctx_stack.top + if reqctx is not None: + bp = reqctx.request.blueprint + if bp is not None and bp in self.template_context_processors: + funcs = chain(funcs, self.template_context_processors[bp]) + orig_ctx = context.copy() + for func in funcs: + context.update(func()) + # make sure the original values win. This makes it possible to + # easier add new variables in context processors without breaking + # existing views. + context.update(orig_ctx) + + def make_shell_context(self): + """Returns the shell context for an interactive shell for this + application. This runs all the registered shell context + processors. + + .. versionadded:: 0.11 + """ + rv = {'app': self, 'g': g} + for processor in self.shell_context_processors: + rv.update(processor()) + return rv + + def run(self, host=None, port=None, debug=None, **options): + """Runs the application on a local development server. + + Do not use ``run()`` in a production setting. It is not intended to + meet security and performance requirements for a production server. + Instead, see :ref:`deployment` for WSGI server recommendations. + + If the :attr:`debug` flag is set the server will automatically reload + for code changes and show a debugger in case an exception happened. + + If you want to run the application in debug mode, but disable the + code execution on the interactive debugger, you can pass + ``use_evalex=False`` as parameter. This will keep the debugger's + traceback screen active, but disable code execution. + + It is not recommended to use this function for development with + automatic reloading as this is badly supported. Instead you should + be using the :command:`flask` command line script's ``run`` support. + + .. admonition:: Keep in Mind + + Flask will suppress any server error with a generic error page + unless it is in debug mode. As such to enable just the + interactive debugger without the code reloading, you have to + invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``. + Setting ``use_debugger`` to ``True`` without being in debug mode + won't catch any exceptions because there won't be any to + catch. + + .. versionchanged:: 0.10 + The default port is now picked from the ``SERVER_NAME`` variable. + + :param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to + have the server available externally as well. Defaults to + ``'127.0.0.1'``. + :param port: the port of the webserver. Defaults to ``5000`` or the + port defined in the ``SERVER_NAME`` config variable if + present. + :param debug: if given, enable or disable debug mode. + See :attr:`debug`. + :param options: the options to be forwarded to the underlying + Werkzeug server. See + :func:`werkzeug.serving.run_simple` for more + information. + """ + from werkzeug.serving import run_simple + if host is None: + host = '127.0.0.1' + if port is None: + server_name = self.config['SERVER_NAME'] + if server_name and ':' in server_name: + port = int(server_name.rsplit(':', 1)[1]) + else: + port = 5000 + if debug is not None: + self.debug = bool(debug) + options.setdefault('use_reloader', self.debug) + options.setdefault('use_debugger', self.debug) + try: + run_simple(host, port, self, **options) + finally: + # reset the first request information if the development server + # reset normally. This makes it possible to restart the server + # without reloader and that stuff from an interactive shell. + self._got_first_request = False + + def test_client(self, use_cookies=True, **kwargs): + """Creates a test client for this application. For information + about unit testing head over to :ref:`testing`. + + Note that if you are testing for assertions or exceptions in your + application code, you must set ``app.testing = True`` in order for the + exceptions to propagate to the test client. Otherwise, the exception + will be handled by the application (not visible to the test client) and + the only indication of an AssertionError or other exception will be a + 500 status code response to the test client. See the :attr:`testing` + attribute. For example:: + + app.testing = True + client = app.test_client() + + The test client can be used in a ``with`` block to defer the closing down + of the context until the end of the ``with`` block. This is useful if + you want to access the context locals for testing:: + + with app.test_client() as c: + rv = c.get('/?vodka=42') + assert request.args['vodka'] == '42' + + Additionally, you may pass optional keyword arguments that will then + be passed to the application's :attr:`test_client_class` constructor. + For example:: + + from flask.testing import FlaskClient + + class CustomClient(FlaskClient): + def __init__(self, *args, **kwargs): + self._authentication = kwargs.pop("authentication") + super(CustomClient,self).__init__( *args, **kwargs) + + app.test_client_class = CustomClient + client = app.test_client(authentication='Basic ....') + + See :class:`~flask.testing.FlaskClient` for more information. + + .. versionchanged:: 0.4 + added support for ``with`` block usage for the client. + + .. versionadded:: 0.7 + The `use_cookies` parameter was added as well as the ability + to override the client to be used by setting the + :attr:`test_client_class` attribute. + + .. versionchanged:: 0.11 + Added `**kwargs` to support passing additional keyword arguments to + the constructor of :attr:`test_client_class`. + """ + cls = self.test_client_class + if cls is None: + from flask.testing import FlaskClient as cls + return cls(self, self.response_class, use_cookies=use_cookies, **kwargs) + + def open_session(self, request): + """Creates or opens a new session. Default implementation stores all + session data in a signed cookie. This requires that the + :attr:`secret_key` is set. Instead of overriding this method + we recommend replacing the :class:`session_interface`. + + :param request: an instance of :attr:`request_class`. + """ + return self.session_interface.open_session(self, request) + + def save_session(self, session, response): + """Saves the session if it needs updates. For the default + implementation, check :meth:`open_session`. Instead of overriding this + method we recommend replacing the :class:`session_interface`. + + :param session: the session to be saved (a + :class:`~werkzeug.contrib.securecookie.SecureCookie` + object) + :param response: an instance of :attr:`response_class` + """ + return self.session_interface.save_session(self, session, response) + + def make_null_session(self): + """Creates a new instance of a missing session. Instead of overriding + this method we recommend replacing the :class:`session_interface`. + + .. versionadded:: 0.7 + """ + return self.session_interface.make_null_session(self) + + @setupmethod + def register_blueprint(self, blueprint, **options): + """Registers a blueprint on the application. + + .. versionadded:: 0.7 + """ + first_registration = False + if blueprint.name in self.blueprints: + assert self.blueprints[blueprint.name] is blueprint, \ + 'A blueprint\'s name collision occurred between %r and ' \ + '%r. Both share the same name "%s". Blueprints that ' \ + 'are created on the fly need unique names.' % \ + (blueprint, self.blueprints[blueprint.name], blueprint.name) + else: + self.blueprints[blueprint.name] = blueprint + self._blueprint_order.append(blueprint) + first_registration = True + blueprint.register(self, options, first_registration) + + def iter_blueprints(self): + """Iterates over all blueprints by the order they were registered. + + .. versionadded:: 0.11 + """ + return iter(self._blueprint_order) + + @setupmethod + def add_url_rule(self, rule, endpoint=None, view_func=None, **options): + """Connects a URL rule. Works exactly like the :meth:`route` + decorator. If a view_func is provided it will be registered with the + endpoint. + + Basically this example:: + + @app.route('/') + def index(): + pass + + Is equivalent to the following:: + + def index(): + pass + app.add_url_rule('/', 'index', index) + + If the view_func is not provided you will need to connect the endpoint + to a view function like so:: + + app.view_functions['index'] = index + + Internally :meth:`route` invokes :meth:`add_url_rule` so if you want + to customize the behavior via subclassing you only need to change + this method. + + For more information refer to :ref:`url-route-registrations`. + + .. versionchanged:: 0.2 + `view_func` parameter added. + + .. versionchanged:: 0.6 + ``OPTIONS`` is added automatically as method. + + :param rule: the URL rule as string + :param endpoint: the endpoint for the registered URL rule. Flask + itself assumes the name of the view function as + endpoint + :param view_func: the function to call when serving a request to the + provided endpoint + :param options: the options to be forwarded to the underlying + :class:`~werkzeug.routing.Rule` object. A change + to Werkzeug is handling of method options. methods + is a list of methods this rule should be limited + to (``GET``, ``POST`` etc.). By default a rule + just listens for ``GET`` (and implicitly ``HEAD``). + Starting with Flask 0.6, ``OPTIONS`` is implicitly + added and handled by the standard request handling. + """ + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) + options['endpoint'] = endpoint + methods = options.pop('methods', None) + + # if the methods are not given and the view_func object knows its + # methods we can use that instead. If neither exists, we go with + # a tuple of only ``GET`` as default. + if methods is None: + methods = getattr(view_func, 'methods', None) or ('GET',) + if isinstance(methods, string_types): + raise TypeError('Allowed methods have to be iterables of strings, ' + 'for example: @app.route(..., methods=["POST"])') + methods = set(item.upper() for item in methods) + + # Methods that should always be added + required_methods = set(getattr(view_func, 'required_methods', ())) + + # starting with Flask 0.8 the view_func object can disable and + # force-enable the automatic options handling. + provide_automatic_options = getattr(view_func, + 'provide_automatic_options', None) + + if provide_automatic_options is None: + if 'OPTIONS' not in methods: + provide_automatic_options = True + required_methods.add('OPTIONS') + else: + provide_automatic_options = False + + # Add the required methods now. + methods |= required_methods + + rule = self.url_rule_class(rule, methods=methods, **options) + rule.provide_automatic_options = provide_automatic_options + + self.url_map.add(rule) + if view_func is not None: + old_func = self.view_functions.get(endpoint) + if old_func is not None and old_func != view_func: + raise AssertionError('View function mapping is overwriting an ' + 'existing endpoint function: %s' % endpoint) + self.view_functions[endpoint] = view_func + + def route(self, rule, **options): + """A decorator that is used to register a view function for a + given URL rule. This does the same thing as :meth:`add_url_rule` + but is intended for decorator usage:: + + @app.route('/') + def index(): + return 'Hello World' + + For more information refer to :ref:`url-route-registrations`. + + :param rule: the URL rule as string + :param endpoint: the endpoint for the registered URL rule. Flask + itself assumes the name of the view function as + endpoint + :param options: the options to be forwarded to the underlying + :class:`~werkzeug.routing.Rule` object. A change + to Werkzeug is handling of method options. methods + is a list of methods this rule should be limited + to (``GET``, ``POST`` etc.). By default a rule + just listens for ``GET`` (and implicitly ``HEAD``). + Starting with Flask 0.6, ``OPTIONS`` is implicitly + added and handled by the standard request handling. + """ + def decorator(f): + endpoint = options.pop('endpoint', None) + self.add_url_rule(rule, endpoint, f, **options) + return f + return decorator + + @setupmethod + def endpoint(self, endpoint): + """A decorator to register a function as an endpoint. + Example:: + + @app.endpoint('example.endpoint') + def example(): + return "example" + + :param endpoint: the name of the endpoint + """ + def decorator(f): + self.view_functions[endpoint] = f + return f + return decorator + + @staticmethod + def _get_exc_class_and_code(exc_class_or_code): + """Ensure that we register only exceptions as handler keys""" + if isinstance(exc_class_or_code, integer_types): + exc_class = default_exceptions[exc_class_or_code] + else: + exc_class = exc_class_or_code + + assert issubclass(exc_class, Exception) + + if issubclass(exc_class, HTTPException): + return exc_class, exc_class.code + else: + return exc_class, None + + @setupmethod + def errorhandler(self, code_or_exception): + """A decorator that is used to register a function given an + error code. Example:: + + @app.errorhandler(404) + def page_not_found(error): + return 'This page does not exist', 404 + + You can also register handlers for arbitrary exceptions:: + + @app.errorhandler(DatabaseError) + def special_exception_handler(error): + return 'Database connection failed', 500 + + You can also register a function as error handler without using + the :meth:`errorhandler` decorator. The following example is + equivalent to the one above:: + + def page_not_found(error): + return 'This page does not exist', 404 + app.error_handler_spec[None][404] = page_not_found + + Setting error handlers via assignments to :attr:`error_handler_spec` + however is discouraged as it requires fiddling with nested dictionaries + and the special case for arbitrary exception types. + + The first ``None`` refers to the active blueprint. If the error + handler should be application wide ``None`` shall be used. + + .. versionadded:: 0.7 + Use :meth:`register_error_handler` instead of modifying + :attr:`error_handler_spec` directly, for application wide error + handlers. + + .. versionadded:: 0.7 + One can now additionally also register custom exception types + that do not necessarily have to be a subclass of the + :class:`~werkzeug.exceptions.HTTPException` class. + + :param code_or_exception: the code as integer for the handler, or + an arbitrary exception + """ + def decorator(f): + self._register_error_handler(None, code_or_exception, f) + return f + return decorator + + def register_error_handler(self, code_or_exception, f): + """Alternative error attach function to the :meth:`errorhandler` + decorator that is more straightforward to use for non decorator + usage. + + .. versionadded:: 0.7 + """ + self._register_error_handler(None, code_or_exception, f) + + @setupmethod + def _register_error_handler(self, key, code_or_exception, f): + """ + :type key: None|str + :type code_or_exception: int|T<=Exception + :type f: callable + """ + if isinstance(code_or_exception, HTTPException): # old broken behavior + raise ValueError( + 'Tried to register a handler for an exception instance {0!r}. ' + 'Handlers can only be registered for exception classes or HTTP error codes.' + .format(code_or_exception)) + + exc_class, code = self._get_exc_class_and_code(code_or_exception) + + handlers = self.error_handler_spec.setdefault(key, {}).setdefault(code, {}) + handlers[exc_class] = f + + @setupmethod + def template_filter(self, name=None): + """A decorator that is used to register custom template filter. + You can specify a name for the filter, otherwise the function + name will be used. Example:: + + @app.template_filter() + def reverse(s): + return s[::-1] + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + def decorator(f): + self.add_template_filter(f, name=name) + return f + return decorator + + @setupmethod + def add_template_filter(self, f, name=None): + """Register a custom template filter. Works exactly like the + :meth:`template_filter` decorator. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + self.jinja_env.filters[name or f.__name__] = f + + @setupmethod + def template_test(self, name=None): + """A decorator that is used to register custom template test. + You can specify a name for the test, otherwise the function + name will be used. Example:: + + @app.template_test() + def is_prime(n): + if n == 2: + return True + for i in range(2, int(math.ceil(math.sqrt(n))) + 1): + if n % i == 0: + return False + return True + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + def decorator(f): + self.add_template_test(f, name=name) + return f + return decorator + + @setupmethod + def add_template_test(self, f, name=None): + """Register a custom template test. Works exactly like the + :meth:`template_test` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + self.jinja_env.tests[name or f.__name__] = f + + @setupmethod + def template_global(self, name=None): + """A decorator that is used to register a custom template global function. + You can specify a name for the global function, otherwise the function + name will be used. Example:: + + @app.template_global() + def double(n): + return 2 * n + + .. versionadded:: 0.10 + + :param name: the optional name of the global function, otherwise the + function name will be used. + """ + def decorator(f): + self.add_template_global(f, name=name) + return f + return decorator + + @setupmethod + def add_template_global(self, f, name=None): + """Register a custom template global function. Works exactly like the + :meth:`template_global` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the global function, otherwise the + function name will be used. + """ + self.jinja_env.globals[name or f.__name__] = f + + @setupmethod + def before_request(self, f): + """Registers a function to run before each request. + + The function will be called without any arguments. + If the function returns a non-None value, it's handled as + if it was the return value from the view and further + request handling is stopped. + """ + self.before_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def before_first_request(self, f): + """Registers a function to be run before the first request to this + instance of the application. + + The function will be called without any arguments and its return + value is ignored. + + .. versionadded:: 0.8 + """ + self.before_first_request_funcs.append(f) + return f + + @setupmethod + def after_request(self, f): + """Register a function to be run after each request. + + Your function must take one parameter, an instance of + :attr:`response_class` and return a new response object or the + same (see :meth:`process_response`). + + As of Flask 0.7 this function might not be executed at the end of the + request in case an unhandled exception occurred. + """ + self.after_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def teardown_request(self, f): + """Register a function to be run at the end of each request, + regardless of whether there was an exception or not. These functions + are executed when the request context is popped, even if not an + actual request was performed. + + Example:: + + ctx = app.test_request_context() + ctx.push() + ... + ctx.pop() + + When ``ctx.pop()`` is executed in the above example, the teardown + functions are called just before the request context moves from the + stack of active contexts. This becomes relevant if you are using + such constructs in tests. + + Generally teardown functions must take every necessary step to avoid + that they will fail. If they do execute code that might fail they + will have to surround the execution of these code by try/except + statements and log occurring errors. + + When a teardown function was called because of a exception it will + be passed an error object. + + The return values of teardown functions are ignored. + + .. admonition:: Debug Note + + In debug mode Flask will not tear down a request on an exception + immediately. Instead it will keep it alive so that the interactive + debugger can still access it. This behavior can be controlled + by the ``PRESERVE_CONTEXT_ON_EXCEPTION`` configuration variable. + """ + self.teardown_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def teardown_appcontext(self, f): + """Registers a function to be called when the application context + ends. These functions are typically also called when the request + context is popped. + + Example:: + + ctx = app.app_context() + ctx.push() + ... + ctx.pop() + + When ``ctx.pop()`` is executed in the above example, the teardown + functions are called just before the app context moves from the + stack of active contexts. This becomes relevant if you are using + such constructs in tests. + + Since a request context typically also manages an application + context it would also be called when you pop a request context. + + When a teardown function was called because of an exception it will + be passed an error object. + + The return values of teardown functions are ignored. + + .. versionadded:: 0.9 + """ + self.teardown_appcontext_funcs.append(f) + return f + + @setupmethod + def context_processor(self, f): + """Registers a template context processor function.""" + self.template_context_processors[None].append(f) + return f + + @setupmethod + def shell_context_processor(self, f): + """Registers a shell context processor function. + + .. versionadded:: 0.11 + """ + self.shell_context_processors.append(f) + return f + + @setupmethod + def url_value_preprocessor(self, f): + """Registers a function as URL value preprocessor for all view + functions of the application. It's called before the view functions + are called and can modify the url values provided. + """ + self.url_value_preprocessors.setdefault(None, []).append(f) + return f + + @setupmethod + def url_defaults(self, f): + """Callback function for URL defaults for all view functions of the + application. It's called with the endpoint and values and should + update the values passed in place. + """ + self.url_default_functions.setdefault(None, []).append(f) + return f + + def _find_error_handler(self, e): + """Finds a registered error handler for the request’s blueprint. + Otherwise falls back to the app, returns None if not a suitable + handler is found. + """ + exc_class, code = self._get_exc_class_and_code(type(e)) + + def find_handler(handler_map): + if not handler_map: + return + for cls in exc_class.__mro__: + handler = handler_map.get(cls) + if handler is not None: + # cache for next time exc_class is raised + handler_map[exc_class] = handler + return handler + + # try blueprint handlers + handler = find_handler(self.error_handler_spec + .get(request.blueprint, {}) + .get(code)) + if handler is not None: + return handler + + # fall back to app handlers + return find_handler(self.error_handler_spec[None].get(code)) + + def handle_http_exception(self, e): + """Handles an HTTP exception. By default this will invoke the + registered error handlers and fall back to returning the + exception as response. + + .. versionadded:: 0.3 + """ + # Proxy exceptions don't have error codes. We want to always return + # those unchanged as errors + if e.code is None: + return e + + handler = self._find_error_handler(e) + if handler is None: + return e + return handler(e) + + def trap_http_exception(self, e): + """Checks if an HTTP exception should be trapped or not. By default + this will return ``False`` for all exceptions except for a bad request + key error if ``TRAP_BAD_REQUEST_ERRORS`` is set to ``True``. It + also returns ``True`` if ``TRAP_HTTP_EXCEPTIONS`` is set to ``True``. + + This is called for all HTTP exceptions raised by a view function. + If it returns ``True`` for any exception the error handler for this + exception is not called and it shows up as regular exception in the + traceback. This is helpful for debugging implicitly raised HTTP + exceptions. + + .. versionadded:: 0.8 + """ + if self.config['TRAP_HTTP_EXCEPTIONS']: + return True + if self.config['TRAP_BAD_REQUEST_ERRORS']: + return isinstance(e, BadRequest) + return False + + def handle_user_exception(self, e): + """This method is called whenever an exception occurs that should be + handled. A special case are + :class:`~werkzeug.exception.HTTPException`\s which are forwarded by + this function to the :meth:`handle_http_exception` method. This + function will either return a response value or reraise the + exception with the same traceback. + + .. versionadded:: 0.7 + """ + exc_type, exc_value, tb = sys.exc_info() + assert exc_value is e + + # ensure not to trash sys.exc_info() at that point in case someone + # wants the traceback preserved in handle_http_exception. Of course + # we cannot prevent users from trashing it themselves in a custom + # trap_http_exception method so that's their fault then. + + if isinstance(e, HTTPException) and not self.trap_http_exception(e): + return self.handle_http_exception(e) + + handler = self._find_error_handler(e) + + if handler is None: + reraise(exc_type, exc_value, tb) + return handler(e) + + def handle_exception(self, e): + """Default exception handling that kicks in when an exception + occurs that is not caught. In debug mode the exception will + be re-raised immediately, otherwise it is logged and the handler + for a 500 internal server error is used. If no such handler + exists, a default 500 internal server error message is displayed. + + .. versionadded:: 0.3 + """ + exc_type, exc_value, tb = sys.exc_info() + + got_request_exception.send(self, exception=e) + handler = self._find_error_handler(InternalServerError()) + + if self.propagate_exceptions: + # if we want to repropagate the exception, we can attempt to + # raise it with the whole traceback in case we can do that + # (the function was actually called from the except part) + # otherwise, we just raise the error again + if exc_value is e: + reraise(exc_type, exc_value, tb) + else: + raise e + + self.log_exception((exc_type, exc_value, tb)) + if handler is None: + return InternalServerError() + return self.finalize_request(handler(e), from_error_handler=True) + + def log_exception(self, exc_info): + """Logs an exception. This is called by :meth:`handle_exception` + if debugging is disabled and right before the handler is called. + The default implementation logs the exception as error on the + :attr:`logger`. + + .. versionadded:: 0.8 + """ + self.logger.error('Exception on %s [%s]' % ( + request.path, + request.method + ), exc_info=exc_info) + + def raise_routing_exception(self, request): + """Exceptions that are recording during routing are reraised with + this method. During debug we are not reraising redirect requests + for non ``GET``, ``HEAD``, or ``OPTIONS`` requests and we're raising + a different error instead to help debug situations. + + :internal: + """ + if not self.debug \ + or not isinstance(request.routing_exception, RequestRedirect) \ + or request.method in ('GET', 'HEAD', 'OPTIONS'): + raise request.routing_exception + + from .debughelpers import FormDataRoutingRedirect + raise FormDataRoutingRedirect(request) + + def dispatch_request(self): + """Does the request dispatching. Matches the URL and returns the + return value of the view or error handler. This does not have to + be a response object. In order to convert the return value to a + proper response object, call :func:`make_response`. + + .. versionchanged:: 0.7 + This no longer does the exception handling, this code was + moved to the new :meth:`full_dispatch_request`. + """ + req = _request_ctx_stack.top.request + if req.routing_exception is not None: + self.raise_routing_exception(req) + rule = req.url_rule + # if we provide automatic options for this URL and the + # request came with the OPTIONS method, reply automatically + if getattr(rule, 'provide_automatic_options', False) \ + and req.method == 'OPTIONS': + return self.make_default_options_response() + # otherwise dispatch to the handler for that endpoint + return self.view_functions[rule.endpoint](**req.view_args) + + def full_dispatch_request(self): + """Dispatches the request and on top of that performs request + pre and postprocessing as well as HTTP exception catching and + error handling. + + .. versionadded:: 0.7 + """ + self.try_trigger_before_first_request_functions() + try: + request_started.send(self) + rv = self.preprocess_request() + if rv is None: + rv = self.dispatch_request() + except Exception as e: + rv = self.handle_user_exception(e) + return self.finalize_request(rv) + + def finalize_request(self, rv, from_error_handler=False): + """Given the return value from a view function this finalizes + the request by converting it into a response and invoking the + postprocessing functions. This is invoked for both normal + request dispatching as well as error handlers. + + Because this means that it might be called as a result of a + failure a special safe mode is available which can be enabled + with the `from_error_handler` flag. If enabled, failures in + response processing will be logged and otherwise ignored. + + :internal: + """ + response = self.make_response(rv) + try: + response = self.process_response(response) + request_finished.send(self, response=response) + except Exception: + if not from_error_handler: + raise + self.logger.exception('Request finalizing failed with an ' + 'error while handling an error') + return response + + def try_trigger_before_first_request_functions(self): + """Called before each request and will ensure that it triggers + the :attr:`before_first_request_funcs` and only exactly once per + application instance (which means process usually). + + :internal: + """ + if self._got_first_request: + return + with self._before_request_lock: + if self._got_first_request: + return + for func in self.before_first_request_funcs: + func() + self._got_first_request = True + + def make_default_options_response(self): + """This method is called to create the default ``OPTIONS`` response. + This can be changed through subclassing to change the default + behavior of ``OPTIONS`` responses. + + .. versionadded:: 0.7 + """ + adapter = _request_ctx_stack.top.url_adapter + if hasattr(adapter, 'allowed_methods'): + methods = adapter.allowed_methods() + else: + # fallback for Werkzeug < 0.7 + methods = [] + try: + adapter.match(method='--') + except MethodNotAllowed as e: + methods = e.valid_methods + except HTTPException as e: + pass + rv = self.response_class() + rv.allow.update(methods) + return rv + + def should_ignore_error(self, error): + """This is called to figure out if an error should be ignored + or not as far as the teardown system is concerned. If this + function returns ``True`` then the teardown handlers will not be + passed the error. + + .. versionadded:: 0.10 + """ + return False + + def make_response(self, rv): + """Converts the return value from a view function to a real + response object that is an instance of :attr:`response_class`. + + The following types are allowed for `rv`: + + .. tabularcolumns:: |p{3.5cm}|p{9.5cm}| + + ======================= =========================================== + :attr:`response_class` the object is returned unchanged + :class:`str` a response object is created with the + string as body + :class:`unicode` a response object is created with the + string encoded to utf-8 as body + a WSGI function the function is called as WSGI application + and buffered as response object + :class:`tuple` A tuple in the form ``(response, status, + headers)`` or ``(response, headers)`` + where `response` is any of the + types defined here, `status` is a string + or an integer and `headers` is a list or + a dictionary with header values. + ======================= =========================================== + + :param rv: the return value from the view function + + .. versionchanged:: 0.9 + Previously a tuple was interpreted as the arguments for the + response object. + """ + status_or_headers = headers = None + if isinstance(rv, tuple): + rv, status_or_headers, headers = rv + (None,) * (3 - len(rv)) + + if rv is None: + raise ValueError('View function did not return a response') + + if isinstance(status_or_headers, (dict, list)): + headers, status_or_headers = status_or_headers, None + + if not isinstance(rv, self.response_class): + # When we create a response object directly, we let the constructor + # set the headers and status. We do this because there can be + # some extra logic involved when creating these objects with + # specific values (like default content type selection). + if isinstance(rv, (text_type, bytes, bytearray)): + rv = self.response_class(rv, headers=headers, + status=status_or_headers) + headers = status_or_headers = None + else: + rv = self.response_class.force_type(rv, request.environ) + + if status_or_headers is not None: + if isinstance(status_or_headers, string_types): + rv.status = status_or_headers + else: + rv.status_code = status_or_headers + if headers: + rv.headers.extend(headers) + + return rv + + def create_url_adapter(self, request): + """Creates a URL adapter for the given request. The URL adapter + is created at a point where the request context is not yet set up + so the request is passed explicitly. + + .. versionadded:: 0.6 + + .. versionchanged:: 0.9 + This can now also be called without a request object when the + URL adapter is created for the application context. + """ + if request is not None: + return self.url_map.bind_to_environ(request.environ, + server_name=self.config['SERVER_NAME']) + # We need at the very least the server name to be set for this + # to work. + if self.config['SERVER_NAME'] is not None: + return self.url_map.bind( + self.config['SERVER_NAME'], + script_name=self.config['APPLICATION_ROOT'] or '/', + url_scheme=self.config['PREFERRED_URL_SCHEME']) + + def inject_url_defaults(self, endpoint, values): + """Injects the URL defaults for the given endpoint directly into + the values dictionary passed. This is used internally and + automatically called on URL building. + + .. versionadded:: 0.7 + """ + funcs = self.url_default_functions.get(None, ()) + if '.' in endpoint: + bp = endpoint.rsplit('.', 1)[0] + funcs = chain(funcs, self.url_default_functions.get(bp, ())) + for func in funcs: + func(endpoint, values) + + def handle_url_build_error(self, error, endpoint, values): + """Handle :class:`~werkzeug.routing.BuildError` on :meth:`url_for`. + """ + exc_type, exc_value, tb = sys.exc_info() + for handler in self.url_build_error_handlers: + try: + rv = handler(error, endpoint, values) + if rv is not None: + return rv + except BuildError as e: + # make error available outside except block (py3) + error = e + + # At this point we want to reraise the exception. If the error is + # still the same one we can reraise it with the original traceback, + # otherwise we raise it from here. + if error is exc_value: + reraise(exc_type, exc_value, tb) + raise error + + def preprocess_request(self): + """Called before the actual request dispatching and will + call each :meth:`before_request` decorated function, passing no + arguments. + If any of these functions returns a value, it's handled as + if it was the return value from the view and further + request handling is stopped. + + This also triggers the :meth:`url_value_preprocessor` functions before + the actual :meth:`before_request` functions are called. + """ + bp = _request_ctx_stack.top.request.blueprint + + funcs = self.url_value_preprocessors.get(None, ()) + if bp is not None and bp in self.url_value_preprocessors: + funcs = chain(funcs, self.url_value_preprocessors[bp]) + for func in funcs: + func(request.endpoint, request.view_args) + + funcs = self.before_request_funcs.get(None, ()) + if bp is not None and bp in self.before_request_funcs: + funcs = chain(funcs, self.before_request_funcs[bp]) + for func in funcs: + rv = func() + if rv is not None: + return rv + + def process_response(self, response): + """Can be overridden in order to modify the response object + before it's sent to the WSGI server. By default this will + call all the :meth:`after_request` decorated functions. + + .. versionchanged:: 0.5 + As of Flask 0.5 the functions registered for after request + execution are called in reverse order of registration. + + :param response: a :attr:`response_class` object. + :return: a new response object or the same, has to be an + instance of :attr:`response_class`. + """ + ctx = _request_ctx_stack.top + bp = ctx.request.blueprint + funcs = ctx._after_request_functions + if bp is not None and bp in self.after_request_funcs: + funcs = chain(funcs, reversed(self.after_request_funcs[bp])) + if None in self.after_request_funcs: + funcs = chain(funcs, reversed(self.after_request_funcs[None])) + for handler in funcs: + response = handler(response) + if not self.session_interface.is_null_session(ctx.session): + self.save_session(ctx.session, response) + return response + + def do_teardown_request(self, exc=_sentinel): + """Called after the actual request dispatching and will + call every as :meth:`teardown_request` decorated function. This is + not actually called by the :class:`Flask` object itself but is always + triggered when the request context is popped. That way we have a + tighter control over certain resources under testing environments. + + .. versionchanged:: 0.9 + Added the `exc` argument. Previously this was always using the + current exception information. + """ + if exc is _sentinel: + exc = sys.exc_info()[1] + funcs = reversed(self.teardown_request_funcs.get(None, ())) + bp = _request_ctx_stack.top.request.blueprint + if bp is not None and bp in self.teardown_request_funcs: + funcs = chain(funcs, reversed(self.teardown_request_funcs[bp])) + for func in funcs: + func(exc) + request_tearing_down.send(self, exc=exc) + + def do_teardown_appcontext(self, exc=_sentinel): + """Called when an application context is popped. This works pretty + much the same as :meth:`do_teardown_request` but for the application + context. + + .. versionadded:: 0.9 + """ + if exc is _sentinel: + exc = sys.exc_info()[1] + for func in reversed(self.teardown_appcontext_funcs): + func(exc) + appcontext_tearing_down.send(self, exc=exc) + + def app_context(self): + """Binds the application only. For as long as the application is bound + to the current context the :data:`flask.current_app` points to that + application. An application context is automatically created when a + request context is pushed if necessary. + + Example usage:: + + with app.app_context(): + ... + + .. versionadded:: 0.9 + """ + return AppContext(self) + + def request_context(self, environ): + """Creates a :class:`~flask.ctx.RequestContext` from the given + environment and binds it to the current context. This must be used in + combination with the ``with`` statement because the request is only bound + to the current context for the duration of the ``with`` block. + + Example usage:: + + with app.request_context(environ): + do_something_with(request) + + The object returned can also be used without the ``with`` statement + which is useful for working in the shell. The example above is + doing exactly the same as this code:: + + ctx = app.request_context(environ) + ctx.push() + try: + do_something_with(request) + finally: + ctx.pop() + + .. versionchanged:: 0.3 + Added support for non-with statement usage and ``with`` statement + is now passed the ctx object. + + :param environ: a WSGI environment + """ + return RequestContext(self, environ) + + def test_request_context(self, *args, **kwargs): + """Creates a WSGI environment from the given values (see + :class:`werkzeug.test.EnvironBuilder` for more information, this + function accepts the same arguments). + """ + from flask.testing import make_test_environ_builder + builder = make_test_environ_builder(self, *args, **kwargs) + try: + return self.request_context(builder.get_environ()) + finally: + builder.close() + + def wsgi_app(self, environ, start_response): + """The actual WSGI application. This is not implemented in + `__call__` so that middlewares can be applied without losing a + reference to the class. So instead of doing this:: + + app = MyMiddleware(app) + + It's a better idea to do this instead:: + + app.wsgi_app = MyMiddleware(app.wsgi_app) + + Then you still have the original application object around and + can continue to call methods on it. + + .. versionchanged:: 0.7 + The behavior of the before and after request callbacks was changed + under error conditions and a new callback was added that will + always execute at the end of the request, independent on if an + error occurred or not. See :ref:`callbacks-and-errors`. + + :param environ: a WSGI environment + :param start_response: a callable accepting a status code, + a list of headers and an optional + exception context to start the response + """ + ctx = self.request_context(environ) + ctx.push() + error = None + try: + try: + response = self.full_dispatch_request() + except Exception as e: + error = e + response = self.handle_exception(e) + except: + error = sys.exc_info()[1] + raise + return response(environ, start_response) + finally: + if self.should_ignore_error(error): + error = None + ctx.auto_pop(error) + + def __call__(self, environ, start_response): + """Shortcut for :attr:`wsgi_app`.""" + return self.wsgi_app(environ, start_response) + + def __repr__(self): + return '<%s %r>' % ( + self.__class__.__name__, + self.name, + ) diff --git a/flex/lib/python3.6/site-packages/flask/blueprints.py b/flex/lib/python3.6/site-packages/flask/blueprints.py new file mode 100644 index 0000000..586a1b0 --- /dev/null +++ b/flex/lib/python3.6/site-packages/flask/blueprints.py @@ -0,0 +1,413 @@ +# -*- coding: utf-8 -*- +""" + flask.blueprints + ~~~~~~~~~~~~~~~~ + + Blueprints are the recommended way to implement larger or more + pluggable applications in Flask 0.7 and later. + + :copyright: (c) 2015 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" +from functools import update_wrapper + +from .helpers import _PackageBoundObject, _endpoint_from_view_func + + +class BlueprintSetupState(object): + """Temporary holder object for registering a blueprint with the + application. An instance of this class is created by the + :meth:`~flask.Blueprint.make_setup_state` method and later passed + to all register callback functions. + """ + + def __init__(self, blueprint, app, options, first_registration): + #: a reference to the current application + self.app = app + + #: a reference to the blueprint that created this setup state. + self.blueprint = blueprint + + #: a dictionary with all options that were passed to the + #: :meth:`~flask.Flask.register_blueprint` method. + self.options = options + + #: as blueprints can be registered multiple times with the + #: application and not everything wants to be registered + #: multiple times on it, this attribute can be used to figure + #: out if the blueprint was registered in the past already. + self.first_registration = first_registration + + subdomain = self.options.get('subdomain') + if subdomain is None: + subdomain = self.blueprint.subdomain + + #: The subdomain that the blueprint should be active for, ``None`` + #: otherwise. + self.subdomain = subdomain + + url_prefix = self.options.get('url_prefix') + if url_prefix is None: + url_prefix = self.blueprint.url_prefix + + #: The prefix that should be used for all URLs defined on the + #: blueprint. + self.url_prefix = url_prefix + + #: A dictionary with URL defaults that is added to each and every + #: URL that was defined with the blueprint. + self.url_defaults = dict(self.blueprint.url_values_defaults) + self.url_defaults.update(self.options.get('url_defaults', ())) + + def add_url_rule(self, rule, endpoint=None, view_func=None, **options): + """A helper method to register a rule (and optionally a view function) + to the application. The endpoint is automatically prefixed with the + blueprint's name. + """ + if self.url_prefix: + rule = self.url_prefix + rule + options.setdefault('subdomain', self.subdomain) + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) + defaults = self.url_defaults + if 'defaults' in options: + defaults = dict(defaults, **options.pop('defaults')) + self.app.add_url_rule(rule, '%s.%s' % (self.blueprint.name, endpoint), + view_func, defaults=defaults, **options) + + +class Blueprint(_PackageBoundObject): + """Represents a blueprint. A blueprint is an object that records + functions that will be called with the + :class:`~flask.blueprints.BlueprintSetupState` later to register functions + or other things on the main application. See :ref:`blueprints` for more + information. + + .. versionadded:: 0.7 + """ + + warn_on_modifications = False + _got_registered_once = False + + def __init__(self, name, import_name, static_folder=None, + static_url_path=None, template_folder=None, + url_prefix=None, subdomain=None, url_defaults=None, + root_path=None): + _PackageBoundObject.__init__(self, import_name, template_folder, + root_path=root_path) + self.name = name + self.url_prefix = url_prefix + self.subdomain = subdomain + self.static_folder = static_folder + self.static_url_path = static_url_path + self.deferred_functions = [] + if url_defaults is None: + url_defaults = {} + self.url_values_defaults = url_defaults + + def record(self, func): + """Registers a function that is called when the blueprint is + registered on the application. This function is called with the + state as argument as returned by the :meth:`make_setup_state` + method. + """ + if self._got_registered_once and self.warn_on_modifications: + from warnings import warn + warn(Warning('The blueprint was already registered once ' + 'but is getting modified now. These changes ' + 'will not show up.')) + self.deferred_functions.append(func) + + def record_once(self, func): + """Works like :meth:`record` but wraps the function in another + function that will ensure the function is only called once. If the + blueprint is registered a second time on the application, the + function passed is not called. + """ + def wrapper(state): + if state.first_registration: + func(state) + return self.record(update_wrapper(wrapper, func)) + + def make_setup_state(self, app, options, first_registration=False): + """Creates an instance of :meth:`~flask.blueprints.BlueprintSetupState` + object that is later passed to the register callback functions. + Subclasses can override this to return a subclass of the setup state. + """ + return BlueprintSetupState(self, app, options, first_registration) + + def register(self, app, options, first_registration=False): + """Called by :meth:`Flask.register_blueprint` to register a blueprint + on the application. This can be overridden to customize the register + behavior. Keyword arguments from + :func:`~flask.Flask.register_blueprint` are directly forwarded to this + method in the `options` dictionary. + """ + self._got_registered_once = True + state = self.make_setup_state(app, options, first_registration) + if self.has_static_folder: + state.add_url_rule(self.static_url_path + '/', + view_func=self.send_static_file, + endpoint='static') + + for deferred in self.deferred_functions: + deferred(state) + + def route(self, rule, **options): + """Like :meth:`Flask.route` but for a blueprint. The endpoint for the + :func:`url_for` function is prefixed with the name of the blueprint. + """ + def decorator(f): + endpoint = options.pop("endpoint", f.__name__) + self.add_url_rule(rule, endpoint, f, **options) + return f + return decorator + + def add_url_rule(self, rule, endpoint=None, view_func=None, **options): + """Like :meth:`Flask.add_url_rule` but for a blueprint. The endpoint for + the :func:`url_for` function is prefixed with the name of the blueprint. + """ + if endpoint: + assert '.' not in endpoint, "Blueprint endpoints should not contain dots" + self.record(lambda s: + s.add_url_rule(rule, endpoint, view_func, **options)) + + def endpoint(self, endpoint): + """Like :meth:`Flask.endpoint` but for a blueprint. This does not + prefix the endpoint with the blueprint name, this has to be done + explicitly by the user of this method. If the endpoint is prefixed + with a `.` it will be registered to the current blueprint, otherwise + it's an application independent endpoint. + """ + def decorator(f): + def register_endpoint(state): + state.app.view_functions[endpoint] = f + self.record_once(register_endpoint) + return f + return decorator + + def app_template_filter(self, name=None): + """Register a custom template filter, available application wide. Like + :meth:`Flask.template_filter` but for a blueprint. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + def decorator(f): + self.add_app_template_filter(f, name=name) + return f + return decorator + + def add_app_template_filter(self, f, name=None): + """Register a custom template filter, available application wide. Like + :meth:`Flask.add_template_filter` but for a blueprint. Works exactly + like the :meth:`app_template_filter` decorator. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + def register_template(state): + state.app.jinja_env.filters[name or f.__name__] = f + self.record_once(register_template) + + def app_template_test(self, name=None): + """Register a custom template test, available application wide. Like + :meth:`Flask.template_test` but for a blueprint. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + def decorator(f): + self.add_app_template_test(f, name=name) + return f + return decorator + + def add_app_template_test(self, f, name=None): + """Register a custom template test, available application wide. Like + :meth:`Flask.add_template_test` but for a blueprint. Works exactly + like the :meth:`app_template_test` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + def register_template(state): + state.app.jinja_env.tests[name or f.__name__] = f + self.record_once(register_template) + + def app_template_global(self, name=None): + """Register a custom template global, available application wide. Like + :meth:`Flask.template_global` but for a blueprint. + + .. versionadded:: 0.10 + + :param name: the optional name of the global, otherwise the + function name will be used. + """ + def decorator(f): + self.add_app_template_global(f, name=name) + return f + return decorator + + def add_app_template_global(self, f, name=None): + """Register a custom template global, available application wide. Like + :meth:`Flask.add_template_global` but for a blueprint. Works exactly + like the :meth:`app_template_global` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the global, otherwise the + function name will be used. + """ + def register_template(state): + state.app.jinja_env.globals[name or f.__name__] = f + self.record_once(register_template) + + def before_request(self, f): + """Like :meth:`Flask.before_request` but for a blueprint. This function + is only executed before each request that is handled by a function of + that blueprint. + """ + self.record_once(lambda s: s.app.before_request_funcs + .setdefault(self.name, []).append(f)) + return f + + def before_app_request(self, f): + """Like :meth:`Flask.before_request`. Such a function is executed + before each request, even if outside of a blueprint. + """ + self.record_once(lambda s: s.app.before_request_funcs + .setdefault(None, []).append(f)) + return f + + def before_app_first_request(self, f): + """Like :meth:`Flask.before_first_request`. Such a function is + executed before the first request to the application. + """ + self.record_once(lambda s: s.app.before_first_request_funcs.append(f)) + return f + + def after_request(self, f): + """Like :meth:`Flask.after_request` but for a blueprint. This function + is only executed after each request that is handled by a function of + that blueprint. + """ + self.record_once(lambda s: s.app.after_request_funcs + .setdefault(self.name, []).append(f)) + return f + + def after_app_request(self, f): + """Like :meth:`Flask.after_request` but for a blueprint. Such a function + is executed after each request, even if outside of the blueprint. + """ + self.record_once(lambda s: s.app.after_request_funcs + .setdefault(None, []).append(f)) + return f + + def teardown_request(self, f): + """Like :meth:`Flask.teardown_request` but for a blueprint. This + function is only executed when tearing down requests handled by a + function of that blueprint. Teardown request functions are executed + when the request context is popped, even when no actual request was + performed. + """ + self.record_once(lambda s: s.app.teardown_request_funcs + .setdefault(self.name, []).append(f)) + return f + + def teardown_app_request(self, f): + """Like :meth:`Flask.teardown_request` but for a blueprint. Such a + function is executed when tearing down each request, even if outside of + the blueprint. + """ + self.record_once(lambda s: s.app.teardown_request_funcs + .setdefault(None, []).append(f)) + return f + + def context_processor(self, f): + """Like :meth:`Flask.context_processor` but for a blueprint. This + function is only executed for requests handled by a blueprint. + """ + self.record_once(lambda s: s.app.template_context_processors + .setdefault(self.name, []).append(f)) + return f + + def app_context_processor(self, f): + """Like :meth:`Flask.context_processor` but for a blueprint. Such a + function is executed each request, even if outside of the blueprint. + """ + self.record_once(lambda s: s.app.template_context_processors + .setdefault(None, []).append(f)) + return f + + def app_errorhandler(self, code): + """Like :meth:`Flask.errorhandler` but for a blueprint. This + handler is used for all requests, even if outside of the blueprint. + """ + def decorator(f): + self.record_once(lambda s: s.app.errorhandler(code)(f)) + return f + return decorator + + def url_value_preprocessor(self, f): + """Registers a function as URL value preprocessor for this + blueprint. It's called before the view functions are called and + can modify the url values provided. + """ + self.record_once(lambda s: s.app.url_value_preprocessors + .setdefault(self.name, []).append(f)) + return f + + def url_defaults(self, f): + """Callback function for URL defaults for this blueprint. It's called + with the endpoint and values and should update the values passed + in place. + """ + self.record_once(lambda s: s.app.url_default_functions + .setdefault(self.name, []).append(f)) + return f + + def app_url_value_preprocessor(self, f): + """Same as :meth:`url_value_preprocessor` but application wide. + """ + self.record_once(lambda s: s.app.url_value_preprocessors + .setdefault(None, []).append(f)) + return f + + def app_url_defaults(self, f): + """Same as :meth:`url_defaults` but application wide. + """ + self.record_once(lambda s: s.app.url_default_functions + .setdefault(None, []).append(f)) + return f + + def errorhandler(self, code_or_exception): + """Registers an error handler that becomes active for this blueprint + only. Please be aware that routing does not happen local to a + blueprint so an error handler for 404 usually is not handled by + a blueprint unless it is caused inside a view function. Another + special case is the 500 internal server error which is always looked + up from the application. + + Otherwise works as the :meth:`~flask.Flask.errorhandler` decorator + of the :class:`~flask.Flask` object. + """ + def decorator(f): + self.record_once(lambda s: s.app._register_error_handler( + self.name, code_or_exception, f)) + return f + return decorator + + def register_error_handler(self, code_or_exception, f): + """Non-decorator version of the :meth:`errorhandler` error attach + function, akin to the :meth:`~flask.Flask.register_error_handler` + application-wide function of the :class:`~flask.Flask` object but + for error handlers limited to this blueprint. + + .. versionadded:: 0.11 + """ + self.record_once(lambda s: s.app._register_error_handler( + self.name, code_or_exception, f)) diff --git a/flex/lib/python3.6/site-packages/flask/cli.py b/flex/lib/python3.6/site-packages/flask/cli.py new file mode 100644 index 0000000..074ee76 --- /dev/null +++ b/flex/lib/python3.6/site-packages/flask/cli.py @@ -0,0 +1,517 @@ +# -*- coding: utf-8 -*- +""" + flask.cli + ~~~~~~~~~ + + A simple command line application to run flask apps. + + :copyright: (c) 2015 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + +import os +import sys +from threading import Lock, Thread +from functools import update_wrapper + +import click + +from ._compat import iteritems, reraise +from .helpers import get_debug_flag +from . import __version__ + +class NoAppException(click.UsageError): + """Raised if an application cannot be found or loaded.""" + + +def find_best_app(module): + """Given a module instance this tries to find the best possible + application in the module or raises an exception. + """ + from . import Flask + + # Search for the most common names first. + for attr_name in 'app', 'application': + app = getattr(module, attr_name, None) + if app is not None and isinstance(app, Flask): + return app + + # Otherwise find the only object that is a Flask instance. + matches = [v for k, v in iteritems(module.__dict__) + if isinstance(v, Flask)] + + if len(matches) == 1: + return matches[0] + raise NoAppException('Failed to find application in module "%s". Are ' + 'you sure it contains a Flask application? Maybe ' + 'you wrapped it in a WSGI middleware or you are ' + 'using a factory function.' % module.__name__) + + +def prepare_exec_for_file(filename): + """Given a filename this will try to calculate the python path, add it + to the search path and return the actual module name that is expected. + """ + module = [] + + # Chop off file extensions or package markers + if os.path.split(filename)[1] == '__init__.py': + filename = os.path.dirname(filename) + elif filename.endswith('.py'): + filename = filename[:-3] + else: + raise NoAppException('The file provided (%s) does exist but is not a ' + 'valid Python file. This means that it cannot ' + 'be used as application. Please change the ' + 'extension to .py' % filename) + filename = os.path.realpath(filename) + + dirpath = filename + while 1: + dirpath, extra = os.path.split(dirpath) + module.append(extra) + if not os.path.isfile(os.path.join(dirpath, '__init__.py')): + break + + sys.path.insert(0, dirpath) + return '.'.join(module[::-1]) + + +def locate_app(app_id): + """Attempts to locate the application.""" + __traceback_hide__ = True + if ':' in app_id: + module, app_obj = app_id.split(':', 1) + else: + module = app_id + app_obj = None + + try: + __import__(module) + except ImportError: + # Reraise the ImportError if it occurred within the imported module. + # Determine this by checking whether the trace has a depth > 1. + if sys.exc_info()[-1].tb_next: + raise + else: + raise NoAppException('The file/path provided (%s) does not appear' + ' to exist. Please verify the path is ' + 'correct. If app is not on PYTHONPATH, ' + 'ensure the extension is .py' % module) + + mod = sys.modules[module] + if app_obj is None: + app = find_best_app(mod) + else: + app = getattr(mod, app_obj, None) + if app is None: + raise RuntimeError('Failed to find application in module "%s"' + % module) + + return app + + +def find_default_import_path(): + app = os.environ.get('FLASK_APP') + if app is None: + return + if os.path.isfile(app): + return prepare_exec_for_file(app) + return app + + +def get_version(ctx, param, value): + if not value or ctx.resilient_parsing: + return + message = 'Flask %(version)s\nPython %(python_version)s' + click.echo(message % { + 'version': __version__, + 'python_version': sys.version, + }, color=ctx.color) + ctx.exit() + +version_option = click.Option(['--version'], + help='Show the flask version', + expose_value=False, + callback=get_version, + is_flag=True, is_eager=True) + +class DispatchingApp(object): + """Special application that dispatches to a Flask application which + is imported by name in a background thread. If an error happens + it is recorded and shown as part of the WSGI handling which in case + of the Werkzeug debugger means that it shows up in the browser. + """ + + def __init__(self, loader, use_eager_loading=False): + self.loader = loader + self._app = None + self._lock = Lock() + self._bg_loading_exc_info = None + if use_eager_loading: + self._load_unlocked() + else: + self._load_in_background() + + def _load_in_background(self): + def _load_app(): + __traceback_hide__ = True + with self._lock: + try: + self._load_unlocked() + except Exception: + self._bg_loading_exc_info = sys.exc_info() + t = Thread(target=_load_app, args=()) + t.start() + + def _flush_bg_loading_exception(self): + __traceback_hide__ = True + exc_info = self._bg_loading_exc_info + if exc_info is not None: + self._bg_loading_exc_info = None + reraise(*exc_info) + + def _load_unlocked(self): + __traceback_hide__ = True + self._app = rv = self.loader() + self._bg_loading_exc_info = None + return rv + + def __call__(self, environ, start_response): + __traceback_hide__ = True + if self._app is not None: + return self._app(environ, start_response) + self._flush_bg_loading_exception() + with self._lock: + if self._app is not None: + rv = self._app + else: + rv = self._load_unlocked() + return rv(environ, start_response) + + +class ScriptInfo(object): + """Help object to deal with Flask applications. This is usually not + necessary to interface with as it's used internally in the dispatching + to click. In future versions of Flask this object will most likely play + a bigger role. Typically it's created automatically by the + :class:`FlaskGroup` but you can also manually create it and pass it + onwards as click object. + """ + + def __init__(self, app_import_path=None, create_app=None): + if create_app is None: + if app_import_path is None: + app_import_path = find_default_import_path() + self.app_import_path = app_import_path + else: + app_import_path = None + + #: Optionally the import path for the Flask application. + self.app_import_path = app_import_path + #: Optionally a function that is passed the script info to create + #: the instance of the application. + self.create_app = create_app + #: A dictionary with arbitrary data that can be associated with + #: this script info. + self.data = {} + self._loaded_app = None + + def load_app(self): + """Loads the Flask app (if not yet loaded) and returns it. Calling + this multiple times will just result in the already loaded app to + be returned. + """ + __traceback_hide__ = True + if self._loaded_app is not None: + return self._loaded_app + if self.create_app is not None: + rv = self.create_app(self) + else: + if not self.app_import_path: + raise NoAppException( + 'Could not locate Flask application. You did not provide ' + 'the FLASK_APP environment variable.\n\nFor more ' + 'information see ' + 'http://flask.pocoo.org/docs/latest/quickstart/') + rv = locate_app(self.app_import_path) + debug = get_debug_flag() + if debug is not None: + rv.debug = debug + self._loaded_app = rv + return rv + + +pass_script_info = click.make_pass_decorator(ScriptInfo, ensure=True) + + +def with_appcontext(f): + """Wraps a callback so that it's guaranteed to be executed with the + script's application context. If callbacks are registered directly + to the ``app.cli`` object then they are wrapped with this function + by default unless it's disabled. + """ + @click.pass_context + def decorator(__ctx, *args, **kwargs): + with __ctx.ensure_object(ScriptInfo).load_app().app_context(): + return __ctx.invoke(f, *args, **kwargs) + return update_wrapper(decorator, f) + + +class AppGroup(click.Group): + """This works similar to a regular click :class:`~click.Group` but it + changes the behavior of the :meth:`command` decorator so that it + automatically wraps the functions in :func:`with_appcontext`. + + Not to be confused with :class:`FlaskGroup`. + """ + + def command(self, *args, **kwargs): + """This works exactly like the method of the same name on a regular + :class:`click.Group` but it wraps callbacks in :func:`with_appcontext` + unless it's disabled by passing ``with_appcontext=False``. + """ + wrap_for_ctx = kwargs.pop('with_appcontext', True) + def decorator(f): + if wrap_for_ctx: + f = with_appcontext(f) + return click.Group.command(self, *args, **kwargs)(f) + return decorator + + def group(self, *args, **kwargs): + """This works exactly like the method of the same name on a regular + :class:`click.Group` but it defaults the group class to + :class:`AppGroup`. + """ + kwargs.setdefault('cls', AppGroup) + return click.Group.group(self, *args, **kwargs) + + +class FlaskGroup(AppGroup): + """Special subclass of the :class:`AppGroup` group that supports + loading more commands from the configured Flask app. Normally a + developer does not have to interface with this class but there are + some very advanced use cases for which it makes sense to create an + instance of this. + + For information as of why this is useful see :ref:`custom-scripts`. + + :param add_default_commands: if this is True then the default run and + shell commands wil be added. + :param add_version_option: adds the ``--version`` option. + :param create_app: an optional callback that is passed the script info + and returns the loaded app. + """ + + def __init__(self, add_default_commands=True, create_app=None, + add_version_option=True, **extra): + params = list(extra.pop('params', None) or ()) + + if add_version_option: + params.append(version_option) + + AppGroup.__init__(self, params=params, **extra) + self.create_app = create_app + + if add_default_commands: + self.add_command(run_command) + self.add_command(shell_command) + + self._loaded_plugin_commands = False + + def _load_plugin_commands(self): + if self._loaded_plugin_commands: + return + try: + import pkg_resources + except ImportError: + self._loaded_plugin_commands = True + return + + for ep in pkg_resources.iter_entry_points('flask.commands'): + self.add_command(ep.load(), ep.name) + self._loaded_plugin_commands = True + + def get_command(self, ctx, name): + self._load_plugin_commands() + + # We load built-in commands first as these should always be the + # same no matter what the app does. If the app does want to + # override this it needs to make a custom instance of this group + # and not attach the default commands. + # + # This also means that the script stays functional in case the + # application completely fails. + rv = AppGroup.get_command(self, ctx, name) + if rv is not None: + return rv + + info = ctx.ensure_object(ScriptInfo) + try: + rv = info.load_app().cli.get_command(ctx, name) + if rv is not None: + return rv + except NoAppException: + pass + + def list_commands(self, ctx): + self._load_plugin_commands() + + # The commands available is the list of both the application (if + # available) plus the builtin commands. + rv = set(click.Group.list_commands(self, ctx)) + info = ctx.ensure_object(ScriptInfo) + try: + rv.update(info.load_app().cli.list_commands(ctx)) + except Exception: + # Here we intentionally swallow all exceptions as we don't + # want the help page to break if the app does not exist. + # If someone attempts to use the command we try to create + # the app again and this will give us the error. + pass + return sorted(rv) + + def main(self, *args, **kwargs): + obj = kwargs.get('obj') + if obj is None: + obj = ScriptInfo(create_app=self.create_app) + kwargs['obj'] = obj + kwargs.setdefault('auto_envvar_prefix', 'FLASK') + return AppGroup.main(self, *args, **kwargs) + + +@click.command('run', short_help='Runs a development server.') +@click.option('--host', '-h', default='127.0.0.1', + help='The interface to bind to.') +@click.option('--port', '-p', default=5000, + help='The port to bind to.') +@click.option('--reload/--no-reload', default=None, + help='Enable or disable the reloader. By default the reloader ' + 'is active if debug is enabled.') +@click.option('--debugger/--no-debugger', default=None, + help='Enable or disable the debugger. By default the debugger ' + 'is active if debug is enabled.') +@click.option('--eager-loading/--lazy-loader', default=None, + help='Enable or disable eager loading. By default eager ' + 'loading is enabled if the reloader is disabled.') +@click.option('--with-threads/--without-threads', default=False, + help='Enable or disable multithreading.') +@pass_script_info +def run_command(info, host, port, reload, debugger, eager_loading, + with_threads): + """Runs a local development server for the Flask application. + + This local server is recommended for development purposes only but it + can also be used for simple intranet deployments. By default it will + not support any sort of concurrency at all to simplify debugging. This + can be changed with the --with-threads option which will enable basic + multithreading. + + The reloader and debugger are by default enabled if the debug flag of + Flask is enabled and disabled otherwise. + """ + from werkzeug.serving import run_simple + + debug = get_debug_flag() + if reload is None: + reload = bool(debug) + if debugger is None: + debugger = bool(debug) + if eager_loading is None: + eager_loading = not reload + + app = DispatchingApp(info.load_app, use_eager_loading=eager_loading) + + # Extra startup messages. This depends a bit on Werkzeug internals to + # not double execute when the reloader kicks in. + if os.environ.get('WERKZEUG_RUN_MAIN') != 'true': + # If we have an import path we can print it out now which can help + # people understand what's being served. If we do not have an + # import path because the app was loaded through a callback then + # we won't print anything. + if info.app_import_path is not None: + print(' * Serving Flask app "%s"' % info.app_import_path) + if debug is not None: + print(' * Forcing debug mode %s' % (debug and 'on' or 'off')) + + run_simple(host, port, app, use_reloader=reload, + use_debugger=debugger, threaded=with_threads) + + +@click.command('shell', short_help='Runs a shell in the app context.') +@with_appcontext +def shell_command(): + """Runs an interactive Python shell in the context of a given + Flask application. The application will populate the default + namespace of this shell according to it's configuration. + + This is useful for executing small snippets of management code + without having to manually configuring the application. + """ + import code + from flask.globals import _app_ctx_stack + app = _app_ctx_stack.top.app + banner = 'Python %s on %s\nApp: %s%s\nInstance: %s' % ( + sys.version, + sys.platform, + app.import_name, + app.debug and ' [debug]' or '', + app.instance_path, + ) + ctx = {} + + # Support the regular Python interpreter startup script if someone + # is using it. + startup = os.environ.get('PYTHONSTARTUP') + if startup and os.path.isfile(startup): + with open(startup, 'r') as f: + eval(compile(f.read(), startup, 'exec'), ctx) + + ctx.update(app.make_shell_context()) + + code.interact(banner=banner, local=ctx) + + +cli = FlaskGroup(help="""\ +This shell command acts as general utility script for Flask applications. + +It loads the application configured (through the FLASK_APP environment +variable) and then provides commands either provided by the application or +Flask itself. + +The most useful commands are the "run" and "shell" command. + +Example usage: + +\b + %(prefix)s%(cmd)s FLASK_APP=hello.py + %(prefix)s%(cmd)s FLASK_DEBUG=1 + %(prefix)sflask run +""" % { + 'cmd': os.name == 'posix' and 'export' or 'set', + 'prefix': os.name == 'posix' and '$ ' or '', +}) + + +def main(as_module=False): + this_module = __package__ + '.cli' + args = sys.argv[1:] + + if as_module: + if sys.version_info >= (2, 7): + name = 'python -m ' + this_module.rsplit('.', 1)[0] + else: + name = 'python -m ' + this_module + + # This module is always executed as "python -m flask.run" and as such + # we need to ensure that we restore the actual command line so that + # the reloader can properly operate. + sys.argv = ['-m', this_module] + sys.argv[1:] + else: + name = None + + cli.main(args=args, prog_name=name) + + +if __name__ == '__main__': + main(as_module=True) diff --git a/flex/lib/python3.6/site-packages/flask/config.py b/flex/lib/python3.6/site-packages/flask/config.py new file mode 100644 index 0000000..697add7 --- /dev/null +++ b/flex/lib/python3.6/site-packages/flask/config.py @@ -0,0 +1,263 @@ +# -*- coding: utf-8 -*- +""" + flask.config + ~~~~~~~~~~~~ + + Implements the configuration related objects. + + :copyright: (c) 2015 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + +import os +import types +import errno + +from werkzeug.utils import import_string +from ._compat import string_types, iteritems +from . import json + + +class ConfigAttribute(object): + """Makes an attribute forward to the config""" + + def __init__(self, name, get_converter=None): + self.__name__ = name + self.get_converter = get_converter + + def __get__(self, obj, type=None): + if obj is None: + return self + rv = obj.config[self.__name__] + if self.get_converter is not None: + rv = self.get_converter(rv) + return rv + + def __set__(self, obj, value): + obj.config[self.__name__] = value + + +class Config(dict): + """Works exactly like a dict but provides ways to fill it from files + or special dictionaries. There are two common patterns to populate the + config. + + Either you can fill the config from a config file:: + + app.config.from_pyfile('yourconfig.cfg') + + Or alternatively you can define the configuration options in the + module that calls :meth:`from_object` or provide an import path to + a module that should be loaded. It is also possible to tell it to + use the same module and with that provide the configuration values + just before the call:: + + DEBUG = True + SECRET_KEY = 'development key' + app.config.from_object(__name__) + + In both cases (loading from any Python file or loading from modules), + only uppercase keys are added to the config. This makes it possible to use + lowercase values in the config file for temporary values that are not added + to the config or to define the config keys in the same file that implements + the application. + + Probably the most interesting way to load configurations is from an + environment variable pointing to a file:: + + app.config.from_envvar('YOURAPPLICATION_SETTINGS') + + In this case before launching the application you have to set this + environment variable to the file you want to use. On Linux and OS X + use the export statement:: + + export YOURAPPLICATION_SETTINGS='/path/to/config/file' + + On windows use `set` instead. + + :param root_path: path to which files are read relative from. When the + config object is created by the application, this is + the application's :attr:`~flask.Flask.root_path`. + :param defaults: an optional dictionary of default values + """ + + def __init__(self, root_path, defaults=None): + dict.__init__(self, defaults or {}) + self.root_path = root_path + + def from_envvar(self, variable_name, silent=False): + """Loads a configuration from an environment variable pointing to + a configuration file. This is basically just a shortcut with nicer + error messages for this line of code:: + + app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS']) + + :param variable_name: name of the environment variable + :param silent: set to ``True`` if you want silent failure for missing + files. + :return: bool. ``True`` if able to load config, ``False`` otherwise. + """ + rv = os.environ.get(variable_name) + if not rv: + if silent: + return False + raise RuntimeError('The environment variable %r is not set ' + 'and as such configuration could not be ' + 'loaded. Set this variable and make it ' + 'point to a configuration file' % + variable_name) + return self.from_pyfile(rv, silent=silent) + + def from_pyfile(self, filename, silent=False): + """Updates the values in the config from a Python file. This function + behaves as if the file was imported as module with the + :meth:`from_object` function. + + :param filename: the filename of the config. This can either be an + absolute filename or a filename relative to the + root path. + :param silent: set to ``True`` if you want silent failure for missing + files. + + .. versionadded:: 0.7 + `silent` parameter. + """ + filename = os.path.join(self.root_path, filename) + d = types.ModuleType('config') + d.__file__ = filename + try: + with open(filename, mode='rb') as config_file: + exec(compile(config_file.read(), filename, 'exec'), d.__dict__) + except IOError as e: + if silent and e.errno in (errno.ENOENT, errno.EISDIR): + return False + e.strerror = 'Unable to load configuration file (%s)' % e.strerror + raise + self.from_object(d) + return True + + def from_object(self, obj): + """Updates the values from the given object. An object can be of one + of the following two types: + + - a string: in this case the object with that name will be imported + - an actual object reference: that object is used directly + + Objects are usually either modules or classes. :meth:`from_object` + loads only the uppercase attributes of the module/class. A ``dict`` + object will not work with :meth:`from_object` because the keys of a + ``dict`` are not attributes of the ``dict`` class. + + Example of module-based configuration:: + + app.config.from_object('yourapplication.default_config') + from yourapplication import default_config + app.config.from_object(default_config) + + You should not use this function to load the actual configuration but + rather configuration defaults. The actual config should be loaded + with :meth:`from_pyfile` and ideally from a location not within the + package because the package might be installed system wide. + + See :ref:`config-dev-prod` for an example of class-based configuration + using :meth:`from_object`. + + :param obj: an import name or object + """ + if isinstance(obj, string_types): + obj = import_string(obj) + for key in dir(obj): + if key.isupper(): + self[key] = getattr(obj, key) + + def from_json(self, filename, silent=False): + """Updates the values in the config from a JSON file. This function + behaves as if the JSON object was a dictionary and passed to the + :meth:`from_mapping` function. + + :param filename: the filename of the JSON file. This can either be an + absolute filename or a filename relative to the + root path. + :param silent: set to ``True`` if you want silent failure for missing + files. + + .. versionadded:: 0.11 + """ + filename = os.path.join(self.root_path, filename) + + try: + with open(filename) as json_file: + obj = json.loads(json_file.read()) + except IOError as e: + if silent and e.errno in (errno.ENOENT, errno.EISDIR): + return False + e.strerror = 'Unable to load configuration file (%s)' % e.strerror + raise + return self.from_mapping(obj) + + def from_mapping(self, *mapping, **kwargs): + """Updates the config like :meth:`update` ignoring items with non-upper + keys. + + .. versionadded:: 0.11 + """ + mappings = [] + if len(mapping) == 1: + if hasattr(mapping[0], 'items'): + mappings.append(mapping[0].items()) + else: + mappings.append(mapping[0]) + elif len(mapping) > 1: + raise TypeError( + 'expected at most 1 positional argument, got %d' % len(mapping) + ) + mappings.append(kwargs.items()) + for mapping in mappings: + for (key, value) in mapping: + if key.isupper(): + self[key] = value + return True + + def get_namespace(self, namespace, lowercase=True, trim_namespace=True): + """Returns a dictionary containing a subset of configuration options + that match the specified namespace/prefix. Example usage:: + + app.config['IMAGE_STORE_TYPE'] = 'fs' + app.config['IMAGE_STORE_PATH'] = '/var/app/images' + app.config['IMAGE_STORE_BASE_URL'] = 'http://img.website.com' + image_store_config = app.config.get_namespace('IMAGE_STORE_') + + The resulting dictionary `image_store_config` would look like:: + + { + 'type': 'fs', + 'path': '/var/app/images', + 'base_url': 'http://img.website.com' + } + + This is often useful when configuration options map directly to + keyword arguments in functions or class constructors. + + :param namespace: a configuration namespace + :param lowercase: a flag indicating if the keys of the resulting + dictionary should be lowercase + :param trim_namespace: a flag indicating if the keys of the resulting + dictionary should not include the namespace + + .. versionadded:: 0.11 + """ + rv = {} + for k, v in iteritems(self): + if not k.startswith(namespace): + continue + if trim_namespace: + key = k[len(namespace):] + else: + key = k + if lowercase: + key = key.lower() + rv[key] = v + return rv + + def __repr__(self): + return '<%s %s>' % (self.__class__.__name__, dict.__repr__(self)) diff --git a/flex/lib/python3.6/site-packages/flask/ctx.py b/flex/lib/python3.6/site-packages/flask/ctx.py new file mode 100644 index 0000000..480d9c5 --- /dev/null +++ b/flex/lib/python3.6/site-packages/flask/ctx.py @@ -0,0 +1,410 @@ +# -*- coding: utf-8 -*- +""" + flask.ctx + ~~~~~~~~~ + + Implements the objects required to keep the context. + + :copyright: (c) 2015 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + +import sys +from functools import update_wrapper + +from werkzeug.exceptions import HTTPException + +from .globals import _request_ctx_stack, _app_ctx_stack +from .signals import appcontext_pushed, appcontext_popped +from ._compat import BROKEN_PYPY_CTXMGR_EXIT, reraise + + +# a singleton sentinel value for parameter defaults +_sentinel = object() + + +class _AppCtxGlobals(object): + """A plain object.""" + + def get(self, name, default=None): + return self.__dict__.get(name, default) + + def pop(self, name, default=_sentinel): + if default is _sentinel: + return self.__dict__.pop(name) + else: + return self.__dict__.pop(name, default) + + def setdefault(self, name, default=None): + return self.__dict__.setdefault(name, default) + + def __contains__(self, item): + return item in self.__dict__ + + def __iter__(self): + return iter(self.__dict__) + + def __repr__(self): + top = _app_ctx_stack.top + if top is not None: + return '' % top.app.name + return object.__repr__(self) + + +def after_this_request(f): + """Executes a function after this request. This is useful to modify + response objects. The function is passed the response object and has + to return the same or a new one. + + Example:: + + @app.route('/') + def index(): + @after_this_request + def add_header(response): + response.headers['X-Foo'] = 'Parachute' + return response + return 'Hello World!' + + This is more useful if a function other than the view function wants to + modify a response. For instance think of a decorator that wants to add + some headers without converting the return value into a response object. + + .. versionadded:: 0.9 + """ + _request_ctx_stack.top._after_request_functions.append(f) + return f + + +def copy_current_request_context(f): + """A helper function that decorates a function to retain the current + request context. This is useful when working with greenlets. The moment + the function is decorated a copy of the request context is created and + then pushed when the function is called. + + Example:: + + import gevent + from flask import copy_current_request_context + + @app.route('/') + def index(): + @copy_current_request_context + def do_some_work(): + # do some work here, it can access flask.request like you + # would otherwise in the view function. + ... + gevent.spawn(do_some_work) + return 'Regular response' + + .. versionadded:: 0.10 + """ + top = _request_ctx_stack.top + if top is None: + raise RuntimeError('This decorator can only be used at local scopes ' + 'when a request context is on the stack. For instance within ' + 'view functions.') + reqctx = top.copy() + def wrapper(*args, **kwargs): + with reqctx: + return f(*args, **kwargs) + return update_wrapper(wrapper, f) + + +def has_request_context(): + """If you have code that wants to test if a request context is there or + not this function can be used. For instance, you may want to take advantage + of request information if the request object is available, but fail + silently if it is unavailable. + + :: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and has_request_context(): + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + Alternatively you can also just test any of the context bound objects + (such as :class:`request` or :class:`g` for truthness):: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and request: + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + .. versionadded:: 0.7 + """ + return _request_ctx_stack.top is not None + + +def has_app_context(): + """Works like :func:`has_request_context` but for the application + context. You can also just do a boolean check on the + :data:`current_app` object instead. + + .. versionadded:: 0.9 + """ + return _app_ctx_stack.top is not None + + +class AppContext(object): + """The application context binds an application object implicitly + to the current thread or greenlet, similar to how the + :class:`RequestContext` binds request information. The application + context is also implicitly created if a request context is created + but the application is not on top of the individual application + context. + """ + + def __init__(self, app): + self.app = app + self.url_adapter = app.create_url_adapter(None) + self.g = app.app_ctx_globals_class() + + # Like request context, app contexts can be pushed multiple times + # but there a basic "refcount" is enough to track them. + self._refcnt = 0 + + def push(self): + """Binds the app context to the current context.""" + self._refcnt += 1 + if hasattr(sys, 'exc_clear'): + sys.exc_clear() + _app_ctx_stack.push(self) + appcontext_pushed.send(self.app) + + def pop(self, exc=_sentinel): + """Pops the app context.""" + try: + self._refcnt -= 1 + if self._refcnt <= 0: + if exc is _sentinel: + exc = sys.exc_info()[1] + self.app.do_teardown_appcontext(exc) + finally: + rv = _app_ctx_stack.pop() + assert rv is self, 'Popped wrong app context. (%r instead of %r)' \ + % (rv, self) + appcontext_popped.send(self.app) + + def __enter__(self): + self.push() + return self + + def __exit__(self, exc_type, exc_value, tb): + self.pop(exc_value) + + if BROKEN_PYPY_CTXMGR_EXIT and exc_type is not None: + reraise(exc_type, exc_value, tb) + + +class RequestContext(object): + """The request context contains all request relevant information. It is + created at the beginning of the request and pushed to the + `_request_ctx_stack` and removed at the end of it. It will create the + URL adapter and request object for the WSGI environment provided. + + Do not attempt to use this class directly, instead use + :meth:`~flask.Flask.test_request_context` and + :meth:`~flask.Flask.request_context` to create this object. + + When the request context is popped, it will evaluate all the + functions registered on the application for teardown execution + (:meth:`~flask.Flask.teardown_request`). + + The request context is automatically popped at the end of the request + for you. In debug mode the request context is kept around if + exceptions happen so that interactive debuggers have a chance to + introspect the data. With 0.4 this can also be forced for requests + that did not fail and outside of ``DEBUG`` mode. By setting + ``'flask._preserve_context'`` to ``True`` on the WSGI environment the + context will not pop itself at the end of the request. This is used by + the :meth:`~flask.Flask.test_client` for example to implement the + deferred cleanup functionality. + + You might find this helpful for unittests where you need the + information from the context local around for a little longer. Make + sure to properly :meth:`~werkzeug.LocalStack.pop` the stack yourself in + that situation, otherwise your unittests will leak memory. + """ + + def __init__(self, app, environ, request=None): + self.app = app + if request is None: + request = app.request_class(environ) + self.request = request + self.url_adapter = app.create_url_adapter(self.request) + self.flashes = None + self.session = None + + # Request contexts can be pushed multiple times and interleaved with + # other request contexts. Now only if the last level is popped we + # get rid of them. Additionally if an application context is missing + # one is created implicitly so for each level we add this information + self._implicit_app_ctx_stack = [] + + # indicator if the context was preserved. Next time another context + # is pushed the preserved context is popped. + self.preserved = False + + # remembers the exception for pop if there is one in case the context + # preservation kicks in. + self._preserved_exc = None + + # Functions that should be executed after the request on the response + # object. These will be called before the regular "after_request" + # functions. + self._after_request_functions = [] + + self.match_request() + + def _get_g(self): + return _app_ctx_stack.top.g + def _set_g(self, value): + _app_ctx_stack.top.g = value + g = property(_get_g, _set_g) + del _get_g, _set_g + + def copy(self): + """Creates a copy of this request context with the same request object. + This can be used to move a request context to a different greenlet. + Because the actual request object is the same this cannot be used to + move a request context to a different thread unless access to the + request object is locked. + + .. versionadded:: 0.10 + """ + return self.__class__(self.app, + environ=self.request.environ, + request=self.request + ) + + def match_request(self): + """Can be overridden by a subclass to hook into the matching + of the request. + """ + try: + url_rule, self.request.view_args = \ + self.url_adapter.match(return_rule=True) + self.request.url_rule = url_rule + except HTTPException as e: + self.request.routing_exception = e + + def push(self): + """Binds the request context to the current context.""" + # If an exception occurs in debug mode or if context preservation is + # activated under exception situations exactly one context stays + # on the stack. The rationale is that you want to access that + # information under debug situations. However if someone forgets to + # pop that context again we want to make sure that on the next push + # it's invalidated, otherwise we run at risk that something leaks + # memory. This is usually only a problem in test suite since this + # functionality is not active in production environments. + top = _request_ctx_stack.top + if top is not None and top.preserved: + top.pop(top._preserved_exc) + + # Before we push the request context we have to ensure that there + # is an application context. + app_ctx = _app_ctx_stack.top + if app_ctx is None or app_ctx.app != self.app: + app_ctx = self.app.app_context() + app_ctx.push() + self._implicit_app_ctx_stack.append(app_ctx) + else: + self._implicit_app_ctx_stack.append(None) + + if hasattr(sys, 'exc_clear'): + sys.exc_clear() + + _request_ctx_stack.push(self) + + # Open the session at the moment that the request context is + # available. This allows a custom open_session method to use the + # request context (e.g. code that access database information + # stored on `g` instead of the appcontext). + self.session = self.app.open_session(self.request) + if self.session is None: + self.session = self.app.make_null_session() + + def pop(self, exc=_sentinel): + """Pops the request context and unbinds it by doing that. This will + also trigger the execution of functions registered by the + :meth:`~flask.Flask.teardown_request` decorator. + + .. versionchanged:: 0.9 + Added the `exc` argument. + """ + app_ctx = self._implicit_app_ctx_stack.pop() + + try: + clear_request = False + if not self._implicit_app_ctx_stack: + self.preserved = False + self._preserved_exc = None + if exc is _sentinel: + exc = sys.exc_info()[1] + self.app.do_teardown_request(exc) + + # If this interpreter supports clearing the exception information + # we do that now. This will only go into effect on Python 2.x, + # on 3.x it disappears automatically at the end of the exception + # stack. + if hasattr(sys, 'exc_clear'): + sys.exc_clear() + + request_close = getattr(self.request, 'close', None) + if request_close is not None: + request_close() + clear_request = True + finally: + rv = _request_ctx_stack.pop() + + # get rid of circular dependencies at the end of the request + # so that we don't require the GC to be active. + if clear_request: + rv.request.environ['werkzeug.request'] = None + + # Get rid of the app as well if necessary. + if app_ctx is not None: + app_ctx.pop(exc) + + assert rv is self, 'Popped wrong request context. ' \ + '(%r instead of %r)' % (rv, self) + + def auto_pop(self, exc): + if self.request.environ.get('flask._preserve_context') or \ + (exc is not None and self.app.preserve_context_on_exception): + self.preserved = True + self._preserved_exc = exc + else: + self.pop(exc) + + def __enter__(self): + self.push() + return self + + def __exit__(self, exc_type, exc_value, tb): + # do not pop the request stack if we are in debug mode and an + # exception happened. This will allow the debugger to still + # access the request object in the interactive shell. Furthermore + # the context can be force kept alive for the test client. + # See flask.testing for how this works. + self.auto_pop(exc_value) + + if BROKEN_PYPY_CTXMGR_EXIT and exc_type is not None: + reraise(exc_type, exc_value, tb) + + def __repr__(self): + return '<%s \'%s\' [%s] of %s>' % ( + self.__class__.__name__, + self.request.url, + self.request.method, + self.app.name, + ) diff --git a/flex/lib/python3.6/site-packages/flask/debughelpers.py b/flex/lib/python3.6/site-packages/flask/debughelpers.py new file mode 100644 index 0000000..90710dd --- /dev/null +++ b/flex/lib/python3.6/site-packages/flask/debughelpers.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- +""" + flask.debughelpers + ~~~~~~~~~~~~~~~~~~ + + Various helpers to make the development experience better. + + :copyright: (c) 2015 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" +from ._compat import implements_to_string, text_type +from .app import Flask +from .blueprints import Blueprint +from .globals import _request_ctx_stack + + +class UnexpectedUnicodeError(AssertionError, UnicodeError): + """Raised in places where we want some better error reporting for + unexpected unicode or binary data. + """ + + +@implements_to_string +class DebugFilesKeyError(KeyError, AssertionError): + """Raised from request.files during debugging. The idea is that it can + provide a better error message than just a generic KeyError/BadRequest. + """ + + def __init__(self, request, key): + form_matches = request.form.getlist(key) + buf = ['You tried to access the file "%s" in the request.files ' + 'dictionary but it does not exist. The mimetype for the request ' + 'is "%s" instead of "multipart/form-data" which means that no ' + 'file contents were transmitted. To fix this error you should ' + 'provide enctype="multipart/form-data" in your form.' % + (key, request.mimetype)] + if form_matches: + buf.append('\n\nThe browser instead transmitted some file names. ' + 'This was submitted: %s' % ', '.join('"%s"' % x + for x in form_matches)) + self.msg = ''.join(buf) + + def __str__(self): + return self.msg + + +class FormDataRoutingRedirect(AssertionError): + """This exception is raised by Flask in debug mode if it detects a + redirect caused by the routing system when the request method is not + GET, HEAD or OPTIONS. Reasoning: form data will be dropped. + """ + + def __init__(self, request): + exc = request.routing_exception + buf = ['A request was sent to this URL (%s) but a redirect was ' + 'issued automatically by the routing system to "%s".' + % (request.url, exc.new_url)] + + # In case just a slash was appended we can be extra helpful + if request.base_url + '/' == exc.new_url.split('?')[0]: + buf.append(' The URL was defined with a trailing slash so ' + 'Flask will automatically redirect to the URL ' + 'with the trailing slash if it was accessed ' + 'without one.') + + buf.append(' Make sure to directly send your %s-request to this URL ' + 'since we can\'t make browsers or HTTP clients redirect ' + 'with form data reliably or without user interaction.' % + request.method) + buf.append('\n\nNote: this exception is only raised in debug mode') + AssertionError.__init__(self, ''.join(buf).encode('utf-8')) + + +def attach_enctype_error_multidict(request): + """Since Flask 0.8 we're monkeypatching the files object in case a + request is detected that does not use multipart form data but the files + object is accessed. + """ + oldcls = request.files.__class__ + class newcls(oldcls): + def __getitem__(self, key): + try: + return oldcls.__getitem__(self, key) + except KeyError: + if key not in request.form: + raise + raise DebugFilesKeyError(request, key) + newcls.__name__ = oldcls.__name__ + newcls.__module__ = oldcls.__module__ + request.files.__class__ = newcls + + +def _dump_loader_info(loader): + yield 'class: %s.%s' % (type(loader).__module__, type(loader).__name__) + for key, value in sorted(loader.__dict__.items()): + if key.startswith('_'): + continue + if isinstance(value, (tuple, list)): + if not all(isinstance(x, (str, text_type)) for x in value): + continue + yield '%s:' % key + for item in value: + yield ' - %s' % item + continue + elif not isinstance(value, (str, text_type, int, float, bool)): + continue + yield '%s: %r' % (key, value) + + +def explain_template_loading_attempts(app, template, attempts): + """This should help developers understand what failed""" + info = ['Locating template "%s":' % template] + total_found = 0 + blueprint = None + reqctx = _request_ctx_stack.top + if reqctx is not None and reqctx.request.blueprint is not None: + blueprint = reqctx.request.blueprint + + for idx, (loader, srcobj, triple) in enumerate(attempts): + if isinstance(srcobj, Flask): + src_info = 'application "%s"' % srcobj.import_name + elif isinstance(srcobj, Blueprint): + src_info = 'blueprint "%s" (%s)' % (srcobj.name, + srcobj.import_name) + else: + src_info = repr(srcobj) + + info.append('% 5d: trying loader of %s' % ( + idx + 1, src_info)) + + for line in _dump_loader_info(loader): + info.append(' %s' % line) + + if triple is None: + detail = 'no match' + else: + detail = 'found (%r)' % (triple[1] or '') + total_found += 1 + info.append(' -> %s' % detail) + + seems_fishy = False + if total_found == 0: + info.append('Error: the template could not be found.') + seems_fishy = True + elif total_found > 1: + info.append('Warning: multiple loaders returned a match for the template.') + seems_fishy = True + + if blueprint is not None and seems_fishy: + info.append(' The template was looked up from an endpoint that ' + 'belongs to the blueprint "%s".' % blueprint) + info.append(' Maybe you did not place a template in the right folder?') + info.append(' See http://flask.pocoo.org/docs/blueprints/#templates') + + app.logger.info('\n'.join(info)) diff --git a/flex/lib/python3.6/site-packages/flask/ext/__init__.py b/flex/lib/python3.6/site-packages/flask/ext/__init__.py new file mode 100644 index 0000000..051f44a --- /dev/null +++ b/flex/lib/python3.6/site-packages/flask/ext/__init__.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +""" + flask.ext + ~~~~~~~~~ + + Redirect imports for extensions. This module basically makes it possible + for us to transition from flaskext.foo to flask_foo without having to + force all extensions to upgrade at the same time. + + When a user does ``from flask.ext.foo import bar`` it will attempt to + import ``from flask_foo import bar`` first and when that fails it will + try to import ``from flaskext.foo import bar``. + + We're switching from namespace packages because it was just too painful for + everybody involved. + + :copyright: (c) 2015 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + + +def setup(): + from ..exthook import ExtensionImporter + importer = ExtensionImporter(['flask_%s', 'flaskext.%s'], __name__) + importer.install() + + +setup() +del setup diff --git a/flex/lib/python3.6/site-packages/flask/ext/__pycache__/__init__.cpython-36.pyc b/flex/lib/python3.6/site-packages/flask/ext/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9ad1660fabc98e719bb5f424cb93101d7fba1bf2 GIT binary patch literal 1075 zcmZuw&2G~`5MC!~69tNdkPyeY6o^FQmZpeA2mz&sBGf}$2`L<$jdvYyV|(4*bwZ++ zOL-ZdfJZ^fl@qVPiP?1`g4B^b+VRfM_l-aAZ*4Vy{s{XYs)YO^YgWPY8+`O5bd2-~ z^H}8@>3iI}As+ecvFaIV)#x=QHUTY4s2;cZ7vrL@D{H#&lry1tXh5X7R7OK26<{vU zw2+x@1DwY~Ln>L3a2Qf8LYgEqNa>hs5C(FowHPM69EHV&1|z{JiX9C0fJn)-1c80q zk;F?`#(@o{!o;#L5YvgsMtHaC6mq~(YhY|$k&hH*cw@lC95hWi7?JXJN#|3{GoXlp zD_{~44hH|m+a0+1C0Asl1_R4sDsT=phNn5UEdeZZ*6SVI|7s(lv;mqinA*W6MpzLQ ziQA0r>bMv+v(RtpcpIP<6aGXYKip0j+r2m%8Pe4`#m%4_(-9IJ@{l53M}um(C=igr zwdPc0QIXj1=|J!aSF@pHGZ5KCCKJw(}SmB3!d-p9l&q~Z&fNXIF%U< zW3Jk+NiPv0Duegn-P!wRpgD(+$A?EJXGcyqsYJ+(8@qvaGemtlvx-F(lS6#;V{}%r z2}!+c)aw;tRaP5SOy#C>?Ok~nRjXn~P{SK1zinyDTiicdDe~CKl&g8e$vW89^E>Wj zSGlcQwSFB>v6N$FYZr|muuBVqMO|dtprBfnrY<|(T{dU)uI{`Xce-i!MQ0anl=`. + + To integrate applications, :class:`Flask` has a hook to intercept URL build + errors through :attr:`Flask.url_build_error_handlers`. The `url_for` + function results in a :exc:`~werkzeug.routing.BuildError` when the current + app does not have a URL for the given endpoint and values. When it does, the + :data:`~flask.current_app` calls its :attr:`~Flask.url_build_error_handlers` if + it is not ``None``, which can return a string to use as the result of + `url_for` (instead of `url_for`'s default to raise the + :exc:`~werkzeug.routing.BuildError` exception) or re-raise the exception. + An example:: + + def external_url_handler(error, endpoint, values): + "Looks up an external URL when `url_for` cannot build a URL." + # This is an example of hooking the build_error_handler. + # Here, lookup_url is some utility function you've built + # which looks up the endpoint in some external URL registry. + url = lookup_url(endpoint, **values) + if url is None: + # External lookup did not have a URL. + # Re-raise the BuildError, in context of original traceback. + exc_type, exc_value, tb = sys.exc_info() + if exc_value is error: + raise exc_type, exc_value, tb + else: + raise error + # url_for will use this result, instead of raising BuildError. + return url + + app.url_build_error_handlers.append(external_url_handler) + + Here, `error` is the instance of :exc:`~werkzeug.routing.BuildError`, and + `endpoint` and `values` are the arguments passed into `url_for`. Note + that this is for building URLs outside the current application, and not for + handling 404 NotFound errors. + + .. versionadded:: 0.10 + The `_scheme` parameter was added. + + .. versionadded:: 0.9 + The `_anchor` and `_method` parameters were added. + + .. versionadded:: 0.9 + Calls :meth:`Flask.handle_build_error` on + :exc:`~werkzeug.routing.BuildError`. + + :param endpoint: the endpoint of the URL (name of the function) + :param values: the variable arguments of the URL rule + :param _external: if set to ``True``, an absolute URL is generated. Server + address can be changed via ``SERVER_NAME`` configuration variable which + defaults to `localhost`. + :param _scheme: a string specifying the desired URL scheme. The `_external` + parameter must be set to ``True`` or a :exc:`ValueError` is raised. The default + behavior uses the same scheme as the current request, or + ``PREFERRED_URL_SCHEME`` from the :ref:`app configuration ` if no + request context is available. As of Werkzeug 0.10, this also can be set + to an empty string to build protocol-relative URLs. + :param _anchor: if provided this is added as anchor to the URL. + :param _method: if provided this explicitly specifies an HTTP method. + """ + appctx = _app_ctx_stack.top + reqctx = _request_ctx_stack.top + if appctx is None: + raise RuntimeError('Attempted to generate a URL without the ' + 'application context being pushed. This has to be ' + 'executed when application context is available.') + + # If request specific information is available we have some extra + # features that support "relative" URLs. + if reqctx is not None: + url_adapter = reqctx.url_adapter + blueprint_name = request.blueprint + if not reqctx.request._is_old_module: + if endpoint[:1] == '.': + if blueprint_name is not None: + endpoint = blueprint_name + endpoint + else: + endpoint = endpoint[1:] + else: + # TODO: get rid of this deprecated functionality in 1.0 + if '.' not in endpoint: + if blueprint_name is not None: + endpoint = blueprint_name + '.' + endpoint + elif endpoint.startswith('.'): + endpoint = endpoint[1:] + external = values.pop('_external', False) + + # Otherwise go with the url adapter from the appctx and make + # the URLs external by default. + else: + url_adapter = appctx.url_adapter + if url_adapter is None: + raise RuntimeError('Application was not able to create a URL ' + 'adapter for request independent URL generation. ' + 'You might be able to fix this by setting ' + 'the SERVER_NAME config variable.') + external = values.pop('_external', True) + + anchor = values.pop('_anchor', None) + method = values.pop('_method', None) + scheme = values.pop('_scheme', None) + appctx.app.inject_url_defaults(endpoint, values) + + # This is not the best way to deal with this but currently the + # underlying Werkzeug router does not support overriding the scheme on + # a per build call basis. + old_scheme = None + if scheme is not None: + if not external: + raise ValueError('When specifying _scheme, _external must be True') + old_scheme = url_adapter.url_scheme + url_adapter.url_scheme = scheme + + try: + try: + rv = url_adapter.build(endpoint, values, method=method, + force_external=external) + finally: + if old_scheme is not None: + url_adapter.url_scheme = old_scheme + except BuildError as error: + # We need to inject the values again so that the app callback can + # deal with that sort of stuff. + values['_external'] = external + values['_anchor'] = anchor + values['_method'] = method + return appctx.app.handle_url_build_error(error, endpoint, values) + + if anchor is not None: + rv += '#' + url_quote(anchor) + return rv + + +def get_template_attribute(template_name, attribute): + """Loads a macro (or variable) a template exports. This can be used to + invoke a macro from within Python code. If you for example have a + template named :file:`_cider.html` with the following contents: + + .. sourcecode:: html+jinja + + {% macro hello(name) %}Hello {{ name }}!{% endmacro %} + + You can access this from Python code like this:: + + hello = get_template_attribute('_cider.html', 'hello') + return hello('World') + + .. versionadded:: 0.2 + + :param template_name: the name of the template + :param attribute: the name of the variable of macro to access + """ + return getattr(current_app.jinja_env.get_template(template_name).module, + attribute) + + +def flash(message, category='message'): + """Flashes a message to the next request. In order to remove the + flashed message from the session and to display it to the user, + the template has to call :func:`get_flashed_messages`. + + .. versionchanged:: 0.3 + `category` parameter added. + + :param message: the message to be flashed. + :param category: the category for the message. The following values + are recommended: ``'message'`` for any kind of message, + ``'error'`` for errors, ``'info'`` for information + messages and ``'warning'`` for warnings. However any + kind of string can be used as category. + """ + # Original implementation: + # + # session.setdefault('_flashes', []).append((category, message)) + # + # This assumed that changes made to mutable structures in the session are + # are always in sync with the session object, which is not true for session + # implementations that use external storage for keeping their keys/values. + flashes = session.get('_flashes', []) + flashes.append((category, message)) + session['_flashes'] = flashes + message_flashed.send(current_app._get_current_object(), + message=message, category=category) + + +def get_flashed_messages(with_categories=False, category_filter=[]): + """Pulls all flashed messages from the session and returns them. + Further calls in the same request to the function will return + the same messages. By default just the messages are returned, + but when `with_categories` is set to ``True``, the return value will + be a list of tuples in the form ``(category, message)`` instead. + + Filter the flashed messages to one or more categories by providing those + categories in `category_filter`. This allows rendering categories in + separate html blocks. The `with_categories` and `category_filter` + arguments are distinct: + + * `with_categories` controls whether categories are returned with message + text (``True`` gives a tuple, where ``False`` gives just the message text). + * `category_filter` filters the messages down to only those matching the + provided categories. + + See :ref:`message-flashing-pattern` for examples. + + .. versionchanged:: 0.3 + `with_categories` parameter added. + + .. versionchanged:: 0.9 + `category_filter` parameter added. + + :param with_categories: set to ``True`` to also receive categories. + :param category_filter: whitelist of categories to limit return values + """ + flashes = _request_ctx_stack.top.flashes + if flashes is None: + _request_ctx_stack.top.flashes = flashes = session.pop('_flashes') \ + if '_flashes' in session else [] + if category_filter: + flashes = list(filter(lambda f: f[0] in category_filter, flashes)) + if not with_categories: + return [x[1] for x in flashes] + return flashes + + +def send_file(filename_or_fp, mimetype=None, as_attachment=False, + attachment_filename=None, add_etags=True, + cache_timeout=None, conditional=False, last_modified=None): + """Sends the contents of a file to the client. This will use the + most efficient method available and configured. By default it will + try to use the WSGI server's file_wrapper support. Alternatively + you can set the application's :attr:`~Flask.use_x_sendfile` attribute + to ``True`` to directly emit an ``X-Sendfile`` header. This however + requires support of the underlying webserver for ``X-Sendfile``. + + By default it will try to guess the mimetype for you, but you can + also explicitly provide one. For extra security you probably want + to send certain files as attachment (HTML for instance). The mimetype + guessing requires a `filename` or an `attachment_filename` to be + provided. + + ETags will also be attached automatically if a `filename` is provided. You + can turn this off by setting `add_etags=False`. + + If `conditional=True` and `filename` is provided, this method will try to + upgrade the response stream to support range requests. This will allow + the request to be answered with partial content response. + + Please never pass filenames to this function from user sources; + you should use :func:`send_from_directory` instead. + + .. versionadded:: 0.2 + + .. versionadded:: 0.5 + The `add_etags`, `cache_timeout` and `conditional` parameters were + added. The default behavior is now to attach etags. + + .. versionchanged:: 0.7 + mimetype guessing and etag support for file objects was + deprecated because it was unreliable. Pass a filename if you are + able to, otherwise attach an etag yourself. This functionality + will be removed in Flask 1.0 + + .. versionchanged:: 0.9 + cache_timeout pulls its default from application config, when None. + + .. versionchanged:: 0.12 + The filename is no longer automatically inferred from file objects. If + you want to use automatic mimetype and etag support, pass a filepath via + `filename_or_fp` or `attachment_filename`. + + .. versionchanged:: 0.12 + The `attachment_filename` is preferred over `filename` for MIME-type + detection. + + :param filename_or_fp: the filename of the file to send in `latin-1`. + This is relative to the :attr:`~Flask.root_path` + if a relative path is specified. + Alternatively a file object might be provided in + which case ``X-Sendfile`` might not work and fall + back to the traditional method. Make sure that the + file pointer is positioned at the start of data to + send before calling :func:`send_file`. + :param mimetype: the mimetype of the file if provided. If a file path is + given, auto detection happens as fallback, otherwise an + error will be raised. + :param as_attachment: set to ``True`` if you want to send this file with + a ``Content-Disposition: attachment`` header. + :param attachment_filename: the filename for the attachment if it + differs from the file's filename. + :param add_etags: set to ``False`` to disable attaching of etags. + :param conditional: set to ``True`` to enable conditional responses. + + :param cache_timeout: the timeout in seconds for the headers. When ``None`` + (default), this value is set by + :meth:`~Flask.get_send_file_max_age` of + :data:`~flask.current_app`. + :param last_modified: set the ``Last-Modified`` header to this value, + a :class:`~datetime.datetime` or timestamp. + If a file was passed, this overrides its mtime. + """ + mtime = None + fsize = None + if isinstance(filename_or_fp, string_types): + filename = filename_or_fp + if not os.path.isabs(filename): + filename = os.path.join(current_app.root_path, filename) + file = None + if attachment_filename is None: + attachment_filename = os.path.basename(filename) + else: + file = filename_or_fp + filename = None + + if mimetype is None: + if attachment_filename is not None: + mimetype = mimetypes.guess_type(attachment_filename)[0] \ + or 'application/octet-stream' + + if mimetype is None: + raise ValueError( + 'Unable to infer MIME-type because no filename is available. ' + 'Please set either `attachment_filename`, pass a filepath to ' + '`filename_or_fp` or set your own MIME-type via `mimetype`.' + ) + + headers = Headers() + if as_attachment: + if attachment_filename is None: + raise TypeError('filename unavailable, required for ' + 'sending as attachment') + headers.add('Content-Disposition', 'attachment', + filename=attachment_filename) + + if current_app.use_x_sendfile and filename: + if file is not None: + file.close() + headers['X-Sendfile'] = filename + fsize = os.path.getsize(filename) + headers['Content-Length'] = fsize + data = None + else: + if file is None: + file = open(filename, 'rb') + mtime = os.path.getmtime(filename) + fsize = os.path.getsize(filename) + headers['Content-Length'] = fsize + data = wrap_file(request.environ, file) + + rv = current_app.response_class(data, mimetype=mimetype, headers=headers, + direct_passthrough=True) + + if last_modified is not None: + rv.last_modified = last_modified + elif mtime is not None: + rv.last_modified = mtime + + rv.cache_control.public = True + if cache_timeout is None: + cache_timeout = current_app.get_send_file_max_age(filename) + if cache_timeout is not None: + rv.cache_control.max_age = cache_timeout + rv.expires = int(time() + cache_timeout) + + if add_etags and filename is not None: + from warnings import warn + + try: + rv.set_etag('%s-%s-%s' % ( + os.path.getmtime(filename), + os.path.getsize(filename), + adler32( + filename.encode('utf-8') if isinstance(filename, text_type) + else filename + ) & 0xffffffff + )) + except OSError: + warn('Access %s failed, maybe it does not exist, so ignore etags in ' + 'headers' % filename, stacklevel=2) + + if conditional: + if callable(getattr(Range, 'to_content_range_header', None)): + # Werkzeug supports Range Requests + # Remove this test when support for Werkzeug <0.12 is dropped + try: + rv = rv.make_conditional(request, accept_ranges=True, + complete_length=fsize) + except RequestedRangeNotSatisfiable: + file.close() + raise + else: + rv = rv.make_conditional(request) + # make sure we don't send x-sendfile for servers that + # ignore the 304 status code for x-sendfile. + if rv.status_code == 304: + rv.headers.pop('x-sendfile', None) + return rv + + +def safe_join(directory, *pathnames): + """Safely join `directory` and zero or more untrusted `pathnames` + components. + + Example usage:: + + @app.route('/wiki/') + def wiki_page(filename): + filename = safe_join(app.config['WIKI_FOLDER'], filename) + with open(filename, 'rb') as fd: + content = fd.read() # Read and process the file content... + + :param directory: the trusted base directory. + :param pathnames: the untrusted pathnames relative to that directory. + :raises: :class:`~werkzeug.exceptions.NotFound` if one or more passed + paths fall out of its boundaries. + """ + + parts = [directory] + + for filename in pathnames: + if filename != '': + filename = posixpath.normpath(filename) + + if ( + any(sep in filename for sep in _os_alt_seps) + or os.path.isabs(filename) + or filename == '..' + or filename.startswith('../') + ): + raise NotFound() + + parts.append(filename) + + return posixpath.join(*parts) + + +def send_from_directory(directory, filename, **options): + """Send a file from a given directory with :func:`send_file`. This + is a secure way to quickly expose static files from an upload folder + or something similar. + + Example usage:: + + @app.route('/uploads/') + def download_file(filename): + return send_from_directory(app.config['UPLOAD_FOLDER'], + filename, as_attachment=True) + + .. admonition:: Sending files and Performance + + It is strongly recommended to activate either ``X-Sendfile`` support in + your webserver or (if no authentication happens) to tell the webserver + to serve files for the given path on its own without calling into the + web application for improved performance. + + .. versionadded:: 0.5 + + :param directory: the directory where all the files are stored. + :param filename: the filename relative to that directory to + download. + :param options: optional keyword arguments that are directly + forwarded to :func:`send_file`. + """ + filename = safe_join(directory, filename) + if not os.path.isabs(filename): + filename = os.path.join(current_app.root_path, filename) + try: + if not os.path.isfile(filename): + raise NotFound() + except (TypeError, ValueError): + raise BadRequest() + options.setdefault('conditional', True) + return send_file(filename, **options) + + +def get_root_path(import_name): + """Returns the path to a package or cwd if that cannot be found. This + returns the path of a package or the folder that contains a module. + + Not to be confused with the package path returned by :func:`find_package`. + """ + # Module already imported and has a file attribute. Use that first. + mod = sys.modules.get(import_name) + if mod is not None and hasattr(mod, '__file__'): + return os.path.dirname(os.path.abspath(mod.__file__)) + + # Next attempt: check the loader. + loader = pkgutil.get_loader(import_name) + + # Loader does not exist or we're referring to an unloaded main module + # or a main module without path (interactive sessions), go with the + # current working directory. + if loader is None or import_name == '__main__': + return os.getcwd() + + # For .egg, zipimporter does not have get_filename until Python 2.7. + # Some other loaders might exhibit the same behavior. + if hasattr(loader, 'get_filename'): + filepath = loader.get_filename(import_name) + else: + # Fall back to imports. + __import__(import_name) + mod = sys.modules[import_name] + filepath = getattr(mod, '__file__', None) + + # If we don't have a filepath it might be because we are a + # namespace package. In this case we pick the root path from the + # first module that is contained in our package. + if filepath is None: + raise RuntimeError('No root path can be found for the provided ' + 'module "%s". This can happen because the ' + 'module came from an import hook that does ' + 'not provide file name information or because ' + 'it\'s a namespace package. In this case ' + 'the root path needs to be explicitly ' + 'provided.' % import_name) + + # filepath is import_name.py for a module, or __init__.py for a package. + return os.path.dirname(os.path.abspath(filepath)) + + +def _matching_loader_thinks_module_is_package(loader, mod_name): + """Given the loader that loaded a module and the module this function + attempts to figure out if the given module is actually a package. + """ + # If the loader can tell us if something is a package, we can + # directly ask the loader. + if hasattr(loader, 'is_package'): + return loader.is_package(mod_name) + # importlib's namespace loaders do not have this functionality but + # all the modules it loads are packages, so we can take advantage of + # this information. + elif (loader.__class__.__module__ == '_frozen_importlib' and + loader.__class__.__name__ == 'NamespaceLoader'): + return True + # Otherwise we need to fail with an error that explains what went + # wrong. + raise AttributeError( + ('%s.is_package() method is missing but is required by Flask of ' + 'PEP 302 import hooks. If you do not use import hooks and ' + 'you encounter this error please file a bug against Flask.') % + loader.__class__.__name__) + + +def find_package(import_name): + """Finds a package and returns the prefix (or None if the package is + not installed) as well as the folder that contains the package or + module as a tuple. The package path returned is the module that would + have to be added to the pythonpath in order to make it possible to + import the module. The prefix is the path below which a UNIX like + folder structure exists (lib, share etc.). + """ + root_mod_name = import_name.split('.')[0] + loader = pkgutil.get_loader(root_mod_name) + if loader is None or import_name == '__main__': + # import name is not found, or interactive/main module + package_path = os.getcwd() + else: + # For .egg, zipimporter does not have get_filename until Python 2.7. + if hasattr(loader, 'get_filename'): + filename = loader.get_filename(root_mod_name) + elif hasattr(loader, 'archive'): + # zipimporter's loader.archive points to the .egg or .zip + # archive filename is dropped in call to dirname below. + filename = loader.archive + else: + # At least one loader is missing both get_filename and archive: + # Google App Engine's HardenedModulesHook + # + # Fall back to imports. + __import__(import_name) + filename = sys.modules[import_name].__file__ + package_path = os.path.abspath(os.path.dirname(filename)) + + # In case the root module is a package we need to chop of the + # rightmost part. This needs to go through a helper function + # because of python 3.3 namespace packages. + if _matching_loader_thinks_module_is_package( + loader, root_mod_name): + package_path = os.path.dirname(package_path) + + site_parent, site_folder = os.path.split(package_path) + py_prefix = os.path.abspath(sys.prefix) + if package_path.startswith(py_prefix): + return py_prefix, package_path + elif site_folder.lower() == 'site-packages': + parent, folder = os.path.split(site_parent) + # Windows like installations + if folder.lower() == 'lib': + base_dir = parent + # UNIX like installations + elif os.path.basename(parent).lower() == 'lib': + base_dir = os.path.dirname(parent) + else: + base_dir = site_parent + return base_dir, package_path + return None, package_path + + +class locked_cached_property(object): + """A decorator that converts a function into a lazy property. The + function wrapped is called the first time to retrieve the result + and then that calculated result is used the next time you access + the value. Works like the one in Werkzeug but has a lock for + thread safety. + """ + + def __init__(self, func, name=None, doc=None): + self.__name__ = name or func.__name__ + self.__module__ = func.__module__ + self.__doc__ = doc or func.__doc__ + self.func = func + self.lock = RLock() + + def __get__(self, obj, type=None): + if obj is None: + return self + with self.lock: + value = obj.__dict__.get(self.__name__, _missing) + if value is _missing: + value = self.func(obj) + obj.__dict__[self.__name__] = value + return value + + +class _PackageBoundObject(object): + + def __init__(self, import_name, template_folder=None, root_path=None): + #: The name of the package or module. Do not change this once + #: it was set by the constructor. + self.import_name = import_name + + #: location of the templates. ``None`` if templates should not be + #: exposed. + self.template_folder = template_folder + + if root_path is None: + root_path = get_root_path(self.import_name) + + #: Where is the app root located? + self.root_path = root_path + + self._static_folder = None + self._static_url_path = None + + def _get_static_folder(self): + if self._static_folder is not None: + return os.path.join(self.root_path, self._static_folder) + def _set_static_folder(self, value): + self._static_folder = value + static_folder = property(_get_static_folder, _set_static_folder, doc=''' + The absolute path to the configured static folder. + ''') + del _get_static_folder, _set_static_folder + + def _get_static_url_path(self): + if self._static_url_path is not None: + return self._static_url_path + if self.static_folder is not None: + return '/' + os.path.basename(self.static_folder) + def _set_static_url_path(self, value): + self._static_url_path = value + static_url_path = property(_get_static_url_path, _set_static_url_path) + del _get_static_url_path, _set_static_url_path + + @property + def has_static_folder(self): + """This is ``True`` if the package bound object's container has a + folder for static files. + + .. versionadded:: 0.5 + """ + return self.static_folder is not None + + @locked_cached_property + def jinja_loader(self): + """The Jinja loader for this package bound object. + + .. versionadded:: 0.5 + """ + if self.template_folder is not None: + return FileSystemLoader(os.path.join(self.root_path, + self.template_folder)) + + def get_send_file_max_age(self, filename): + """Provides default cache_timeout for the :func:`send_file` functions. + + By default, this function returns ``SEND_FILE_MAX_AGE_DEFAULT`` from + the configuration of :data:`~flask.current_app`. + + Static file functions such as :func:`send_from_directory` use this + function, and :func:`send_file` calls this function on + :data:`~flask.current_app` when the given cache_timeout is ``None``. If a + cache_timeout is given in :func:`send_file`, that timeout is used; + otherwise, this method is called. + + This allows subclasses to change the behavior when sending files based + on the filename. For example, to set the cache timeout for .js files + to 60 seconds:: + + class MyFlask(flask.Flask): + def get_send_file_max_age(self, name): + if name.lower().endswith('.js'): + return 60 + return flask.Flask.get_send_file_max_age(self, name) + + .. versionadded:: 0.9 + """ + return total_seconds(current_app.send_file_max_age_default) + + def send_static_file(self, filename): + """Function used internally to send static files from the static + folder to the browser. + + .. versionadded:: 0.5 + """ + if not self.has_static_folder: + raise RuntimeError('No static folder for this object') + # Ensure get_send_file_max_age is called in all cases. + # Here, we ensure get_send_file_max_age is called for Blueprints. + cache_timeout = self.get_send_file_max_age(filename) + return send_from_directory(self.static_folder, filename, + cache_timeout=cache_timeout) + + def open_resource(self, resource, mode='rb'): + """Opens a resource from the application's resource folder. To see + how this works, consider the following folder structure:: + + /myapplication.py + /schema.sql + /static + /style.css + /templates + /layout.html + /index.html + + If you want to open the :file:`schema.sql` file you would do the + following:: + + with app.open_resource('schema.sql') as f: + contents = f.read() + do_something_with(contents) + + :param resource: the name of the resource. To access resources within + subfolders use forward slashes as separator. + :param mode: resource file opening mode, default is 'rb'. + """ + if mode not in ('r', 'rb'): + raise ValueError('Resources can only be opened for reading') + return open(os.path.join(self.root_path, resource), mode) + + +def total_seconds(td): + """Returns the total seconds from a timedelta object. + + :param timedelta td: the timedelta to be converted in seconds + + :returns: number of seconds + :rtype: int + """ + return td.days * 60 * 60 * 24 + td.seconds diff --git a/flex/lib/python3.6/site-packages/flask/json.py b/flex/lib/python3.6/site-packages/flask/json.py new file mode 100644 index 0000000..16e0c29 --- /dev/null +++ b/flex/lib/python3.6/site-packages/flask/json.py @@ -0,0 +1,269 @@ +# -*- coding: utf-8 -*- +""" + flask.jsonimpl + ~~~~~~~~~~~~~~ + + Implementation helpers for the JSON support in Flask. + + :copyright: (c) 2015 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" +import io +import uuid +from datetime import date +from .globals import current_app, request +from ._compat import text_type, PY2 + +from werkzeug.http import http_date +from jinja2 import Markup + +# Use the same json implementation as itsdangerous on which we +# depend anyways. +from itsdangerous import json as _json + + +# Figure out if simplejson escapes slashes. This behavior was changed +# from one version to another without reason. +_slash_escape = '\\/' not in _json.dumps('/') + + +__all__ = ['dump', 'dumps', 'load', 'loads', 'htmlsafe_dump', + 'htmlsafe_dumps', 'JSONDecoder', 'JSONEncoder', + 'jsonify'] + + +def _wrap_reader_for_text(fp, encoding): + if isinstance(fp.read(0), bytes): + fp = io.TextIOWrapper(io.BufferedReader(fp), encoding) + return fp + + +def _wrap_writer_for_text(fp, encoding): + try: + fp.write('') + except TypeError: + fp = io.TextIOWrapper(fp, encoding) + return fp + + +class JSONEncoder(_json.JSONEncoder): + """The default Flask JSON encoder. This one extends the default simplejson + encoder by also supporting ``datetime`` objects, ``UUID`` as well as + ``Markup`` objects which are serialized as RFC 822 datetime strings (same + as the HTTP date format). In order to support more data types override the + :meth:`default` method. + """ + + def default(self, o): + """Implement this method in a subclass such that it returns a + serializable object for ``o``, or calls the base implementation (to + raise a :exc:`TypeError`). + + For example, to support arbitrary iterators, you could implement + default like this:: + + def default(self, o): + try: + iterable = iter(o) + except TypeError: + pass + else: + return list(iterable) + return JSONEncoder.default(self, o) + """ + if isinstance(o, date): + return http_date(o.timetuple()) + if isinstance(o, uuid.UUID): + return str(o) + if hasattr(o, '__html__'): + return text_type(o.__html__()) + return _json.JSONEncoder.default(self, o) + + +class JSONDecoder(_json.JSONDecoder): + """The default JSON decoder. This one does not change the behavior from + the default simplejson decoder. Consult the :mod:`json` documentation + for more information. This decoder is not only used for the load + functions of this module but also :attr:`~flask.Request`. + """ + + +def _dump_arg_defaults(kwargs): + """Inject default arguments for dump functions.""" + if current_app: + kwargs.setdefault('cls', current_app.json_encoder) + if not current_app.config['JSON_AS_ASCII']: + kwargs.setdefault('ensure_ascii', False) + kwargs.setdefault('sort_keys', current_app.config['JSON_SORT_KEYS']) + else: + kwargs.setdefault('sort_keys', True) + kwargs.setdefault('cls', JSONEncoder) + + +def _load_arg_defaults(kwargs): + """Inject default arguments for load functions.""" + if current_app: + kwargs.setdefault('cls', current_app.json_decoder) + else: + kwargs.setdefault('cls', JSONDecoder) + + +def dumps(obj, **kwargs): + """Serialize ``obj`` to a JSON formatted ``str`` by using the application's + configured encoder (:attr:`~flask.Flask.json_encoder`) if there is an + application on the stack. + + This function can return ``unicode`` strings or ascii-only bytestrings by + default which coerce into unicode strings automatically. That behavior by + default is controlled by the ``JSON_AS_ASCII`` configuration variable + and can be overridden by the simplejson ``ensure_ascii`` parameter. + """ + _dump_arg_defaults(kwargs) + encoding = kwargs.pop('encoding', None) + rv = _json.dumps(obj, **kwargs) + if encoding is not None and isinstance(rv, text_type): + rv = rv.encode(encoding) + return rv + + +def dump(obj, fp, **kwargs): + """Like :func:`dumps` but writes into a file object.""" + _dump_arg_defaults(kwargs) + encoding = kwargs.pop('encoding', None) + if encoding is not None: + fp = _wrap_writer_for_text(fp, encoding) + _json.dump(obj, fp, **kwargs) + + +def loads(s, **kwargs): + """Unserialize a JSON object from a string ``s`` by using the application's + configured decoder (:attr:`~flask.Flask.json_decoder`) if there is an + application on the stack. + """ + _load_arg_defaults(kwargs) + if isinstance(s, bytes): + s = s.decode(kwargs.pop('encoding', None) or 'utf-8') + return _json.loads(s, **kwargs) + + +def load(fp, **kwargs): + """Like :func:`loads` but reads from a file object. + """ + _load_arg_defaults(kwargs) + if not PY2: + fp = _wrap_reader_for_text(fp, kwargs.pop('encoding', None) or 'utf-8') + return _json.load(fp, **kwargs) + + +def htmlsafe_dumps(obj, **kwargs): + """Works exactly like :func:`dumps` but is safe for use in `` + + + + +