diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 000000000..e63978a5f --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,186 @@ +environment: + + global: + # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the + # /E:ON and /V:ON options are not enabled in the batch script intepreter + # See: http://stackoverflow.com/a/13751649/163740 + CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_env.cmd" + + matrix: + + # Python 2.7.10 is the latest version and is not pre-installed. + + - PYTHON: "C:\\Python27.10" + PYTHON_VERSION: "2.7.10" + PYTHON_ARCH: "32" + + #- PYTHON: "C:\\Python27.10-x64" + # PYTHON_VERSION: "2.7.10" + # PYTHON_ARCH: "64" + + # Pre-installed Python versions, which Appveyor may upgrade to + # a later point release. + # See: http://www.appveyor.com/docs/installed-software#python + + #- PYTHON: "C:\\Python27" + # PYTHON_VERSION: "2.7.x" # currently 2.7.9 + # PYTHON_ARCH: "32" + + #- PYTHON: "C:\\Python27-x64" + # PYTHON_VERSION: "2.7.x" # currently 2.7.9 + # PYTHON_ARCH: "64" + + #- PYTHON: "C:\\Python33" + # PYTHON_VERSION: "3.3.x" # currently 3.3.5 + # PYTHON_ARCH: "32" + + #- PYTHON: "C:\\Python33-x64" + # PYTHON_VERSION: "3.3.x" # currently 3.3.5 + # PYTHON_ARCH: "64" + + #- PYTHON: "C:\\Python34" + # PYTHON_VERSION: "3.4.x" # currently 3.4.3 + # PYTHON_ARCH: "32" + + #- PYTHON: "C:\\Python34-x64" + # PYTHON_VERSION: "3.4.x" # currently 3.4.3 + # PYTHON_ARCH: "64" + + # Python versions not pre-installed + + # Python 2.6.6 is the latest Python 2.6 with a Windows installer + # See: https://github.com/ogrisel/python-appveyor-demo/issues/10 + + #- PYTHON: "C:\\Python266" + # PYTHON_VERSION: "2.6.6" + # PYTHON_ARCH: "32" + + #- PYTHON: "C:\\Python266-x64" + # PYTHON_VERSION: "2.6.6" + # PYTHON_ARCH: "64" + + #- PYTHON: "C:\\Python35" + # PYTHON_VERSION: "3.5.0" + # PYTHON_ARCH: "32" + + #- PYTHON: "C:\\Python35-x64" + # PYTHON_VERSION: "3.5.0" + # PYTHON_ARCH: "64" + + # Major and minor releases (i.e x.0.0 and x.y.0) prior to 3.3.0 use + # a different naming scheme. + + #- PYTHON: "C:\\Python270" + # PYTHON_VERSION: "2.7.0" + # PYTHON_ARCH: "32" + + #- PYTHON: "C:\\Python270-x64" + # PYTHON_VERSION: "2.7.0" + # PYTHON_ARCH: "64" + +install: + # If there is a newer build queued for the same PR, cancel this one. + # The AppVeyor 'rollout builds' option is supposed to serve the same + # purpose but it is problematic because it tends to cancel builds pushed + # directly to master instead of just PR builds (or the converse). + # credits: JuliaLang developers. + - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` + https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` + Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` + throw "There are newer queued builds for this pull request, failing early." } + + # Install wxPython + - 'ECHO Downloading wxPython.' + - "appveyor DownloadFile https://goo.gl/yvO8PB -FileName C:\\wxpython.exe" + #- "appveyor DownloadFile https://goo.gl/Uj0jV3 -FileName C:\\wxpython64.exe" + + - 'ECHO Install wxPython' + - "C:\\wxpython.exe /SP- /VERYSILENT /NORESTART" + #- "C:\\wxpython64.exe /SP- /VERYSILENT /NORESTART" + + - ECHO "Filesystem root:" + - ps: "ls \"C:/\"" + + - ECHO "Filesystem pyfa root:" + - ps: "ls \"C:\\projects\\pyfa\\\"" + + - ECHO "Installed SDKs:" + - ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\"" + + # Install Python (from the official .msi of http://python.org) and pip when + # not already installed. + # - ps: if (-not(Test-Path($env:PYTHON))) { & appveyor\install.ps1 } + + # Prepend newly installed Python to the PATH of this build (this cannot be + # done from inside the powershell script as it would require to restart + # the parent CMD process). + - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" + + # Check that we have the expected version and architecture for Python + - "python --version" + - "python -c \"import struct; print(struct.calcsize('P') * 8)\"" + + # Upgrade to the latest version of pip to avoid it displaying warnings + # about it being out of date. + - "pip install --disable-pip-version-check --user --upgrade pip" + + # Install the build dependencies of the project. If some dependencies contain + # compiled extensions and are not provided as pre-built wheel packages, + # pip will build them from source using the MSVC compiler matching the + # target Python version and architecture + # C:\\projects\\eve-gnosis\\ + - ECHO "Install pip requirements:" + - "pip install -r requirements.txt" + - "pip install -r requirements_test.txt" + - "pip install -r requirements_build_windows.txt" + +build_script: + # Build the compiled extension + # - "python setup.py build" + - ECHO "Build pyfa:" + #- copy C:\projects\pyfa\dist_assets\win\pyfa.spec C:\projects\pyfa\pyfa.spec + - "python C:\\projects\\pyfa\\setup.py build" + + #- ECHO "Build pyfa (Debug):" + #- copy C:\projects\pyfa\dist_assets\win\pyfa_debug.spec C:\projects\pyfa\pyfa_debug.spec + #- "pyinstaller.exe --clean --noconfirm --windowed --upx-dir=C:\\projects\\pyfa\\scripts\\upx.exe C:\\projects\\pyfa\\pyfa_debug.spec" + +build: on + +after_build: + - ps: "ls \"./\"" + #- ps: "ls \"C:\\projects\\pyfa\\build\\pyfa\\\"" + - ps: "ls \"C:\\projects\\pyfa\\build\\\"" + - ps: "ls \"C:\\projects\\pyfa\\build\\exe.win32-2.7\\\"" + # Zip + # APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER + #- 7z a build.zip -r C:\projects\pyfa\build\pyfa\*.* + - 7z a pyfa.zip -r C:\projects\pyfa\build\exe.win32-2.7\*.* + #- 7z a pyfa_debug.zip -r C:\projects\pyfa\dist\pyfa_debug\*.* + +on_success: + # Do nothing right now + +test_script: + #- tox + #- "py.test --cov=./" + # Run the project tests + # - "%CMD_IN_ENV% python C:/projects/eve-gnosis/setup.py nosetests" + +after_test: + # If tests are successful, create binary packages for the project. + # - "%CMD_IN_ENV% python setup.py bdist_wheel" + # - "%CMD_IN_ENV% python setup.py bdist_wininst" + # - "%CMD_IN_ENV% python setup.py bdist_msi" + # - ps: "ls dist" + +artifacts: + # Archive the generated packages in the ci.appveyor.com build report. + - path: pyfa.zip + name: 'pyfa.zip' + #- path: pyfa_debug.zip + # name: Pyfa_debug + +#on_success: +# - TODO: upload the content of dist/*.whl to a public wheelhouse +# \ No newline at end of file diff --git a/.gitignore b/.gitignore index 4b6d3bde8..41586d1b5 100644 --- a/.gitignore +++ b/.gitignore @@ -49,7 +49,6 @@ Pyfa.egg-info/ # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest -*.spec # Installer logs pip-log.txt diff --git a/README.md b/README.md index f78438e89..5700287f8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # pyfa -[![Join us on Slack!](https://pyfainvite.azurewebsites.net/badge.svg)](https://pyfainvite.azurewebsites.net/) +[![Join us on Slack!](https://pyfainvite.azurewebsites.net/badge.svg)](https://pyfainvite.azurewebsites.net/) [![Build Status](https://travis-ci.org/pyfa-org/Pyfa.svg?branch=master)](https://travis-ci.org/pyfa-org/Pyfa) ![pyfa](https://cloud.githubusercontent.com/assets/3904767/10271512/af385ef2-6ade-11e5-8f67-52b8b1e4c797.PNG) @@ -42,6 +42,7 @@ If you wish to help with development or simply need to run pyfa through a Python * `dateutil` * `matplotlib` (for some Linux distributions you may need to install separate wxPython bindings such as `python-matplotlib-wx`) * `requests` +* `logbook` >= 1.0.0 ## Bug Reporting The preferred method of reporting bugs is through the project's [GitHub Issues interface](https://github.com/pyfa-org/Pyfa/issues). Alternatively, posting a report in the [pyfa thread](http://forums.eveonline.com/default.aspx?g=posts&t=247609) on the official EVE Online forums is acceptable. Guidelines for bug reporting can be found on [this wiki page](https://github.com/DarkFenX/Pyfa/wiki/Bug-Reporting). @@ -51,8 +52,7 @@ pyfa is licensed under the GNU GPL v3.0, see LICENSE ## Resources * Development repository: [https://github.com/pyfa-org/Pyfa](https://github.com/pyfa-org/Pyfa) -* XMPP conference: [pyfa@conference.jabber.org](pyfa@conference.jabber.org) -* [EVE forum thread](http://forums.eveonline.com/default.aspx?g=posts&t=247609) +* [EVE forum thread](https://forums.eveonline.com/default.aspx?g=posts&t=466425) * [EVE University guide using pyfa](http://wiki.eveuniversity.org/Guide_to_using_PYFA) * [EVE Online website](http://www.eveonline.com/) diff --git a/_development/Pyfa_CodeStyle.xml b/_development/Pyfa_CodeStyle.xml new file mode 100644 index 000000000..a7980e4df --- /dev/null +++ b/_development/Pyfa_CodeStyle.xml @@ -0,0 +1,13 @@ + + diff --git a/_development/Pyfa_Inspections.xml b/_development/Pyfa_Inspections.xml new file mode 100644 index 000000000..0a0da06d4 --- /dev/null +++ b/_development/Pyfa_Inspections.xml @@ -0,0 +1,54 @@ + + diff --git a/config.py b/config.py index aa9221023..884803d76 100644 --- a/config.py +++ b/config.py @@ -1,27 +1,28 @@ import os import sys -# TODO: move all logging back to pyfa.py main loop -# We moved it here just to avoid rebuilding windows skeleton for now (any change to pyfa.py needs it) -import logging -import logging.handlers +from logbook import Logger + +pyfalog = Logger(__name__) # Load variable overrides specific to distribution type try: import configforced except ImportError: + pyfalog.warning("Failed to import: configforced") configforced = None + # Turns on debug mode debug = False # Defines if our saveddata will be in pyfa root or not saveInRoot = False # Version data -version = "1.26.1" +version = "1.28.2" tag = "git" -expansionName = "YC118.10" -expansionVersion = "1.2" +expansionName = "YC119.3" +expansionVersion = "1.0" evemonMinVersion = "4081" pyfaPath = None @@ -30,22 +31,6 @@ saveDB = None gameDB = None -class StreamToLogger(object): - """ - Fake file-like stream object that redirects writes to a logger instance. - From: http://www.electricmonk.nl/log/2011/08/14/redirect-stdout-and-stderr-to-a-logger-in-python/ - """ - - def __init__(self, logger, log_level=logging.INFO): - self.logger = logger - self.log_level = log_level - self.linebuf = '' - - def write(self, buf): - for line in buf.rstrip().splitlines(): - self.logger.log(self.log_level, line.rstrip()) - - def isFrozen(): if hasattr(sys, 'frozen'): return True @@ -58,6 +43,17 @@ def __createDirs(path): os.makedirs(path) +def getPyfaRoot(): + base = getattr(sys.modules['__main__'], "__file__", sys.executable) if isFrozen() else sys.argv[0] + root = os.path.dirname(os.path.realpath(os.path.abspath(base))) + root = unicode(root, sys.getfilesystemencoding()) + return root + + +def getDefaultSave(): + return unicode(os.path.expanduser(os.path.join("~", ".pyfa")), sys.getfilesystemencoding()) + + def defPaths(customSavePath): global debug global pyfaPath @@ -66,65 +62,42 @@ def defPaths(customSavePath): global gameDB global saveInRoot - if debug: - logLevel = logging.DEBUG - else: - logLevel = logging.WARN + pyfalog.debug("Configuring Pyfa") # The main pyfa directory which contains run.py # Python 2.X uses ANSI by default, so we need to convert the character encoding pyfaPath = getattr(configforced, "pyfaPath", pyfaPath) if pyfaPath is None: - pyfaPath = getPyfaPath() + pyfaPath = getPyfaRoot() # Where we store the saved fits etc, default is the current users home directory if saveInRoot is True: savePath = getattr(configforced, "savePath", None) if savePath is None: - savePath = getPyfaPath("saveddata") + savePath = os.path.join(pyfaPath, "saveddata") else: savePath = getattr(configforced, "savePath", None) if savePath is None: if customSavePath is None: # customSavePath is not overriden - savePath = os.path.expanduser(os.path.join("~", ".pyfa")) + savePath = getDefaultSave() else: savePath = customSavePath __createDirs(savePath) if isFrozen(): - certName = "cacert.pem" - os.environ["REQUESTS_CA_BUNDLE"] = getPyfaPath(certName).encode('utf8') - os.environ["SSL_CERT_FILE"] = getPyfaPath(certName).encode('utf8') - - loggingFormat = '%(asctime)s %(name)-24s %(levelname)-8s %(message)s' - logging.basicConfig(format=loggingFormat, level=logLevel) - handler = logging.handlers.RotatingFileHandler(getSavePath("log.txt"), maxBytes=1000000, backupCount=3) - formatter = logging.Formatter(loggingFormat) - handler.setFormatter(formatter) - logging.getLogger('').addHandler(handler) - - logging.info("Starting pyfa") - - if hasattr(sys, 'frozen'): - stdout_logger = logging.getLogger('STDOUT') - sl = StreamToLogger(stdout_logger, logging.INFO) - sys.stdout = sl - - # This interferes with cx_Freeze's own handling of exceptions. Find a way to fix this. - # stderr_logger = logging.getLogger('STDERR') - # sl = StreamToLogger(stderr_logger, logging.ERROR) - # sys.stderr = sl + os.environ["REQUESTS_CA_BUNDLE"] = os.path.join(pyfaPath, "cacert.pem").encode('utf8') + os.environ["SSL_CERT_FILE"] = os.path.join(pyfaPath, "cacert.pem").encode('utf8') # The database where we store all the fits etc - saveDB = getSavePath("saveddata.db") + saveDB = os.path.join(savePath, "saveddata.db") # The database where the static EVE data from the datadump is kept. # This is not the standard sqlite datadump but a modified version created by eos # maintenance script - gameDB = getPyfaPath("eve.db") + gameDB = os.path.join(pyfaPath, "eve.db") - # DON'T MODIFY ANYTHING BELOW! + # DON'T MODIFY ANYTHING BELOW import eos.config # Caching modifiers, disable all gamedata caching, its unneeded. @@ -133,40 +106,6 @@ def defPaths(customSavePath): eos.config.saveddata_connectionstring = "sqlite:///" + saveDB + "?check_same_thread=False" eos.config.gamedata_connectionstring = "sqlite:///" + gameDB + "?check_same_thread=False" - -def getPyfaPath(Append=None): - base = getattr(sys.modules['__main__'], "__file__", sys.executable) if isFrozen() else sys.argv[0] - root = os.path.dirname(os.path.realpath(os.path.abspath(base))) - - if Append: - path = parsePath(root, Append) - else: - path = parsePath(root) - - return path - - -def getSavePath(Append=None): - root = savePath - - if Append: - path = parsePath(root, Append) - else: - path = parsePath(root) - - return path - - -def parsePath(root, Append=None): - if Append: - path = os.path.join(root, Append) - else: - path = root - - if type(path) == str: # leave unicode ones alone - try: - path = path.decode('utf8') - except UnicodeDecodeError: - path = path.decode('windows-1252') - - return path + # initialize the settings + from service.settings import EOSSettings + eos.config.settings = EOSSettings.getInstance().EOSSettings # this is kind of confusing, but whatever diff --git a/dist_assets/cacert.pem b/dist_assets/cacert.pem new file mode 100644 index 000000000..06d6150be --- /dev/null +++ b/dist_assets/cacert.pem @@ -0,0 +1,5666 @@ + +# Issuer: O=Equifax OU=Equifax Secure Certificate Authority +# Subject: O=Equifax OU=Equifax Secure Certificate Authority +# Label: "Equifax Secure CA" +# Serial: 903804111 +# MD5 Fingerprint: 67:cb:9d:c0:13:24:8a:82:9b:b2:17:1e:d1:1b:ec:d4 +# SHA1 Fingerprint: d2:32:09:ad:23:d3:14:23:21:74:e4:0d:7f:9d:62:13:97:86:63:3a +# SHA256 Fingerprint: 08:29:7a:40:47:db:a2:36:80:c7:31:db:6e:31:76:53:ca:78:48:e1:be:bd:3a:0b:01:79:a7:07:f9:2c:f1:78 +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV +UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy +dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 +MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx +dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f +BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A +cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC +AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm +aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw +ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj +IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF +MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA +A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y +7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh +1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 +-----END CERTIFICATE----- + +# 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=VeriSign Class 4 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 4 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only +# Label: "Verisign Class 4 Public Primary Certification Authority - G3" +# Serial: 314531972711909413743075096039378935511 +# MD5 Fingerprint: db:c8:f2:27:2e:b1:ea:6a:29:23:5d:fe:56:3e:33:df +# SHA1 Fingerprint: c8:ec:8c:87:92:69:cb:4b:ab:39:e9:8d:7e:57:67:f3:14:95:73:9d +# SHA256 Fingerprint: e3:89:36:0d:0f:db:ae:b3:d2:50:58:4b:47:30:31:4e:22:2f:39:c1:56:a0:20:14:4e:8d:96:05:61:79:15:06 +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 +GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ ++mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd +U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm +NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY +ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ +ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 +CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq +g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm +fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c +2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ +bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== +-----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 Class 1 CA Root O=AddTrust AB OU=AddTrust TTP Network +# Subject: CN=AddTrust Class 1 CA Root O=AddTrust AB OU=AddTrust TTP Network +# Label: "AddTrust Low-Value Services Root" +# Serial: 1 +# MD5 Fingerprint: 1e:42:95:02:33:92:6b:b9:5f:c0:7f:da:d6:b2:4b:fc +# SHA1 Fingerprint: cc:ab:0e:a0:4c:23:01:d6:69:7b:dd:37:9f:cd:12:eb:24:e3:94:9d +# SHA256 Fingerprint: 8c:72:09:27:9a:c0:4e:27:5e:16:d0:7f:d3:b7:75:e8:01:54:b5:96:80:46:e3:1f:52:dd:25:76:63:24:e9:a7 +-----BEGIN CERTIFICATE----- +MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw +MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD +VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul +CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n +tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl +dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch +PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC ++Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O +BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl +MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk +ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB +IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X +7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz +43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY +eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl +pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA +WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= +-----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=AddTrust Public CA Root O=AddTrust AB OU=AddTrust TTP Network +# Subject: CN=AddTrust Public CA Root O=AddTrust AB OU=AddTrust TTP Network +# Label: "AddTrust Public Services Root" +# Serial: 1 +# MD5 Fingerprint: c1:62:3e:23:c5:82:73:9c:03:59:4b:2b:e9:77:49:7f +# SHA1 Fingerprint: 2a:b6:28:48:5e:78:fb:f3:ad:9e:79:10:dd:6b:df:99:72:2c:96:e5 +# SHA256 Fingerprint: 07:91:ca:07:49:b2:07:82:aa:d3:c7:d7:bd:0c:df:c9:48:58:35:84:3e:b2:d7:99:60:09:ce:43:ab:6c:69:27 +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx +MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB +ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV +BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV +6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX +GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP +dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH +1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF +62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW +BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL +MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU +cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv +b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6 +IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/ +iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao +GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh +4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm +XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY= +-----END CERTIFICATE----- + +# Issuer: CN=AddTrust Qualified CA Root O=AddTrust AB OU=AddTrust TTP Network +# Subject: CN=AddTrust Qualified CA Root O=AddTrust AB OU=AddTrust TTP Network +# Label: "AddTrust Qualified Certificates Root" +# Serial: 1 +# MD5 Fingerprint: 27:ec:39:47:cd:da:5a:af:e2:9a:01:65:21:a9:4c:bb +# SHA1 Fingerprint: 4d:23:78:ec:91:95:39:b5:00:7f:75:8f:03:3b:21:1e:c5:4d:8b:cf +# SHA256 Fingerprint: 80:95:21:08:05:db:4b:bc:35:5e:44:28:d8:fd:6e:c2:cd:e3:ab:5f:b9:7a:99:42:98:8e:b8:f4:dc:d0:60:16 +-----BEGIN CERTIFICATE----- +MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1 +MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK +EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh +BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq +xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G +87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i +2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U +WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1 +0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G +A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr +pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL +ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm +aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv +hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm +hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X +dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3 +P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y +iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no +xqE= +-----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: O=RSA Security Inc OU=RSA Security 2048 V3 +# Subject: O=RSA Security Inc OU=RSA Security 2048 V3 +# Label: "RSA Security 2048 v3" +# Serial: 13297492616345471454730593562152402946 +# MD5 Fingerprint: 77:0d:19:b1:21:fd:00:42:9c:3e:0c:a5:dd:0b:02:8e +# SHA1 Fingerprint: 25:01:90:19:cf:fb:d9:99:1c:b7:68:25:74:8d:94:5f:30:93:95:42 +# SHA256 Fingerprint: af:8b:67:62:a1:e5:28:22:81:61:a9:5d:5c:55:9e:e2:66:27:8f:75:d7:9e:83:01:89:a5:03:50:6a:bd:6b:4c +-----BEGIN CERTIFICATE----- +MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6 +MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp +dHkgMjA0OCBWMzAeFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAX +BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAy +MDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt49VcdKA3Xtp +eafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7Jylg +/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGl +wSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnh +AMFRD0xS+ARaqn1y07iHKrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2 +PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpu +AWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NR +MKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYc +HnmYv/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/ +Zb5gEydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+ +f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVO +rSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEkllgVsRch +6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kApKnXwiJPZ9d3 +7CAFYd4= +-----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 Global CA 2 O=GeoTrust Inc. +# Subject: CN=GeoTrust Global CA 2 O=GeoTrust Inc. +# Label: "GeoTrust Global CA 2" +# Serial: 1 +# MD5 Fingerprint: 0e:40:a7:6c:de:03:5d:8f:d1:0f:e4:d1:8d:f9:6c:a9 +# SHA1 Fingerprint: a9:e9:78:08:14:37:58:88:f2:05:19:b0:6d:2b:0d:2b:60:16:90:7d +# SHA256 Fingerprint: ca:2d:82:a0:86:77:07:2f:8a:b6:76:4f:f0:35:67:6c:fe:3e:5e:32:5e:01:21:72:df:3f:92:09:6d:b7:9b:85 +-----BEGIN CERTIFICATE----- +MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs +IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg +R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A +PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8 +Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL +TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL +5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7 +S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe +2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap +EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td +EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv +/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN +A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0 +abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF +I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz +4iIprn2DQKi6bA== +-----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=Certum CA O=Unizeto Sp. z o.o. +# Subject: CN=Certum CA O=Unizeto Sp. z o.o. +# Label: "Certum Root CA" +# Serial: 65568 +# MD5 Fingerprint: 2c:8f:9f:66:1d:18:90:b1:47:26:9d:8e:86:82:8c:a9 +# SHA1 Fingerprint: 62:52:dc:40:f7:11:43:a2:2f:de:9e:f7:34:8e:06:42:51:b1:81:18 +# SHA256 Fingerprint: d8:e0:fe:bc:1d:b2:e3:8d:00:94:0f:37:d2:7d:41:34:4d:99:3e:73:4b:99:d5:65:6d:97:78:d4:d8:14:36:24 +-----BEGIN CERTIFICATE----- +MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBM +MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD +QTAeFw0wMjA2MTExMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBM +MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD +QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6xwS7TT3zNJc4YPk/E +jG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdLkKWo +ePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GI +ULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapu +Ob7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg +AKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7 +HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA +uI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQa +TOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTg +xSvgGrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1q +CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x +O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs +6GAqm4VKQPNriiTsBhYscw== +-----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=Secure Certificate Services O=Comodo CA Limited +# Subject: CN=Secure Certificate Services O=Comodo CA Limited +# Label: "Comodo Secure Services root" +# Serial: 1 +# MD5 Fingerprint: d3:d9:bd:ae:9f:ac:67:24:b3:c8:1b:52:e1:b9:a9:bd +# SHA1 Fingerprint: 4a:65:d5:f4:1d:ef:39:b8:b8:90:4a:4a:d3:64:81:33:cf:c7:a1:d1 +# SHA256 Fingerprint: bd:81:ce:3b:4f:65:91:d1:1a:67:b5:fc:7a:47:fd:ef:25:52:1b:f9:aa:4e:18:b9:e3:df:2e:34:a7:80:3b:e8 +-----BEGIN CERTIFICATE----- +MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp +ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow +fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV +BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM +cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S +HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996 +CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk +3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz +6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV +HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud +EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv +Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw +Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww +DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0 +5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj +Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI +gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ +aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl +izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk= +-----END CERTIFICATE----- + +# Issuer: CN=Trusted Certificate Services O=Comodo CA Limited +# Subject: CN=Trusted Certificate Services O=Comodo CA Limited +# Label: "Comodo Trusted Services root" +# Serial: 1 +# MD5 Fingerprint: 91:1b:3f:6e:cd:9e:ab:ee:07:fe:1f:71:d2:b3:61:27 +# SHA1 Fingerprint: e1:9f:e3:0e:8b:84:60:9e:80:9b:17:0d:72:a8:c5:ba:6e:14:09:bd +# SHA256 Fingerprint: 3f:06:e5:56:81:d4:96:f5:be:16:9e:b5:38:9f:9f:2b:8f:f6:1e:17:08:df:68:81:72:48:49:cd:5d:27:cb:69 +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0 +aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla +MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO +BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD +VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW +fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt +TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL +fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW +1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7 +kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G +A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v +ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo +dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu +Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/ +HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 +pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS +jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+ +xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn +dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi +-----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=Staat der Nederlanden Root CA O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden Root CA O=Staat der Nederlanden +# Label: "Staat der Nederlanden Root CA" +# Serial: 10000010 +# MD5 Fingerprint: 60:84:7c:5a:ce:db:0c:d4:cb:a7:e9:fe:02:c6:a9:c0 +# SHA1 Fingerprint: 10:1d:fa:3f:d5:0b:cb:bb:9b:b5:60:0c:19:55:a4:1a:f4:73:3a:04 +# SHA256 Fingerprint: d4:1d:82:9e:8c:16:59:82:2a:f9:3f:ce:62:bf:fc:de:26:4f:c8:4e:8b:95:0c:5f:f2:75:d0:52:35:46:95:a3 +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJO +TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEy +MTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVk +ZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENB +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFtvszn +ExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw71 +9tV2U02PjLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MO +hXeiD+EwR+4A5zN9RGcaC1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+U +tFE5A3+y3qcym7RHjm+0Sq7lr7HcsBthvJly3uSJt3omXdozSVtSnA71iq3DuD3o +BmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn622r+I/q85Ej0ZytqERAh +SQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRVHSAAMDww +OgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMv +cm9vdC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA +7Jbg0zTBLL9s+DANBgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k +/rvuFbQvBgwp8qiSpGEN/KtcCFtREytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzm +eafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbwMVcoEoJz6TMvplW0C5GUR5z6 +u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3ynGQI0DvDKcWy +7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR +iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== +-----END CERTIFICATE----- + +# Issuer: CN=UTN - DATACorp SGC O=The USERTRUST Network OU=http://www.usertrust.com +# Subject: CN=UTN - DATACorp SGC O=The USERTRUST Network OU=http://www.usertrust.com +# Label: "UTN DATACorp SGC Root CA" +# Serial: 91374294542884689855167577680241077609 +# MD5 Fingerprint: b3:a5:3e:77:21:6d:ac:4a:c0:c9:fb:d5:41:3d:ca:06 +# SHA1 Fingerprint: 58:11:9f:0e:12:82:87:ea:50:fd:d9:87:45:6f:4f:78:dc:fa:d6:d4 +# SHA256 Fingerprint: 85:fb:2f:91:dd:12:27:5a:01:45:b6:36:53:4f:84:02:4a:d6:8b:69:b8:ee:88:68:4f:f7:11:37:58:05:b3:48 +-----BEGIN CERTIFICATE----- +MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB +kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw +IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD +VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu +dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 +E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ +D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK +4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq +lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW +bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB +o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT +MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js +LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr +BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB +AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft +Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj +j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH +KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv +2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 +mfnGV/TJVTl4uix5yaaIK/QI +-----END CERTIFICATE----- + +# Issuer: CN=UTN-USERFirst-Hardware O=The USERTRUST Network OU=http://www.usertrust.com +# Subject: CN=UTN-USERFirst-Hardware O=The USERTRUST Network OU=http://www.usertrust.com +# Label: "UTN USERFirst Hardware Root CA" +# Serial: 91374294542884704022267039221184531197 +# MD5 Fingerprint: 4c:56:41:e5:0d:bb:2b:e8:ca:a3:ed:18:08:ad:43:39 +# SHA1 Fingerprint: 04:83:ed:33:99:ac:36:08:05:87:22:ed:bc:5e:46:00:e3:be:f9:d7 +# SHA256 Fingerprint: 6e:a5:47:41:d0:04:66:7e:ed:1b:48:16:63:4a:a3:a7:9e:6e:4b:96:95:0f:82:79:da:fc:8d:9b:d8:81:21:37 +-----BEGIN CERTIFICATE----- +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB +lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt +SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe +MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v +d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh +cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn +0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ +M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a +MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd +oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI +DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy +oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 +dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy +bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF +BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli +CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE +CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t +3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS +KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== +-----END CERTIFICATE----- + +# Issuer: CN=Chambers of Commerce Root O=AC Camerfirma SA CIF A82743287 OU=http://www.chambersign.org +# Subject: CN=Chambers of Commerce Root O=AC Camerfirma SA CIF A82743287 OU=http://www.chambersign.org +# Label: "Camerfirma Chambers of Commerce Root" +# Serial: 0 +# MD5 Fingerprint: b0:01:ee:14:d9:af:29:18:94:76:8e:f1:69:33:2a:84 +# SHA1 Fingerprint: 6e:3a:55:a4:19:0c:19:5c:93:84:3c:c0:db:72:2e:31:30:61:f0:b1 +# SHA256 Fingerprint: 0c:25:8a:12:a5:67:4a:ef:25:f2:8b:a7:dc:fa:ec:ee:a3:48:e5:41:e6:f5:cc:4e:e6:3b:71:b3:61:60:6a:c3 +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn +MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg +b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa +MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB +ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw +IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B +AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb +unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d +BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq +7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 +0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX +roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG +A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j +aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p +26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA +BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud +EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN +BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz +aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB +AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd +p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi +1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc +XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 +eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu +tGWaIZDgqtCYvDi1czyL+Nw= +-----END CERTIFICATE----- + +# Issuer: CN=Global Chambersign Root O=AC Camerfirma SA CIF A82743287 OU=http://www.chambersign.org +# Subject: CN=Global Chambersign Root O=AC Camerfirma SA CIF A82743287 OU=http://www.chambersign.org +# Label: "Camerfirma Global Chambersign Root" +# Serial: 0 +# MD5 Fingerprint: c5:e6:7b:bf:06:d0:4f:43:ed:c4:7a:65:8a:fb:6b:19 +# SHA1 Fingerprint: 33:9b:6b:14:50:24:9b:55:7a:01:87:72:84:d9:e0:2f:c3:d2:d8:e9 +# SHA256 Fingerprint: ef:3c:b4:17:fc:8e:bf:6f:97:87:6c:9e:4e:ce:39:de:1e:a5:fe:64:91:41:d1:02:8b:7d:11:c0:b2:29:8c:ed +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn +MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo +YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9 +MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy +NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G +A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA +A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0 +Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s +QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV +eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795 +B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh +z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T +AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i +ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w +TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH +MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD +VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE +VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh +bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B +AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM +bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi +ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG +VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c +ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/ +AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== +-----END CERTIFICATE----- + +# Issuer: CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado O=NetLock Halozatbiztonsagi Kft. OU=Tanusitvanykiadok +# Subject: CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado O=NetLock Halozatbiztonsagi Kft. OU=Tanusitvanykiadok +# Label: "NetLock Notary (Class A) Root" +# Serial: 259 +# MD5 Fingerprint: 86:38:6d:5e:49:63:6c:85:5c:db:6d:dc:94:b7:d0:f7 +# SHA1 Fingerprint: ac:ed:5f:65:53:fd:25:ce:01:5f:1f:7a:48:3b:6a:74:9f:61:78:c6 +# SHA256 Fingerprint: 7f:12:cd:5f:7e:5e:29:0e:c7:d8:51:79:d5:b7:2c:20:a5:be:75:08:ff:db:5b:f8:1a:b9:68:4a:7f:c9:f6:67 +-----BEGIN CERTIFICATE----- +MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhV +MRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMe +TmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0 +dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFzcyBB +KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oXDTE5MDIxOTIzMTQ0 +N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhC +dWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQu +MRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBL +b3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeLVu0ThEDaiD +zl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX9EUi +3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8 +WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LY +Oph7tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2Esi +NCubMvJIH5+hCoR64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCC +ApswDgYDVR0PAQH/BAQDAgAGMBIGA1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4 +QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZRUxFTSEgRXplbiB0 +YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRhdGFz +aSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu +IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtm +ZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMg +ZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVs +amFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJhc2EgbWVndGFsYWxoYXRv +IGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBzOi8vd3d3 +Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6 +ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1 +YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3Qg +dG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRs +b2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNAbmV0bG9jay5uZXQuMA0G +CSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5ayZrU3/b39/zcT0mwBQO +xmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjPytoUMaFP +0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQ +QeJBCWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxk +f1qbFFgBJ34TUMdrKuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK +8CtmdWOMovsEPoMOmzbwGOQmIMOM8CgHrTwXZoi1/baI +-----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: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing +# Subject: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing +# Label: "StartCom Certification Authority" +# Serial: 1 +# MD5 Fingerprint: 22:4d:8f:8a:fc:f7:35:c2:bb:57:34:90:7b:8b:22:16 +# SHA1 Fingerprint: 3e:2b:f7:f2:03:1b:96:f3:8c:e6:c4:d8:a8:5d:3e:2d:58:47:6a:0f +# SHA256 Fingerprint: c7:66:a9:be:f2:d4:07:1c:86:3a:31:aa:49:20:e8:13:b2:d1:98:60:8c:b7:b7:cf:e2:11:43:b8:36:df:09:ea +-----BEGIN CERTIFICATE----- +MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW +MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg +Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 +MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi +U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh +cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk +pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf +OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C +Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT +Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi +HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM +Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w ++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ +Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 +Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B +26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID +AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE +FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j +ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js +LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM +BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 +Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy +dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh +cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh +YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg +dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp +bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ +YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT +TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ +9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 +jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW +FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz +ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 +ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L +EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu +L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq +yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC +O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V +um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh +NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= +-----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=Swisscom Root CA 1 O=Swisscom OU=Digital Certificate Services +# Subject: CN=Swisscom Root CA 1 O=Swisscom OU=Digital Certificate Services +# Label: "Swisscom Root CA 1" +# Serial: 122348795730808398873664200247279986742 +# MD5 Fingerprint: f8:38:7c:77:88:df:2c:16:68:2e:c2:e2:52:4b:b8:f9 +# SHA1 Fingerprint: 5f:3a:fc:0a:8b:64:f6:86:67:34:74:df:7e:a9:a2:fe:f9:fa:7a:51 +# SHA256 Fingerprint: 21:db:20:12:36:60:bb:2e:d4:18:20:5d:a1:1e:e7:a8:5a:65:e2:bc:6e:55:b5:af:7e:78:99:c8:a2:66:d9:2e +-----BEGIN CERTIFICATE----- +MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBk +MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 +YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg +Q0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4MTgyMjA2MjBaMGQxCzAJBgNVBAYT +AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp +Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9 +m2BtRsiMMW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdih +FvkcxC7mlSpnzNApbjyFNDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/ +TilftKaNXXsLmREDA/7n29uj/x2lzZAeAR81sH8A25Bvxn570e56eqeqDFdvpG3F +EzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkCb6dJtDZd0KTeByy2dbco +kdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn7uHbHaBu +HYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNF +vJbNcA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo +19AOeCMgkckkKmUpWyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjC +L3UcPX7ape8eYIVpQtPM+GP+HkM5haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJW +bjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNYMUJDLXT5xp6mig/p/r+D5kNX +JLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw +FDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j +BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzc +K6FptWfUjNP9MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzf +ky9NfEBWMXrrpA9gzXrzvsMnjgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7Ik +Vh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQMbFamIp1TpBcahQq4FJHgmDmHtqB +sfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4HVtA4oJVwIHaM190e +3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtlvrsR +ls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ip +mXeascClOS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HH +b6D0jqTsNFFbjCYDcKF31QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksf +rK/7DZBaZmBwXarNeNQk7shBoJMBkpxqnvy5JMWzFYJ+vq6VK+uxwNrjAWALXmms +hFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCyx/yP2FS1k2Kdzs9Z+z0Y +zirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMWNY6E0F/6 +MBr1mmz0DlP5OlvRHA== +-----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=DST ACES CA X6 O=Digital Signature Trust OU=DST ACES +# Subject: CN=DST ACES CA X6 O=Digital Signature Trust OU=DST ACES +# Label: "DST ACES CA X6" +# Serial: 17771143917277623872238992636097467865 +# MD5 Fingerprint: 21:d8:4c:82:2b:99:09:33:a2:eb:14:24:8d:8e:5f:e8 +# SHA1 Fingerprint: 40:54:da:6f:1c:3f:40:74:ac:ed:0f:ec:cd:db:79:d1:53:fb:90:1d +# SHA256 Fingerprint: 76:7c:95:5a:76:41:2c:89:af:68:8e:90:a1:c7:0f:55:6c:fd:6b:60:25:db:ea:10:41:6d:7e:b6:83:1f:8c:40 +-----BEGIN CERTIFICATE----- +MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBb +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3Qx +ETAPBgNVBAsTCERTVCBBQ0VTMRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0w +MzExMjAyMTE5NThaFw0xNzExMjAyMTE5NThaMFsxCzAJBgNVBAYTAlVTMSAwHgYD +VQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UECxMIRFNUIEFDRVMx +FzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPu +ktKe1jzIDZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7 +gLFViYsx+tC3dr5BPTCapCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZH +fAjIgrrep4c9oW24MFbCswKBXy314powGCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4a +ahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPyMjwmR/onJALJfh1biEIT +ajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rk +c3QuY29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjto +dHRwOi8vd3d3LnRydXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMt +aW5kZXguaHRtbDAdBgNVHQ4EFgQUCXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZI +hvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V25FYrnJmQ6AgwbN99Pe7lv7Uk +QIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6tFr8hlxCBPeP/ +h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq +nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpR +rscL9yuwNwXsvFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf2 +9w4LTJxoeHtxMcfrHuBnQfO3oKfN5XozNmr6mis= +-----END CERTIFICATE----- + +# Issuer: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı O=(c) 2005 TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. +# Subject: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı O=(c) 2005 TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. +# Label: "TURKTRUST Certificate Services Provider Root 1" +# Serial: 1 +# MD5 Fingerprint: f1:6a:22:18:c9:cd:df:ce:82:1d:1d:b7:78:5c:a9:a5 +# SHA1 Fingerprint: 79:98:a3:08:e1:4d:65:85:e6:c2:1e:15:3a:71:9f:ba:5a:d3:4a:d9 +# SHA256 Fingerprint: 44:04:e3:3b:5e:14:0d:cf:99:80:51:fd:fc:80:28:c7:c8:16:15:c5:ee:73:7b:11:1b:58:82:33:a9:b5:35:a0 +-----BEGIN CERTIFICATE----- +MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOc +UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx +c8SxMQswCQYDVQQGDAJUUjEPMA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykg +MjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 +dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMxMDI3MTdaFw0xNTAz +MjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2Vy +dGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYD +VQQHDAZBTktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kg +xLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEu +xZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7 +XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GXyGl8hMW0kWxsE2qkVa2k +heiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8iSi9BB35J +YbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5C +urKZ8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1 +JuTm5Rh8i27fbMx4W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51 +b0dewQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV +9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46sWrv7/hg0Uw2ZkUd82YCdAR7 +kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxEq8Sn5RTOPEFh +fEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy +B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdA +aLX/7KfS0zgYnNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKS +RGQDJereW26fyfJOrN3H +-----END CERTIFICATE----- + +# Issuer: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Kasım 2005 +# Subject: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Kasım 2005 +# Label: "TURKTRUST Certificate Services Provider Root 2" +# Serial: 1 +# MD5 Fingerprint: 37:a5:6e:d4:b1:25:84:97:b7:fd:56:15:7a:f9:a2:00 +# SHA1 Fingerprint: b4:35:d4:e1:11:9d:1c:66:90:a7:49:eb:b3:94:bd:63:7b:a7:82:b7 +# SHA256 Fingerprint: c4:70:cf:54:7e:23:02:b9:77:fb:29:dd:71:a8:9a:7b:6c:1f:60:77:7b:03:29:f5:60:17:f3:28:bf:4f:6b:e6 +-----BEGIN CERTIFICATE----- +MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOc +UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx +c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xS +S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg +SGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcNMDUxMTA3MTAwNzU3 +WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVrdHJv +bmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJU +UjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSw +bGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWe +LiAoYykgS2FzxLFtIDIwMDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqeLCDe2JAOCtFp0if7qnef +J1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKIx+XlZEdh +R3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJ +Qv2gQrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGX +JHpsmxcPbe9TmJEr5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1p +zpwACPI2/z7woQ8arBT9pmAPAgMBAAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58S +Fq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/nttRbj2hWyfIvwq +ECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 +Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFz +gw2lGh1uEpJ+hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotH +uFEJjOp9zYhys2AzsfAKRO8P9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LS +y3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5UrbnBEI= +-----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----- +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV +BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln +biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF +MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT +d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 +76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ +bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c +6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE +emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd +MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt +MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y +MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y +FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi +aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM +gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB +qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 +lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn +8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 +45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO +UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 +O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC +bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv +GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a +77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC +hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 +92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp +Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w +ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt +Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ +-----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----- +MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE +BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu +IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow +RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY +U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv +Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br +YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF +nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH +6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt +eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/ +c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ +MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH +HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf +jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6 +5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB +rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU +F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c +wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 +cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB +AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp +WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9 +xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ +2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ +IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8 +aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X +em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR +dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/ +OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+ +hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy +tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u +-----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=WellsSecure Public Root Certificate Authority O=Wells Fargo WellsSecure OU=Wells Fargo Bank NA +# Subject: CN=WellsSecure Public Root Certificate Authority O=Wells Fargo WellsSecure OU=Wells Fargo Bank NA +# Label: "WellsSecure Public Root Certificate Authority" +# Serial: 1 +# MD5 Fingerprint: 15:ac:a5:c2:92:2d:79:bc:e8:7f:cb:67:ed:02:cf:36 +# SHA1 Fingerprint: e7:b4:f6:9d:61:ec:90:69:db:7e:90:a7:40:1a:3c:f4:7d:4f:e8:ee +# SHA256 Fingerprint: a7:12:72:ae:aa:a3:cf:e8:72:7f:7f:b3:9f:0f:b3:d1:e5:42:6e:90:60:b0:6e:e6:f1:3e:9a:3c:58:33:cd:43 +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMx +IDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxs +cyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9v +dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcxMjEzMTcwNzU0WhcNMjIxMjE0 +MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdl +bGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQD +DC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+r +WxxTkqxtnt3CxC5FlAM1iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjU +Dk/41itMpBb570OYj7OeUt9tkTmPOL13i0Nj67eT/DBMHAGTthP796EfvyXhdDcs +HqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8bJVhHlfXBIEyg1J55oNj +z7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiBK0HmOFaf +SZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/Slwxl +AgMBAAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqG +KGh0dHA6Ly9jcmwucGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0P +AQH/BAQDAgHGMB0GA1UdDgQWBBQmlRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0j +BIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGBi6SBiDCBhTELMAkGA1UEBhMC +VVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNX +ZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEB +ALkVsUSRzCPIK0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd +/ZDJPHV3V3p9+N701NX3leZ0bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pB +A4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSljqHyita04pO2t/caaH/+Xc/77szWn +k4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+esE2fDbbFwRnzVlhE9 +iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJtylv +2G0xffX8oRAHh84vWdw+WNs= +-----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=IGC/A O=PM/SGDN OU=DCSSI +# Subject: CN=IGC/A O=PM/SGDN OU=DCSSI +# Label: "IGC/A" +# Serial: 245102874772 +# MD5 Fingerprint: 0c:7f:dd:6a:f4:2a:b9:c8:9b:bd:20:7e:a9:db:5c:37 +# SHA1 Fingerprint: 60:d6:89:74:b5:c2:65:9e:8a:0f:c1:88:7c:88:d2:46:69:1b:18:2c +# SHA256 Fingerprint: b9:be:a7:86:0a:96:2e:a3:61:1d:ab:97:ab:6d:a3:e2:1c:10:68:b9:7d:55:57:5e:d0:e1:12:79:c1:1c:89:32 +-----BEGIN CERTIFICATE----- +MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYT +AkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQ +TS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG +9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMB4XDTAyMTIxMzE0MjkyM1oXDTIw +MTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAM +BgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEO +MAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2 +LmZyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaI +s9z4iPf930Pfeo2aSVz2TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2 +xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCWSo7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4 +u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYyHF2fYPepraX/z9E0+X1b +F8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNdfrGoRpAx +Vs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGd +PDPQtQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNV +HSAEDjAMMAoGCCqBegF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAx +NjAfBgNVHSMEGDAWgBSjBS8YYFDCiQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUF +AAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RKq89toB9RlPhJy3Q2FLwV3duJ +L92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3QMZsyK10XZZOY +YLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg +Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2a +NjSaTFR+FwNIlQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R +0982gaEbeC9xs/FZTEYYKKuF0mBWWg== +-----END CERTIFICATE----- + +# Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication EV RootCA1 +# Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication EV RootCA1 +# Label: "Security Communication EV RootCA1" +# Serial: 0 +# MD5 Fingerprint: 22:2d:a6:01:ea:7c:0a:f7:f0:6c:56:43:3f:77:76:d3 +# SHA1 Fingerprint: fe:b8:c4:32:dc:f9:76:9a:ce:ae:3d:d8:90:8f:fd:28:86:65:64:7d +# SHA256 Fingerprint: a2:2d:ba:68:1e:97:37:6e:2d:39:7d:72:8a:ae:3a:9b:62:96:b9:fd:ba:60:bc:2e:11:f6:47:f2:c6:75:fb:37 +-----BEGIN CERTIFICATE----- +MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMh +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIz +MloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09N +IFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNlY3VyaXR5IENvbW11 +bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSE +RMqm4miO/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gO +zXppFodEtZDkBp2uoQSXWHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5 +bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4zZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDF +MxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4bepJz11sS6/vmsJWXMY1 +VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK9U2vP9eC +OKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HW +tWS3irO4G8za+6xmiEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZ +q51ihPZRwSzJIxXYKLerJRO1RuGGAv8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDb +EJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnWmHyojf6GPgcWkuF75x3sM3Z+ +Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEWT1MKZPlO9L9O +VL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 +-----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=Microsec e-Szigno Root CA O=Microsec Ltd. OU=e-Szigno CA +# Subject: CN=Microsec e-Szigno Root CA O=Microsec Ltd. OU=e-Szigno CA +# Label: "Microsec e-Szigno Root CA" +# Serial: 272122594155480254301341951808045322001 +# MD5 Fingerprint: f0:96:b6:2f:c5:10:d5:67:8e:83:25:32:e8:5e:2e:e5 +# SHA1 Fingerprint: 23:88:c9:d3:71:cc:9e:96:3d:ff:7d:3c:a7:ce:fc:d6:25:ec:19:0d +# SHA256 Fingerprint: 32:7a:3d:76:1a:ba:de:a0:34:eb:99:84:06:27:5c:b1:a4:77:6e:fd:ae:2f:df:6d:01:68:ea:1c:4f:55:67:d0 +-----BEGIN CERTIFICATE----- +MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAw +cjELMAkGA1UEBhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNy +b3NlYyBMdGQuMRQwEgYDVQQLEwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9z +ZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0MDYxMjI4NDRaFw0xNzA0MDYxMjI4 +NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEWMBQGA1UEChMN +TWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMTGU1p +Y3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2u +uO/TEdyB5s87lozWbxXGd36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+ +LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/NoqdNAoI/gqyFxuEPkEeZlApxcpMqyabA +vjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjcQR/Ji3HWVBTji1R4P770 +Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJPqW+jqpx +62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcB +AQRbMFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3Aw +LQYIKwYBBQUHMAKGIWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAP +BgNVHRMBAf8EBTADAQH/MIIBcwYDVR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIB +AQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3LmUtc3ppZ25vLmh1L1NaU1ov +MIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0AdAB2AOEAbgB5 +ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn +AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABT +AHoAbwBsAGcA4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABh +ACAAcwB6AGUAcgBpAG4AdAAgAGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABo +AHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMAegBpAGcAbgBvAC4AaAB1AC8AUwBa +AFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6Ly93d3cuZS1zemln +bm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NOPU1p +Y3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxP +PU1pY3Jvc2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZv +Y2F0aW9uTGlzdDtiaW5hcnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuB +EGluZm9AZS1zemlnbm8uaHWkdzB1MSMwIQYDVQQDDBpNaWNyb3NlYyBlLVN6aWdu +w7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhTWjEWMBQGA1UEChMNTWlj +cm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhVMIGsBgNV +HSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJI +VTERMA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDAS +BgNVBAsTC2UtU3ppZ25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBS +b290IENBghEAzLjnv04pGv2i3GalHCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS +8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMTnGZjWS7KXHAM/IO8VbH0jgds +ZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FEaGAHQzAxQmHl +7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a +86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfR +hUZLphK3dehKyVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/ +MPMMNz7UwiiAc7EBt51alhQBS6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= +-----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=TC TrustCenter Class 2 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 2 CA +# Subject: CN=TC TrustCenter Class 2 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 2 CA +# Label: "TC TrustCenter Class 2 CA II" +# Serial: 941389028203453866782103406992443 +# MD5 Fingerprint: ce:78:33:5c:59:78:01:6e:18:ea:b9:36:a0:b9:2e:23 +# SHA1 Fingerprint: ae:50:83:ed:7c:f4:5c:bc:8f:61:c6:21:fe:68:5d:79:42:21:15:6e +# SHA256 Fingerprint: e6:b8:f8:76:64:85:f8:07:ae:7f:8d:ac:16:70:46:1f:07:c0:a1:3e:ef:3a:1f:f7:17:53:8d:7a:ba:d3:91:b4 +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjEL +MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV +BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 +Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYwMTEyMTQzODQzWhcNMjUxMjMxMjI1 +OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i +SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UEAxMc +VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jf +tMjWQ+nEdVl//OEd+DFwIxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKg +uNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2J +XjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQXa7pIXSSTYtZgo+U4+lK +8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7uSNQZu+99 +5OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3 +kUrL84J6E1wIqzCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy +dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6 +Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz +JTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 +Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u +TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iS +GNn3Bzn1LL4GdXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprt +ZjluS5TmVfwLG4t3wVMTZonZKNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8 +au0WOB9/WIFaGusyiC2y8zl3gK9etmF1KdsjTYjKUCjLhdLTEKJZbtOTVAB6okaV +hgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kPJOzHdiEoZa5X6AeI +dUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfkvQ== +-----END CERTIFICATE----- + +# Issuer: CN=TC TrustCenter Universal CA I O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA +# Subject: CN=TC TrustCenter Universal CA I O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA +# Label: "TC TrustCenter Universal CA I" +# Serial: 601024842042189035295619584734726 +# MD5 Fingerprint: 45:e1:a5:72:c5:a9:36:64:40:9e:f5:e4:58:84:67:8c +# SHA1 Fingerprint: 6b:2f:34:ad:89:58:be:62:fd:b0:6b:5c:ce:bb:9d:d9:4f:4e:39:f3 +# SHA256 Fingerprint: eb:f3:c0:2a:87:89:b1:fb:7d:51:19:95:d6:63:b7:29:06:d9:13:ce:0d:5e:10:56:8a:8a:77:e2:58:61:67:e7 +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTEL +MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV +BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1 +c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcNMDYwMzIyMTU1NDI4WhcNMjUxMjMx +MjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIg +R21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYwJAYD +VQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSR +JJZ4Hgmgm5qVSkr1YnwCqMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3T +fCZdzHd55yx4Oagmcw6iXSVphU9VDprvxrlE4Vc93x9UIuVvZaozhDrzznq+VZeu +jRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtwag+1m7Z3W0hZneTvWq3z +wZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9OgdwZu5GQ +fezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYD +VR0jBBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0G +CSqGSIb3DQEBBQUAA4IBAQAo0uCG1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X1 +7caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/CyvwbZ71q+s2IhtNerNXxTPqYn +8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3ghUJGooWMNjs +ydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT +ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/ +2TYcuiUaUj0a7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY +-----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=ComSign Secured CA O=ComSign +# Subject: CN=ComSign Secured CA O=ComSign +# Label: "ComSign Secured CA" +# Serial: 264725503855295744117309814499492384489 +# MD5 Fingerprint: 40:01:25:06:8d:21:43:6a:0e:43:00:9c:e7:43:f3:d5 +# SHA1 Fingerprint: f9:cd:0e:2c:da:76:24:c1:8f:bd:f0:f0:ab:b6:45:b8:f7:fe:d5:7a +# SHA256 Fingerprint: 50:79:41:c7:44:60:a0:b4:70:86:22:0d:4e:99:32:57:2a:b5:d1:b5:bb:cb:89:80:ab:1c:b1:76:51:a8:44:d2 +-----BEGIN CERTIFICATE----- +MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAw +PDEbMBkGA1UEAxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWdu +MQswCQYDVQQGEwJJTDAeFw0wNDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwx +GzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjEL +MAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGtWhf +HZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs49oh +gHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sW +v+bznkqH7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ue +Mv5WJDmyVIRD9YTC2LxBkMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr +9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d19guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt +6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUwAwEB/zBEBgNVHR8EPTA7 +MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29tU2lnblNl +Y3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58 +ADsAj8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkq +hkiG9w0BAQUFAAOCAQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7p +iL1DRYHjZiM/EoZNGeQFsOY3wo3aBijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtC +dsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtpFhpFfTMDZflScZAmlaxMDPWL +kz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP51qJThRv4zdL +hfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz +OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== +-----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: CN=TÜBİTAK UEKAE Kök Sertifika Hizmet Sağlayıcısı - Sürüm 3 O=Türkiye Bilimsel ve Teknolojik Araştırma Kurumu - TÜBİTAK OU=Ulusal Elektronik ve Kriptoloji Araştırma Enstitüsü - UEKAE/Kamu Sertifikasyon Merkezi +# Subject: CN=TÜBİTAK UEKAE Kök Sertifika Hizmet Sağlayıcısı - Sürüm 3 O=Türkiye Bilimsel ve Teknolojik Araştırma Kurumu - TÜBİTAK OU=Ulusal Elektronik ve Kriptoloji Araştırma Enstitüsü - UEKAE/Kamu Sertifikasyon Merkezi +# Label: "T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3" +# Serial: 17 +# MD5 Fingerprint: ed:41:f5:8c:50:c5:2b:9c:73:e6:ee:6c:eb:c2:a8:26 +# SHA1 Fingerprint: 1b:4b:39:61:26:27:6b:64:91:a2:68:6d:d7:02:43:21:2d:1f:1d:96 +# SHA256 Fingerprint: e4:c7:34:30:d7:a5:b5:09:25:df:43:37:0a:0d:21:6e:9a:79:b9:d6:db:83:73:a0:c6:9e:b1:cc:31:c7:c5:2a +-----BEGIN CERTIFICATE----- +MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRS +MRgwFgYDVQQHDA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJp +bGltc2VsIHZlIFRla25vbG9qaWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSw +VEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ryb25payB2ZSBLcmlwdG9sb2ppIEFy +YcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNVBAsMGkthbXUgU2Vy +dGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUgS8O2 +ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAe +Fw0wNzA4MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIx +GDAWBgNVBAcMD0dlYnplIC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmls +aW1zZWwgdmUgVGVrbm9sb2ppayBBcmHFn3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBU +QUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZlIEtyaXB0b2xvamkgQXJh +xZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2FtdSBTZXJ0 +aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7Zr +IFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4h +gb46ezzb8R1Sf1n68yJMlaCQvEhOEav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yK +O7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1xnnRFDDtG1hba+818qEhTsXO +fJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR6Oqeyjh1jmKw +lZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL +hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQID +AQABo0IwQDAdBgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/ +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmP +NOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4N5EY3ATIZJkrGG2AA1nJrvhY0D7t +wyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLTy9LQQfMmNkqblWwM +7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYhLBOh +gLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5n +oN+J1q2MdqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUs +yZyQ2uypQjyttgI= +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 2 CA 1 O=Buypass AS-983163327 +# Subject: CN=Buypass Class 2 CA 1 O=Buypass AS-983163327 +# Label: "Buypass Class 2 CA 1" +# Serial: 1 +# MD5 Fingerprint: b8:08:9a:f0:03:cc:1b:0d:c8:6c:0b:76:a1:75:64:23 +# SHA1 Fingerprint: a0:a1:ab:90:c9:fc:84:7b:3b:12:61:e8:97:7d:5f:d3:22:61:d3:cc +# SHA256 Fingerprint: 0f:4e:9c:dd:26:4b:02:55:50:d1:70:80:63:40:21:4f:e9:44:34:c9:b0:2f:69:7e:c7:10:fc:5f:ea:fb:5e:38 +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg +Q2xhc3MgMiBDQSAxMB4XDTA2MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzEL +MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD +VQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7McXA0 +ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLX +l18xoS830r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVB +HfCuuCkslFJgNJQ72uA40Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B +5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/RuFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3 +WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0PAQH/BAQD +AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLP +gcIV1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+ +DKhQ7SLHrQVMdvvt7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKu +BctN518fV4bVIJwo+28TOPX2EZL2fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHs +h7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5wwDX3OaJdZtB7WZ+oRxKaJyOk +LY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 3 CA 1 O=Buypass AS-983163327 +# Subject: CN=Buypass Class 3 CA 1 O=Buypass AS-983163327 +# Label: "Buypass Class 3 CA 1" +# Serial: 2 +# MD5 Fingerprint: df:3c:73:59:81:e7:39:50:81:04:4c:34:a2:cb:b3:7b +# SHA1 Fingerprint: 61:57:3a:11:df:0e:d8:7e:d5:92:65:22:ea:d0:56:d7:44:b3:23:71 +# SHA256 Fingerprint: b7:b1:2b:17:1f:82:1d:aa:99:0c:d0:fe:50:87:b1:28:44:8b:a8:e5:18:4f:84:c5:1e:02:b5:c8:fb:96:2b:24 +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg +Q2xhc3MgMyBDQSAxMB4XDTA1MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzEL +MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD +VQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKxifZg +isRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//z +NIqeKNc0n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI ++MkcVyzwPX6UvCWThOiaAJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2R +hzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+ +mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0PAQH/BAQD +AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFP +Bdy7pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27s +EzNxZy5p+qksP2bAEllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2 +mSlf56oBzKwzqBwKu5HEA6BvtjT5htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yC +e/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQjel/wroQk5PMr+4okoyeYZdow +dXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 +-----END CERTIFICATE----- + +# Issuer: CN=EBG Elektronik Sertifika Hizmet Sağlayıcısı O=EBG Bilişim Teknolojileri ve Hizmetleri A.Ş. +# Subject: CN=EBG Elektronik Sertifika Hizmet Sağlayıcısı O=EBG Bilişim Teknolojileri ve Hizmetleri A.Ş. +# Label: "EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1" +# Serial: 5525761995591021570 +# MD5 Fingerprint: 2c:20:26:9d:cb:1a:4a:00:85:b5:b7:5a:ae:c2:01:37 +# SHA1 Fingerprint: 8c:96:ba:eb:dd:2b:07:07:48:ee:30:32:66:a0:f3:98:6e:7c:ae:58 +# SHA256 Fingerprint: 35:ae:5b:dd:d8:f7:ae:63:5c:ff:ba:56:82:a8:f0:0b:95:f4:84:62:c7:10:8e:e9:a0:e5:29:2b:07:4a:af:b2 +-----BEGIN CERTIFICATE----- +MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNV +BAMML0VCRyBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx +c8SxMTcwNQYDVQQKDC5FQkcgQmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXpt +ZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAeFw0wNjA4MTcwMDIxMDlaFw0xNjA4 +MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25payBTZXJ0aWZpa2Eg +SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2ltIFRl +a25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h +4fuXd7hxlugTlkaDT7byX3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAk +tiHq6yOU/im/+4mRDGSaBUorzAzu8T2bgmmkTPiab+ci2hC6X5L8GCcKqKpE+i4s +tPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfreYteIAbTdgtsApWjluTL +dlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZTqNGFav4 +c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8Um +TDGyY5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z ++kI2sSXFCjEmN1ZnuqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0O +Lna9XvNRiYuoP1Vzv9s6xiQFlpJIqkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMW +OeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vmExH8nYQKE3vwO9D8owrXieqW +fo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0Nokb+Clsi7n2 +l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgw +FoAU587GT/wWZ5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+ +8ygjdsZs93/mQJ7ANtyVDR2tFcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI +6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgmzJNSroIBk5DKd8pNSe/iWtkqvTDO +TLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64kXPBfrAowzIpAoHME +wfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqTbCmY +Iai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJn +xk1Gj7sURT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4Q +DgZxGhBM/nV+/x5XOULK1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9q +Kd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11t +hie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQY9iJSrSq3RZj9W6+YKH4 +7ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9AahH3eU7 +QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT +-----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=CNNIC ROOT O=CNNIC +# Subject: CN=CNNIC ROOT O=CNNIC +# Label: "CNNIC ROOT" +# Serial: 1228079105 +# MD5 Fingerprint: 21:bc:82:ab:49:c4:13:3b:4b:b2:2b:5c:6b:90:9c:19 +# SHA1 Fingerprint: 8b:af:4c:9b:1d:f0:2a:92:f7:da:12:8e:b9:1b:ac:f4:98:60:4b:6f +# SHA256 Fingerprint: e2:83:93:77:3d:a8:45:a6:79:f2:08:0c:c7:fb:44:a3:b7:a1:c3:79:2c:b7:eb:77:29:fd:cb:6a:8d:99:ae:a7 +-----BEGIN CERTIFICATE----- +MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJD +TjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2 +MDcwOTE0WhcNMjcwNDE2MDcwOTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMF +Q05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzDo+/hn7E7SIX1mlwh +IhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tizVHa6 +dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZO +V/kbZKKTVrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrC +GHn2emU1z5DrvTOTn1OrczvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gN +v7Sg2Ca+I19zN38m5pIEo3/PIKe38zrKy5nLAgMBAAGjczBxMBEGCWCGSAGG+EIB +AQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscCwQ7vptU7ETAPBgNVHRMB +Af8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991SlgrHAsEO +76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnK +OOK5Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvH +ugDnuL8BV8F3RTIMO/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7Hgvi +yJA/qIYM/PmLXoXLT1tLYhFHxUV8BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fL +buXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2G8kS1sHNzYDzAgE8yGnLRUhj +2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5mmxE= +-----END CERTIFICATE----- + +# Issuer: O=Japanese Government OU=ApplicationCA +# Subject: O=Japanese Government OU=ApplicationCA +# Label: "ApplicationCA - Japanese Government" +# Serial: 49 +# MD5 Fingerprint: 7e:23:4e:5b:a7:a5:b4:25:e9:00:07:74:11:62:ae:d6 +# SHA1 Fingerprint: 7f:8a:b0:cf:d0:51:87:6a:66:f3:36:0f:47:c8:8d:8c:d3:35:fc:74 +# SHA256 Fingerprint: 2d:47:43:7d:e1:79:51:21:5a:12:f3:c5:8e:51:c7:29:a5:80:26:ef:1f:cc:0a:5f:b3:d9:dc:01:2f:60:0d:19 +-----BEGIN CERTIFICATE----- +MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEc +MBoGA1UEChMTSmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRp +b25DQTAeFw0wNzEyMTIxNTAwMDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYT +AkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zlcm5tZW50MRYwFAYDVQQLEw1BcHBs +aWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp23gdE6H +j6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4fl+K +f5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55 +IrmTwcrNwVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cw +FO5cjFW6WY2H/CPek9AEjP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDiht +QWEjdnjDuGWk81quzMKq2edY3rZ+nYVunyoKb58DKTCXKB28t89UKU5RMfkntigm +/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRUWssmP3HMlEYNllPqa0jQ +k/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNVBAYTAkpQ +MRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOC +seODvOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADlqRHZ3ODrso2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJ +hyzjVOGjprIIC8CFqMjSnHH2HZ9g/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+ +eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYDio+nEhEMy/0/ecGc/WLuo89U +DNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmWdupwX3kSa+Sj +B1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL +rosot4LKGAfmt1t06SAZf7IbiVQ= +-----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őtanúsítvány O=NetLock Kft. OU=Tanúsítványkiadók (Certification Services) +# Subject: CN=NetLock Arany (Class Gold) Főtanúsítvány O=NetLock Kft. OU=Tanúsítványkiadók (Certification Services) +# Label: "NetLock Arany (Class Gold) Főtanúsítvány" +# 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=CA Disig O=Disig a.s. +# Subject: CN=CA Disig O=Disig a.s. +# Label: "CA Disig" +# Serial: 1 +# MD5 Fingerprint: 3f:45:96:39:e2:50:87:f7:bb:fe:98:0c:3c:20:98:e6 +# SHA1 Fingerprint: 2a:c8:d5:8b:57:ce:bf:2f:49:af:f2:fc:76:8f:51:14:62:90:7a:41 +# SHA256 Fingerprint: 92:bf:51:19:ab:ec:ca:d0:b1:33:2d:c4:e1:d0:5f:ba:75:b5:67:90:44:ee:0c:a2:6e:93:1f:74:4f:2f:33:cf +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzET +MBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UE +AxMIQ0EgRGlzaWcwHhcNMDYwMzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQsw +CQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcg +YS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgmGErE +Nx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnX +mjxUizkDPw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYD +XcDtab86wYqg6I7ZuUUohwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhW +S8+2rT+MitcE5eN4TPWGqvWP+j1scaMtymfraHtuM6kMgiioTGohQBUgDCZbg8Kp +FhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8wgfwwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0PAQH/BAQD +AgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cu +ZGlzaWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5z +ay9jYS9jcmwvY2FfZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2sv +Y2EvY3JsL2NhX2Rpc2lnLmNybDAaBgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEw +DQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59tWDYcPQuBDRIrRhCA/ec8J9B6 +yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3mkkp7M5+cTxq +EEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ +CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeB +EicTXxChds6KezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFN +PGO+I++MzVpQuGhU+QqZMxEA4Z7CRneC9VkGjCFMhwnN5ag= +-----END CERTIFICATE----- + +# Issuer: CN=Juur-SK O=AS Sertifitseerimiskeskus +# Subject: CN=Juur-SK O=AS Sertifitseerimiskeskus +# Label: "Juur-SK" +# Serial: 999181308 +# MD5 Fingerprint: aa:8e:5d:d9:f8:db:0a:58:b7:8d:26:87:6c:82:35:55 +# SHA1 Fingerprint: 40:9d:4b:d9:17:b5:5c:27:b6:9b:64:cb:98:22:44:0d:cd:09:b8:89 +# SHA256 Fingerprint: ec:c3:e9:c3:40:75:03:be:e0:91:aa:95:2f:41:34:8f:f8:8b:aa:86:3b:22:64:be:fa:c8:07:90:15:74:e9:39 +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcN +AQkBFglwa2lAc2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZp +dHNlZXJpbWlza2Vza3VzMRAwDgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMw +MVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMQsw +CQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEQ +MA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOB +SvZiF3tfTQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkz +ABpTpyHhOEvWgxutr2TC+Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvH +LCu3GFH+4Hv2qEivbDtPL+/40UceJlfwUR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMP +PbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDaTpxt4brNj3pssAki14sL +2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQFMAMBAf8w +ggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwIC +MIHDHoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDk +AGwAagBhAHMAdABhAHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0 +AHMAZQBlAHIAaQBtAGkAcwBrAGUAcwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABz +AGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABrAGkAbgBuAGkAdABhAG0AaQBz +AGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nwcy8wKwYDVR0f +BCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE +FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcY +P2/v6X2+MA4GA1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOi +CfP+JmeaUOTDBS8rNXiRTHyoERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+g +kcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyLabVAyJRld/JXIWY7zoVAtjNjGr95 +HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678IIbsSt4beDI3poHS +na9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkhMp6q +qIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0Z +TbvGRNs2yyqcjg== +-----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=ACEDICOM Root O=EDICOM OU=PKI +# Subject: CN=ACEDICOM Root O=EDICOM OU=PKI +# Label: "ACEDICOM Root" +# Serial: 7029493972724711941 +# MD5 Fingerprint: 42:81:a0:e2:1c:e3:55:10:de:55:89:42:65:96:22:e6 +# SHA1 Fingerprint: e0:b4:32:2e:b2:f6:a5:68:b6:54:53:84:48:18:4a:50:36:87:43:84 +# SHA256 Fingerprint: 03:95:0f:b4:9a:53:1f:3e:19:91:94:23:98:df:a9:e0:ea:32:d7:ba:1c:dd:9b:c8:5d:b5:7e:d9:40:0b:43:4a +-----BEGIN CERTIFICATE----- +MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UE +AwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00x +CzAJBgNVBAYTAkVTMB4XDTA4MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEW +MBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZF +RElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC +AgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHkWLn7 +09gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7 +XBZXehuDYAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5P +Grjm6gSSrj0RuVFCPYewMYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAK +t0SdE3QrwqXrIhWYENiLxQSfHY9g5QYbm8+5eaA9oiM/Qj9r+hwDezCNzmzAv+Yb +X79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbkHQl/Sog4P75n/TSW9R28 +MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTTxKJxqvQU +fecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI +2Sf23EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyH +K9caUPgn6C9D4zq92Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEae +ZAwUswdbxcJzbPEHXEUkFDWug/FqTYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAP +BgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz4SsrSbbXc6GqlPUB53NlTKxQ +MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU9QHnc2VMrFAw +RAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv +bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWIm +fQwng4/F9tqgaHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3 +gvoFNTPhNahXwOf9jU8/kzJPeGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKe +I6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1PwkzQSulgUV1qzOMPPKC8W64iLgpq0i +5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1ThCojz2GuHURwCRi +ipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oIKiMn +MCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZ +o5NjEFIqnxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6 +zqylfDJKZ0DcMDQj3dcEI2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacN +GHk0vFQYXlPKNFHtRQrmjseCNj6nOGOpMCwXEGCSn1WHElkQwg9naRHMTh5+Spqt +r0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3otkYNbn5XOmeUwssfnHdK +Z05phkOTOPu220+DkdRgfks+KzgHVZhepA== +-----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----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 +MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 +ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD +VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j +b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq +scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO +xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H +LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX +uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD +yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ +JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q +rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN +BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L +hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB +QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ +HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu +Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg +QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB +BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA +A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb +laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 +awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo +JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw +LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT +VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk +LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb +UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ +QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ +naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls +QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----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=Certinomis - Autorité Racine O=Certinomis OU=0002 433998903 +# Subject: CN=Certinomis - Autorité Racine O=Certinomis OU=0002 433998903 +# Label: "Certinomis - Autorité Racine" +# Serial: 1 +# MD5 Fingerprint: 7f:30:78:8c:03:e3:ca:c9:0a:e2:c9:ea:1e:aa:55:1a +# SHA1 Fingerprint: 2e:14:da:ec:28:f0:fa:1e:8e:38:9a:4e:ab:eb:26:c0:0a:d3:83:c3 +# SHA256 Fingerprint: fc:bf:e2:88:62:06:f7:2b:27:59:3c:8b:07:02:97:e1:2d:76:9e:d1:0e:d7:93:07:05:a8:09:8e:ff:c1:4d:17 +-----BEGIN CERTIFICATE----- +MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjET +MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAk +BgNVBAMMHUNlcnRpbm9taXMgLSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4 +Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNl +cnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYwJAYDVQQDDB1DZXJ0 +aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jY +F1AMnmHawE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N +8y4oH3DfVS9O7cdxbwlyLu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWe +rP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K +/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92NjMD2AR5vpTESOH2VwnHu +7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9qc1pkIuVC +28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6 +lSTClrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1E +nn1So2+WLhl+HPNbxxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB +0iSVL1N6aaLwD4ZFjliCK0wi1F6g530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql09 +5gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna4NH4+ej9Uji29YnfAgMBAAGj +WzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQN +jLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ +KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9s +ov3/4gbIOZ/xWqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZM +OH8oMDX/nyNTt7buFHAAQCvaR6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q +619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40nJ+U8/aGH88bc62UeYdocMMzpXDn +2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1BCxMjidPJC+iKunqj +o3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjvJL1v +nxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG +5ERQL1TEqkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWq +pdEdnV1j6CTmNhTih60bWfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZb +dsLLO7XSAPCjDuGtbkD326C00EauFddEwk01+dIL8hf2rGbVJLJP0RyZwG71fet0 +BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/vgt2Fl43N+bYdJeimUV5 +-----END CERTIFICATE----- + +# Issuer: CN=Root CA Generalitat Valenciana O=Generalitat Valenciana OU=PKIGVA +# Subject: CN=Root CA Generalitat Valenciana O=Generalitat Valenciana OU=PKIGVA +# Label: "Root CA Generalitat Valenciana" +# Serial: 994436456 +# MD5 Fingerprint: 2c:8c:17:5e:b1:54:ab:93:17:b5:36:5a:db:d1:c6:f2 +# SHA1 Fingerprint: a0:73:e5:c5:bd:43:61:0d:86:4c:21:13:0a:85:58:57:cc:9c:ea:46 +# SHA256 Fingerprint: 8c:4e:df:d0:43:48:f3:22:96:9e:7e:29:a4:cd:4d:ca:00:46:55:06:1c:16:e1:b0:76:42:2e:f3:42:ad:63:0e +-----BEGIN CERTIFICATE----- +MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJF +UzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJ +R1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcN +MDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3WjBoMQswCQYDVQQGEwJFUzEfMB0G +A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScw +JQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+ +WmmmO3I2F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKj +SgbwJ/BXufjpTjJ3Cj9BZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGl +u6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQD0EbtFpKd71ng+CT516nDOeB0/RSrFOy +A8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXteJajCq+TA81yc477OMUxk +Hl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMBAAGjggM7 +MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBr +aS5ndmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIIC +IwYKKwYBBAG/VQIBADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8A +cgBpAGQAYQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIA +YQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIAYQBsAGkAdABhAHQAIABWAGEA +bABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQByAGEAYwBpAPMA +bgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA +aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMA +aQBvAG4AYQBtAGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQA +ZQAgAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEA +YwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBuAHQAcgBhACAAZQBuACAAbABhACAA +ZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAAOgAvAC8AdwB3AHcA +LgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0dHA6 +Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+y +eAT8MIGVBgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQsw +CQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0G +A1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVu +Y2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRhTvW1yEICKrNcda3Fbcrn +lD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdzCkj+IHLt +b8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg +9J63NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XF +ducTZnV+ZfsBn5OHiJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmC +IoaZM3Fa6hlXPZHNqcCjbgcTpsnt+GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= +-----END CERTIFICATE----- + +# Issuer: CN=A-Trust-nQual-03 O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH OU=A-Trust-nQual-03 +# Subject: CN=A-Trust-nQual-03 O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH OU=A-Trust-nQual-03 +# Label: "A-Trust-nQual-03" +# Serial: 93214 +# MD5 Fingerprint: 49:63:ae:27:f4:d5:95:3d:d8:db:24:86:b8:9c:07:53 +# SHA1 Fingerprint: d3:c0:63:f2:19:ed:07:3e:34:ad:5d:75:0b:32:76:29:ff:d5:9a:f2 +# SHA256 Fingerprint: 79:3c:bf:45:59:b9:fd:e3:8a:b2:2d:f1:68:69:f6:98:81:ae:14:c4:b0:13:9a:c7:88:a7:8a:1a:fc:ca:02:fb +-----BEGIN CERTIFICATE----- +MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJB +VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp +bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5R +dWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5RdWFsLTAzMB4XDTA1MDgxNzIyMDAw +MFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgwRgYDVQQKDD9BLVRy +dXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0ZW52 +ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMM +EEEtVHJ1c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCtPWFuA/OQO8BBC4SAzewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUj +lUC5B3ilJfYKvUWG6Nm9wASOhURh73+nyfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZ +znF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPESU7l0+m0iKsMrmKS1GWH +2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4iHQF63n1 +k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs +2e3Vcuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYD +VR0OBAoECERqlWdVeRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC +AQEAVdRU0VlIXLOThaq/Yy/kgM40ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fG +KOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmrsQd7TZjTXLDR8KdCoLXEjq/+ +8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZdJXDRZslo+S4R +FGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS +mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmE +DNuxUCAKGkq6ahq97BvIxYSazQ== +-----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=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing +# Subject: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing +# Label: "StartCom Certification Authority" +# Serial: 45 +# MD5 Fingerprint: c9:3b:0d:84:41:fc:a4:76:79:23:08:57:de:10:19:16 +# SHA1 Fingerprint: a3:f1:33:3f:e2:42:bf:cf:c5:d1:4e:8f:39:42:98:40:68:10:d1:a0 +# SHA256 Fingerprint: e1:78:90:ee:09:a3:fb:f4:f4:8b:9c:41:4a:17:d6:37:b7:a5:06:47:e9:bc:75:23:22:72:7f:cc:17:42:a9:11 +-----BEGIN CERTIFICATE----- +MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW +MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg +Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9 +MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi +U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh +cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk +pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf +OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C +Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT +Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi +HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM +Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w ++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ +Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 +Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B +26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID +AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul +F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC +ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w +ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk +aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0 +YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg +c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93 +d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG +CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF +wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS +Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst +0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc +pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl +CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF +P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK +1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm +KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE +JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ +8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm +fyWl8kgAwKQB2j8= +-----END CERTIFICATE----- + +# Issuer: CN=StartCom Certification Authority G2 O=StartCom Ltd. +# Subject: CN=StartCom Certification Authority G2 O=StartCom Ltd. +# Label: "StartCom Certification Authority G2" +# Serial: 59 +# MD5 Fingerprint: 78:4b:fb:9e:64:82:0a:d3:b8:4c:62:f3:64:f2:90:64 +# SHA1 Fingerprint: 31:f1:fd:68:22:63:20:ee:c6:3b:3f:9d:ea:4a:3e:53:7c:7c:39:17 +# SHA256 Fingerprint: c7:ba:65:67:de:93:a7:98:ae:1f:aa:79:1e:71:2d:37:8f:ae:1f:93:c4:39:7f:ea:44:1b:b7:cb:e6:fd:59:95 +-----BEGIN CERTIFICATE----- +MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEW +MBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkgRzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1 +OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoG +A1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRzIwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8Oo1XJ +JZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsD +vfOpL9HG4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnoo +D/Uefyf3lLE3PbfHkffiAez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/ +Q0kGi4xDuFby2X8hQxfqp0iVAXV16iulQ5XqFYSdCI0mblWbq9zSOdIxHWDirMxW +RST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbsO+wmETRIjfaAKxojAuuK +HDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8HvKTlXcxN +nw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM +0D4LnMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/i +UUjXuG+v+E5+M5iSFGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9 +Ha90OrInwMEePnWjFqmveiJdnxMaz6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHg +TuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE +AwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJKoZIhvcNAQEL +BQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K +2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfX +UfEpY9Z1zRbkJ4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl +6/2o1PXWT6RbdejF0mCy2wl+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK +9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG/+gyRr61M3Z3qAFdlsHB1b6uJcDJ +HgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTcnIhT76IxW1hPkWLI +wpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/XldblhY +XzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5l +IxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo +hdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulr +so8uBtjRkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI +-----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=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Aralık 2007 +# Subject: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Aralık 2007 +# Label: "TURKTRUST Certificate Services Provider Root 2007" +# Serial: 1 +# MD5 Fingerprint: 2b:70:20:56:86:82:a0:18:c8:07:53:12:28:70:21:72 +# SHA1 Fingerprint: f1:7f:6f:b6:31:dc:99:e3:a3:c8:7f:fe:1c:f1:81:10:88:d9:60:33 +# SHA256 Fingerprint: 97:8c:d9:66:f2:fa:a0:7b:a7:aa:95:00:d9:c0:2e:9d:77:f2:cd:ad:a6:ad:6b:a7:4a:f4:b9:1c:66:59:3c:50 +-----BEGIN CERTIFICATE----- +MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOc +UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx +c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xS +S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg +SGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4XDTA3MTIyNTE4Mzcx +OVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxla3Ry +b25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMC +VFIxDzANBgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDE +sGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7F +ni4gKGMpIEFyYWzEsWsgMjAwNzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9NYvDdE3ePYakqtdTyuTFY +KTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQvKUmi8wUG ++7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveG +HtyaKhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6P +IzdezKKqdfcYbwnTrqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M +733WB2+Y8a+xwXrXgTW4qhe04MsCAwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHk +Yb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/sPx+EnWVUXKgW +AkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I +aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5 +mxRZNTZPz/OOXl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsa +XRik7r4EW5nVcV9VZWRi1aKbBFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZ +qxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAKpoRq0Tl9 +-----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=Autoridad de Certificacion Raiz del Estado Venezolano O=Sistema Nacional de Certificacion Electronica OU=Superintendencia de Servicios de Certificacion Electronica +# Subject: CN=PSCProcert O=Sistema Nacional de Certificacion Electronica OU=Proveedor de Certificados PROCERT +# Label: "PSCProcert" +# Serial: 11 +# MD5 Fingerprint: e6:24:e9:12:01:ae:0c:de:8e:85:c4:ce:a3:12:dd:ec +# SHA1 Fingerprint: 70:c1:8d:74:b4:28:81:0a:e4:fd:a5:75:d7:01:9f:99:b0:3d:50:74 +# SHA256 Fingerprint: 3c:fc:3c:14:d1:f6:84:ff:17:e3:8c:43:ca:44:0c:00:b9:67:ec:93:3e:8b:fe:06:4c:a1:d7:2c:90:f2:ad:b0 +-----BEGIN CERTIFICATE----- +MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1 +dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9s +YW5vMQswCQYDVQQGEwJWRTEQMA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlz +dHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0 +aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBlcmludGVuZGVuY2lh +IGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUwIwYJ +KoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEw +MFoXDTIwMTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHBy +b2NlcnQubmV0LnZlMQ8wDQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGEx +KjAoBgNVBAsTIVByb3ZlZWRvciBkZSBDZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQG +A1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9u +aWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo9 +7BVCwfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74 +BCXfgI8Qhd19L3uA3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38G +ieU89RLAu9MLmV+QfI4tL3czkkohRqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9 +JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmOEO8GqQKJ/+MMbpfg353bIdD0 +PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG20qCZyFSTXai2 +0b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH +0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/ +6mnbVSKVUyqUtd+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1m +v6JpIzi4mWCZDlZTOpx+FIywBm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7 +K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvpr2uKGcfLFFb14dq12fy/czja+eev +bqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/AgEBMDcGA1UdEgQw +MC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAzNi0w +MB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFD +gBStuyIdxuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0 +b3JpZGFkIGRlIENlcnRpZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xh +bm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQHEwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0 +cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5hY2lvbmFsIGRlIENlcnRp +ZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5kZW5jaWEg +ZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkq +hkiG9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQD +AgEGME0GA1UdEQRGMESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0w +MDAwMDKgGwYFYIZeAgKgEgwQUklGLUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEag +RKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9sY3IvQ0VSVElGSUNBRE8t +UkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNyYWl6LnN1c2Nl +cnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v +Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsG +AQUFBwIBFh5odHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcN +AQELBQADggIBACtZ6yKZu4SqT96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS +1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmNg7+mvTV+LFwxNG9s2/NkAZiqlCxB +3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4quxtxj7mkoP3Yldmv +Wb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1n8Gh +HVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHm +pHmJWhSnFFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXz +sOfIt+FTvZLm8wyWuevo5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bE +qCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq3TNWOByyrYDT13K9mmyZY+gAu0F2Bbdb +mRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5poLWccret9W6aAjtmcz9 +opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3YeMLEYC/H +YvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km +-----END CERTIFICATE----- + +# Issuer: CN=China Internet Network Information Center EV Certificates Root O=China Internet Network Information Center +# Subject: CN=China Internet Network Information Center EV Certificates Root O=China Internet Network Information Center +# Label: "China Internet Network Information Center EV Certificates Root" +# Serial: 1218379777 +# MD5 Fingerprint: 55:5d:63:00:97:bd:6a:97:f5:67:ab:4b:fb:6e:63:15 +# SHA1 Fingerprint: 4f:99:aa:93:fb:2b:d1:37:26:a1:99:4a:ce:7f:f0:05:f2:93:5d:1e +# SHA256 Fingerprint: 1c:01:c6:f4:db:b2:fe:fc:22:55:8b:2b:ca:32:56:3f:49:84:4a:cf:c3:2b:7b:e4:b0:ff:59:9f:9e:8c:7a:f7 +-----BEGIN CERTIFICATE----- +MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC +Q04xMjAwBgNVBAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24g +Q2VudGVyMUcwRQYDVQQDDD5DaGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0 +aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMgUm9vdDAeFw0xMDA4MzEwNzExMjVa +Fw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAGA1UECgwpQ2hpbmEg +SW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMMPkNo +aW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRp +ZmljYXRlcyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z +7r07eKpkQ0H1UN+U8i6yjUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA// +DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV98YPjUesWgbdYavi7NifFy2cyjw1l1Vx +zUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2HklY0bBoQCxfVWhyXWIQ8 +hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23KzhmBsUs +4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54u +gQEC7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oY +NJKiyoOCWTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E +FgQUfHJLOcfA22KlT5uqGDSSosqDglkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3 +j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd50XPFtQO3WKwMVC/GVhMPMdoG +52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM7+czV0I664zB +echNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws +ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrI +zo9uoV1/A3U05K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATy +wy39FCqQmbkHzJ8= +-----END CERTIFICATE----- + +# Issuer: CN=Swisscom Root CA 2 O=Swisscom OU=Digital Certificate Services +# Subject: CN=Swisscom Root CA 2 O=Swisscom OU=Digital Certificate Services +# Label: "Swisscom Root CA 2" +# Serial: 40698052477090394928831521023204026294 +# MD5 Fingerprint: 5b:04:69:ec:a5:83:94:63:18:a7:86:d0:e4:f2:6e:19 +# SHA1 Fingerprint: 77:47:4f:c6:30:e4:0f:4c:47:64:3f:84:ba:b8:c6:95:4a:8a:41:ec +# SHA256 Fingerprint: f0:9b:12:2c:71:14:f4:a0:9b:d4:ea:4f:4a:99:d5:58:b4:6e:4c:25:cd:81:14:0d:29:c0:56:13:91:4c:38:41 +-----BEGIN CERTIFICATE----- +MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBk +MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 +YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg +Q0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2MjUwNzM4MTRaMGQxCzAJBgNVBAYT +AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp +Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvEr +jw0DzpPMLgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r +0rk0X2s682Q2zsKwzxNoysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f +2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJwDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVP +ACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpHWrumnf2U5NGKpV+GY3aF +y6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1aSgJA/MTA +tukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL +6yxSNLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0 +uPoTXGiTOmekl9AbmbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrAL +acywlKinh/LTSlDcX3KwFnUey7QYYpqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velh +k6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3qPyZ7iVNTA6z00yPhOgpD/0Q +VAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw +FDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O +BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqh +b97iEoHF8TwuMA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4R +fbgZPnm3qKhyN2abGu2sEzsOv2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv +/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ82YqZh6NM4OKb3xuqFp1mrjX2lhI +REeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLzo9v/tdhZsnPdTSpx +srpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcsa0vv +aGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciAT +woCqISxxOQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99n +Bjx8Oto0QuFmtEYE3saWmA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5W +t6NlUe07qxS/TFED6F+KBZvuim6c779o+sjaC+NCydAXFJy3SuCvkychVSa1ZC+N +8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TCrvJcwhbtkj6EPnNgiLx2 +9CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX5OfNeOI5 +wSsSnqaeG8XmDtkx2Q== +-----END CERTIFICATE----- + +# Issuer: CN=Swisscom Root EV CA 2 O=Swisscom OU=Digital Certificate Services +# Subject: CN=Swisscom Root EV CA 2 O=Swisscom OU=Digital Certificate Services +# Label: "Swisscom Root EV CA 2" +# Serial: 322973295377129385374608406479535262296 +# MD5 Fingerprint: 7b:30:34:9f:dd:0a:4b:6b:35:ca:31:51:28:5d:ae:ec +# SHA1 Fingerprint: e7:a1:90:29:d3:d5:52:dc:0d:0f:c6:92:d3:ea:88:0d:15:2e:1a:6b +# SHA256 Fingerprint: d9:5f:ea:3c:a4:ee:dc:e7:4c:d7:6e:75:fc:6d:1f:f6:2c:44:1f:0f:a8:bc:77:f0:34:b1:9e:5d:b2:58:01:5d +-----BEGIN CERTIFICATE----- +MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAw +ZzELMAkGA1UEBhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdp +dGFsIENlcnRpZmljYXRlIFNlcnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290 +IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcNMzEwNjI1MDg0NTA4WjBnMQswCQYD +VQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2Vy +dGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYgQ0Eg +MjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7Bx +UglgRCgzo3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD +1ycfMQ4jFrclyxy0uYAyXhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPH +oCE2G3pXKSinLr9xJZDzRINpUKTk4RtiGZQJo/PDvO/0vezbE53PnUgJUmfANykR +HvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8LiqG12W0OfvrSdsyaGOx9/ +5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaHZa0zKcQv +idm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHL +OdAGalNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaC +NYGu+HuB5ur+rPQam3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f +46Fq9mDU5zXNysRojddxyNMkM3OxbPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCB +UWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDixzgHcgplwLa7JSnaFp6LNYth +7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/BAQDAgGGMB0G +A1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED +MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWB +bj2ITY1x0kbBbkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6x +XCX5145v9Ydkn+0UjrgEjihLj6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98T +PLr+flaYC/NUn81ETm484T4VvwYmneTwkLbUwp4wLh/vx3rEUMfqe9pQy3omywC0 +Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7XwgiG/W9mR4U9s70 +WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH59yL +Gn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm +7JFe3VE/23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4S +nr8PyQUQ3nqjsTzyP6WqJ3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VN +vBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyAHmBR3NdUIR7KYndP+tiPsys6DXhyyWhB +WkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/giuMod89a2GQ+fYWVq6nTI +fI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuWl8PVP3wb +I+2ksx0WckNLIOFZfsLorSa/ovc= +-----END CERTIFICATE----- + +# Issuer: CN=CA Disig Root R1 O=Disig a.s. +# Subject: CN=CA Disig Root R1 O=Disig a.s. +# Label: "CA Disig Root R1" +# Serial: 14052245610670616104 +# MD5 Fingerprint: be:ec:11:93:9a:f5:69:21:bc:d7:c1:c0:67:89:cc:2a +# SHA1 Fingerprint: 8e:1c:74:f8:a6:20:b9:e5:8a:f4:61:fa:ec:2b:47:56:51:1a:52:c6 +# SHA256 Fingerprint: f9:6f:23:f4:c3:e7:9c:07:7a:46:98:8d:5a:f5:90:06:76:a0:f0:39:cb:64:5d:d1:75:49:b2:16:c8:24:40:ce +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNV +BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu +MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQy +MDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx +EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjEw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy3QRk +D2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/o +OI7bm+V8u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3A +fQ+lekLZWnDZv6fXARz2m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJe +IgpFy4QxTaz+29FHuvlglzmxZcfe+5nkCiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8n +oc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTaYVKvJrT1cU/J19IG32PK +/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6vpmumwKj +rckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD +3AjLLhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE +7cderVC6xkGbrPAXZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkC +yC2fg69naQanMVXVz0tv/wQFx1isXxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLd +qvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ04IwDQYJKoZI +hvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR +xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaA +SfX8MPWbTx9BLxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXo +HqJPYNcHKfyyo6SdbhWSVhlMCrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpB +emOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5GfbVSUZP/3oNn6z4eGBrxEWi1CXYBmC +AMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85YmLLW1AL14FABZyb +7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKSds+x +DzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvk +F7mGnjixlAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqF +a3qdnom2piiZk4hA9z7NUaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsT +Q6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJa7+h89n07eLw4+1knj0vllJPgFOL +-----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ğra EBG Bilişim Teknolojileri ve Hizmetleri A.Ş. OU=E-Tugra Sertifikasyon Merkezi +# Subject: CN=E-Tugra Certification Authority O=E-Tuğra EBG Bilişim Teknolojileri ve Hizmetleri A.Ş. 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=Certification Authority of WoSign O=WoSign CA Limited +# Subject: CN=Certification Authority of WoSign O=WoSign CA Limited +# Label: "WoSign" +# Serial: 125491772294754854453622855443212256657 +# MD5 Fingerprint: a1:f2:f9:b5:d2:c8:7a:74:b8:f3:05:f1:d7:e1:84:8d +# SHA1 Fingerprint: b9:42:94:bf:91:ea:8f:b6:4b:e6:10:97:c7:fb:00:13:59:b6:76:cb +# SHA256 Fingerprint: 4b:22:d5:a6:ae:c9:9f:3c:db:79:aa:5e:c0:68:38:47:9c:d5:ec:ba:71:64:f7:f2:2d:c1:d6:5f:63:d8:57:08 +-----BEGIN CERTIFICATE----- +MIIFdjCCA16gAwIBAgIQXmjWEXGUY1BWAGjzPsnFkTANBgkqhkiG9w0BAQUFADBV +MQswCQYDVQQGEwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxKjAoBgNV +BAMTIUNlcnRpZmljYXRpb24gQXV0aG9yaXR5IG9mIFdvU2lnbjAeFw0wOTA4MDgw +MTAwMDFaFw0zOTA4MDgwMTAwMDFaMFUxCzAJBgNVBAYTAkNOMRowGAYDVQQKExFX +b1NpZ24gQ0EgTGltaXRlZDEqMCgGA1UEAxMhQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgb2YgV29TaWduMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvcqN +rLiRFVaXe2tcesLea9mhsMMQI/qnobLMMfo+2aYpbxY94Gv4uEBf2zmoAHqLoE1U +fcIiePyOCbiohdfMlZdLdNiefvAA5A6JrkkoRBoQmTIPJYhTpA2zDxIIFgsDcScc +f+Hb0v1naMQFXQoOXXDX2JegvFNBmpGN9J42Znp+VsGQX+axaCA2pIwkLCxHC1l2 +ZjC1vt7tj/id07sBMOby8w7gLJKA84X5KIq0VC6a7fd2/BVoFutKbOsuEo/Uz/4M +x1wdC34FMr5esAkqQtXJTpCzWQ27en7N1QhatH/YHGkR+ScPewavVIMYe+HdVHpR +aG53/Ma/UkpmRqGyZxq7o093oL5d//xWC0Nyd5DKnvnyOfUNqfTq1+ezEC8wQjch +zDBwyYaYD8xYTYO7feUapTeNtqwylwA6Y3EkHp43xP901DfA4v6IRmAR3Qg/UDar +uHqklWJqbrDKaiFaafPz+x1wOZXzp26mgYmhiMU7ccqjUu6Du/2gd/Tkb+dC221K +mYo0SLwX3OSACCK28jHAPwQ+658geda4BmRkAjHXqc1S+4RFaQkAKtxVi8QGRkvA +Sh0JWzko/amrzgD5LkhLJuYwTKVYyrREgk/nkR4zw7CT/xH8gdLKH3Ep3XZPkiWv +HYG3Dy+MwwbMLyejSuQOmbp8HkUff6oZRZb9/D0CAwEAAaNCMEAwDgYDVR0PAQH/ +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOFmzw7R8bNLtwYgFP6H +EtX2/vs+MA0GCSqGSIb3DQEBBQUAA4ICAQCoy3JAsnbBfnv8rWTjMnvMPLZdRtP1 +LOJwXcgu2AZ9mNELIaCJWSQBnfmvCX0KI4I01fx8cpm5o9dU9OpScA7F9dY74ToJ +MuYhOZO9sxXqT2r09Ys/L3yNWC7F4TmgPsc9SnOeQHrAK2GpZ8nzJLmzbVUsWh2e +JXLOC62qx1ViC777Y7NhRCOjy+EaDveaBk3e1CNOIZZbOVtXHS9dCF4Jef98l7VN +g64N1uajeeAz0JmWAjCnPv/So0M/BVoG6kQC2nz4SNAzqfkHx5Xh9T71XXG68pWp +dIhhWeO/yloTunK0jF02h+mmxTwTv97QRCbut+wucPrXnbes5cVAWubXbHssw1ab +R80LzvobtCHXt2a49CUwi1wNuepnsvRtrtWhnk/Yn+knArAdBtaP4/tIEp9/EaEQ +PkxROpaw0RPxx9gmrjrKkcRpnd8BKWRRb2jaFOwIQZeQjdCygPLPwj2/kWjFgGce +xGATVdVhmVd8upUPYUk6ynW8yQqTP2cOEvIo4jEbwFcW3wh8GcF+Dx+FHgo2fFt+ +J7x6v+Db9NpSvd4MVHAxkUOVyLzwPt0JfjBkUO1/AaQzZ01oT74V77D2AhGiGxMl +OtzCWfHjXEa7ZywCRuoeSKbmW9m1vFGikpbbqsY3Iqb+zCB0oy2pLmvLwIIRIbWT +ee5Ehr7XHuQe+w== +-----END CERTIFICATE----- + +# Issuer: CN=CA 沃通根证书 O=WoSign CA Limited +# Subject: CN=CA 沃通根证书 O=WoSign CA Limited +# Label: "WoSign China" +# Serial: 106921963437422998931660691310149453965 +# MD5 Fingerprint: 78:83:5b:52:16:76:c4:24:3b:83:78:e8:ac:da:9a:93 +# SHA1 Fingerprint: 16:32:47:8d:89:f9:21:3a:92:00:85:63:f5:a4:a7:d3:12:40:8a:d6 +# SHA256 Fingerprint: d6:f0:34:bd:94:aa:23:3f:02:97:ec:a4:24:5b:28:39:73:e4:47:aa:59:0f:31:0c:77:f4:8f:df:83:11:22:54 +-----BEGIN CERTIFICATE----- +MIIFWDCCA0CgAwIBAgIQUHBrzdgT/BtOOzNy0hFIjTANBgkqhkiG9w0BAQsFADBG +MQswCQYDVQQGEwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNV +BAMMEkNBIOayg+mAmuagueivgeS5pjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgw +MTAwMDFaMEYxCzAJBgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRl +ZDEbMBkGA1UEAwwSQ0Eg5rKD6YCa5qC56K+B5LmmMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA0EkhHiX8h8EqwqzbdoYGTufQdDTc7WU1/FDWiD+k8H/r +D195L4mx/bxjWDeTmzj4t1up+thxx7S8gJeNbEvxUNUqKaqoGXqW5pWOdO2XCld1 +9AXbbQs5uQF/qvbW2mzmBeCkTVL829B0txGMe41P/4eDrv8FAxNXUDf+jJZSEExf +v5RxadmWPgxDT74wwJ85dE8GRV2j1lY5aAfMh09Qd5Nx2UQIsYo06Yms25tO4dnk +UkWMLhQfkWsZHWgpLFbE4h4TV2TwYeO5Ed+w4VegG63XX9Gv2ystP9Bojg/qnw+L +NVgbExz03jWhCl3W6t8Sb8D7aQdGctyB9gQjF+BNdeFyb7Ao65vh4YOhn0pdr8yb ++gIgthhid5E7o9Vlrdx8kHccREGkSovrlXLp9glk3Kgtn3R46MGiCWOc76DbT52V +qyBPt7D3h1ymoOQ3OMdc4zUPLK2jgKLsLl3Az+2LBcLmc272idX10kaO6m1jGx6K +yX2m+Jzr5dVjhU1zZmkR/sgO9MHHZklTfuQZa/HpelmjbX7FF+Ynxu8b22/8DU0G +AbQOXDBGVWCvOGU6yke6rCzMRh+yRpY/8+0mBe53oWprfi1tWFxK1I5nuPHa1UaK +J/kR8slC/k7e3x9cxKSGhxYzoacXGKUN5AXlK8IrC6KVkLn9YDxOiT7nnO4fuwEC +AwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFOBNv9ybQV0T6GTwp+kVpOGBwboxMA0GCSqGSIb3DQEBCwUAA4ICAQBqinA4 +WbbaixjIvirTthnVZil6Xc1bL3McJk6jfW+rtylNpumlEYOnOXOvEESS5iVdT2H6 +yAa+Tkvv/vMx/sZ8cApBWNromUuWyXi8mHwCKe0JgOYKOoICKuLJL8hWGSbueBwj +/feTZU7n85iYr83d2Z5AiDEoOqsuC7CsDCT6eiaY8xJhEPRdF/d+4niXVOKM6Cm6 +jBAyvd0zaziGfjk9DgNyp115j0WKWa5bIW4xRtVZjc8VX90xJc/bYNaBRHIpAlf2 +ltTW/+op2znFuCyKGo3Oy+dCMYYFaA6eFN0AkLppRQjbbpCBhqcqBT/mhDn4t/lX +X0ykeVoQDF7Va/81XwVRHmyjdanPUIPTfPRm94KNPQx96N97qA4bLJyuQHCH2u2n +FoJavjVsIE4iYdm8UXrNemHcSxH5/mc0zy4EZmFcV5cjjPOGG0jfKq+nwf/Yjj4D +u9gqsPoUJbJRa4ZDhS4HIxaAjUz7tGM7zMN07RujHv41D198HRaG9Q7DlfEvr10l +O1Hm13ZBONFLAzkopR6RctR9q5czxNM+4Gm2KHmgCY0c0f9BckgG/Jou5yD5m6Le +ie2uPAmvylezkolwQOQvT8Jwg0DXJCxr5wkf09XHwQj02w47HAcLQxGEIYbpgNR1 +2KvxAmLBsX5VYc8T1yaw15zLKYs4SgsOkI26oQ== +-----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=Entrust.net Secure Server Certification Authority O=Entrust.net OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Subject: CN=Entrust.net Secure Server Certification Authority O=Entrust.net OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Label: "Entrust.net Secure Server CA" +# Serial: 927650371 +# MD5 Fingerprint: df:f2:80:73:cc:f1:e6:61:73:fc:f5:42:e9:c5:7c:ee +# SHA1 Fingerprint: 99:a6:9b:e6:1a:fe:88:6b:4d:2b:82:00:7c:b8:54:fc:31:7e:15:39 +# SHA256 Fingerprint: 62:f2:40:27:8c:56:4c:4d:d8:bf:7d:9d:4f:6f:36:6e:a8:94:d2:2f:5f:34:d9:89:a9:83:ac:ec:2f:ff:ed:50 +-----BEGIN CERTIFICATE----- +MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u +ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc +KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u +ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 +MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE +ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j +b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF +bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg +U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ +I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 +wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC +AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb +oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 +BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p +dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk +MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp +b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu +dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 +MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi +E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa +MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI +hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN +95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd +2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= +-----END CERTIFICATE----- + +# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 2 Policy Validation Authority +# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 2 Policy Validation Authority +# Label: "ValiCert Class 2 VA" +# Serial: 1 +# MD5 Fingerprint: a9:23:75:9b:ba:49:36:6e:31:c2:db:f2:e7:66:ba:87 +# SHA1 Fingerprint: 31:7a:2a:d0:7f:2b:33:5e:f5:a1:c3:4e:4b:57:e8:b7:d8:f1:fc:a6 +# SHA256 Fingerprint: 58:d0:17:27:9c:d4:dc:63:ab:dd:b1:96:a6:c9:90:6c:30:c4:e0:87:83:ea:e8:c1:60:99:54:d6:93:55:59:6b +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy +NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY +dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 +WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS +v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v +UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu +IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC +W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd +-----END CERTIFICATE----- + +# Issuer: CN=NetLock Expressz (Class C) Tanusitvanykiado O=NetLock Halozatbiztonsagi Kft. OU=Tanusitvanykiadok +# Subject: CN=NetLock Expressz (Class C) Tanusitvanykiado O=NetLock Halozatbiztonsagi Kft. OU=Tanusitvanykiadok +# Label: "NetLock Express (Class C) Root" +# Serial: 104 +# MD5 Fingerprint: 4f:eb:f1:f0:70:c2:80:63:5d:58:9f:da:12:3c:a9:c4 +# SHA1 Fingerprint: e3:92:51:2f:0a:cf:f5:05:df:f6:de:06:7f:75:37:e1:65:ea:57:4b +# SHA256 Fingerprint: 0b:5e:ed:4e:84:64:03:cf:55:e0:65:84:84:40:ed:2a:82:75:8b:f5:b9:aa:1f:25:3d:46:13:cf:a0:80:ff:3f +-----BEGIN CERTIFICATE----- +MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUx +ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 +b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQD +EytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBDKSBUYW51c2l0dmFueWtpYWRvMB4X +DTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJBgNVBAYTAkhVMREw +DwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9u +c2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMr +TmV0TG9jayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNA +OoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3ZW3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC +2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63euyucYT2BDMIJTLrdKwW +RMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQwDgYDVR0P +AQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEW +ggJNRklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0 +YWxhbm9zIFN6b2xnYWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFz +b2sgYWxhcGphbiBrZXN6dWx0LiBBIGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBO +ZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1iaXp0b3NpdGFzYSB2ZWRpLiBB +IGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0ZWxlIGF6IGVs +b2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs +ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25s +YXBqYW4gYSBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kg +a2VyaGV0byBheiBlbGxlbm9yemVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4g +SU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5kIHRoZSB1c2Ugb2YgdGhpcyBjZXJ0 +aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQUyBhdmFpbGFibGUg +YXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwgYXQg +Y3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmY +ta3UzbM2xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2g +pO0u9f38vf5NNwgMvOOWgyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4 +Fp1hBWeAyNDYpQcCNJgEjTME1A== +-----END CERTIFICATE----- + +# Issuer: CN=NetLock Uzleti (Class B) Tanusitvanykiado O=NetLock Halozatbiztonsagi Kft. OU=Tanusitvanykiadok +# Subject: CN=NetLock Uzleti (Class B) Tanusitvanykiado O=NetLock Halozatbiztonsagi Kft. OU=Tanusitvanykiadok +# Label: "NetLock Business (Class B) Root" +# Serial: 105 +# MD5 Fingerprint: 39:16:aa:b9:6a:41:e1:14:69:df:9e:6c:3b:72:dc:b6 +# SHA1 Fingerprint: 87:9f:4b:ee:05:df:98:58:3b:e3:60:d6:33:e7:0d:3f:fe:98:71:af +# SHA256 Fingerprint: 39:df:7b:68:2b:7b:93:8f:84:71:54:81:cc:de:8d:60:d8:f2:2e:c5:98:87:7d:0a:aa:c1:2b:59:18:2b:03:12 +-----BEGIN CERTIFICATE----- +MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUx +ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 +b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQD +EylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikgVGFudXNpdHZhbnlraWFkbzAeFw05 +OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYDVQQGEwJIVTERMA8G +A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh +Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5l +dExvY2sgVXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xK +gZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX +iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvc +Q7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8E +BAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1G +SUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFu +b3MgU3pvbGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBh +bGFwamFuIGtlc3p1bHQuIEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExv +Y2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGln +aXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0 +IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh +c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGph +biBhIGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJo +ZXRvIGF6IGVsbGVub3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBP +UlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmlj +YXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBo +dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNA +bmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06 +sPgzTEdM43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXa +n3BukxowOR0w2y7jfLKRstE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKS +NitjrFgBazMpUIaD8QFI +-----END CERTIFICATE----- + +# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 3 Policy Validation Authority +# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 3 Policy Validation Authority +# Label: "RSA Root Certificate 1" +# Serial: 1 +# MD5 Fingerprint: a2:6f:53:b7:ee:40:db:4a:68:e7:fa:18:d9:10:4b:72 +# SHA1 Fingerprint: 69:bd:8c:f4:9c:d3:00:fb:59:2e:17:93:ca:55:6a:f3:ec:aa:35:fb +# SHA256 Fingerprint: bc:23:f9:8a:31:3c:b9:2d:e3:bb:fc:3a:5a:9f:44:61:ac:39:49:4c:4a:e1:5a:9e:9d:f1:31:e9:9b:73:01:9a +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy +NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD +cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs +2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY +JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE +Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ +n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A +PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu +-----END CERTIFICATE----- + +# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 1 Policy Validation Authority +# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 1 Policy Validation Authority +# Label: "ValiCert Class 1 VA" +# Serial: 1 +# MD5 Fingerprint: 65:58:ab:15:ad:57:6c:1e:a8:a7:b5:69:ac:bf:ff:eb +# SHA1 Fingerprint: e5:df:74:3c:b6:01:c4:9b:98:43:dc:ab:8c:e8:6a:81:10:9f:e4:8e +# SHA256 Fingerprint: f4:c1:49:55:1a:30:13:a3:5b:c7:bf:fe:17:a7:f3:44:9b:c1:ab:5b:5a:0a:e7:4b:06:c2:3b:90:00:4c:01:04 +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy +NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y +LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+ +TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y +TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0 +LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW +I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw +nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI +-----END CERTIFICATE----- + +# Issuer: CN=Equifax Secure eBusiness CA-1 O=Equifax Secure Inc. +# Subject: CN=Equifax Secure eBusiness CA-1 O=Equifax Secure Inc. +# Label: "Equifax Secure eBusiness CA 1" +# Serial: 4 +# MD5 Fingerprint: 64:9c:ef:2e:44:fc:c6:8f:52:07:d0:51:73:8f:cb:3d +# SHA1 Fingerprint: da:40:18:8b:91:89:a3:ed:ee:ae:da:97:fe:2f:9d:f5:b7:d1:8a:41 +# SHA256 Fingerprint: cf:56:ff:46:a4:a1:86:10:9d:d9:65:84:b5:ee:b5:8a:51:0c:42:75:b0:e5:f9:4f:40:bb:ae:86:5e:19:f6:73 +-----BEGIN CERTIFICATE----- +MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT +ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw +MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j +LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ +KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo +RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu +WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw +Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD +AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK +eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM +zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ +WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN +/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== +-----END CERTIFICATE----- + +# Issuer: CN=Equifax Secure Global eBusiness CA-1 O=Equifax Secure Inc. +# Subject: CN=Equifax Secure Global eBusiness CA-1 O=Equifax Secure Inc. +# Label: "Equifax Secure Global eBusiness CA" +# Serial: 1 +# MD5 Fingerprint: 8f:5d:77:06:27:c4:98:3c:5b:93:78:e7:d7:7d:9b:cc +# SHA1 Fingerprint: 7e:78:4a:10:1c:82:65:cc:2d:e1:f1:6d:47:b4:40:ca:d9:0a:19:45 +# SHA256 Fingerprint: 5f:0b:62:ea:b5:e3:53:ea:65:21:65:16:58:fb:b6:53:59:f4:43:28:0a:4a:fb:d1:04:d7:7d:10:f9:f0:4c:07 +-----BEGIN CERTIFICATE----- +MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT +ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw +MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj +dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l +c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC +UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc +58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ +o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH +MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr +aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA +A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA +Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv +8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV +-----END CERTIFICATE----- + +# Issuer: CN=Thawte Premium Server CA O=Thawte Consulting cc OU=Certification Services Division +# Subject: CN=Thawte Premium Server CA O=Thawte Consulting cc OU=Certification Services Division +# Label: "Thawte Premium Server CA" +# Serial: 1 +# MD5 Fingerprint: 06:9f:69:79:16:66:90:02:1b:8c:8c:a2:c3:07:6f:3a +# SHA1 Fingerprint: 62:7f:8d:78:27:65:63:99:d2:7d:7f:90:44:c9:fe:b3:f3:3e:fa:9a +# SHA256 Fingerprint: ab:70:36:36:5c:71:54:aa:29:c2:c2:9f:5d:41:91:16:3b:16:2a:22:25:01:13:57:d5:6d:07:ff:a7:bc:1f:72 +-----BEGIN CERTIFICATE----- +MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD +VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy +dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t +MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB +MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG +A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp +b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl +cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv +bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE +VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ +ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR +uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG +9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI +hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM +pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== +-----END CERTIFICATE----- + +# Issuer: CN=Thawte Server CA O=Thawte Consulting cc OU=Certification Services Division +# Subject: CN=Thawte Server CA O=Thawte Consulting cc OU=Certification Services Division +# Label: "Thawte Server CA" +# Serial: 1 +# MD5 Fingerprint: c5:70:c4:a2:ed:53:78:0c:c8:10:53:81:64:cb:d0:1d +# SHA1 Fingerprint: 23:e5:94:94:51:95:f2:41:48:03:b4:d5:64:d2:a3:a3:f5:d8:8b:8c +# SHA256 Fingerprint: b4:41:0b:73:e2:e6:ea:ca:47:fb:c4:2f:8f:a4:01:8a:f4:38:1d:c5:4c:fa:a8:44:50:46:1e:ed:09:45:4d:e9 +-----BEGIN CERTIFICATE----- +MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD +VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm +MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx +MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 +dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl +cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 +DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 +yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX +L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj +EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG +7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e +QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ +qdq5snUb9kLy78fyGPmJvKP/iiMucEc= +-----END CERTIFICATE----- + +# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority +# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority +# Label: "Verisign Class 3 Public Primary Certification Authority" +# Serial: 149843929435818692848040365716851702463 +# MD5 Fingerprint: 10:fc:63:5d:f6:26:3e:0d:f3:25:be:5f:79:cd:67:67 +# SHA1 Fingerprint: 74:2c:31:92:e6:07:e4:24:eb:45:49:54:2b:e1:bb:c5:3e:61:74:e2 +# SHA256 Fingerprint: e7:68:56:34:ef:ac:f6:9a:ce:93:9a:6b:25:5b:7b:4f:ab:ef:42:93:5b:50:a2:65:ac:b5:cb:60:27:e4:4e:70 +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE +BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is +I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G +CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do +lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc +AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k +-----END CERTIFICATE----- + +# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority +# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority +# Label: "Verisign Class 3 Public Primary Certification Authority" +# Serial: 80507572722862485515306429940691309246 +# MD5 Fingerprint: ef:5a:f1:33:ef:f1:cd:bb:51:02:ee:12:14:4b:96:c4 +# SHA1 Fingerprint: a1:db:63:93:91:6f:17:e4:18:55:09:40:04:15:c7:02:40:b0:ae:6b +# SHA256 Fingerprint: a4:b6:b3:99:6f:c2:f3:06:b3:fd:86:81:bd:63:41:3d:8c:50:09:cc:4f:a3:29:c2:cc:f0:e2:fa:1b:14:03:05 +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE +BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is +I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G +CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i +2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ +2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ +-----END CERTIFICATE----- + +# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority - G2/(c) 1998 VeriSign, Inc. - For authorized use only/VeriSign Trust Network +# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority - G2/(c) 1998 VeriSign, Inc. - For authorized use only/VeriSign Trust Network +# Label: "Verisign Class 3 Public Primary Certification Authority - G2" +# Serial: 167285380242319648451154478808036881606 +# MD5 Fingerprint: a2:33:9b:4c:74:78:73:d4:6c:e7:c1:f3:8d:cb:5c:e9 +# SHA1 Fingerprint: 85:37:1c:a6:e5:50:14:3d:ce:28:03:47:1b:de:3a:09:e8:f8:77:0f +# SHA256 Fingerprint: 83:ce:3c:12:29:68:8a:59:3d:48:5f:81:97:3c:0f:91:95:43:1e:da:37:cc:5e:36:43:0e:79:c7:a8:88:63:8b +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 +pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 +13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk +U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i +F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY +oJ2daZH9 +-----END CERTIFICATE----- + +# Issuer: CN=GTE CyberTrust Global Root O=GTE Corporation OU=GTE CyberTrust Solutions, Inc. +# Subject: CN=GTE CyberTrust Global Root O=GTE Corporation OU=GTE CyberTrust Solutions, Inc. +# Label: "GTE CyberTrust Global Root" +# Serial: 421 +# MD5 Fingerprint: ca:3d:d3:68:f1:03:5c:d0:32:fa:b8:2b:59:e8:5a:db +# SHA1 Fingerprint: 97:81:79:50:d8:1c:96:70:cc:34:d8:09:cf:79:44:31:36:7e:f4:74 +# SHA256 Fingerprint: a5:31:25:18:8d:21:10:aa:96:4b:02:c7:b7:c6:da:32:03:17:08:94:e5:fb:71:ff:fb:66:67:d5:e6:81:0a:36 +-----BEGIN CERTIFICATE----- +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv +b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds +b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH +iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS +r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 +04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r +GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 +3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P +lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +-----END CERTIFICATE----- diff --git a/dist_assets/win/pyfa.spec b/dist_assets/win/pyfa.spec new file mode 100644 index 000000000..0f61a860d --- /dev/null +++ b/dist_assets/win/pyfa.spec @@ -0,0 +1,83 @@ +# -*- mode: python -*- + +# Note: This script is provided AS-IS for those that may be interested. +# pyfa does not currently support pyInstaller (or any other build process) 100% at the moment + +# Command line to build: +# (Run from directory where pyfa.py and pyfa.spec lives.) +# c:\Python27\scripts\pyinstaller.exe --clean --noconfirm --windowed --upx-dir=.\scripts\upx.exe pyfa.spec + +# Don't forget to change the path to where your pyfa.py and pyfa.spec lives +# pathex=['C:\\Users\\Ebag333\\Documents\\GitHub\\Ebag333\\Pyfa'], + +import os + +block_cipher = None + +added_files = [ + ( 'imgs/gui/*.png', 'imgs/gui' ), + ( 'imgs/gui/*.gif', 'imgs/gui' ), + ( 'imgs/icons/*.png', 'imgs/icons' ), + ( 'imgs/renders/*.png', 'imgs/renders' ), + ( 'dist_assets/win/pyfa.ico', '.' ), + ( 'dist_assets/cacert.pem', '.' ), + ( 'eve.db', '.' ), + ( 'README.md', '.' ), + ( 'LICENSE', '.' ), + ] + +import_these = [] + +# Walk eos.effects and add all effects so we can import them properly +for root, folders, files in os.walk("eos/effects"): + for file_ in files: + if file_.endswith(".py") and not file_.startswith("_"): + mod_name = "{}.{}".format( + root.replace("/", "."), + file_.split(".py")[0], + ) + import_these.append(mod_name) + +a = Analysis( + ['pyfa.py'], + pathex=['C:\\projects\\pyfa\\'], + binaries=[], + datas=added_files, + hiddenimports=import_these, + hookspath=[], + runtime_hooks=[], + excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=block_cipher, + ) + +pyz = PYZ( + a.pure, + a.zipped_data, + cipher=block_cipher, + ) + +exe = EXE(pyz, + a.scripts, + exclude_binaries=True, + debug=False, + console=False, + strip=False, + upx=True, + name='pyfa', + icon='dist_assets/win/pyfa.ico', + onefile=False, + ) + +coll = COLLECT( + exe, + a.binaries, + a.zipfiles, + a.datas, + strip=False, + upx=True, + onefile=False, + name='pyfa', + icon='dist_assets/win/pyfa.ico', + ) diff --git a/dist_assets/win/pyfa_debug.spec b/dist_assets/win/pyfa_debug.spec new file mode 100644 index 000000000..bc604dd10 --- /dev/null +++ b/dist_assets/win/pyfa_debug.spec @@ -0,0 +1,83 @@ +# -*- mode: python -*- + +# Note: This script is provided AS-IS for those that may be interested. +# pyfa does not currently support pyInstaller (or any other build process) 100% at the moment + +# Command line to build: +# (Run from directory where pyfa.py and pyfa.spec lives.) +# c:\Python27\scripts\pyinstaller.exe --clean --noconfirm --windowed --upx-dir=.\scripts\upx.exe pyfa.spec + +# Don't forget to change the path to where your pyfa.py and pyfa.spec lives +# pathex=['C:\\Users\\Ebag333\\Documents\\GitHub\\Ebag333\\Pyfa'], + +import os + +block_cipher = None + +added_files = [ + ( 'imgs/gui/*.png', 'imgs/gui' ), + ( 'imgs/gui/*.gif', 'imgs/gui' ), + ( 'imgs/icons/*.png', 'imgs/icons' ), + ( 'imgs/renders/*.png', 'imgs/renders' ), + ( 'dist_assets/win/pyfa.ico', '.' ), + ( 'dist_assets/cacert.pem', '.' ), + ( 'eve.db', '.' ), + ( 'README.md', '.' ), + ( 'LICENSE', '.' ), + ] + +import_these = [] + +# Walk eos.effects and add all effects so we can import them properly +for root, folders, files in os.walk("eos/effects"): + for file_ in files: + if file_.endswith(".py") and not file_.startswith("_"): + mod_name = "{}.{}".format( + root.replace("/", "."), + file_.split(".py")[0], + ) + import_these.append(mod_name) + +a = Analysis( + ['pyfa.py'], + pathex=['C:\\projects\\pyfa\\'], + binaries=[], + datas=added_files, + hiddenimports=import_these, + hookspath=[], + runtime_hooks=[], + excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=block_cipher, + ) + +pyz = PYZ( + a.pure, + a.zipped_data, + cipher=block_cipher, + ) + +exe = EXE(pyz, + a.scripts, + exclude_binaries=True, + debug=True, + console=True, + strip=False, + upx=True, + name='pyfa_debug', + icon='dist_assets/win/pyfa.ico', + onefile=False, + ) + +coll = COLLECT( + exe, + a.binaries, + a.zipfiles, + a.datas, + strip=False, + upx=True, + onefile=False, + name='pyfa_debug', + icon='dist_assets/win/pyfa.ico', + ) diff --git a/eos/__init__.py b/eos/__init__.py index 96a3c75be..83ab57f41 100644 --- a/eos/__init__.py +++ b/eos/__init__.py @@ -1,8 +1,2 @@ version = "0.2.3" tag = "git" - - -def test(): - import tests.runTests - import unittest - unittest.main(defaultTest="discover", testLoader=tests.runTests.loader) diff --git a/eos/config.py b/eos/config.py index 01d65cfe0..38371e299 100644 --- a/eos/config.py +++ b/eos/config.py @@ -10,6 +10,9 @@ gamedata_connectionstring = 'sqlite:///' + unicode(realpath(join(dirname(abspath saveddata_connectionstring = 'sqlite:///' + unicode( realpath(join(dirname(abspath(__file__)), "..", "saveddata", "saveddata.db")), sys.getfilesystemencoding()) +settings = { + "setting1": True +} # Autodetect path, only change if the autodetection bugs out. path = dirname(unicode(__file__, sys.getfilesystemencoding())) diff --git a/eos/db/__init__.py b/eos/db/__init__.py index e0dd4d135..680c67e1e 100644 --- a/eos/db/__init__.py +++ b/eos/db/__init__.py @@ -20,13 +20,13 @@ import threading from sqlalchemy import MetaData, create_engine -from sqlalchemy.orm import sessionmaker, scoped_session -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy import pool - +from sqlalchemy.orm import sessionmaker import migration from eos import config +from logbook import Logger + +pyfalog = Logger(__name__) class ReadOnlyException(Exception): @@ -49,7 +49,9 @@ try: config.gamedata_version = gamedata_session.execute( "SELECT `field_value` FROM `metadata` WHERE `field_name` LIKE 'client_build'" ).fetchone()[0] -except: +except Exception as e: + pyfalog.warning("Missing gamedata version.") + pyfalog.critical(e) config.gamedata_version = None saveddata_connectionstring = config.saveddata_connectionstring @@ -62,16 +64,22 @@ if saveddata_connectionstring is not None: saveddata_meta = MetaData() saveddata_meta.bind = saveddata_engine saveddata_session = sessionmaker(bind=saveddata_engine, autoflush=False, expire_on_commit=False)() +else: + saveddata_meta = None # Lock controlling any changes introduced to session sd_lock = threading.Lock() # Import all the definitions for all our database stuff -from eos.db.gamedata import * -from eos.db.saveddata import * +# noinspection PyPep8 +from eos.db.gamedata import alphaClones, attribute, category, effect, group, icon, item, marketGroup, metaData, metaGroup, queries, traits, unit +# noinspection PyPep8 +from eos.db.saveddata import booster, cargo, character, crest, damagePattern, databaseRepair, drone, fighter, fit, implant, implantSet, loadDefaultDatabaseValues, miscData, module, override, price, queries, skill, targetResists, user # Import queries +# noinspection PyPep8 from eos.db.gamedata.queries import * +# noinspection PyPep8 from eos.db.saveddata.queries import * # If using in memory saveddata, you'll want to reflect it so the data structure is good. diff --git a/eos/db/gamedata/alphaClones.py b/eos/db/gamedata/alphaClones.py index 184ec1538..d18130358 100644 --- a/eos/db/gamedata/alphaClones.py +++ b/eos/db/gamedata/alphaClones.py @@ -21,7 +21,7 @@ from sqlalchemy import Column, String, Integer, Table, ForeignKey from sqlalchemy.orm import relation, mapper, synonym from eos.db import gamedata_meta -from eos.types import AlphaClone, AlphaCloneSkill +from eos.gamedata import AlphaClone, AlphaCloneSkill alphaclones_table = Table( "alphaClones", diff --git a/eos/db/gamedata/attribute.py b/eos/db/gamedata/attribute.py index e09e0865b..ac2f73978 100644 --- a/eos/db/gamedata/attribute.py +++ b/eos/db/gamedata/attribute.py @@ -22,7 +22,7 @@ from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.orm import relation, mapper, synonym, deferred from eos.db import gamedata_meta -from eos.types import Attribute, Icon, AttributeInfo, Unit +from eos.gamedata import Attribute, AttributeInfo, Unit, Icon typeattributes_table = Table("dgmtypeattribs", gamedata_meta, Column("value", Float), diff --git a/eos/db/gamedata/category.py b/eos/db/gamedata/category.py index d33cce130..884f93666 100644 --- a/eos/db/gamedata/category.py +++ b/eos/db/gamedata/category.py @@ -21,7 +21,7 @@ from sqlalchemy import Column, String, Integer, ForeignKey, Boolean, Table from sqlalchemy.orm import relation, mapper, synonym, deferred from eos.db import gamedata_meta -from eos.types import Category, Icon +from eos.gamedata import Category, Icon categories_table = Table("invcategories", gamedata_meta, Column("categoryID", Integer, primary_key=True), diff --git a/eos/db/gamedata/effect.py b/eos/db/gamedata/effect.py index 001d05162..d766b29eb 100644 --- a/eos/db/gamedata/effect.py +++ b/eos/db/gamedata/effect.py @@ -22,7 +22,7 @@ from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.orm import mapper, synonym, relation, deferred from eos.db import gamedata_meta -from eos.types import Effect, EffectInfo +from eos.gamedata import Effect, EffectInfo typeeffects_table = Table("dgmtypeeffects", gamedata_meta, Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True, index=True), diff --git a/eos/db/gamedata/group.py b/eos/db/gamedata/group.py index cbf0a34d8..cd6763923 100644 --- a/eos/db/gamedata/group.py +++ b/eos/db/gamedata/group.py @@ -21,7 +21,7 @@ from sqlalchemy import Column, String, Integer, Boolean, ForeignKey, Table from sqlalchemy.orm import relation, mapper, synonym, deferred from eos.db import gamedata_meta -from eos.types import Group, Icon, Category +from eos.gamedata import Category, Group, Icon groups_table = Table("invgroups", gamedata_meta, Column("groupID", Integer, primary_key=True), diff --git a/eos/db/gamedata/icon.py b/eos/db/gamedata/icon.py index d0315b28f..396c5c582 100644 --- a/eos/db/gamedata/icon.py +++ b/eos/db/gamedata/icon.py @@ -21,7 +21,7 @@ from sqlalchemy import Column, String, Integer, Table from sqlalchemy.orm import mapper, synonym, deferred from eos.db import gamedata_meta -from eos.types import Icon +from eos.gamedata import Icon icons_table = Table("icons", gamedata_meta, Column("iconID", Integer, primary_key=True), diff --git a/eos/db/gamedata/item.py b/eos/db/gamedata/item.py index f0100e761..da43f9ef2 100644 --- a/eos/db/gamedata/item.py +++ b/eos/db/gamedata/item.py @@ -23,7 +23,7 @@ from sqlalchemy.orm import relation, mapper, synonym, deferred from sqlalchemy.orm.collections import attribute_mapped_collection from eos.db import gamedata_meta -from eos.types import Icon, Attribute, Item, Effect, MetaType, Group, Traits +from eos.gamedata import Attribute, Effect, Group, Icon, Item, MetaType, Traits items_table = Table("invtypes", gamedata_meta, Column("typeID", Integer, primary_key=True), @@ -39,8 +39,8 @@ items_table = Table("invtypes", gamedata_meta, Column("iconID", Integer, ForeignKey("icons.iconID")), Column("groupID", Integer, ForeignKey("invgroups.groupID"), index=True)) -from .metaGroup import metatypes_table # noqa -from .traits import traits_table # noqa +from .metaGroup import metatypes_table # noqa +from .traits import traits_table # noqa mapper(Item, items_table, properties={"group": relation(Group, backref="items"), diff --git a/eos/db/gamedata/marketGroup.py b/eos/db/gamedata/marketGroup.py index b5b631ea3..c107c486d 100644 --- a/eos/db/gamedata/marketGroup.py +++ b/eos/db/gamedata/marketGroup.py @@ -21,7 +21,7 @@ from sqlalchemy import Column, String, Integer, Boolean, ForeignKey, Table from sqlalchemy.orm import relation, mapper, synonym, deferred from eos.db import gamedata_meta -from eos.types import Item, MarketGroup, Icon +from eos.gamedata import Icon, Item, MarketGroup marketgroups_table = Table("invmarketgroups", gamedata_meta, Column("marketGroupID", Integer, primary_key=True), diff --git a/eos/db/gamedata/metaData.py b/eos/db/gamedata/metaData.py index bb23e9315..d42f46a6f 100644 --- a/eos/db/gamedata/metaData.py +++ b/eos/db/gamedata/metaData.py @@ -21,7 +21,7 @@ from sqlalchemy import Column, Table, String from sqlalchemy.orm import mapper from eos.db import gamedata_meta -from eos.types import MetaData +from eos.gamedata import MetaData metadata_table = Table("metadata", gamedata_meta, Column("field_name", String, primary_key=True), diff --git a/eos/db/gamedata/metaGroup.py b/eos/db/gamedata/metaGroup.py index e5ed5c399..713e8a2c4 100644 --- a/eos/db/gamedata/metaGroup.py +++ b/eos/db/gamedata/metaGroup.py @@ -23,7 +23,7 @@ from sqlalchemy.orm import relation, mapper, synonym from eos.db import gamedata_meta from eos.db.gamedata.item import items_table -from eos.types import MetaGroup, Item, MetaType +from eos.gamedata import Item, MetaGroup, MetaType metagroups_table = Table("invmetagroups", gamedata_meta, Column("metaGroupID", Integer, primary_key=True), diff --git a/eos/db/gamedata/queries.py b/eos/db/gamedata/queries.py index d449dd062..673f1767f 100644 --- a/eos/db/gamedata/queries.py +++ b/eos/db/gamedata/queries.py @@ -21,13 +21,11 @@ from sqlalchemy.orm import join, exc from sqlalchemy.sql import and_, or_, select import eos.config -# TODO: Unsure which item the code below needs :( -# from eos.gamedata import Item -from eos.gamedata import Attribute from eos.db import gamedata_session from eos.db.gamedata.metaGroup import metatypes_table, items_table +from eos.db.gamedata.group import groups_table from eos.db.util import processEager, processWhere -from eos.types import Item, Category, Group, MarketGroup, AttributeInfo, MetaData, MetaGroup, AlphaClone +from eos.gamedata import AlphaClone, Attribute, Category, Group, Item, MarketGroup, MetaGroup, AttributeInfo, MetaData configVal = getattr(eos.config, "gamedataCache", None) if configVal is True: @@ -252,7 +250,7 @@ def searchItems(nameLike, where=None, join=None, eager=None): @cachedQuery(2, "where", "itemids") -def getVariations(itemids, where=None, eager=None): +def getVariations(itemids, groupIDs=None, where=None, eager=None): for itemid in itemids: if not isinstance(itemid, int): raise TypeError("All passed item IDs must be integers") @@ -265,7 +263,17 @@ def getVariations(itemids, where=None, eager=None): joinon = items_table.c.typeID == metatypes_table.c.typeID vars = gamedata_session.query(Item).options(*processEager(eager)).join((metatypes_table, joinon)).filter( filter).all() - return vars + + if vars: + return vars + elif groupIDs: + itemfilter = or_(*(groups_table.c.groupID == groupID for groupID in groupIDs)) + filter = processWhere(itemfilter, where) + joinon = items_table.c.groupID == groups_table.c.groupID + vars = gamedata_session.query(Item).options(*processEager(eager)).join((groups_table, joinon)).filter( + filter).all() + + return vars @cachedQuery(1, "attr") diff --git a/eos/db/gamedata/traits.py b/eos/db/gamedata/traits.py index 1dbc4d43d..d70c6ca58 100644 --- a/eos/db/gamedata/traits.py +++ b/eos/db/gamedata/traits.py @@ -2,7 +2,7 @@ from sqlalchemy import Column, Table, Integer, String, ForeignKey from sqlalchemy.orm import mapper from eos.db import gamedata_meta -from eos.types import Traits +from eos.gamedata import Traits traits_table = Table("invtraits", gamedata_meta, Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True), diff --git a/eos/db/gamedata/unit.py b/eos/db/gamedata/unit.py index 55594eb90..5c6556ef1 100644 --- a/eos/db/gamedata/unit.py +++ b/eos/db/gamedata/unit.py @@ -21,7 +21,7 @@ from sqlalchemy import Column, Table, Integer, String from sqlalchemy.orm import mapper, synonym from eos.db import gamedata_meta -from eos.types import Unit +from eos.gamedata import Unit groups_table = Table("dgmunits", gamedata_meta, Column("unitID", Integer, primary_key=True), diff --git a/eos/db/migration.py b/eos/db/migration.py index 6dc59565c..3d8921eb2 100644 --- a/eos/db/migration.py +++ b/eos/db/migration.py @@ -1,11 +1,11 @@ -import logging +from logbook import Logger import shutil import time import config import migrations -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) def getVersion(db): @@ -37,7 +37,7 @@ def update(saveddata_engine): for version in xrange(dbVersion, appVersion): func = migrations.updates[version + 1] if func: - logger.info("Applying database update: %d", version + 1) + pyfalog.info("Applying database update: {0}", version + 1) func(saveddata_engine) # when all is said and done, set version to current diff --git a/eos/db/migrations/upgrade15.py b/eos/db/migrations/upgrade15.py index 13852b035..feb824dad 100644 --- a/eos/db/migrations/upgrade15.py +++ b/eos/db/migrations/upgrade15.py @@ -4,8 +4,6 @@ Migration 15 - Delete projected modules on citadels """ -import sqlalchemy - def upgrade(saveddata_engine): sql = """ diff --git a/eos/db/migrations/upgrade17.py b/eos/db/migrations/upgrade17.py index 1d6a4cff8..90ed6e646 100644 --- a/eos/db/migrations/upgrade17.py +++ b/eos/db/migrations/upgrade17.py @@ -4,8 +4,6 @@ Migration 17 - Moves all fleet boosters to the new schema """ -import sqlalchemy - def upgrade(saveddata_engine): from eos.db import saveddata_session diff --git a/eos/db/migrations/upgrade19.py b/eos/db/migrations/upgrade19.py index 090f07dda..d10836e31 100644 --- a/eos/db/migrations/upgrade19.py +++ b/eos/db/migrations/upgrade19.py @@ -4,8 +4,6 @@ Migration 19 - Deletes broken references to fits from the commandFits table (see GH issue #844) """ -import sqlalchemy - def upgrade(saveddata_engine): from eos.db import saveddata_session diff --git a/eos/db/migrations/upgrade21.py b/eos/db/migrations/upgrade21.py new file mode 100644 index 000000000..e6101b3ad --- /dev/null +++ b/eos/db/migrations/upgrade21.py @@ -0,0 +1,10 @@ +""" +Migration 21 + +- Fixes discrepancy in drone table where we may have an amount active that is not equal to the amount in the stack + (we don't support activating only 2/5 drones). See GH issue #728 +""" + + +def upgrade(saveddata_engine): + saveddata_engine.execute("UPDATE drones SET amountActive = amount where amountActive > 0 AND amountActive <> amount;") diff --git a/eos/db/saveddata/booster.py b/eos/db/saveddata/booster.py index 9b8272540..11ef16506 100644 --- a/eos/db/saveddata/booster.py +++ b/eos/db/saveddata/booster.py @@ -22,7 +22,7 @@ from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.orm import mapper, relation from eos.db import saveddata_meta -from eos.types import Booster +from eos.saveddata.booster import Booster boosters_table = Table("boosters", saveddata_meta, Column("ID", Integer, primary_key=True), diff --git a/eos/db/saveddata/cargo.py b/eos/db/saveddata/cargo.py index d4b829777..a0222ac3b 100644 --- a/eos/db/saveddata/cargo.py +++ b/eos/db/saveddata/cargo.py @@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, ForeignKey from sqlalchemy.orm import mapper from eos.db import saveddata_meta -from eos.types import Cargo +from eos.saveddata.cargo import Cargo cargo_table = Table("cargo", saveddata_meta, Column("ID", Integer, primary_key=True), diff --git a/eos/db/saveddata/character.py b/eos/db/saveddata/character.py index aa9a99c74..aaa8a3829 100644 --- a/eos/db/saveddata/character.py +++ b/eos/db/saveddata/character.py @@ -23,7 +23,9 @@ from sqlalchemy.orm import relation, mapper from eos.db import saveddata_meta from eos.db.saveddata.implant import charImplants_table from eos.effectHandlerHelpers import HandledImplantBoosterList -from eos.types import Character, User, Skill, Implant +from eos.saveddata.implant import Implant +from eos.saveddata.user import User +from eos.saveddata.character import Character, Skill characters_table = Table("characters", saveddata_meta, Column("ID", Integer, primary_key=True), diff --git a/eos/db/saveddata/crest.py b/eos/db/saveddata/crest.py index 2cbeeb44a..c5cbcbb05 100644 --- a/eos/db/saveddata/crest.py +++ b/eos/db/saveddata/crest.py @@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, String from sqlalchemy.orm import mapper from eos.db import saveddata_meta -from eos.types import CrestChar +from eos.saveddata.crestchar import CrestChar crest_table = Table("crest", saveddata_meta, Column("ID", Integer, primary_key=True), diff --git a/eos/db/saveddata/damagePattern.py b/eos/db/saveddata/damagePattern.py index a9e59f228..d31c66ea6 100644 --- a/eos/db/saveddata/damagePattern.py +++ b/eos/db/saveddata/damagePattern.py @@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, ForeignKey, String from sqlalchemy.orm import mapper from eos.db import saveddata_meta -from eos.types import DamagePattern +from eos.saveddata.damagePattern import DamagePattern damagePatterns_table = Table("damagePatterns", saveddata_meta, Column("ID", Integer, primary_key=True), diff --git a/eos/db/saveddata/databaseRepair.py b/eos/db/saveddata/databaseRepair.py index 2644fd507..d16c412b0 100644 --- a/eos/db/saveddata/databaseRepair.py +++ b/eos/db/saveddata/databaseRepair.py @@ -17,13 +17,13 @@ # along with pyfa. If not, see . # =============================================================================== -import sqlalchemy -import logging +from sqlalchemy.exc import DatabaseError +from logbook import Logger -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) -class DatabaseCleanup: +class DatabaseCleanup(object): def __init__(self): pass @@ -32,8 +32,8 @@ class DatabaseCleanup: try: results = saveddata_engine.execute(query) return results - except sqlalchemy.exc.DatabaseError: - logger.error("Failed to connect to database or error executing query:\n%s", query) + except DatabaseError: + pyfalog.error("Failed to connect to database or error executing query:\n{0}", query) return None @staticmethod @@ -41,7 +41,7 @@ class DatabaseCleanup: # Find orphaned character skills. # This solves an issue where the character doesn't exist, but skills for that character do. # See issue #917 - logger.debug("Running database cleanup for character skills.") + pyfalog.debug("Running database cleanup for character skills.") query = "SELECT COUNT(*) AS num FROM characterSkills WHERE characterID NOT IN (SELECT ID from characters)" results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) @@ -53,14 +53,14 @@ class DatabaseCleanup: if row and row['num']: query = "DELETE FROM characterSkills WHERE characterID NOT IN (SELECT ID from characters)" delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) - logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) + pyfalog.error("Database corruption found. Cleaning up {0} records.", delete.rowcount) @staticmethod def OrphanedFitDamagePatterns(saveddata_engine): # Find orphaned damage patterns. # This solves an issue where the damage pattern doesn't exist, but fits reference the pattern. # See issue #777 - logger.debug("Running database cleanup for orphaned damage patterns attached to fits.") + pyfalog.debug("Running database cleanup for orphaned damage patterns attached to fits.") query = "SELECT COUNT(*) AS num FROM fits WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL" results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) @@ -80,20 +80,20 @@ class DatabaseCleanup: rows = uniform_results.fetchall() if len(rows) == 0: - logger.error("Missing uniform damage pattern.") + pyfalog.error("Missing uniform damage pattern.") elif len(rows) > 1: - logger.error("More than one uniform damage pattern found.") + pyfalog.error("More than one uniform damage pattern found.") else: uniform_damage_pattern_id = rows[0]['ID'] - update_query = "UPDATE 'fits' SET 'damagePatternID' = " + str(uniform_damage_pattern_id) + \ - " WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL" + update_query = "UPDATE 'fits' SET 'damagePatternID' = {} " \ + "WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL".format(uniform_damage_pattern_id) update_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, update_query) - logger.error("Database corruption found. Cleaning up %d records.", update_results.rowcount) + pyfalog.error("Database corruption found. Cleaning up {0} records.", update_results.rowcount) @staticmethod def OrphanedFitCharacterIDs(saveddata_engine): # Find orphaned character IDs. This solves an issue where the character doesn't exist, but fits reference the pattern. - logger.debug("Running database cleanup for orphaned characters attached to fits.") + pyfalog.debug("Running database cleanup for orphaned characters attached to fits.") query = "SELECT COUNT(*) AS num FROM fits WHERE characterID NOT IN (SELECT ID FROM characters) OR characterID IS NULL" results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) @@ -113,22 +113,22 @@ class DatabaseCleanup: rows = all5_results.fetchall() if len(rows) == 0: - logger.error("Missing 'All 5' character.") + pyfalog.error("Missing 'All 5' character.") elif len(rows) > 1: - logger.error("More than one 'All 5' character found.") + pyfalog.error("More than one 'All 5' character found.") else: all5_id = rows[0]['ID'] - update_query = "UPDATE 'fits' SET 'characterID' = " + str(all5_id) + \ + update_query = "UPDATE 'fits' SET 'characterID' = " + str(all5_id) + \ " WHERE characterID not in (select ID from characters) OR characterID IS NULL" update_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, update_query) - logger.error("Database corruption found. Cleaning up %d records.", update_results.rowcount) + pyfalog.error("Database corruption found. Cleaning up {0} records.", update_results.rowcount) @staticmethod def NullDamagePatternNames(saveddata_engine): # Find damage patterns that are missing the name. # This solves an issue where the damage pattern ends up with a name that is null. # See issue #949 - logger.debug("Running database cleanup for missing damage pattern names.") + pyfalog.debug("Running database cleanup for missing damage pattern names.") query = "SELECT COUNT(*) AS num FROM damagePatterns WHERE name IS NULL OR name = ''" results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) @@ -140,14 +140,14 @@ class DatabaseCleanup: if row and row['num']: query = "DELETE FROM damagePatterns WHERE name IS NULL OR name = ''" delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) - logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) + pyfalog.error("Database corruption found. Cleaning up {0} records.", delete.rowcount) @staticmethod def NullTargetResistNames(saveddata_engine): # Find target resists that are missing the name. # This solves an issue where the target resist ends up with a name that is null. # See issue #949 - logger.debug("Running database cleanup for missing target resist names.") + pyfalog.debug("Running database cleanup for missing target resist names.") query = "SELECT COUNT(*) AS num FROM targetResists WHERE name IS NULL OR name = ''" results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) @@ -159,4 +159,81 @@ class DatabaseCleanup: if row and row['num']: query = "DELETE FROM targetResists WHERE name IS NULL OR name = ''" delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) - logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) + pyfalog.error("Database corruption found. Cleaning up {0} records.", delete.rowcount) + + @staticmethod + def OrphanedFitIDItemID(saveddata_engine): + # Orphaned items that are missing the fit ID or item ID. + # See issue #954 + for table in ['drones', 'cargo', 'fighters']: + pyfalog.debug("Running database cleanup for orphaned {0} items.", table) + query = "SELECT COUNT(*) AS num FROM {} WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format( + table) + results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + + if results is None: + return + + row = results.first() + + if row and row['num']: + query = "DELETE FROM {} WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format( + table) + delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + pyfalog.error("Database corruption found. Cleaning up {0} records.", delete.rowcount) + + for table in ['modules']: + pyfalog.debug("Running database cleanup for orphaned {0} items.", table) + query = "SELECT COUNT(*) AS num FROM {} WHERE itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format( + table) + results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + + if results is None: + return + + row = results.first() + + if row and row['num']: + query = "DELETE FROM {} WHERE itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(table) + delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + pyfalog.error("Database corruption found. Cleaning up {0} records.", delete.rowcount) + + @staticmethod + def NullDamageTargetPatternValues(saveddata_engine): + # Find patterns that have null values + # See issue #954 + for profileType in ['damagePatterns', 'targetResists']: + for damageType in ['em', 'thermal', 'kinetic', 'explosive']: + pyfalog.debug("Running database cleanup for null {0} values. ({1})", profileType, damageType) + query = "SELECT COUNT(*) AS num FROM {0} WHERE {1}Amount IS NULL OR {1}Amount = ''".format(profileType, + damageType) + results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + + if results is None: + return + + row = results.first() + + if row and row['num']: + query = "UPDATE '{0}' SET '{1}Amount' = '0' WHERE {1}Amount IS NULL OR {1}Amount = ''".format(profileType, + damageType) + delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + pyfalog.error("Database corruption found. Cleaning up {0} records.", delete.rowcount) + + @staticmethod + def DuplicateSelectedAmmoName(saveddata_engine): + # Orphaned items that are missing the fit ID or item ID. + # See issue #954 + pyfalog.debug("Running database cleanup for duplicated selected ammo profiles.") + query = "SELECT COUNT(*) AS num FROM damagePatterns WHERE name = 'Selected Ammo'" + results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + + if results is None: + return + + row = results.first() + + if row and row['num'] > 1: + query = "DELETE FROM damagePatterns WHERE name = 'Selected Ammo'" + delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + pyfalog.error("Database corruption found. Cleaning up {0} records.", delete.rowcount) diff --git a/eos/db/saveddata/drone.py b/eos/db/saveddata/drone.py index 7163c06ff..6a5ffa8bb 100644 --- a/eos/db/saveddata/drone.py +++ b/eos/db/saveddata/drone.py @@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean from sqlalchemy.orm import mapper from eos.db import saveddata_meta -from eos.types import Drone +from eos.saveddata.drone import Drone drones_table = Table("drones", saveddata_meta, Column("groupID", Integer, primary_key=True), diff --git a/eos/db/saveddata/fighter.py b/eos/db/saveddata/fighter.py index 179edab11..bd7d8fd54 100644 --- a/eos/db/saveddata/fighter.py +++ b/eos/db/saveddata/fighter.py @@ -21,8 +21,9 @@ from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean from sqlalchemy.orm import mapper, relation from eos.db import saveddata_meta -from eos.types import Fighter, Fit -from eos.types import FighterAbility +from eos.saveddata.fighterAbility import FighterAbility +from eos.saveddata.fighter import Fighter +from eos.saveddata.fit import Fit fighters_table = Table("fighters", saveddata_meta, Column("groupID", Integer, primary_key=True), diff --git a/eos/db/saveddata/fit.py b/eos/db/saveddata/fit.py index c698a4ec7..8cbdb4d6f 100644 --- a/eos/db/saveddata/fit.py +++ b/eos/db/saveddata/fit.py @@ -32,8 +32,17 @@ from eos.db.saveddata.implant import fitImplants_table from eos.db.saveddata.module import modules_table from eos.effectHandlerHelpers import HandledModuleList, HandledImplantBoosterList, HandledProjectedModList, \ HandledDroneCargoList, HandledProjectedDroneList -from eos.types import Fit as es_Fit, Module, User, Booster, Drone, Fighter, Cargo, Implant, Character, DamagePattern, \ - TargetResists, ImplantLocation +from eos.saveddata.implant import Implant +from eos.saveddata.character import Character +from eos.saveddata.user import User +from eos.saveddata.fighter import Fighter +from eos.saveddata.fit import Fit as es_Fit, ImplantLocation +from eos.saveddata.drone import Drone +from eos.saveddata.booster import Booster +from eos.saveddata.module import Module +from eos.saveddata.cargo import Cargo +from eos.saveddata.damagePattern import DamagePattern +from eos.saveddata.targetResists import TargetResists fits_table = Table("fits", saveddata_meta, Column("ID", Integer, primary_key=True), @@ -131,7 +140,7 @@ mapper(es_Fit, fits_table, "_Fit__modules": relation( Module, collection_class=HandledModuleList, - primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False), # noqa + primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False), # noqa order_by=modules_table.c.position, cascade='all, delete, delete-orphan'), "_Fit__projectedModules": relation( @@ -139,7 +148,7 @@ mapper(es_Fit, fits_table, collection_class=HandledProjectedModList, cascade='all, delete, delete-orphan', single_parent=True, - primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)), # noqa + primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)), # noqa "owner": relation( User, backref="fits"), @@ -155,13 +164,13 @@ mapper(es_Fit, fits_table, collection_class=HandledDroneCargoList, cascade='all, delete, delete-orphan', single_parent=True, - primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)), # noqa + primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)), # noqa "_Fit__fighters": relation( Fighter, collection_class=HandledDroneCargoList, cascade='all, delete, delete-orphan', single_parent=True, - primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == False)), # noqa + primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == False)), # noqa "_Fit__cargo": relation( Cargo, collection_class=HandledDroneCargoList, @@ -173,13 +182,13 @@ mapper(es_Fit, fits_table, collection_class=HandledProjectedDroneList, cascade='all, delete, delete-orphan', single_parent=True, - primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)), # noqa + primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)), # noqa "_Fit__projectedFighters": relation( Fighter, collection_class=HandledProjectedDroneList, cascade='all, delete, delete-orphan', single_parent=True, - primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == True)), # noqa + primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == True)), # noqa "_Fit__implants": relation( Implant, collection_class=HandledImplantBoosterList, diff --git a/eos/db/saveddata/implant.py b/eos/db/saveddata/implant.py index 21145698f..c5bfc4cc5 100644 --- a/eos/db/saveddata/implant.py +++ b/eos/db/saveddata/implant.py @@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean from sqlalchemy.orm import mapper from eos.db import saveddata_meta -from eos.types import Implant +from eos.saveddata.implant import Implant implants_table = Table("implants", saveddata_meta, Column("ID", Integer, primary_key=True), diff --git a/eos/db/saveddata/implantSet.py b/eos/db/saveddata/implantSet.py index 042e986f6..955accc07 100644 --- a/eos/db/saveddata/implantSet.py +++ b/eos/db/saveddata/implantSet.py @@ -23,7 +23,8 @@ from sqlalchemy.orm import relation, mapper from eos.db import saveddata_meta from eos.db.saveddata.implant import implantsSetMap_table from eos.effectHandlerHelpers import HandledImplantBoosterList -from eos.types import Implant, ImplantSet +from eos.saveddata.implant import Implant +from eos.saveddata.implantSet import ImplantSet implant_set_table = Table("implantSets", saveddata_meta, Column("ID", Integer, primary_key=True), diff --git a/eos/db/saveddata/loadDefaultDatabaseValues.py b/eos/db/saveddata/loadDefaultDatabaseValues.py index 29534bc5e..befaad44b 100644 --- a/eos/db/saveddata/loadDefaultDatabaseValues.py +++ b/eos/db/saveddata/loadDefaultDatabaseValues.py @@ -26,7 +26,7 @@ class ImportError(Exception): pass -class DefaultDatabaseValues(): +class DefaultDatabaseValues(object): def __init__(self): pass diff --git a/eos/db/saveddata/miscData.py b/eos/db/saveddata/miscData.py index ac4c85b2d..2f6ceedeb 100644 --- a/eos/db/saveddata/miscData.py +++ b/eos/db/saveddata/miscData.py @@ -21,7 +21,7 @@ from sqlalchemy import Column, Table, String from sqlalchemy.orm import mapper from eos.db import saveddata_meta -from eos.types import MiscData +from eos.saveddata.miscData import MiscData miscdata_table = Table("miscdata", saveddata_meta, Column("fieldName", String, primary_key=True), diff --git a/eos/db/saveddata/module.py b/eos/db/saveddata/module.py index d6c2b068c..c5533d4ed 100644 --- a/eos/db/saveddata/module.py +++ b/eos/db/saveddata/module.py @@ -21,7 +21,8 @@ from sqlalchemy import Table, Column, Integer, ForeignKey, CheckConstraint, Bool from sqlalchemy.orm import relation, mapper from eos.db import saveddata_meta -from eos.types import Module, Fit +from eos.saveddata.module import Module +from eos.saveddata.fit import Fit modules_table = Table("modules", saveddata_meta, Column("ID", Integer, primary_key=True), diff --git a/eos/db/saveddata/override.py b/eos/db/saveddata/override.py index e260cd3df..2ca622966 100644 --- a/eos/db/saveddata/override.py +++ b/eos/db/saveddata/override.py @@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, Float from sqlalchemy.orm import mapper from eos.db import saveddata_meta -from eos.types import Override +from eos.saveddata.override import Override overrides_table = Table("overrides", saveddata_meta, Column("itemID", Integer, primary_key=True, index=True), diff --git a/eos/db/saveddata/price.py b/eos/db/saveddata/price.py index 021d341e8..2135d20cf 100644 --- a/eos/db/saveddata/price.py +++ b/eos/db/saveddata/price.py @@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Float, Integer from sqlalchemy.orm import mapper from eos.db import saveddata_meta -from eos.types import Price +from eos.saveddata.price import Price prices_table = Table("prices", saveddata_meta, Column("typeID", Integer, primary_key=True), diff --git a/eos/db/saveddata/queries.py b/eos/db/saveddata/queries.py index 484ea7a45..16f6a3bf9 100644 --- a/eos/db/saveddata/queries.py +++ b/eos/db/saveddata/queries.py @@ -22,8 +22,17 @@ from sqlalchemy.sql import and_ from eos.db import saveddata_session, sd_lock from eos.db.saveddata.fit import projectedFits_table from eos.db.util import processEager, processWhere +from eos.saveddata.price import Price +from eos.saveddata.user import User +from eos.saveddata.crestchar import CrestChar +from eos.saveddata.damagePattern import DamagePattern +from eos.saveddata.targetResists import TargetResists +from eos.saveddata.character import Character +from eos.saveddata.implantSet import ImplantSet +from eos.saveddata.fit import Fit +from eos.saveddata.miscData import MiscData +from eos.saveddata.override import Override -from eos.types import * import eos.config configVal = getattr(eos.config, "saveddataCache", None) @@ -59,6 +68,7 @@ if configVal is True: def checkAndReturn(*args, **kwargs): useCache = kwargs.pop("useCache", True) cacheKey = [] + items = None cacheKey.extend(args) for keyword in keywords: cacheKey.append(kwargs.get(keyword)) diff --git a/eos/db/saveddata/skill.py b/eos/db/saveddata/skill.py index 1c488a2cd..5b279e0d3 100644 --- a/eos/db/saveddata/skill.py +++ b/eos/db/saveddata/skill.py @@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, ForeignKey from sqlalchemy.orm import mapper from eos.db import saveddata_meta -from eos.types import Skill +from eos.saveddata.character import Skill skills_table = Table("characterSkills", saveddata_meta, Column("characterID", ForeignKey("characters.ID"), primary_key=True, index=True), diff --git a/eos/db/saveddata/targetResists.py b/eos/db/saveddata/targetResists.py index 88c1ca104..e8f125c5c 100644 --- a/eos/db/saveddata/targetResists.py +++ b/eos/db/saveddata/targetResists.py @@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, Float, ForeignKey, String from sqlalchemy.orm import mapper from eos.db import saveddata_meta -from eos.types import TargetResists +from eos.saveddata.targetResists import TargetResists targetResists_table = Table("targetResists", saveddata_meta, Column("ID", Integer, primary_key=True), diff --git a/eos/db/saveddata/user.py b/eos/db/saveddata/user.py index f7ec10629..b4d20fa7f 100644 --- a/eos/db/saveddata/user.py +++ b/eos/db/saveddata/user.py @@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, String, Boolean from sqlalchemy.orm import mapper from eos.db import saveddata_meta -from eos.types import User +from eos.saveddata.user import User users_table = Table("users", saveddata_meta, Column("ID", Integer, primary_key=True), diff --git a/eos/effectHandlerHelpers.py b/eos/effectHandlerHelpers.py index b0a61be69..0b0b5e795 100644 --- a/eos/effectHandlerHelpers.py +++ b/eos/effectHandlerHelpers.py @@ -17,12 +17,9 @@ # along with eos. If not, see . # =============================================================================== -# from sqlalchemy.orm.attributes import flag_modified -import logging +from logbook import Logger -import eos.db - -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class HandledList(list): @@ -139,10 +136,6 @@ class HandledModuleList(HandledList): self.remove(mod) return - # fix for #529, where a module may be in incorrect state after CCP changes mechanics of module - if not mod.isValidState(mod.state): - mod.state = eos.types.State.ONLINE - def insert(self, index, mod): mod.position = index i = index @@ -162,7 +155,7 @@ class HandledModuleList(HandledList): def toDummy(self, index): mod = self[index] if not mod.isEmpty: - dummy = eos.types.Module.buildEmpty(mod.slot) + dummy = mod.buildEmpty(mod.slot) dummy.position = index self[index] = dummy @@ -205,7 +198,7 @@ class HandledImplantBoosterList(HandledList): # if needed, remove booster that was occupying slot oldObj = next((m for m in self if m.slot == thing.slot), None) if oldObj: - logging.info("Slot %d occupied with %s, replacing with %s", thing.slot, oldObj.item.name, thing.item.name) + pyfalog.info("Slot {0} occupied with {1}, replacing with {2}", thing.slot, oldObj.item.name, thing.item.name) oldObj.itemID = 0 # hack to remove from DB. See GH issue #324 self.remove(oldObj) @@ -229,7 +222,7 @@ class HandledProjectedModList(HandledList): oldEffect = next((m for m in self if m.item.group.name == "Effect Beacon"), None) if oldEffect: - logging.info("System effect occupied with %s, replacing with %s", oldEffect.item.name, proj.item.name) + pyfalog.info("System effect occupied with {0}, replacing with {1}", oldEffect.item.name, proj.item.name) self.remove(oldEffect) HandledList.append(self, proj) diff --git a/eos/effects/adaptivearmorhardener.py b/eos/effects/adaptivearmorhardener.py index 33e9f143c..8d017715d 100644 --- a/eos/effects/adaptivearmorhardener.py +++ b/eos/effects/adaptivearmorhardener.py @@ -2,9 +2,9 @@ # # Used by: # Module: Reactive Armor Hardener -import logging +from logbook import Logger -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) runTime = "late" type = "active" @@ -15,8 +15,6 @@ def handler(fit, module, context): # Skip if there is no damage pattern. Example: projected ships or fleet boosters if damagePattern: - # logger.debug("Damage Pattern: %f/%f/%f/%f", damagePattern.emAmount, damagePattern.thermalAmount, damagePattern.kineticAmount, damagePattern.explosiveAmount) - # logger.debug("Original Armor Resists: %f/%f/%f/%f", fit.ship.getModifiedItemAttr('armorEmDamageResonance'), fit.ship.getModifiedItemAttr('armorThermalDamageResonance'), fit.ship.getModifiedItemAttr('armorKineticDamageResonance'), fit.ship.getModifiedItemAttr('armorExplosiveDamageResonance')) # Populate a tuple with the damage profile modified by current armor resists. baseDamageTaken = ( @@ -25,7 +23,7 @@ def handler(fit, module, context): damagePattern.kineticAmount * fit.ship.getModifiedItemAttr('armorKineticDamageResonance'), damagePattern.explosiveAmount * fit.ship.getModifiedItemAttr('armorExplosiveDamageResonance'), ) - # logger.debug("Damage Adjusted for Armor Resists: %f/%f/%f/%f", baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3]) + # pyfalog.debug("Damage Adjusted for Armor Resists: %f/%f/%f/%f", baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3]) resistanceShiftAmount = module.getModifiedItemAttr( 'resistanceShiftAmount') / 100 # The attribute is in percent and we want a fraction @@ -41,7 +39,7 @@ def handler(fit, module, context): cycleList = [] loopStart = -20 for num in range(50): - # logger.debug("Starting cycle %d.", num) + # pyfalog.debug("Starting cycle %d.", num) # The strange order is to emulate the ingame sorting when different types have taken the same amount of damage. # This doesn't take into account stacking penalties. In a few cases fitting a Damage Control causes an inaccurate result. damagePattern_tuples = [ @@ -50,7 +48,6 @@ def handler(fit, module, context): (2, baseDamageTaken[2] * RAHResistance[2], RAHResistance[2]), (1, baseDamageTaken[1] * RAHResistance[1], RAHResistance[1]), ] - # logger.debug("Damage taken this cycle: %f/%f/%f/%f", damagePattern_tuples[0][1], damagePattern_tuples[3][1], damagePattern_tuples[2][1], damagePattern_tuples[1][1]) # Sort the tuple to drop the highest damage value to the bottom sortedDamagePattern_tuples = sorted(damagePattern_tuples, key=lambda damagePattern: damagePattern[1]) @@ -80,7 +77,7 @@ def handler(fit, module, context): RAHResistance[sortedDamagePattern_tuples[1][0]] = sortedDamagePattern_tuples[1][2] + change1 RAHResistance[sortedDamagePattern_tuples[2][0]] = sortedDamagePattern_tuples[2][2] + change2 RAHResistance[sortedDamagePattern_tuples[3][0]] = sortedDamagePattern_tuples[3][2] + change3 - # logger.debug("Resistances shifted to %f/%f/%f/%f", RAHResistance[0], RAHResistance[1], RAHResistance[2], RAHResistance[3]) + # pyfalog.debug("Resistances shifted to %f/%f/%f/%f", RAHResistance[0], RAHResistance[1], RAHResistance[2], RAHResistance[3]) # See if the current RAH profile has been encountered before, indicating a loop. for i, val in enumerate(cycleList): @@ -90,7 +87,7 @@ def handler(fit, module, context): abs(RAHResistance[2] - val[2]) <= tolerance and \ abs(RAHResistance[3] - val[3]) <= tolerance: loopStart = i - # logger.debug("Loop found: %d-%d", loopStart, num) + # pyfalog.debug("Loop found: %d-%d", loopStart, num) break if loopStart >= 0: break @@ -98,7 +95,7 @@ def handler(fit, module, context): cycleList.append(list(RAHResistance)) if loopStart < 0: - logger.error("Reactive Armor Hardener failed to find equilibrium. Damage profile after armor: %f/%f/%f/%f", + pyfalog.error("Reactive Armor Hardener failed to find equilibrium. Damage profile after armor: {0}/{1}/{2}/{3}", baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3]) # Average the profiles in the RAH loop, or the last 20 if it didn't find a loop. @@ -113,7 +110,7 @@ def handler(fit, module, context): average[i] = round(average[i] / numCycles, 3) # Set the new resistances - # logger.debug("Setting new resist profile: %f/%f/%f/%f", average[0], average[1], average[2],average[3]) + # pyfalog.debug("Setting new resist profile: %f/%f/%f/%f", average[0], average[1], average[2],average[3]) for i, attr in enumerate(( 'armorEmDamageResonance', 'armorThermalDamageResonance', 'armorKineticDamageResonance', 'armorExplosiveDamageResonance')): diff --git a/eos/effects/ammoinfluencecapneed.py b/eos/effects/ammoinfluencecapneed.py index 3b696d552..c30a91bd1 100644 --- a/eos/effects/ammoinfluencecapneed.py +++ b/eos/effects/ammoinfluencecapneed.py @@ -1,7 +1,7 @@ # ammoInfluenceCapNeed # # Used by: -# Items from category: Charge (465 of 899) +# Items from category: Charge (465 of 912) # Charges from group: Frequency Crystal (185 of 185) # Charges from group: Hybrid Charge (209 of 209) type = "passive" diff --git a/eos/effects/ammoinfluencerange.py b/eos/effects/ammoinfluencerange.py index 5569a3dfb..ea6860bbe 100644 --- a/eos/effects/ammoinfluencerange.py +++ b/eos/effects/ammoinfluencerange.py @@ -1,7 +1,7 @@ # ammoInfluenceRange # # Used by: -# Items from category: Charge (571 of 899) +# Items from category: Charge (571 of 912) type = "passive" diff --git a/eos/effects/ammospeedmultiplier.py b/eos/effects/ammospeedmultiplier.py index 14f4298f5..afef8b267 100644 --- a/eos/effects/ammospeedmultiplier.py +++ b/eos/effects/ammospeedmultiplier.py @@ -1,7 +1,7 @@ # ammoSpeedMultiplier # # Used by: -# Charges from group: Festival Charges (9 of 9) +# Charges from group: Festival Charges (22 of 22) # Charges from group: Interdiction Probe (2 of 2) # Charges from group: Survey Probe (3 of 3) type = "passive" diff --git a/eos/effects/armorhpmultiply.py b/eos/effects/armorhpmultiply.py index d9326eb73..25039f35f 100644 --- a/eos/effects/armorhpmultiply.py +++ b/eos/effects/armorhpmultiply.py @@ -3,7 +3,6 @@ # Used by: # Modules from group: Armor Coating (202 of 202) # Modules from group: Armor Plating Energized (187 of 187) -# Modules named like: QA Multiship Module Players (4 of 4) type = "passive" diff --git a/eos/effects/armorrepairamountbonussubcap.py b/eos/effects/armorrepairamountbonussubcap.py index e50b74ab9..725c43f33 100644 --- a/eos/effects/armorrepairamountbonussubcap.py +++ b/eos/effects/armorrepairamountbonussubcap.py @@ -1,7 +1,7 @@ # armorRepairAmountBonusSubcap # # Used by: -# Implants named like: Grade Asklepian (15 of 16) +# Implants named like: grade Asklepian (15 of 18) type = "passive" diff --git a/eos/effects/dohacking.py b/eos/effects/dohacking.py index b41b91069..13412daba 100644 --- a/eos/effects/dohacking.py +++ b/eos/effects/dohacking.py @@ -2,7 +2,6 @@ # # Used by: # Modules from group: Data Miners (15 of 16) -# Module: QA Cross Protocol Analyzer type = "active" diff --git a/eos/effects/electronicattributemodifyonline.py b/eos/effects/electronicattributemodifyonline.py index 28197f971..9e1f52524 100644 --- a/eos/effects/electronicattributemodifyonline.py +++ b/eos/effects/electronicattributemodifyonline.py @@ -2,7 +2,6 @@ # # Used by: # Modules from group: Automated Targeting System (6 of 6) -# Module: QA Damage Module type = "passive" diff --git a/eos/effects/elitebonuscommanddestroyerinfohidden1.py b/eos/effects/elitebonuscommanddestroyerinfohidden1.py index 4ffc352e0..cf31b2b1b 100644 --- a/eos/effects/elitebonuscommanddestroyerinfohidden1.py +++ b/eos/effects/elitebonuscommanddestroyerinfohidden1.py @@ -3,4 +3,7 @@ type = "passive" def handler(fit, src, context): - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Information Command Specialist"), "commandBonusHidden", src.getModifiedItemAttr("eliteBonusCommandDestroyer1"), skill="Command Destroyers") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Information Command Specialist"), + "commandBonusHidden", + src.getModifiedItemAttr("eliteBonusCommandDestroyer1"), + skill="Command Destroyers") diff --git a/eos/effects/elitebonuslogisticremotearmorrepairoptimalfalloff1.py b/eos/effects/elitebonuslogisticremotearmorrepairoptimalfalloff1.py index 7f8e9fec3..cacbd4478 100644 --- a/eos/effects/elitebonuslogisticremotearmorrepairoptimalfalloff1.py +++ b/eos/effects/elitebonuslogisticremotearmorrepairoptimalfalloff1.py @@ -6,5 +6,11 @@ type = "passive" def handler(fit, src, context): - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "falloffEffectiveness", src.getModifiedItemAttr("eliteBonusLogistics1"), skill="Logistics Cruisers") - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "maxRange", src.getModifiedItemAttr("eliteBonusLogistics1"), skill="Logistics Cruisers") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), + "falloffEffectiveness", + src.getModifiedItemAttr("eliteBonusLogistics1"), + skill="Logistics Cruisers") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), + "maxRange", + src.getModifiedItemAttr("eliteBonusLogistics1"), + skill="Logistics Cruisers") diff --git a/eos/effects/energydestabilizationnew.py b/eos/effects/energydestabilizationnew.py index 52a6b40ee..7a45fe8b7 100644 --- a/eos/effects/energydestabilizationnew.py +++ b/eos/effects/energydestabilizationnew.py @@ -1,5 +1,5 @@ # Not used by any item -from eos.types import State +from eos.saveddata.module import State type = "active", "projected" diff --git a/eos/effects/energyneutralizerfalloff.py b/eos/effects/energyneutralizerfalloff.py index e4c22c3fa..bdaaa2d3a 100644 --- a/eos/effects/energyneutralizerfalloff.py +++ b/eos/effects/energyneutralizerfalloff.py @@ -2,7 +2,7 @@ # # Used by: # Modules from group: Energy Neutralizer (51 of 51) -from eos.types import State +from eos.saveddata.module import State type = "active", "projected" diff --git a/eos/effects/energyweapondamagemultiply.py b/eos/effects/energyweapondamagemultiply.py index c1abce625..0eb10ef75 100644 --- a/eos/effects/energyweapondamagemultiply.py +++ b/eos/effects/energyweapondamagemultiply.py @@ -2,8 +2,6 @@ # # Used by: # Modules from group: Heat Sink (18 of 18) -# Modules named like: QA Multiship Module Players (4 of 4) -# Module: QA Damage Module type = "passive" diff --git a/eos/effects/entityenergyneutralizerfalloff.py b/eos/effects/entityenergyneutralizerfalloff.py index a02abca12..f5aa5ead1 100644 --- a/eos/effects/entityenergyneutralizerfalloff.py +++ b/eos/effects/entityenergyneutralizerfalloff.py @@ -2,7 +2,7 @@ # # Used by: # Drones from group: Energy Neutralizer Drone (3 of 3) -from eos.types import State +from eos.saveddata.module import State type = "active", "projected" diff --git a/eos/effects/gunneryfalloffbonusonline.py b/eos/effects/gunneryfalloffbonusonline.py index 553f9d428..00532b254 100644 --- a/eos/effects/gunneryfalloffbonusonline.py +++ b/eos/effects/gunneryfalloffbonusonline.py @@ -2,7 +2,6 @@ # # Used by: # Modules from group: Tracking Enhancer (10 of 10) -# Module: QA Damage Module type = "passive" diff --git a/eos/effects/gunnerymaxrangebonusonline.py b/eos/effects/gunnerymaxrangebonusonline.py index 6f1bc78ed..284d5b3ca 100644 --- a/eos/effects/gunnerymaxrangebonusonline.py +++ b/eos/effects/gunnerymaxrangebonusonline.py @@ -2,7 +2,6 @@ # # Used by: # Modules from group: Tracking Enhancer (10 of 10) -# Module: QA Damage Module type = "passive" diff --git a/eos/effects/gunnerytrackingspeedbonusonline.py b/eos/effects/gunnerytrackingspeedbonusonline.py index f7bed1ecd..bec1111d7 100644 --- a/eos/effects/gunnerytrackingspeedbonusonline.py +++ b/eos/effects/gunnerytrackingspeedbonusonline.py @@ -2,7 +2,6 @@ # # Used by: # Modules from group: Tracking Enhancer (10 of 10) -# Module: QA Damage Module type = "passive" diff --git a/eos/effects/hybridweapondamagemultiply.py b/eos/effects/hybridweapondamagemultiply.py index 94f6149e3..0fe01369c 100644 --- a/eos/effects/hybridweapondamagemultiply.py +++ b/eos/effects/hybridweapondamagemultiply.py @@ -2,8 +2,6 @@ # # Used by: # Modules from group: Magnetic Field Stabilizer (14 of 14) -# Modules named like: QA Multiship Module Players (4 of 4) -# Module: QA Damage Module type = "passive" diff --git a/eos/effects/miningforemanburstbonusics2.py b/eos/effects/miningforemanburstbonusics2.py index 485138a26..0e1140e0e 100644 --- a/eos/effects/miningforemanburstbonusics2.py +++ b/eos/effects/miningforemanburstbonusics2.py @@ -6,13 +6,13 @@ type = "passive" def handler(fit, src, context): - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff4Multiplier", + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff4Value", src.getModifiedItemAttr("shipBonusICS2"), skill="Industrial Command Ships") - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff1Multiplier", + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff1Value", src.getModifiedItemAttr("shipBonusICS2"), skill="Industrial Command Ships") fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "buffDuration", src.getModifiedItemAttr("shipBonusICS2"), skill="Industrial Command Ships") - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff3Multiplier", + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff3Value", src.getModifiedItemAttr("shipBonusICS2"), skill="Industrial Command Ships") - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff2Multiplier", + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff2Value", src.getModifiedItemAttr("shipBonusICS2"), skill="Industrial Command Ships") diff --git a/eos/effects/missiledmgbonus.py b/eos/effects/missiledmgbonus.py index d18ce2e30..48a845345 100644 --- a/eos/effects/missiledmgbonus.py +++ b/eos/effects/missiledmgbonus.py @@ -2,7 +2,6 @@ # # Used by: # Modules from group: Ballistic Control system (17 of 17) -# Modules named like: QA Multiship Module Players (4 of 4) type = "passive" diff --git a/eos/effects/modifyshieldrechargerate.py b/eos/effects/modifyshieldrechargerate.py index 2a1c209ad..bebf517a7 100644 --- a/eos/effects/modifyshieldrechargerate.py +++ b/eos/effects/modifyshieldrechargerate.py @@ -6,7 +6,6 @@ # Modules from group: Reactor Control Unit (22 of 22) # Modules from group: Shield Recharger (4 of 4) # Modules named like: Flux Coil (12 of 12) -# Modules named like: QA Multiship Module Players (4 of 4) type = "passive" diff --git a/eos/effects/remoteweapondisruptentity.py b/eos/effects/npcentityweapondisruptor.py similarity index 97% rename from eos/effects/remoteweapondisruptentity.py rename to eos/effects/npcentityweapondisruptor.py index 486f67f58..e2fb7bf4a 100644 --- a/eos/effects/remoteweapondisruptentity.py +++ b/eos/effects/npcentityweapondisruptor.py @@ -1,4 +1,4 @@ -# remoteWeaponDisruptEntity +# npcEntityWeaponDisruptor # # Used by: # Drones named like: TD (3 of 3) diff --git a/eos/effects/overloadselfdurationbonus.py b/eos/effects/overloadselfdurationbonus.py index 757ba6d76..356eab98a 100644 --- a/eos/effects/overloadselfdurationbonus.py +++ b/eos/effects/overloadselfdurationbonus.py @@ -11,8 +11,6 @@ # Modules from group: Smart Bomb (118 of 118) # Modules from group: Warp Disrupt Field Generator (7 of 7) # Modules named like: Ancillary Remote (8 of 8) -# Module: QA Remote Armor Repair System - 5 Players -# Module: QA Shield Transporter - 5 Players # Module: Reactive Armor Hardener # Module: Target Spectrum Breaker type = "overheat" diff --git a/eos/effects/projectileweapondamagemultiply.py b/eos/effects/projectileweapondamagemultiply.py index 7037897d8..711075efb 100644 --- a/eos/effects/projectileweapondamagemultiply.py +++ b/eos/effects/projectileweapondamagemultiply.py @@ -2,8 +2,6 @@ # # Used by: # Modules from group: Gyrostabilizer (13 of 13) -# Modules named like: QA Multiship Module Players (4 of 4) -# Module: QA Damage Module type = "passive" diff --git a/eos/effects/rolebonusremotearmorrepairoptimalfalloff.py b/eos/effects/rolebonusremotearmorrepairoptimalfalloff.py index c286514f2..fae8acfac 100644 --- a/eos/effects/rolebonusremotearmorrepairoptimalfalloff.py +++ b/eos/effects/rolebonusremotearmorrepairoptimalfalloff.py @@ -6,5 +6,9 @@ type = "passive" def handler(fit, src, context): - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "falloffEffectiveness", src.getModifiedItemAttr("roleBonusRepairRange")) - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "maxRange", src.getModifiedItemAttr("roleBonusRepairRange")) + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), + "falloffEffectiveness", + src.getModifiedItemAttr("roleBonusRepairRange")) + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), + "maxRange", + src.getModifiedItemAttr("roleBonusRepairRange")) diff --git a/eos/effects/scanstrengthbonuspercentactivate.py b/eos/effects/scanstrengthbonuspercentactivate.py index 2ce6a627a..10b66e3c4 100644 --- a/eos/effects/scanstrengthbonuspercentactivate.py +++ b/eos/effects/scanstrengthbonuspercentactivate.py @@ -1,7 +1,4 @@ -# scanStrengthBonusPercentActivate -# -# Used by: -# Module: QA ECCM +# Not used by any item type = "active" diff --git a/eos/effects/scanstrengthbonuspercentpassive.py b/eos/effects/scanstrengthbonuspercentpassive.py index 7e0f43c1d..d00f4e2b6 100644 --- a/eos/effects/scanstrengthbonuspercentpassive.py +++ b/eos/effects/scanstrengthbonuspercentpassive.py @@ -1,7 +1,7 @@ # scanStrengthBonusPercentPassive # # Used by: -# Implants named like: High grade (20 of 61) +# Implants named like: High grade (20 of 66) type = "passive" diff --git a/eos/effects/setbonusasklepian.py b/eos/effects/setbonusasklepian.py index 5d063f470..853626c7d 100644 --- a/eos/effects/setbonusasklepian.py +++ b/eos/effects/setbonusasklepian.py @@ -1,8 +1,7 @@ # setBonusAsklepian # # Used by: -# Implants named like: Grade Asklepian (16 of 16) -# Implants named like: grade Asklepian Omega (2 of 2) +# Implants named like: grade Asklepian (18 of 18) runTime = "early" type = "passive" diff --git a/eos/effects/shieldtransfer.py b/eos/effects/shieldtransfer.py index b55165a32..54bbc1112 100644 --- a/eos/effects/shieldtransfer.py +++ b/eos/effects/shieldtransfer.py @@ -1,7 +1,4 @@ -# shieldTransfer -# -# Used by: -# Module: QA Shield Transporter - 5 Players +# Not used by any item type = "projected", "active" diff --git a/eos/effects/shipbonusforceauxiliarya4warfarelinksbonus.py b/eos/effects/shipbonusforceauxiliarya4warfarelinksbonus.py index a8378046b..824f57069 100644 --- a/eos/effects/shipbonusforceauxiliarya4warfarelinksbonus.py +++ b/eos/effects/shipbonusforceauxiliarya4warfarelinksbonus.py @@ -6,8 +6,18 @@ type = "passive" def handler(fit, src, context): - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "warfareBuff4Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "warfareBuff3Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "warfareBuff1Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "buffDuration", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "warfareBuff2Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or + mod.item.requiresSkill("Information Command"), + "warfareBuff4Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or + mod.item.requiresSkill("Information Command"), + "warfareBuff3Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or + mod.item.requiresSkill("Information Command"), + "warfareBuff1Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or + mod.item.requiresSkill("Information Command"), + "buffDuration", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or + mod.item.requiresSkill("Information Command"), + "warfareBuff2Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") diff --git a/eos/effects/remoteguidancedisruptfalloff.py b/eos/effects/shipmoduleguidancedisruptor.py similarity index 95% rename from eos/effects/remoteguidancedisruptfalloff.py rename to eos/effects/shipmoduleguidancedisruptor.py index 5dfbeba41..1588d52d7 100644 --- a/eos/effects/remoteguidancedisruptfalloff.py +++ b/eos/effects/shipmoduleguidancedisruptor.py @@ -1,4 +1,4 @@ -# remoteGuidanceDisruptFalloff +# shipModuleGuidanceDisruptor # # Used by: # Variations of module: Guidance Disruptor I (6 of 6) diff --git a/eos/effects/remotetrackingassistfalloff.py b/eos/effects/shipmoduleremotetrackingcomputer.py similarity index 96% rename from eos/effects/remotetrackingassistfalloff.py rename to eos/effects/shipmoduleremotetrackingcomputer.py index 411d4fc05..83a63b97f 100644 --- a/eos/effects/remotetrackingassistfalloff.py +++ b/eos/effects/shipmoduleremotetrackingcomputer.py @@ -1,4 +1,4 @@ -# remoteTrackingAssistFalloff +# shipModuleRemoteTrackingComputer # # Used by: # Modules from group: Remote Tracking Computer (8 of 8) diff --git a/eos/effects/remotetrackingdisruptfalloff.py b/eos/effects/shipmoduletrackingdisruptor.py similarity index 96% rename from eos/effects/remotetrackingdisruptfalloff.py rename to eos/effects/shipmoduletrackingdisruptor.py index 18fd3239e..e970dae3c 100644 --- a/eos/effects/remotetrackingdisruptfalloff.py +++ b/eos/effects/shipmoduletrackingdisruptor.py @@ -1,4 +1,4 @@ -# remoteTrackingDisruptFalloff +# shipModuleTrackingDisruptor # # Used by: # Variations of module: Tracking Disruptor I (6 of 6) diff --git a/eos/effects/shipscanresolutionbonusonline.py b/eos/effects/shipscanresolutionbonusonline.py index 1de730658..041b72b75 100644 --- a/eos/effects/shipscanresolutionbonusonline.py +++ b/eos/effects/shipscanresolutionbonusonline.py @@ -2,7 +2,6 @@ # # Used by: # Modules from group: Signal Amplifier (7 of 7) -# Module: QA Damage Module type = "passive" diff --git a/eos/effects/standardmissilesskillboostmissilevelocitybonus.py b/eos/effects/standardmissilesskillboostmissilevelocitybonus.py deleted file mode 100644 index f65a5bc34..000000000 --- a/eos/effects/standardmissilesskillboostmissilevelocitybonus.py +++ /dev/null @@ -1,10 +0,0 @@ -# standardMissilesSkillBoostMissileVelocityBonus -# -# Used by: -# Skill: Defender Missiles -type = "passive" - - -def handler(fit, skill, context): - fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Defender Missiles"), - "maxVelocity", skill.getModifiedItemAttr("missileVelocityBonus") * skill.level) diff --git a/eos/effects/structuralanalysiseffect.py b/eos/effects/structuralanalysiseffect.py index de26cb71b..b94832ca0 100644 --- a/eos/effects/structuralanalysiseffect.py +++ b/eos/effects/structuralanalysiseffect.py @@ -3,7 +3,6 @@ # Used by: # Implants named like: Inherent Implants 'Noble' Repair Proficiency RP (6 of 6) # Modules named like: Auxiliary Nano Pump (8 of 8) -# Modules named like: QA Multiship Module Players (4 of 4) # Implant: Imperial Navy Modified 'Noble' Implant type = "passive" diff --git a/eos/effects/structureenergyneutralizerfalloff.py b/eos/effects/structureenergyneutralizerfalloff.py index e383f523b..02ee9b4f8 100644 --- a/eos/effects/structureenergyneutralizerfalloff.py +++ b/eos/effects/structureenergyneutralizerfalloff.py @@ -1,5 +1,5 @@ # Not used by any item -from eos.types import State +from eos.saveddata.module import State type = "active", "projected" diff --git a/eos/effects/structurehpmultiply.py b/eos/effects/structurehpmultiply.py index 33fc44bf6..0b7618e97 100644 --- a/eos/effects/structurehpmultiply.py +++ b/eos/effects/structurehpmultiply.py @@ -3,7 +3,6 @@ # Used by: # Modules from group: Nanofiber Internal Structure (7 of 7) # Modules from group: Reinforced Bulkhead (8 of 8) -# Modules named like: QA Multiship Module Players (4 of 4) type = "passive" diff --git a/eos/effects/structurewarpscrambleblockmwdwithnpceffect.py b/eos/effects/structurewarpscrambleblockmwdwithnpceffect.py index 4bf33ce41..4103b3f42 100644 --- a/eos/effects/structurewarpscrambleblockmwdwithnpceffect.py +++ b/eos/effects/structurewarpscrambleblockmwdwithnpceffect.py @@ -1,5 +1,5 @@ # Not used by any item -from eos.types import State +from eos.saveddata.module import State # Not used by any item runTime = "early" diff --git a/eos/effects/targetarmorrepair.py b/eos/effects/targetarmorrepair.py index 358ca2c58..0a4c0c154 100644 --- a/eos/effects/targetarmorrepair.py +++ b/eos/effects/targetarmorrepair.py @@ -1,7 +1,4 @@ -# targetArmorRepair -# -# Used by: -# Module: QA Remote Armor Repair System - 5 Players +# Not used by any item type = "projected", "active" diff --git a/eos/effects/tractorbeamcan.py b/eos/effects/tractorbeamcan.py index 293a839ea..2c7f8eae3 100644 --- a/eos/effects/tractorbeamcan.py +++ b/eos/effects/tractorbeamcan.py @@ -2,8 +2,10 @@ # # Used by: # Modules from group: Tractor Beam (4 of 4) +from eos.config import settings type = "active" def handler(fit, module, context): + print settings['setting1'] pass diff --git a/eos/effects/turretweaponrangefallofftrackingspeedmultiplytargethostile.py b/eos/effects/turretweaponrangefallofftrackingspeedmultiplytargethostile.py deleted file mode 100644 index 12d535bb2..000000000 --- a/eos/effects/turretweaponrangefallofftrackingspeedmultiplytargethostile.py +++ /dev/null @@ -1,15 +0,0 @@ -# Not used by any item -type = "projected", "active" - - -def handler(fit, container, context): - if "projected" in context: - fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Gunnery"), - "trackingSpeed", container.getModifiedItemAttr("trackingSpeedMultiplier"), - stackingPenalties=True, penaltyGroup="postMul") - fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Gunnery"), - "maxRange", container.getModifiedItemAttr("maxRangeMultiplier"), - stackingPenalties=True, penaltyGroup="postMul") - fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Gunnery"), - "falloff", container.getModifiedItemAttr("fallofMultiplier"), - stackingPenalties=True, penaltyGroup="postMul") diff --git a/eos/effects/usemissiles.py b/eos/effects/usemissiles.py index 49ef3c5a0..1971dbe46 100644 --- a/eos/effects/usemissiles.py +++ b/eos/effects/usemissiles.py @@ -3,7 +3,7 @@ # Used by: # Modules from group: Missile Launcher Heavy (12 of 12) # Modules from group: Missile Launcher Rocket (15 of 15) -# Modules named like: Launcher (151 of 151) +# Modules named like: Launcher (153 of 153) type = 'active', "projected" diff --git a/eos/effects/warpscrambleblockmwdwithnpceffect.py b/eos/effects/warpscrambleblockmwdwithnpceffect.py index c220fb4fd..1e417b710 100644 --- a/eos/effects/warpscrambleblockmwdwithnpceffect.py +++ b/eos/effects/warpscrambleblockmwdwithnpceffect.py @@ -3,7 +3,7 @@ # Used by: # Modules named like: Warp Scrambler (26 of 26) -from eos.types import State +from eos.saveddata.module import State runTime = "early" type = "projected", "active" diff --git a/eos/enum.py b/eos/enum.py index 04caea536..12e8e09e1 100644 --- a/eos/enum.py +++ b/eos/enum.py @@ -1,4 +1,4 @@ -class Enum(): +class Enum(object): def __init__(self): pass diff --git a/eos/eqBase.py b/eos/eqBase.py index 2b8d35b33..73462c5ae 100644 --- a/eos/eqBase.py +++ b/eos/eqBase.py @@ -19,6 +19,8 @@ class EqBase(object): + ID = None + def __eq__(self, other): return type(self) == type(other) and self.ID == other.ID diff --git a/eos/gamedata.py b/eos/gamedata.py index e4a4afa1c..6b7aae34f 100644 --- a/eos/gamedata.py +++ b/eos/gamedata.py @@ -18,7 +18,6 @@ # =============================================================================== import re -import traceback from sqlalchemy.orm import reconstructor @@ -30,6 +29,10 @@ try: except ImportError: from utils.compat import OrderedDict +from logbook import Logger + +pyfalog = Logger(__name__) + class Effect(EqBase): """ @@ -64,6 +67,8 @@ class Effect(EqBase): if not self.__generated: self.__generateHandler() + pyfalog.debug("Generating effect: {0} ({1}) [runTime: {2}]", self.name, self.effectID, self.runTime) + return self.__handler @property @@ -138,7 +143,7 @@ class Effect(EqBase): @property def isImplemented(self): """ - Wether this effect is implemented in code or not, + Whether this effect is implemented in code or not, unimplemented effects simply do nothing at all when run """ return self.handler != effectDummy @@ -156,36 +161,30 @@ class Effect(EqBase): """ try: self.__effectModule = effectModule = __import__('eos.effects.' + self.handlerName, fromlist=True) - try: - self.__handler = getattr(effectModule, "handler") - except AttributeError: - print "effect {} exists, but no handler".format(self.handlerName) - raise - - try: - self.__runTime = getattr(effectModule, "runTime") or "normal" - except AttributeError: - self.__runTime = "normal" - - try: - self.__activeByDefault = getattr(effectModule, "activeByDefault") - except AttributeError: - self.__activeByDefault = True - - try: - t = getattr(effectModule, "type") - except AttributeError: - t = None + self.__handler = getattr(effectModule, "handler", effectDummy) + self.__runTime = getattr(effectModule, "runTime", "normal") + self.__activeByDefault = getattr(effectModule, "activeByDefault", True) + t = getattr(effectModule, "type", None) t = t if isinstance(t, tuple) or t is None else (t,) self.__type = t - except (ImportError, AttributeError) as e: + except (ImportError) as e: + # Effect probably doesn't exist, so create a dummy effect and flag it with a warning. self.__handler = effectDummy self.__runTime = "normal" self.__activeByDefault = True self.__type = None + pyfalog.warning("ImportError generating handler: {0}", e) + except (AttributeError) as e: + # Effect probably exists but there is an issue with it. Turn it into a dummy effect so we can continue, but flag it with an error. + self.__handler = effectDummy + self.__runTime = "normal" + self.__activeByDefault = True + self.__type = None + pyfalog.error("AttributeError generating handler: {0}", e) except Exception as e: - traceback.print_exc(e) + pyfalog.critical("Exception generating handler:") + pyfalog.critical(e) self.__generated = True @@ -243,9 +242,11 @@ class Item(EqBase): return self.__attributes - def getAttribute(self, key): + def getAttribute(self, key, default=None): if key in self.attributes: return self.attributes[key].value + else: + return default def isType(self, type): for effect in self.effects.itervalues(): @@ -283,8 +284,6 @@ class Item(EqBase): @property def requiredSkills(self): if self.__requiredSkills is None: - # This import should be here to make sure it's fully initialized - from eos import db requiredSkills = OrderedDict() self.__requiredSkills = requiredSkills # Map containing attribute IDs we may need for required skills @@ -295,7 +294,7 @@ class Item(EqBase): # { attributeID : attributeValue } skillAttrs = {} # Get relevant attribute values from db (required skill IDs and levels) for our item - for attrInfo in db.directAttributeRequest((self.ID,), tuple(combinedAttrIDs)): + for attrInfo in eos.db.directAttributeRequest((self.ID,), tuple(combinedAttrIDs)): attrID = attrInfo[1] attrVal = attrInfo[2] skillAttrs[attrID] = attrVal @@ -306,7 +305,7 @@ class Item(EqBase): skillID = int(skillAttrs[srqIDAtrr]) skillLvl = skillAttrs[srqLvlAttr] # Fetch item from database and fill map - item = db.getItem(skillID) + item = eos.db.getItem(skillID) requiredSkills[item] = skillLvl return self.__requiredSkills @@ -339,18 +338,20 @@ class Item(EqBase): # thus keep old mechanism for now except KeyError: # Define race map - map = {1: "caldari", - 2: "minmatar", - 4: "amarr", - 5: "sansha", # Caldari + Amarr - 6: "blood", # Minmatar + Amarr - 8: "gallente", - 9: "guristas", # Caldari + Gallente - 10: "angelserp", # Minmatar + Gallente, final race depends on the order of skills - 12: "sisters", # Amarr + Gallente - 16: "jove", - 32: "sansha", # Incrusion Sansha - 128: "ore"} + map = { + 1 : "caldari", + 2 : "minmatar", + 4 : "amarr", + 5 : "sansha", # Caldari + Amarr + 6 : "blood", # Minmatar + Amarr + 8 : "gallente", + 9 : "guristas", # Caldari + Gallente + 10 : "angelserp", # Minmatar + Gallente, final race depends on the order of skills + 12 : "sisters", # Amarr + Gallente + 16 : "jove", + 32 : "sansha", # Incrusion Sansha + 128: "ore" + } # Race is None by default race = None # Check primary and secondary required skills' races @@ -420,7 +421,7 @@ class Item(EqBase): def __repr__(self): return "Item(ID={}, name={}) at {}".format( - self.ID, self.name, hex(id(self)) + self.ID, self.name, hex(id(self)) ) @@ -474,7 +475,7 @@ class Icon(EqBase): class MarketGroup(EqBase): def __repr__(self): return u"MarketGroup(ID={}, name={}, parent={}) at {}".format( - self.ID, self.name, getattr(self.parent, "name", None), self.name, hex(id(self)) + self.ID, self.name, getattr(self.parent, "name", None), self.name, hex(id(self)) ).encode('utf8') diff --git a/eos/graph/__init__.py b/eos/graph/__init__.py index 44f6905c7..44802171f 100644 --- a/eos/graph/__init__.py +++ b/eos/graph/__init__.py @@ -62,7 +62,7 @@ class Data(object): def parseString(self, dataString): if not isinstance(dataString, basestring): - return (Constant(dataString),) + return Constant(dataString), dataList = [] for data in dataString.split(";"): @@ -93,7 +93,8 @@ class Constant(object): def __iter__(self): yield self.value - def isConstant(self): + @staticmethod + def isConstant(): return True @@ -114,5 +115,6 @@ class Range(object): i += 1 yield current - def isConstant(self): + @staticmethod + def isConstant(): return False diff --git a/eos/graph/fitDps.py b/eos/graph/fitDps.py index 04ef910a5..f09a2c34b 100644 --- a/eos/graph/fitDps.py +++ b/eos/graph/fitDps.py @@ -20,7 +20,10 @@ from math import log, sin, radians, exp from eos.graph import Graph -from eos.types import Hardpoint, State +from eos.saveddata.module import State, Hardpoint +from logbook import Logger + +pyfalog = Logger(__name__) class FitDpsGraph(Graph): @@ -38,7 +41,7 @@ class FitDpsGraph(Graph): fit = self.fit total = 0 distance = data["distance"] * 1000 - abssort = lambda val: -abs(val - 1) + abssort = lambda _val: -abs(_val - 1) for mod in fit.modules: if not mod.isEmpty and mod.state >= State.ACTIVE: @@ -65,8 +68,9 @@ class FitDpsGraph(Graph): bonus = values[i] val *= 1 + (bonus - 1) * exp(- i ** 2 / 7.1289) data[attr] = val - except: - pass + except Exception as e: + pyfalog.critical("Caught exception in calcDPS.") + pyfalog.critical(e) for mod in fit.modules: dps, _ = mod.damageStats(fit.targetResists) @@ -95,7 +99,8 @@ class FitDpsGraph(Graph): return total - def calculateMissileMultiplier(self, mod, data): + @staticmethod + def calculateMissileMultiplier(mod, data): targetSigRad = data["signatureRadius"] targetVelocity = data["velocity"] explosionRadius = mod.getModifiedChargeAttr("aoeCloudSize") @@ -126,7 +131,8 @@ class FitDpsGraph(Graph): multiplier = min(1, (float(targetSigRad) / dmgScaling) ** 2) return multiplier - def calculateFighterMissileMultiplier(self, ability, data): + @staticmethod + def calculateFighterMissileMultiplier(ability, data): prefix = ability.attrPrefix targetSigRad = data["signatureRadius"] @@ -156,7 +162,8 @@ class FitDpsGraph(Graph): return min(sigRadiusFactor, velocityFactor, 1) - def calculateTurretChanceToHit(self, mod, data): + @staticmethod + def calculateTurretChanceToHit(mod, data): distance = data["distance"] * 1000 tracking = mod.getModifiedItemAttr("trackingSpeed") turretOptimal = mod.maxRange @@ -171,7 +178,8 @@ class FitDpsGraph(Graph): return 0.5 ** (trackingEq + rangeEq) - def calculateModuleMultiplier(self, mod, data): + @staticmethod + def calculateModuleMultiplier(mod, data): # Simplified formula, we make some assumptions about the module # This is basically the calculateTurretChanceToHit without tracking values distance = data["distance"] * 1000 @@ -179,4 +187,4 @@ class FitDpsGraph(Graph): turretFalloff = mod.falloff rangeEq = ((max(0, distance - turretOptimal)) / turretFalloff) ** 2 - return 0.5 ** (rangeEq) + return 0.5 ** rangeEq diff --git a/eos/mathUtils.py b/eos/mathUtils.py deleted file mode 100644 index 5de12c60f..000000000 --- a/eos/mathUtils.py +++ /dev/null @@ -1,31 +0,0 @@ -# =============================================================================== -# Copyright (C) 2010 Anton Vorobyov -# -# This file is part of eos. -# -# eos 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 of the License, or -# (at your option) any later version. -# -# eos 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 eos. If not, see . -# =============================================================================== - -import decimal - - -def floorFloat(value): - """Round float down to integer""" - # We have to convert float to str to keep compatibility with - # decimal module in python 2.6 - value = str(value) - # Do the conversions for proper rounding down, avoiding float - # representation errors - result = int(decimal.Decimal(value).to_integral_value(rounding=decimal.ROUND_DOWN)) - return result diff --git a/eos/modifiedAttributeDict.py b/eos/modifiedAttributeDict.py index d060eb425..757d8a3d1 100644 --- a/eos/modifiedAttributeDict.py +++ b/eos/modifiedAttributeDict.py @@ -25,25 +25,25 @@ cappingAttrKeyCache = {} class ItemAttrShortcut(object): - def getModifiedItemAttr(self, key): + def getModifiedItemAttr(self, key, default=None): if key in self.itemModifiedAttributes: return self.itemModifiedAttributes[key] else: - return None + return default class ChargeAttrShortcut(object): - def getModifiedChargeAttr(self, key): + def getModifiedChargeAttr(self, key, default=None): if key in self.chargeModifiedAttributes: return self.chargeModifiedAttributes[key] else: - return None + return default class ModifiedAttributeDict(collections.MutableMapping): OVERRIDES = False - class CalculationPlaceholder(): + class CalculationPlaceholder(object): def __init__(self): pass @@ -212,11 +212,11 @@ class ModifiedAttributeDict(collections.MutableMapping): for penalizedMultipliers in penalizedMultiplierGroups.itervalues(): # A quick explanation of how this works: # 1: Bonuses and penalties are calculated seperately, so we'll have to filter each of them - l1 = filter(lambda val: val > 1, penalizedMultipliers) - l2 = filter(lambda val: val < 1, penalizedMultipliers) + l1 = filter(lambda _val: _val > 1, penalizedMultipliers) + l2 = filter(lambda _val: _val < 1, penalizedMultipliers) # 2: The most significant bonuses take the smallest penalty, # This means we'll have to sort - abssort = lambda val: -abs(val - 1) + abssort = lambda _val: -abs(_val - 1) l1.sort(key=abssort) l2.sort(key=abssort) # 3: The first module doesn't get penalized at all @@ -359,7 +359,7 @@ class ModifiedAttributeDict(collections.MutableMapping): self.__afflict(attributeName, u"\u2263", value) -class Affliction(): +class Affliction(object): def __init__(self, type, amount): self.type = type self.amount = amount diff --git a/eos/saveddata/booster.py b/eos/saveddata/booster.py index 93f0a4bc3..5ef2d78f6 100644 --- a/eos/saveddata/booster.py +++ b/eos/saveddata/booster.py @@ -17,7 +17,7 @@ # along with eos. If not, see . # =============================================================================== -import logging +from logbook import Logger from sqlalchemy.orm import reconstructor, validates @@ -25,7 +25,7 @@ import eos.db from eos.effectHandlerHelpers import HandledItem from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class Booster(HandledItem, ItemAttrShortcut): @@ -47,11 +47,11 @@ class Booster(HandledItem, ItemAttrShortcut): if self.itemID: self.__item = eos.db.getItem(self.itemID) if self.__item is None: - logger.error("Item (id: %d) does not exist", self.itemID) + pyfalog.error("Item (id: {0}) does not exist", self.itemID) return if self.isInvalid: - logger.error("Item (id: %d) is not a Booser", self.itemID) + pyfalog.error("Item (id: {0}) is not a Booster", self.itemID) return self.build() @@ -103,7 +103,8 @@ class Booster(HandledItem, ItemAttrShortcut): def item(self): return self.__item - def __calculateSlot(self, item): + @staticmethod + def __calculateSlot(item): if "boosterness" not in item.attributes: raise ValueError("Passed item is not a booster") @@ -132,11 +133,11 @@ class Booster(HandledItem, ItemAttrShortcut): @validates("ID", "itemID", "ammoID", "active") def validator(self, key, val): - map = {"ID": lambda val: isinstance(val, int), - "itemID": lambda val: isinstance(val, int), - "ammoID": lambda val: isinstance(val, int), - "active": lambda val: isinstance(val, bool), - "slot": lambda val: isinstance(val, int) and 1 <= val <= 3} + map = {"ID": lambda _val: isinstance(_val, int), + "itemID": lambda _val: isinstance(_val, int), + "ammoID": lambda _val: isinstance(_val, int), + "active": lambda _val: isinstance(_val, bool), + "slot": lambda _val: isinstance(_val, int) and 1 <= _val <= 3} if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) diff --git a/eos/saveddata/cargo.py b/eos/saveddata/cargo.py index 4b82dfc33..57da22e79 100644 --- a/eos/saveddata/cargo.py +++ b/eos/saveddata/cargo.py @@ -18,7 +18,7 @@ # =============================================================================== import sys -import logging +from logbook import Logger from sqlalchemy.orm import validates, reconstructor @@ -26,7 +26,7 @@ import eos.db from eos.effectHandlerHelpers import HandledItem from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class Cargo(HandledItem, ItemAttrShortcut): @@ -47,7 +47,7 @@ class Cargo(HandledItem, ItemAttrShortcut): if self.itemID: self.__item = eos.db.getItem(self.itemID) if self.__item is None: - logger.error("Item (id: %d) does not exist", self.itemID) + pyfalog.error("Item (id: {0}) does not exist", self.itemID) return self.__itemModifiedAttributes = ModifiedAttributeDict() @@ -71,9 +71,9 @@ class Cargo(HandledItem, ItemAttrShortcut): @validates("fitID", "itemID", "amount") def validator(self, key, val): - map = {"fitID": lambda val: isinstance(val, int), - "itemID": lambda val: isinstance(val, int), - "amount": lambda val: isinstance(val, int)} + map = {"fitID": lambda _val: isinstance(_val, int), + "itemID": lambda _val: isinstance(_val, int), + "amount": lambda _val: isinstance(_val, int)} if key == "amount" and val > sys.maxint: val = sys.maxint diff --git a/eos/saveddata/character.py b/eos/saveddata/character.py index cd5e278fd..067b9f98d 100644 --- a/eos/saveddata/character.py +++ b/eos/saveddata/character.py @@ -18,17 +18,16 @@ # =============================================================================== -import logging +from logbook import Logger from itertools import chain from sqlalchemy.orm import validates, reconstructor import eos import eos.db -import eos.types from eos.effectHandlerHelpers import HandledItem, HandledImplantBoosterList -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class Character(object): @@ -141,7 +140,17 @@ class Character(object): @property def name(self): - return self.savedName if not self.isDirty else "{} *".format(self.savedName) + name = self.savedName + + if self.isDirty: + name += " *" + + if self.alphaCloneID: + clone = eos.db.getAlphaClone(self.alphaCloneID) + type = clone.alphaCloneName.split()[1] + name += u' (\u03B1{})'.format(type[0].upper()) + + return name @name.setter def name(self, name): @@ -257,10 +266,10 @@ class Character(object): @validates("ID", "name", "apiKey", "ownerID") def validator(self, key, val): - map = {"ID": lambda val: isinstance(val, int), - "name": lambda val: True, - "apiKey": lambda val: val is None or (isinstance(val, basestring) and len(val) > 0), - "ownerID": lambda val: isinstance(val, int) or val is None} + map = {"ID": lambda _val: isinstance(_val, int), + "name": lambda _val: True, + "apiKey": lambda _val: _val is None or (isinstance(_val, basestring) and len(_val) > 0), + "ownerID": lambda _val: isinstance(_val, int) or _val is None} if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) @@ -378,8 +387,8 @@ class Skill(HandledItem): if hasattr(self, "_Skill__ro") and self.__ro is True and key != "characterID": raise ReadOnlyException() - map = {"characterID": lambda val: isinstance(val, int), - "skillID": lambda val: isinstance(val, int)} + map = {"characterID": lambda _val: isinstance(_val, int), + "skillID": lambda _val: isinstance(_val, int)} if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) diff --git a/eos/saveddata/citadel.py b/eos/saveddata/citadel.py index 1c3c22884..90d7ab425 100644 --- a/eos/saveddata/citadel.py +++ b/eos/saveddata/citadel.py @@ -17,16 +17,17 @@ # along with eos. If not, see . # =============================================================================== -import logging +from logbook import Logger -from eos.types import Ship +from eos.saveddata.ship import Ship -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class Citadel(Ship): def validate(self, item): if item.category.name != "Structure": + pyfalog.error("Passed item '{0}' (category: {1}) is not under Structure category", item.name, item.category.name) raise ValueError( 'Passed item "%s" (category: (%s)) is not under Structure category' % (item.name, item.category.name)) diff --git a/eos/saveddata/drone.py b/eos/saveddata/drone.py index d0e8511f5..647e0a99c 100644 --- a/eos/saveddata/drone.py +++ b/eos/saveddata/drone.py @@ -17,7 +17,7 @@ # along with eos. If not, see . # =============================================================================== -import logging +from logbook import Logger from sqlalchemy.orm import validates, reconstructor @@ -25,7 +25,7 @@ import eos.db from eos.effectHandlerHelpers import HandledItem, HandledCharge from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): @@ -53,11 +53,11 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if self.itemID: self.__item = eos.db.getItem(self.itemID) if self.__item is None: - logger.error("Item (id: %d) does not exist", self.itemID) + pyfalog.error("Item (id: {0}) does not exist", self.itemID) return if self.isInvalid: - logger.error("Item (id: %d) is not a Drone", self.itemID) + pyfalog.error("Item (id: {0}) is not a Drone", self.itemID) return self.build() @@ -186,11 +186,11 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): @validates("ID", "itemID", "chargeID", "amount", "amountActive") def validator(self, key, val): - map = {"ID": lambda val: isinstance(val, int), - "itemID": lambda val: isinstance(val, int), - "chargeID": lambda val: isinstance(val, int), - "amount": lambda val: isinstance(val, int) and val >= 0, - "amountActive": lambda val: isinstance(val, int) and self.amount >= val >= 0} + map = {"ID": lambda _val: isinstance(_val, int), + "itemID": lambda _val: isinstance(_val, int), + "chargeID": lambda _val: isinstance(_val, int), + "amount": lambda _val: isinstance(_val, int) and _val >= 0, + "amountActive": lambda _val: isinstance(_val, int) and self.amount >= _val >= 0} if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) diff --git a/eos/saveddata/fighter.py b/eos/saveddata/fighter.py index 94e7e93c6..e10b5b3c5 100644 --- a/eos/saveddata/fighter.py +++ b/eos/saveddata/fighter.py @@ -17,16 +17,17 @@ # along with eos. If not, see . # =============================================================================== -import logging +from logbook import Logger from sqlalchemy.orm import validates, reconstructor import eos.db from eos.effectHandlerHelpers import HandledItem, HandledCharge from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut -from eos.types import FighterAbility, Slot +from eos.saveddata.fighterAbility import FighterAbility +from eos.saveddata.module import Slot -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): @@ -60,11 +61,11 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if self.itemID: self.__item = eos.db.getItem(self.itemID) if self.__item is None: - logger.error("Item (id: %d) does not exist", self.itemID) + pyfalog.error("Item (id: {0}) does not exist", self.itemID) return if self.isInvalid: - logger.error("Item (id: %d) is not a Fighter", self.itemID) + pyfalog.error("Item (id: {0}) is not a Fighter", self.itemID) return self.build() @@ -218,10 +219,10 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): @validates("ID", "itemID", "chargeID", "amount", "amountActive") def validator(self, key, val): - map = {"ID": lambda val: isinstance(val, int), - "itemID": lambda val: isinstance(val, int), - "chargeID": lambda val: isinstance(val, int), - "amount": lambda val: isinstance(val, int) and val >= -1, + map = {"ID": lambda _val: isinstance(_val, int), + "itemID": lambda _val: isinstance(_val, int), + "chargeID": lambda _val: isinstance(_val, int), + "amount": lambda _val: isinstance(_val, int) and _val >= -1, } if not map[key](val): diff --git a/eos/saveddata/fighterAbility.py b/eos/saveddata/fighterAbility.py index cb7c34912..efe429c41 100644 --- a/eos/saveddata/fighterAbility.py +++ b/eos/saveddata/fighterAbility.py @@ -17,11 +17,11 @@ # along with eos. If not, see . # =============================================================================== -import logging +from logbook import Logger from sqlalchemy.orm import reconstructor -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class FighterAbility(object): @@ -59,7 +59,7 @@ class FighterAbility(object): if self.effectID: self.__effect = next((x for x in self.fighter.item.effects.itervalues() if x.ID == self.effectID), None) if self.__effect is None: - logger.error("Effect (id: %d) does not exist", self.effectID) + pyfalog.error("Effect (id: {0}) does not exist", self.effectID) return self.build() diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index 26bac09ea..c2c8f02c4 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -17,7 +17,6 @@ # along with eos. If not, see . # =============================================================================== -import copy import time from copy import deepcopy from itertools import chain @@ -27,26 +26,19 @@ from sqlalchemy.orm import validates, reconstructor import eos.db from eos import capSim -from eos.effectHandlerHelpers import * from eos.effectHandlerHelpers import HandledModuleList, HandledDroneCargoList, HandledImplantBoosterList, HandledProjectedDroneList, HandledProjectedModList from eos.enum import Enum -from eos.saveddata.module import State, Hardpoint -from eos.types import Ship, Character, Slot, Module, Citadel +from eos.saveddata.ship import Ship +from eos.saveddata.character import Character +from eos.saveddata.citadel import Citadel +from eos.saveddata.module import Module, State, Slot, Hardpoint from utils.timer import Timer -import logging +from logbook import Logger -logger = logging.getLogger(__name__) - -try: - from collections import OrderedDict -except ImportError: - from utils.compat import OrderedDict +pyfalog = Logger(__name__) class ImplantLocation(Enum): - def __init__(self): - pass - FIT = 0 CHARACTER = 1 @@ -92,7 +84,7 @@ class Fit(object): if self.shipID: item = eos.db.getItem(self.shipID) if item is None: - logger.error("Item (id: %d) does not exist", self.shipID) + pyfalog.error("Item (id: {0}) does not exist", self.shipID) return try: @@ -105,7 +97,7 @@ class Fit(object): # change all instances in source). Remove this at some point self.extraAttributes = self.__ship.itemModifiedAttributes except ValueError: - logger.error("Item (id: %d) is not a Ship", self.shipID) + pyfalog.error("Item (id: {0}) is not a Ship", self.shipID) return if self.modeID and self.__ship: @@ -135,6 +127,12 @@ class Fit(object): self.__capUsed = None self.__capRecharge = None self.__calculatedTargets = [] + self.__remoteReps = { + "Armor" : None, + "Shield" : None, + "Hull" : None, + "Capacitor": None, + } self.factorReload = False self.boostsFits = set() self.gangBoosts = None @@ -372,9 +370,11 @@ class Fit(object): @validates("ID", "ownerID", "shipID") def validator(self, key, val): - map = {"ID": lambda val: isinstance(val, int), - "ownerID": lambda val: isinstance(val, int) or val is None, - "shipID": lambda val: isinstance(val, int) or val is None} + map = { + "ID" : lambda _val: isinstance(_val, int), + "ownerID": lambda _val: isinstance(_val, int) or _val is None, + "shipID" : lambda _val: isinstance(_val, int) or _val is None + } if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) @@ -400,6 +400,9 @@ class Fit(object): self.ecmProjectedStr = 1 self.commandBonuses = {} + for remoterep_type in self.__remoteReps: + self.__remoteReps[remoterep_type] = None + del self.__calculatedTargets[:] del self.__extraDrains[:] @@ -407,15 +410,15 @@ class Fit(object): self.ship.clear() c = chain( - self.modules, - self.drones, - self.fighters, - self.boosters, - self.implants, - self.projectedDrones, - self.projectedModules, - self.projectedFighters, - (self.character, self.extraAttributes), + self.modules, + self.drones, + self.fighters, + self.boosters, + self.implants, + self.projectedDrones, + self.projectedModules, + self.projectedFighters, + (self.character, self.extraAttributes), ) for stuff in c: @@ -436,9 +439,11 @@ class Fit(object): self.__modifier = currModifier self.__origin = origin if hasattr(currModifier, "itemModifiedAttributes"): - currModifier.itemModifiedAttributes.fit = origin or self + if hasattr(currModifier.itemModifiedAttributes, "fit"): + currModifier.itemModifiedAttributes.fit = origin or self if hasattr(currModifier, "chargeModifiedAttributes"): - currModifier.chargeModifiedAttributes.fit = origin or self + if hasattr(currModifier.itemModifiedAttributes, "fit"): + currModifier.chargeModifiedAttributes.fit = origin or self def getModifier(self): return self.__modifier @@ -454,7 +459,7 @@ class Fit(object): self.commandBonuses[warfareBuffID] = (runTime, value, module, effect) def __runCommandBoosts(self, runTime="normal"): - logger.debug("Applying gang boosts for %r", self) + pyfalog.debug("Applying gang boosts for {0}", self) for warfareBuffID in self.commandBonuses.keys(): # Unpack all data required to run effect properly effect_runTime, value, thing, effect = self.commandBonuses[warfareBuffID] @@ -473,11 +478,11 @@ class Fit(object): if warfareBuffID == 11: # Shield Burst: Active Shielding: Repair Duration/Capacitor self.modules.filteredItemBoost( - lambda mod: mod.item.requiresSkill("Shield Operation") or mod.item.requiresSkill( - "Shield Emission Systems"), "capacitorNeed", value) + lambda mod: mod.item.requiresSkill("Shield Operation") or mod.item.requiresSkill( + "Shield Emission Systems"), "capacitorNeed", value) self.modules.filteredItemBoost( - lambda mod: mod.item.requiresSkill("Shield Operation") or mod.item.requiresSkill( - "Shield Emission Systems"), "duration", value) + lambda mod: mod.item.requiresSkill("Shield Operation") or mod.item.requiresSkill( + "Shield Emission Systems"), "duration", value) if warfareBuffID == 12: # Shield Burst: Shield Extension: Shield HP self.ship.boostItemAttr("shieldCapacity", value, stackingPenalties=True) @@ -487,10 +492,12 @@ class Fit(object): self.ship.boostItemAttr("armor%sDamageResonance" % damageType, value) if warfareBuffID == 14: # Armor Burst: Rapid Repair: Repair Duration/Capacitor - self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems") or mod.item.requiresSkill("Repair Systems"), - "capacitorNeed", value) - self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems") or mod.item.requiresSkill("Repair Systems"), "duration", - value) + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems") or + mod.item.requiresSkill("Repair Systems"), + "capacitorNeed", value) + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems") or + mod.item.requiresSkill("Repair Systems"), + "duration", value) if warfareBuffID == 15: # Armor Burst: Armor Reinforcement: Armor HP self.ship.boostItemAttr("armorHP", value, stackingPenalties=True) @@ -501,26 +508,26 @@ class Fit(object): if warfareBuffID == 17: # Information Burst: Electronic Superiority: EWAR Range and Strength groups = ("ECM", "Sensor Dampener", "Weapon Disruptor", "Target Painter") self.modules.filteredItemBoost(lambda mod: mod.item.group.name in groups, "maxRange", value, - stackingPenalties=True) + stackingPenalties=True) self.modules.filteredItemBoost(lambda mod: mod.item.group.name in groups, - "falloffEffectiveness", value, stackingPenalties=True) + "falloffEffectiveness", value, stackingPenalties=True) for scanType in ("Magnetometric", "Radar", "Ladar", "Gravimetric"): self.modules.filteredItemBoost(lambda mod: mod.item.group.name == "ECM", - "scan%sStrengthBonus" % scanType, value, - stackingPenalties=True) + "scan%sStrengthBonus" % scanType, value, + stackingPenalties=True) for attr in ("missileVelocityBonus", "explosionDelayBonus", "aoeVelocityBonus", "falloffBonus", "maxRangeBonus", "aoeCloudSizeBonus", "trackingSpeedBonus"): self.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Weapon Disruptor", - attr, value) + attr, value) for attr in ("maxTargetRangeBonus", "scanResolutionBonus"): self.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Sensor Dampener", - attr, value) + attr, value) - self.modules.filteredItemBoost(lambda mod: mod.item.gorup.name == "Target Painter", - "signatureRadiusBonus", value, stackingPenalties=True) + self.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Target Painter", + "signatureRadiusBonus", value, stackingPenalties=True) if warfareBuffID == 18: # Information Burst: Electronic Hardening: Scan Strength for scanType in ("Gravimetric", "Radar", "Ladar", "Magnetometric"): @@ -539,34 +546,36 @@ class Fit(object): if warfareBuffID == 21: # Skirmish Burst: Interdiction Maneuvers: Tackle Range groups = ("Stasis Web", "Warp Scrambler") self.modules.filteredItemBoost(lambda mod: mod.item.group.name in groups, "maxRange", value, - stackingPenalties=True) + stackingPenalties=True) if warfareBuffID == 22: # Skirmish Burst: Rapid Deployment: AB/MWD Speed Increase - self.modules.filteredItemBoost( - lambda mod: mod.item.requiresSkill("Afterburner") or mod.item.requiresSkill( - "High Speed Maneuvering"), "speedFactor", value, stackingPenalties=True) + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Afterburner") or + mod.item.requiresSkill("High Speed Maneuvering"), + "speedFactor", value, stackingPenalties=True) if warfareBuffID == 23: # Mining Burst: Mining Laser Field Enhancement: Mining/Survey Range - self.modules.filteredItemBoost( - lambda mod: mod.item.requiresSkill("Mining") or mod.item.requiresSkill( - "Ice Harvesting") or mod.item.requiresSkill("Gas Cloud Harvesting"), "maxRange", - value, stackingPenalties=True) + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining") or + mod.item.requiresSkill("Ice Harvesting") or + mod.item.requiresSkill("Gas Cloud Harvesting"), + "maxRange", value, stackingPenalties=True) + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("CPU Management"), - "surveyScanRange", value, stackingPenalties=True) + "surveyScanRange", value, stackingPenalties=True) if warfareBuffID == 24: # Mining Burst: Mining Laser Optimization: Mining Capacitor/Duration - self.modules.filteredItemBoost( - lambda mod: mod.item.requiresSkill("Mining") or mod.item.requiresSkill( - "Ice Harvesting") or mod.item.requiresSkill("Gas Cloud Harvesting"), - "capacitorNeed", value, stackingPenalties=True) - self.modules.filteredItemBoost( - lambda mod: mod.item.requiresSkill("Mining") or mod.item.requiresSkill( - "Ice Harvesting") or mod.item.requiresSkill("Gas Cloud Harvesting"), "duration", - value, stackingPenalties=True) + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining") or + mod.item.requiresSkill("Ice Harvesting") or + mod.item.requiresSkill("Gas Cloud Harvesting"), + "capacitorNeed", value, stackingPenalties=True) + + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining") or + mod.item.requiresSkill("Ice Harvesting") or + mod.item.requiresSkill("Gas Cloud Harvesting"), + "duration", value, stackingPenalties=True) if warfareBuffID == 25: # Mining Burst: Mining Equipment Preservation: Crystal Volatility self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining"), - "crystalVolatilityChance", value, stackingPenalties=True) + "crystalVolatilityChance", value, stackingPenalties=True) if warfareBuffID == 60: # Skirmish Burst: Evasive Maneuvers: Agility self.ship.boostItemAttr("agility", value, stackingPenalties=True) @@ -624,7 +633,8 @@ class Fit(object): self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Shield Emission Systems"), "shieldBonus", value, stackingPenalties=True) if warfareBuffID == 53: # Leviathan Effect Generator : Armor RR penalty - self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "armorDamageAmount", value, stackingPenalties=True) + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), + "armorDamageAmount", value, stackingPenalties=True) if warfareBuffID == 54: # Ragnarok Effect Generator : Laser and Hybrid Optimal penalty groups = ("Energy Weapon", "Hybrid Weapon") @@ -633,21 +643,21 @@ class Fit(object): del self.commandBonuses[warfareBuffID] def calculateModifiedAttributes(self, targetFit=None, withBoosters=False, dirtyStorage=None): - timer = Timer(u'Fit: {}, {}'.format(self.ID, self.name), logger) - logger.debug("Starting fit calculation on: %r, withBoosters: %s", self, withBoosters) + timer = Timer(u'Fit: {}, {}'.format(self.ID, self.name), pyfalog) + pyfalog.debug("Starting fit calculation on: {0}, withBoosters: {1}", self, withBoosters) shadow = False if targetFit and not withBoosters: - logger.debug("Applying projections to target: %r", targetFit) + pyfalog.debug("Applying projections to target: {0}", targetFit) projectionInfo = self.getProjectionInfo(targetFit.ID) - logger.debug("ProjectionInfo: %s", projectionInfo) + pyfalog.debug("ProjectionInfo: {0}", projectionInfo) if self == targetFit: copied = self # original fit shadow = True # Don't inspect this, we genuinely want to reassign self # noinspection PyMethodFirstArgAssignment - self = copy.deepcopy(self) - logger.debug("Handling self projection - making shadow copy of fit. %r => %r", copied, self) + self = deepcopy(self) + pyfalog.debug("Handling self projection - making shadow copy of fit. {0} => {1}", copied, self) # we delete the fit because when we copy a fit, flush() is # called to properly handle projection updates. However, we do # not want to save this fit to the database, so simply remove it @@ -682,7 +692,7 @@ class Fit(object): # projection have modifying stuff applied, such as gang boosts and other # local modules that may help if self.__calculated and not projected and not withBoosters: - logger.debug("Fit has already been calculated and is not projected, returning: %r", self) + pyfalog.debug("Fit has already been calculated and is not projected, returning: {0}", self) return for runTime in ("early", "normal", "late"): @@ -722,23 +732,28 @@ class Fit(object): self.register(item) item.calculateModifiedAttributes(self, runTime, False) - if projected is True and item not in chain.from_iterable(r): - # apply effects onto target fit - for _ in xrange(projectionInfo.amount): - targetFit.register(item, origin=self) - item.calculateModifiedAttributes(targetFit, runTime, True) - if targetFit and withBoosters and item in self.modules: # Apply the gang boosts to target fit # targetFit.register(item, origin=self) item.calculateModifiedAttributes(targetFit, runTime, False, True) - print "Command: " - print self.commandBonuses + if len(self.commandBonuses) > 0: + pyfalog.info("Command bonuses applied.") + pyfalog.debug(self.commandBonuses) if not withBoosters and self.commandBonuses: self.__runCommandBoosts(runTime) + # Projection effects have been broken out of the main loop, see GH issue #1081 + + if projected is True and projectionInfo: + for item in chain.from_iterable(u): + if item is not None: + # apply effects onto target fit + for _ in xrange(projectionInfo.amount): + targetFit.register(item, origin=self) + item.calculateModifiedAttributes(targetFit, runTime, True) + timer.checkpoint('Done with runtime: %s' % runTime) # Mark fit as calculated @@ -753,7 +768,7 @@ class Fit(object): timer.checkpoint('Done with fit calculation') if shadow: - logger.debug("Delete shadow fit object") + pyfalog.debug("Delete shadow fit object") del self def fill(self): @@ -798,7 +813,8 @@ class Fit(object): x += 1 return x - def getItemAttrSum(self, dict, attr): + @staticmethod + def getItemAttrSum(dict, attr): amount = 0 for mod in dict: add = mod.getModifiedItemAttr(attr) @@ -807,7 +823,8 @@ class Fit(object): return amount - def getItemAttrOnlineSum(self, dict, attr): + @staticmethod + def getItemAttrOnlineSum(dict, attr): amount = 0 for mod in dict: add = mod.getModifiedItemAttr(attr) if mod.state >= State.ONLINE else None @@ -835,15 +852,17 @@ class Fit(object): return amount - slots = {Slot.LOW: "lowSlots", - Slot.MED: "medSlots", - Slot.HIGH: "hiSlots", - Slot.RIG: "rigSlots", - Slot.SUBSYSTEM: "maxSubSystems", - Slot.SERVICE: "serviceSlots", - Slot.F_LIGHT: "fighterLightSlots", - Slot.F_SUPPORT: "fighterSupportSlots", - Slot.F_HEAVY: "fighterHeavySlots"} + slots = { + Slot.LOW : "lowSlots", + Slot.MED : "medSlots", + Slot.HIGH : "hiSlots", + Slot.RIG : "rigSlots", + Slot.SUBSYSTEM: "maxSubSystems", + Slot.SERVICE : "serviceSlots", + Slot.F_LIGHT : "fighterLightSlots", + Slot.F_SUPPORT: "fighterSupportSlots", + Slot.F_HEAVY : "fighterHeavySlots" + } def getSlotsFree(self, type, countDummies=False): if type in (Slot.MODE, Slot.SYSTEM): @@ -918,20 +937,19 @@ class Fit(object): return amount - # Expresses how difficult a target is to probe down with scan probes - # If this is <1.08, the ship is unproabeable @property def probeSize(self): + """ + Expresses how difficult a target is to probe down with scan probes + """ + sigRad = self.ship.getModifiedItemAttr("signatureRadius") sensorStr = float(self.scanStrength) probeSize = sigRad / sensorStr if sensorStr != 0 else None # http://www.eveonline.com/ingameboard.asp?a=topic&threadID=1532170&page=2#42 if probeSize is not None: - # http://forum.eve-ru.com/index.php?showtopic=74195&view=findpost&p=1333691 - # http://forum.eve-ru.com/index.php?showtopic=74195&view=findpost&p=1333763 - # Tests by tester128 and several conclusions by me, prove that cap is in range - # from 1.1 to 1.12, we're picking average value - probeSize = max(probeSize, 1.11) + # Probe size is capped at 1.08 + probeSize = max(probeSize, 1.08) return probeSize @property @@ -993,29 +1011,35 @@ class Fit(object): def calculateSustainableTank(self, effective=True): if self.__sustainableTank is None: if self.capStable: - sustainable = {"armorRepair": self.extraAttributes["armorRepair"], - "shieldRepair": self.extraAttributes["shieldRepair"], - "hullRepair": self.extraAttributes["hullRepair"]} + sustainable = { + "armorRepair" : self.extraAttributes["armorRepair"], + "shieldRepair": self.extraAttributes["shieldRepair"], + "hullRepair" : self.extraAttributes["hullRepair"] + } else: sustainable = {} repairers = [] # Map a repairer type to the attribute it uses - groupAttrMap = {"Armor Repair Unit": "armorDamageAmount", - "Ancillary Armor Repairer": "armorDamageAmount", - "Hull Repair Unit": "structureDamageAmount", - "Shield Booster": "shieldBonus", - "Ancillary Shield Booster": "shieldBonus", - "Remote Armor Repairer": "armorDamageAmount", - "Remote Shield Booster": "shieldBonus"} + groupAttrMap = { + "Armor Repair Unit" : "armorDamageAmount", + "Ancillary Armor Repairer": "armorDamageAmount", + "Hull Repair Unit" : "structureDamageAmount", + "Shield Booster" : "shieldBonus", + "Ancillary Shield Booster": "shieldBonus", + "Remote Armor Repairer" : "armorDamageAmount", + "Remote Shield Booster" : "shieldBonus" + } # Map repairer type to attribute - groupStoreMap = {"Armor Repair Unit": "armorRepair", - "Hull Repair Unit": "hullRepair", - "Shield Booster": "shieldRepair", - "Ancillary Shield Booster": "shieldRepair", - "Remote Armor Repairer": "armorRepair", - "Remote Shield Booster": "shieldRepair", - "Ancillary Armor Repairer": "armorRepair", } + groupStoreMap = { + "Armor Repair Unit" : "armorRepair", + "Hull Repair Unit" : "hullRepair", + "Shield Booster" : "shieldRepair", + "Ancillary Shield Booster": "shieldRepair", + "Remote Armor Repairer" : "armorRepair", + "Remote Shield Booster" : "shieldRepair", + "Ancillary Armor Repairer": "armorRepair", + } capUsed = self.capUsed for attr in ("shieldRepair", "armorRepair", "hullRepair"): @@ -1042,8 +1066,8 @@ class Fit(object): repairers.append(mod) # Sort repairers by efficiency. We want to use the most efficient repairers first - repairers.sort(key=lambda mod: mod.getModifiedItemAttr( - groupAttrMap[mod.item.group.name]) / mod.getModifiedItemAttr("capacitorNeed"), reverse=True) + repairers.sort(key=lambda _mod: _mod.getModifiedItemAttr( + groupAttrMap[_mod.item.group.name]) / _mod.getModifiedItemAttr("capacitorNeed"), reverse=True) # Loop through every module until we're above peak recharge # Most efficient first, as we sorted earlier. @@ -1151,6 +1175,67 @@ class Fit(object): self.__capStable = True self.__capState = 100 + @property + def remoteReps(self): + force_recalc = False + for remote_type in self.__remoteReps: + if self.__remoteReps[remote_type] is None: + force_recalc = True + break + + if force_recalc is False: + return self.__remoteReps + + # We are rerunning the recalcs. Explicitly set to 0 to make sure we don't duplicate anything and correctly set all values to 0. + for remote_type in self.__remoteReps: + self.__remoteReps[remote_type] = 0 + + for module in self.modules: + # Skip empty and non-Active modules + if module.isEmpty or module.state < State.ACTIVE: + continue + + # Covert cycleTime to seconds + duration = module.cycleTime / 1000 + + # Skip modules with no duration. + if not duration: + continue + + fueledMultiplier = module.getModifiedItemAttr("chargedArmorDamageMultiplier", 1) + + remote_module_groups = { + "Remote Armor Repairer" : "Armor", + "Ancillary Remote Armor Repairer": "Armor", + "Remote Hull Repairer" : "Hull", + "Remote Shield Booster" : "Shield", + "Ancillary Remote Shield Booster": "Shield", + "Remote Capacitor Transmitter" : "Capacitor", + } + + module_group = module.item.group.name + + if module_group in remote_module_groups: + remote_type = remote_module_groups[module_group] + else: + # Module isn't in our list of remote rep modules, bail + continue + + if remote_type == "Hull": + hp = module.getModifiedItemAttr("structureDamageAmount", 0) + elif remote_type == "Armor": + hp = module.getModifiedItemAttr("armorDamageAmount", 0) + elif remote_type == "Shield": + hp = module.getModifiedItemAttr("shieldBonus", 0) + elif remote_type == "Capacitor": + hp = module.getModifiedItemAttr("powerTransferAmount", 0) + else: + hp = 0 + + self.__remoteReps[remote_type] += (hp * fueledMultiplier) / duration + + return self.__remoteReps + @property def hp(self): hp = {} @@ -1258,16 +1343,16 @@ class Fit(object): return True - def __deepcopy__(self, memo): - copy = Fit() + def __deepcopy__(self, memo=None): + copy_ship = Fit() # Character and owner are not copied - copy.character = self.__character - copy.owner = self.owner - copy.ship = deepcopy(self.ship, memo) - copy.name = "%s copy" % self.name - copy.damagePattern = self.damagePattern - copy.targetResists = self.targetResists - copy.notes = self.notes + copy_ship.character = self.__character + copy_ship.owner = self.owner + copy_ship.ship = deepcopy(self.ship) + copy_ship.name = "%s copy" % self.name + copy_ship.damagePattern = self.damagePattern + copy_ship.targetResists = self.targetResists + copy_ship.notes = self.notes toCopy = ( "modules", @@ -1281,24 +1366,24 @@ class Fit(object): "projectedFighters") for name in toCopy: orig = getattr(self, name) - c = getattr(copy, name) + c = getattr(copy_ship, name) for i in orig: - c.append(deepcopy(i, memo)) + c.append(deepcopy(i)) for fit in self.projectedFits: - copy.__projectedFits[fit.ID] = fit + copy_ship.__projectedFits[fit.ID] = fit # this bit is required -- see GH issue # 83 eos.db.saveddata_session.flush() eos.db.saveddata_session.refresh(fit) - return copy + return copy_ship def __repr__(self): return u"Fit(ID={}, ship={}, name={}) at {}".format( - self.ID, self.ship.item.name, self.name, hex(id(self)) + self.ID, self.ship.item.name, self.name, hex(id(self)) ).encode('utf8') def __str__(self): return u"{} ({})".format( - self.name, self.ship.item.name + self.name, self.ship.item.name ).encode('utf8') diff --git a/eos/saveddata/implant.py b/eos/saveddata/implant.py index a77190bc4..240a51b0f 100644 --- a/eos/saveddata/implant.py +++ b/eos/saveddata/implant.py @@ -17,7 +17,7 @@ # along with eos. If not, see . # =============================================================================== -import logging +from logbook import Logger from sqlalchemy.orm import validates, reconstructor @@ -25,7 +25,7 @@ import eos.db from eos.effectHandlerHelpers import HandledItem from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class Implant(HandledItem, ItemAttrShortcut): @@ -46,11 +46,11 @@ class Implant(HandledItem, ItemAttrShortcut): if self.itemID: self.__item = eos.db.getItem(self.itemID) if self.__item is None: - logger.error("Item (id: %d) does not exist", self.itemID) + pyfalog.error("Item (id: {0}) does not exist", self.itemID) return if self.isInvalid: - logger.error("Item (id: %d) is not an Implant", self.itemID) + pyfalog.error("Item (id: {0}) is not an Implant", self.itemID) return self.build() @@ -78,7 +78,8 @@ class Implant(HandledItem, ItemAttrShortcut): def item(self): return self.__item - def __calculateSlot(self, item): + @staticmethod + def __calculateSlot(item): if "implantness" not in item.attributes: raise ValueError("Passed item is not an implant") @@ -98,9 +99,9 @@ class Implant(HandledItem, ItemAttrShortcut): @validates("fitID", "itemID", "active") def validator(self, key, val): - map = {"fitID": lambda val: isinstance(val, int), - "itemID": lambda val: isinstance(val, int), - "active": lambda val: isinstance(val, bool)} + map = {"fitID": lambda _val: isinstance(_val, int), + "itemID": lambda _val: isinstance(_val, int), + "active": lambda _val: isinstance(_val, bool)} if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) diff --git a/eos/saveddata/implantSet.py b/eos/saveddata/implantSet.py index 2daaaa3eb..ca0334fff 100644 --- a/eos/saveddata/implantSet.py +++ b/eos/saveddata/implantSet.py @@ -48,13 +48,13 @@ class ImplantSet(object): return out.strip() - def __deepcopy__(self, memo): + def __deepcopy__(self): copy = ImplantSet(self.name) copy.name = "%s copy" % self.name orig = getattr(self, 'implants') c = getattr(copy, 'implants') for i in orig: - c.append(deepcopy(i, memo)) + c.append(deepcopy(i)) return copy diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index d04065233..919b8c7b7 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -17,18 +17,18 @@ # along with eos. If not, see . # =============================================================================== -import logging +from logbook import Logger from sqlalchemy.orm import validates, reconstructor +from math import floor import eos.db from eos.effectHandlerHelpers import HandledItem, HandledCharge from eos.enum import Enum -from eos.mathUtils import floorFloat from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut -from eos.types import Citadel +from eos.saveddata.citadel import Citadel -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class State(Enum): @@ -94,11 +94,11 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if self.itemID: self.__item = eos.db.getItem(self.itemID) if self.__item is None: - logger.error("Item (id: %d) does not exist", self.itemID) + pyfalog.error("Item (id: {0}) does not exist", self.itemID) return if self.isInvalid: - logger.error("Item (id: %d) is not a Module", self.itemID) + pyfalog.error("Item (id: {0}) is not a Module", self.itemID) return if self.chargeID: @@ -172,8 +172,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if chargeVolume is None or containerCapacity is None: charges = 0 else: - charges = floorFloat(float(containerCapacity) / chargeVolume) - return charges + charges = floor(containerCapacity / chargeVolume) + return int(charges) @property def numShots(self): @@ -199,6 +199,10 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if self.owner: return self.owner.modules.index(self) + @property + def isCapitalSize(self): + return self.getModifiedItemAttr("volume", 0) >= 4000 + @property def hpBeforeReload(self): """ @@ -216,9 +220,10 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): def __calculateAmmoShots(self): if self.charge is not None: # Set number of cycles before reload is needed + # numcycles = math.floor(module_capacity / (module_volume * module_chargerate)) chargeRate = self.getModifiedItemAttr("chargeRate") numCharges = self.numCharges - numShots = floorFloat(float(numCharges) / chargeRate) + numShots = floor(numCharges / chargeRate) else: numShots = None return numShots @@ -231,7 +236,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): chance = self.getModifiedChargeAttr("crystalVolatilityChance") damage = self.getModifiedChargeAttr("crystalVolatilityDamage") crystals = self.numCharges - numShots = floorFloat(float(crystals * hp) / (damage * chance)) + numShots = floor((crystals * hp) / (damage * chance)) else: # Set 0 (infinite) for permanent crystals like t1 laser crystals numShots = 0 @@ -417,6 +422,11 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if isinstance(fit.ship, Citadel) and len(fitsOnGroup) == 0 and len(fitsOnType) == 0: return False + # EVE doesn't let capital modules be fit onto subcapital hulls. Confirmed by CCP Larrikin that this is dictated + # by the modules volume. See GH issue #1096 + if (fit.ship.getModifiedItemAttr("isCapitalSize", 0) != 1 and self.isCapitalSize): + return False + # If the mod is a subsystem, don't let two subs in the same slot fit if self.slot == Slot.SUBSYSTEM: subSlot = self.getModifiedItemAttr("subSystemSlot") @@ -547,7 +557,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): return validCharges - def __calculateHardpoint(self, item): + @staticmethod + def __calculateHardpoint(item): effectHardpointMap = {"turretFitted": Hardpoint.TURRET, "launcherFitted": Hardpoint.MISSILE} @@ -560,7 +571,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): return Hardpoint.NONE - def __calculateSlot(self, item): + @staticmethod + def __calculateSlot(item): effectSlotMap = {"rigSlot": Slot.RIG, "loPower": Slot.LOW, "medPower": Slot.MED, @@ -579,9 +591,9 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): @validates("ID", "itemID", "ammoID") def validator(self, key, val): - map = {"ID": lambda val: isinstance(val, int), - "itemID": lambda val: val is None or isinstance(val, int), - "ammoID": lambda val: isinstance(val, int)} + map = {"ID": lambda _val: isinstance(_val, int), + "itemID": lambda _val: _val is None or isinstance(_val, int), + "ammoID": lambda _val: isinstance(_val, int)} if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) @@ -663,32 +675,68 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): @property def cycleTime(self): - reactivation = (self.getModifiedItemAttr("moduleReactivationDelay") or 0) - # Reactivation time starts counting after end of module cycle - speed = self.rawCycleTime + reactivation - if self.charge: - reload = self.reloadTime - else: - reload = 0.0 # Determine if we'll take into account reload time or not factorReload = self.owner.factorReload if self.forceReload is None else self.forceReload - # If reactivation is longer than 10 seconds then module can be reloaded - # during reactivation time, thus we may ignore reload - if factorReload and reactivation < reload: - numShots = self.numShots - # Time it takes to reload module after end of reactivation time, - # given that we started when module cycle has just over - additionalReloadTime = (reload - reactivation) - # Speed here already takes into consideration reactivation time - speed = (speed * numShots + additionalReloadTime) / numShots if numShots > 0 else speed + + numShots = self.numShots + speed = self.rawCycleTime + + if factorReload and self.charge: + raw_reload_time = self.reloadTime + else: + raw_reload_time = 0.0 + + # Module can only fire one shot at a time, think bomb launchers or defender launchers + if self.disallowRepeatingAction: + if numShots > 1: + """ + The actual mechanics behind this is complex. Behavior will be (for 3 ammo): + fire, reactivation delay, fire, reactivation delay, fire, max(reactivation delay, reload) + so your effective reload time depends on where you are at in the cycle. + + We can't do that, so instead we'll average it out. + + Currently would apply to bomb launchers and defender missiles + """ + effective_reload_time = ((self.reactivationDelay * (numShots - 1)) + max(raw_reload_time, self.reactivationDelay, 0)) / numShots + else: + """ + Applies to MJD/MJFG + """ + effective_reload_time = max(raw_reload_time, self.reactivationDelay, 0) + else: + """ + Currently no other modules would have a reactivation delay, so for sanities sake don't try and account for it. + Okay, technically cloaks do, but they also have 0 cycle time and cap usage so why do you care? + """ + effective_reload_time = raw_reload_time + + if numShots > 0 and self.charge: + speed = (speed * numShots + effective_reload_time) / numShots return speed @property def rawCycleTime(self): - speed = self.getModifiedItemAttr("speed") or self.getModifiedItemAttr("duration") + speed = max( + self.getModifiedItemAttr("speed"), # Most weapons + self.getModifiedItemAttr("duration"), # Most average modules + self.getModifiedItemAttr("durationSensorDampeningBurstProjector"), + self.getModifiedItemAttr("durationTargetIlluminationBurstProjector"), + self.getModifiedItemAttr("durationECMJammerBurstProjector"), + self.getModifiedItemAttr("durationWeaponDisruptionBurstProjector"), + 0, # Return 0 if none of the above are valid + ) return speed + @property + def disallowRepeatingAction(self): + return self.getModifiedItemAttr("disallowRepeatingAction", 0) + + @property + def reactivationDelay(self): + return self.getModifiedItemAttr("moduleReactivationDelay", 0) + @property def capUse(self): capNeed = self.getModifiedItemAttr("capacitorNeed") diff --git a/eos/saveddata/override.py b/eos/saveddata/override.py index c4f8a1e02..cc7fb9342 100644 --- a/eos/saveddata/override.py +++ b/eos/saveddata/override.py @@ -17,14 +17,14 @@ # along with eos. If not, see . # =============================================================================== -import logging +from logbook import Logger from sqlalchemy.orm import reconstructor import eos.db from eos.eqBase import EqBase -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class Override(EqBase): @@ -43,13 +43,13 @@ class Override(EqBase): if self.attrID: self.__attr = eos.db.getAttributeInfo(self.attrID) if self.__attr is None: - logger.error("Attribute (id: %d) does not exist", self.attrID) + pyfalog.error("Attribute (id: {0}) does not exist", self.attrID) return if self.itemID: self.__item = eos.db.getItem(self.itemID) if self.__item is None: - logger.error("Item (id: %d) does not exist", self.itemID) + pyfalog.error("Item (id: {0}) does not exist", self.itemID) return @property diff --git a/eos/saveddata/ship.py b/eos/saveddata/ship.py index 4e4020cc7..1e3fd41f0 100644 --- a/eos/saveddata/ship.py +++ b/eos/saveddata/ship.py @@ -17,14 +17,14 @@ # along with eos. If not, see . # =============================================================================== -import logging +from logbook import Logger import eos.db from eos.effectHandlerHelpers import HandledItem from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, cappingAttrKeyCache from eos.saveddata.mode import Mode -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class Ship(ItemAttrShortcut, HandledItem): @@ -63,6 +63,7 @@ class Ship(ItemAttrShortcut, HandledItem): def validate(self, item): if item.category.name != "Ship": + pyfalog.error("Passed item '{0}' (category: {1}) is not under Ship category", item.name, item.category.name) raise ValueError( 'Passed item "%s" (category: (%s)) is not under Ship category' % (item.name, item.category.name)) diff --git a/eos/saveddata/targetResists.py b/eos/saveddata/targetResists.py index 67cd323a8..e50c13791 100644 --- a/eos/saveddata/targetResists.py +++ b/eos/saveddata/targetResists.py @@ -18,6 +18,9 @@ # =============================================================================== import re +from logbook import Logger + +pyfalog = Logger(__name__) class TargetResists(object): @@ -43,7 +46,7 @@ class TargetResists(object): type, data = line.rsplit('=', 1) type, data = type.strip(), data.split(',') except: - # Data isn't in correct format, continue to next line + pyfalog.warning("Data isn't in correct format, continue to next line.") continue if type != "TargetResists": @@ -59,6 +62,7 @@ class TargetResists(object): assert 0 <= val <= 100 fields["%sAmount" % cls.DAMAGE_TYPES[index]] = val / 100 except: + pyfalog.warning("Caught unhandled exception in import patterns.") continue if len(fields) == 4: # Avoid possible blank lines diff --git a/eos/saveddata/user.py b/eos/saveddata/user.py index 8c3905a0d..baf09d9f3 100644 --- a/eos/saveddata/user.py +++ b/eos/saveddata/user.py @@ -49,10 +49,10 @@ class User(object): @validates("ID", "username", "password", "admin") def validator(self, key, val): - map = {"ID": lambda val: isinstance(val, int), - "username": lambda val: isinstance(val, basestring), - "password": lambda val: isinstance(val, basestring) and len(val) == 96, - "admin": lambda val: isinstance(val, bool)} + map = {"ID": lambda _val: isinstance(_val, int), + "username": lambda _val: isinstance(_val, basestring), + "password": lambda _val: isinstance(_val, basestring) and len(_val) == 96, + "admin": lambda _val: isinstance(_val, bool)} if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) diff --git a/eos/types.py b/eos/types.py deleted file mode 100644 index e6663689f..000000000 --- a/eos/types.py +++ /dev/null @@ -1,46 +0,0 @@ -# =============================================================================== -# Copyright (C) 2010 Diego Duclos -# -# This file is part of eos. -# -# eos 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 of the License, or -# (at your option) any later version. -# -# eos 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 eos. If not, see . -# =============================================================================== - -from eos.gamedata import Attribute, Category, Effect, Group, Icon, Item, MarketGroup, \ - MetaGroup, AttributeInfo, Unit, EffectInfo, MetaType, MetaData, Traits, AlphaClone, \ - AlphaCloneSkill -from eos.saveddata.price import Price -from eos.saveddata.user import User -from eos.saveddata.crestchar import CrestChar -from eos.saveddata.damagePattern import DamagePattern -from eos.saveddata.targetResists import TargetResists -from eos.saveddata.character import Character, Skill -from eos.saveddata.ship import Ship -from eos.saveddata.citadel import Citadel -from eos.saveddata.module import Module, State, Slot, Hardpoint, Rack -from eos.saveddata.drone import Drone -from eos.saveddata.fighterAbility import FighterAbility -from eos.saveddata.fighter import Fighter -from eos.saveddata.cargo import Cargo -from eos.saveddata.implant import Implant -from eos.saveddata.implantSet import ImplantSet -# Legacy booster side effect code, disabling as not currently implemented -# from eos.saveddata.booster import SideEffect -from eos.saveddata.booster import Booster -from eos.saveddata.fit import Fit, ImplantLocation -from eos.saveddata.mode import Mode -from eos.saveddata.miscData import MiscData -from eos.saveddata.override import Override - -import eos.db diff --git a/eve.db b/eve.db index 938e8c336..f0717cc7c 100644 Binary files a/eve.db and b/eve.db differ diff --git a/gui/PFListPane.py b/gui/PFListPane.py index 556b97638..e6689ce8d 100644 --- a/gui/PFListPane.py +++ b/gui/PFListPane.py @@ -17,6 +17,7 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx @@ -79,11 +80,11 @@ class PFListPane(wx.ScrolledWindow): new_vs_x, new_vs_y = -1, -1 # is it before the left edge? - if cr.x < 0 and sppu_x > 0: + if cr.x < 0 < sppu_x: new_vs_x = vs_x + (cr.x / sppu_x) # is it above the top? - if cr.y < 0 and sppu_y > 0: + if cr.y < 0 < sppu_y: new_vs_y = vs_y + (cr.y / sppu_y) # For the right and bottom edges, scroll enough to show the @@ -143,10 +144,8 @@ class PFListPane(wx.ScrolledWindow): elif doFocus: self.SetFocus() - clientW, clientH = self.GetSize() for i in xrange(len(self._wList)): iwidth, iheight = self._wList[i].GetSize() - itemX, itemY = self._wList[i].GetPosition() self._wList[i].SetSize((cwidth, iheight)) if doRefresh is True: self._wList[i].Refresh() diff --git a/gui/PFSearchBox.py b/gui/PFSearchBox.py index ece5cef5f..f5f8d8c6d 100644 --- a/gui/PFSearchBox.py +++ b/gui/PFSearchBox.py @@ -1,3 +1,4 @@ +# noinspection PyPackageRequirements import wx import gui.utils.colorUtils as colorUtils import gui.utils.drawUtils as drawUtils @@ -68,7 +69,8 @@ class PFSearchBox(wx.Window): wx.PostEvent(self, TextEnter()) event.Skip() - def OnEditSetFocus(self, event): + @staticmethod + def OnEditSetFocus(event): # value = self.EditBox.GetValue() # if value == self.descriptiveText: # self.EditBox.ChangeValue("") @@ -102,14 +104,15 @@ class PFSearchBox(wx.Window): x, y = target px, py = position aX, aY = area - if (px > x and px < x + aX) and (py > y and py < y + aY): + if (x < px < x + aX) and (y < py < y + aY): return True return False def GetButtonsPos(self): - btnpos = [] - btnpos.append((self.searchButtonX, self.searchButtonY)) - btnpos.append((self.cancelButtonX, self.cancelButtonY)) + btnpos = [ + (self.searchButtonX, self.searchButtonY), + (self.cancelButtonX, self.cancelButtonY) + ] return btnpos def GetButtonsSize(self): diff --git a/gui/additionsPane.py b/gui/additionsPane.py index c0616f597..503fc4135 100644 --- a/gui/additionsPane.py +++ b/gui/additionsPane.py @@ -17,8 +17,8 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx -import gui.mainFrame from gui.boosterView import BoosterView from gui.droneView import DroneView from gui.fighterView import FighterView @@ -31,7 +31,7 @@ from gui.notesView import NotesView from gui.pyfatogglepanel import TogglePanel from gui.bitmapLoader import BitmapLoader -import gui.chromeTabs +from gui.chromeTabs import PFNotebook class AdditionsPane(TogglePanel): @@ -45,9 +45,7 @@ class AdditionsPane(TogglePanel): baseSizer = wx.BoxSizer(wx.HORIZONTAL) pane.SetSizer(baseSizer) - self.mainFrame = gui.mainFrame.MainFrame.getInstance() - - self.notebook = gui.chromeTabs.PFNotebook(pane, False) + self.notebook = PFNotebook(pane, False) self.notebook.SetMinSize((-1, 1000)) baseSizer.Add(self.notebook, 1, wx.EXPAND) @@ -92,9 +90,6 @@ class AdditionsPane(TogglePanel): def select(self, name): self.notebook.SetSelection(self.PANES.index(name)) - def toggleBoosters(self, event): - self.notebook.ToggleShown(self.booster) - def getName(self, idx): return self.PANES[idx] diff --git a/gui/bitmapLoader.py b/gui/bitmapLoader.py index 066fc0c5f..eb53b1f1d 100644 --- a/gui/bitmapLoader.py +++ b/gui/bitmapLoader.py @@ -20,22 +20,27 @@ import cStringIO import os.path import zipfile -from config import parsePath +# noinspection PyPackageRequirements import wx import config +from logbook import Logger +logging = Logger(__name__) + try: from collections import OrderedDict except ImportError: from utils.compat import OrderedDict -class BitmapLoader(): +class BitmapLoader(object): try: - archive = zipfile.ZipFile(config.getPyfaPath('imgs.zip'), 'r') + archive = zipfile.ZipFile(os.path.join(config.pyfaPath, 'imgs.zip'), 'r') + logging.info("Using zipped image files.") except IOError: + logging.info("Using local image files.") archive = None cachedBitmaps = OrderedDict() @@ -77,7 +82,7 @@ class BitmapLoader(): filename = "{0}.png".format(name) if cls.archive: - path = parsePath(location, filename) + path = os.path.join(location, filename) if os.sep != "/" and os.sep in path: path = path.replace(os.sep, "/") @@ -88,7 +93,7 @@ class BitmapLoader(): except KeyError: print("Missing icon file from zip: {0}".format(path)) else: - path = config.getPyfaPath('imgs' + os.sep + location + os.sep + filename) + path = os.path.join(config.pyfaPath, 'imgs' + os.sep + location + os.sep + filename) if os.path.exists(path): return wx.Image(path) diff --git a/gui/boosterView.py b/gui/boosterView.py index d4d631942..fe0d802d3 100644 --- a/gui/boosterView.py +++ b/gui/boosterView.py @@ -17,18 +17,19 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx import gui.display as d import gui.globalEvents as GE -import gui.marketBrowser as mb +import gui.marketBrowser as marketBrowser from gui.builtinViewColumns.state import State from gui.contextMenu import ContextMenu from service.fit import Fit class BoosterViewDrop(wx.PyDropTarget): - def __init__(self, dropFn): - wx.PyDropTarget.__init__(self) + def __init__(self, dropFn, *args, **kwargs): + super(BoosterViewDrop, self).__init__(*args, **kwargs) self.dropFn = dropFn # this is really transferring an EVE itemID self.dropData = wx.PyTextDataObject() @@ -52,7 +53,7 @@ class BoosterView(d.Display): self.lastFitId = None self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged) - self.mainFrame.Bind(mb.ITEM_SELECTED, self.addItem) + self.mainFrame.Bind(marketBrowser.ITEM_SELECTED, self.addItem) self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem) self.Bind(wx.EVT_LEFT_DOWN, self.click) @@ -66,16 +67,16 @@ class BoosterView(d.Display): self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu) def handleListDrag(self, x, y, data): - ''' + """ Handles dragging of items from various pyfa displays which support it data is list with two indices: data[0] is hard-coded str of originating source data[1] is typeID or index of data we want to manipulate - ''' + """ if data[0] == "market": - wx.PostEvent(self.mainFrame, mb.ItemSelected(itemID=int(data[1]))) + wx.PostEvent(self.mainFrame, marketBrowser.ItemSelected(itemID=int(data[1]))) def kbEvent(self, event): keycode = event.GetKeyCode() diff --git a/gui/builtinContextMenus/__init__.py b/gui/builtinContextMenus/__init__.py index c6a41c112..e69de29bb 100644 --- a/gui/builtinContextMenus/__init__.py +++ b/gui/builtinContextMenus/__init__.py @@ -1,25 +0,0 @@ -__all__ = [ - "openFit", - # "moduleGlobalAmmoPicker", - "moduleAmmoPicker", - "itemStats", - "damagePattern", - "marketJump", - "droneSplit", - "itemRemove", - "droneRemoveStack", - "ammoPattern", - "project", - "factorReload", - "whProjector", - "cargo", - "shipJump", - "changeAffectingSkills", - "tacticalMode", - "targetResists", - "priceClear", - "amount", - "metaSwap", - "implantSets", - "fighterAbilities", -] diff --git a/gui/builtinContextMenus/ammoPattern.py b/gui/builtinContextMenus/ammoPattern.py index be2833d9e..1b8dfd95c 100644 --- a/gui/builtinContextMenus/ammoPattern.py +++ b/gui/builtinContextMenus/ammoPattern.py @@ -1,15 +1,21 @@ from gui.contextMenu import ContextMenu import gui.mainFrame +# noinspection PyPackageRequirements import wx import gui.globalEvents as GE from service.fit import Fit +from service.settings import ContextMenuSettings class AmmoPattern(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('ammoPattern'): + return False + if srcContext not in ("marketItemGroup", "marketItemMisc") or self.mainFrame.getActiveFit() is None: return False diff --git a/gui/builtinContextMenus/amount.py b/gui/builtinContextMenus/amount.py index a4984a635..f9dd957ff 100644 --- a/gui/builtinContextMenus/amount.py +++ b/gui/builtinContextMenus/amount.py @@ -1,18 +1,24 @@ from gui.contextMenu import ContextMenu -import eos.types +from eos.saveddata.fit import Fit as es_Fit import gui.mainFrame import gui.globalEvents as GE +# noinspection PyPackageRequirements import wx from service.fit import Fit from eos.saveddata.cargo import Cargo as es_Cargo from eos.saveddata.fighter import Fighter as es_Fighter +from service.settings import ContextMenuSettings class ChangeAmount(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('amount'): + return False + return srcContext in ("cargoItem", "projectedFit", "fighterItem", "projectedFighter") def getText(self, itmContext, selection): @@ -49,9 +55,9 @@ class AmountChanger(wx.Dialog): self.button.Bind(wx.EVT_BUTTON, self.change) def change(self, event): - sFit = Fit.getInstance() if self.input.GetLineText(0).strip() == '': event.Skip() + self.Close() return sFit = Fit.getInstance() @@ -60,7 +66,7 @@ class AmountChanger(wx.Dialog): if isinstance(self.thing, es_Cargo): sFit.addCargo(fitID, self.thing.item.ID, int(float(self.input.GetLineText(0))), replace=True) - elif isinstance(self.thing, eos.types.Fit): + elif isinstance(self.thing, es_Fit): sFit.changeAmount(fitID, self.thing, int(float(self.input.GetLineText(0)))) elif isinstance(self.thing, es_Fighter): sFit.changeActiveFighters(fitID, self.thing, int(float(self.input.GetLineText(0)))) @@ -68,9 +74,11 @@ class AmountChanger(wx.Dialog): wx.PostEvent(mainFrame, GE.FitChanged(fitID=fitID)) event.Skip() + self.Close() # checks to make sure it's valid number - def onChar(self, event): + @staticmethod + def onChar(event): key = event.GetKeyCode() acceptable_characters = "1234567890" diff --git a/gui/builtinContextMenus/cargo.py b/gui/builtinContextMenus/cargo.py index 1f5ad4202..32d6370cf 100644 --- a/gui/builtinContextMenus/cargo.py +++ b/gui/builtinContextMenus/cargo.py @@ -1,22 +1,31 @@ from gui.contextMenu import ContextMenu import gui.mainFrame import gui.globalEvents as GE +# noinspection PyPackageRequirements import wx from service.fit import Fit +from service.settings import ContextMenuSettings class Cargo(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('cargo'): + return False + + if srcContext not in ("marketItemGroup", "marketItemMisc"): + return False + sFit = Fit.getInstance() fitID = self.mainFrame.getActiveFit() - fit = sFit.getFit(fitID) # Make sure context menu registers in the correct view - if srcContext not in ("marketItemGroup", "marketItemMisc") or not fit or fit.isStructure: + if not fit or fit.isStructure: return False + return True def getText(self, itmContext, selection): diff --git a/gui/builtinContextMenus/cargoAmmo.py b/gui/builtinContextMenus/cargoAmmo.py new file mode 100644 index 000000000..12ebe552f --- /dev/null +++ b/gui/builtinContextMenus/cargoAmmo.py @@ -0,0 +1,40 @@ +from gui.contextMenu import ContextMenu +import gui.mainFrame +import gui.globalEvents as GE +import wx +from service.settings import ContextMenuSettings +from service.fit import Fit + + +class CargoAmmo(ContextMenu): + def __init__(self): + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() + + def display(self, srcContext, selection): + if not self.settings.get('cargoAmmo'): + return False + + if srcContext not in ("marketItemGroup", "marketItemMisc") or self.mainFrame.getActiveFit() is None: + return False + + for selected_item in selection: + if selected_item.category.ID in ( + 8, # Charge + ): + return True + + def getText(self, itmContext, selection): + return "Add {0} to Cargo (x1000)".format(itmContext) + + def activate(self, fullContext, selection, i): + sFit = Fit.getInstance() + fitID = self.mainFrame.getActiveFit() + + typeID = int(selection[0].ID) + sFit.addCargo(fitID, typeID, 1000) + self.mainFrame.additionsPane.select("Cargo") + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) + + +CargoAmmo.register() diff --git a/gui/builtinContextMenus/changeAffectingSkills.py b/gui/builtinContextMenus/changeAffectingSkills.py index 79b7bd3bd..dc71fc06d 100644 --- a/gui/builtinContextMenus/changeAffectingSkills.py +++ b/gui/builtinContextMenus/changeAffectingSkills.py @@ -1,19 +1,25 @@ # -*- coding: utf-8 -*- from gui.contextMenu import ContextMenu import gui.mainFrame +# noinspection PyPackageRequirements import wx from gui.bitmapLoader import BitmapLoader -from eos.types import Skill +from eos.saveddata.character import Skill import gui.globalEvents as GE from service.fit import Fit from service.character import Character +from service.settings import ContextMenuSettings class ChangeAffectingSkills(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('changeAffectingSkills'): + return False + if self.mainFrame.getActiveFit() is None or srcContext not in ("fittingModule", "fittingCharge", "fittingShip"): return False diff --git a/gui/builtinContextMenus/damagePattern.py b/gui/builtinContextMenus/damagePattern.py index b2089e9c0..8399dd069 100644 --- a/gui/builtinContextMenus/damagePattern.py +++ b/gui/builtinContextMenus/damagePattern.py @@ -1,22 +1,28 @@ from gui.contextMenu import ContextMenu import gui.mainFrame import gui.globalEvents as GE +# noinspection PyPackageRequirements import wx from gui.bitmapLoader import BitmapLoader from service.fit import Fit from service.damagePattern import DamagePattern as import_DamagePattern +from service.settings import ContextMenuSettings try: from collections import OrderedDict except ImportError: - from gui.utils.compat import OrderedDict + from utils.compat import OrderedDict class DamagePattern(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('damagePattern'): + return False + return srcContext == "resistancesViewFull" and self.mainFrame.getActiveFit() is not None def getText(self, itmContext, selection): diff --git a/gui/builtinContextMenus/droneRemoveStack.py b/gui/builtinContextMenus/droneRemoveStack.py index 8132a8fc9..c7dae1e03 100644 --- a/gui/builtinContextMenus/droneRemoveStack.py +++ b/gui/builtinContextMenus/droneRemoveStack.py @@ -1,15 +1,21 @@ from gui.contextMenu import ContextMenu import gui.mainFrame +# noinspection PyPackageRequirements import wx import gui.globalEvents as GE from service.fit import Fit +from service.settings import ContextMenuSettings class ItemRemove(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('droneRemoveStack'): + return False + return srcContext == "droneItem" def getText(self, itmContext, selection): diff --git a/gui/builtinContextMenus/droneSplit.py b/gui/builtinContextMenus/droneSplit.py index 2f2ec923e..761262a8c 100644 --- a/gui/builtinContextMenus/droneSplit.py +++ b/gui/builtinContextMenus/droneSplit.py @@ -2,14 +2,20 @@ from gui.contextMenu import ContextMenu import gui.mainFrame import gui.globalEvents as GE from service.fit import Fit +# noinspection PyPackageRequirements import wx +from service.settings import ContextMenuSettings class DroneSplit(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('droneSplit'): + return False + return srcContext in ("droneItem", "projectedDrone") and selection[0].amount > 1 def getText(self, itmContext, selection): diff --git a/gui/builtinContextMenus/droneStack.py b/gui/builtinContextMenus/droneStack.py new file mode 100644 index 000000000..99a253796 --- /dev/null +++ b/gui/builtinContextMenus/droneStack.py @@ -0,0 +1,42 @@ +from gui.contextMenu import ContextMenu +import gui.mainFrame +import gui.globalEvents as GE +import wx +from service.settings import ContextMenuSettings +from service.fit import Fit + + +class DroneStack(ContextMenu): + def __init__(self): + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() + + def display(self, srcContext, selection): + if not self.settings.get('droneStack'): + return False + + if srcContext not in ("marketItemGroup", "marketItemMisc") or self.mainFrame.getActiveFit() is None: + return False + + for selected_item in selection: + if selected_item.category.ID in ( + 18, # Drones + ): + return True + + return False + + def getText(self, itmContext, selection): + return "Add {0} to Drone Bay (x5)".format(itmContext) + + def activate(self, fullContext, selection, i): + sFit = Fit.getInstance() + fitID = self.mainFrame.getActiveFit() + + typeID = int(selection[0].ID) + sFit.addDrone(fitID, typeID, 5) + self.mainFrame.additionsPane.select("Drones") + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) + + +DroneStack.register() diff --git a/gui/builtinContextMenus/factorReload.py b/gui/builtinContextMenus/factorReload.py index d7b33658d..6770e64af 100644 --- a/gui/builtinContextMenus/factorReload.py +++ b/gui/builtinContextMenus/factorReload.py @@ -1,16 +1,22 @@ from gui.contextMenu import ContextMenu import gui.mainFrame import gui.globalEvents as GE +# noinspection PyPackageRequirements import wx from gui.bitmapLoader import BitmapLoader from service.fit import Fit +from service.settings import ContextMenuSettings class FactorReload(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('factorReload'): + return False + return srcContext == "firepowerViewFull" and self.mainFrame.getActiveFit() is not None def getText(self, itmContext, selection): diff --git a/gui/builtinContextMenus/fighterAbilities.py b/gui/builtinContextMenus/fighterAbilities.py index d262cb052..6f6bc8051 100644 --- a/gui/builtinContextMenus/fighterAbilities.py +++ b/gui/builtinContextMenus/fighterAbilities.py @@ -1,15 +1,21 @@ +# noinspection PyPackageRequirements import wx from gui.contextMenu import ContextMenu import gui.mainFrame import gui.globalEvents as GE from service.fit import Fit +from service.settings import ContextMenuSettings class FighterAbility(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('fighterAbilities'): + return False + if self.mainFrame.getActiveFit() is None or srcContext not in ("fighterItem", "projectedFighter"): return False diff --git a/gui/builtinContextMenus/implantSets.py b/gui/builtinContextMenus/implantSets.py index 490f52ef2..6a2ee7bfe 100644 --- a/gui/builtinContextMenus/implantSets.py +++ b/gui/builtinContextMenus/implantSets.py @@ -1,17 +1,23 @@ from gui.contextMenu import ContextMenu import gui.mainFrame import gui.globalEvents as GE +# noinspection PyPackageRequirements import wx from service.implantSet import ImplantSets as s_ImplantSets from service.character import Character from service.fit import Fit +from service.settings import ContextMenuSettings class ImplantSets(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('implantSets'): + return False + return srcContext in ("implantView", "implantEditor") def getText(self, itmContext, selection): diff --git a/gui/builtinContextMenus/itemRemove.py b/gui/builtinContextMenus/itemRemove.py index 400890b1a..6ad128220 100644 --- a/gui/builtinContextMenus/itemRemove.py +++ b/gui/builtinContextMenus/itemRemove.py @@ -1,15 +1,21 @@ from gui.contextMenu import ContextMenu import gui.mainFrame +# noinspection PyPackageRequirements import wx import gui.globalEvents as GE from service.fit import Fit +from service.settings import ContextMenuSettings class ItemRemove(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('itemRemove'): + return False + return srcContext in ("fittingModule", "fittingCharge", "droneItem", "implantItem", "boosterItem", "projectedModule", diff --git a/gui/builtinContextMenus/itemStats.py b/gui/builtinContextMenus/itemStats.py index 2ccc3d364..4e1b8187e 100644 --- a/gui/builtinContextMenus/itemStats.py +++ b/gui/builtinContextMenus/itemStats.py @@ -1,15 +1,20 @@ from gui.contextMenu import ContextMenu from gui.itemStats import ItemStatsDialog import gui.mainFrame +# noinspection PyPackageRequirements import wx from service.fit import Fit +from service.settings import ContextMenuSettings class ItemStats(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('itemStats'): + return False return srcContext in ("marketItemGroup", "marketItemMisc", "fittingModule", "fittingCharge", diff --git a/gui/builtinContextMenus/marketJump.py b/gui/builtinContextMenus/marketJump.py index e96292b41..c630312c1 100644 --- a/gui/builtinContextMenus/marketJump.py +++ b/gui/builtinContextMenus/marketJump.py @@ -1,13 +1,18 @@ from gui.contextMenu import ContextMenu import gui.mainFrame from service.market import Market +from service.settings import ContextMenuSettings class MarketJump(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('marketJump'): + return False + validContexts = ("marketItemMisc", "fittingModule", "fittingCharge", "droneItem", "implantItem", "boosterItem", diff --git a/gui/builtinContextMenus/metaSwap.py b/gui/builtinContextMenus/metaSwap.py index 3462410e5..00766905f 100644 --- a/gui/builtinContextMenus/metaSwap.py +++ b/gui/builtinContextMenus/metaSwap.py @@ -1,5 +1,6 @@ # coding: utf-8 +# noinspection PyPackageRequirements import wx from service.fit import Fit @@ -7,15 +8,30 @@ from service.market import Market import gui.mainFrame import gui.globalEvents as GE from gui.contextMenu import ContextMenu +from service.settings import ContextMenuSettings +from eos.saveddata.booster import Booster +from eos.saveddata.module import Module +from eos.saveddata.drone import Drone +from eos.saveddata.fighter import Fighter +from eos.saveddata.implant import Implant class MetaSwap(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('metaSwap'): + return False - if self.mainFrame.getActiveFit() is None or srcContext not in ("fittingModule",): + if self.mainFrame.getActiveFit() is None or srcContext not in ( + "fittingModule", + "droneItem", + "fighterItem", + "boosterItem", + "implantItem", + ): return False # Check if list of variations is same for all of selection @@ -51,6 +67,17 @@ class MetaSwap(ContextMenu): def get_metagroup(x): return x.metaGroup.ID if x.metaGroup is not None else 0 + def get_boosterrank(x): + # If we're returning a lot of items, sort my name + if len(self.variations) > 7: + return x.name + # Sort by booster chance to get some sort of pseudorank. + elif 'boosterEffectChance1' in x.attributes: + return x.attributes['boosterEffectChance1'].value + # the "first" rank (Synth) doesn't have boosterEffectChance1. If we're not pulling back all boosters, return 0 for proper sorting + else: + return 0 + m = wx.Menu() # If on Windows we need to bind out events into the root menu, on other @@ -62,8 +89,17 @@ class MetaSwap(ContextMenu): # Sort items by metalevel, and group within that metalevel items = list(self.variations) - items.sort(key=get_metalevel) - items.sort(key=get_metagroup) + print context + if "implantItem" in context: + # sort implants based on name + items.sort(key=lambda x: x.name) + elif "boosterItem" in context: + # boosters don't have meta or anything concrete that we can rank by. Go by chance to inflict side effect + items.sort(key=get_boosterrank) + else: + # sort by group and meta level + items.sort(key=get_metalevel) + items.sort(key=get_metagroup) group = None for item in items: @@ -73,7 +109,7 @@ class MetaSwap(ContextMenu): else: thisgroup = item.metaGroup.name - if thisgroup != group: + if thisgroup != group and context not in ("implantItem", "boosterItem"): group = thisgroup id = ContextMenu.nextID() m.Append(id, u'─ %s ─' % group) @@ -96,9 +132,56 @@ class MetaSwap(ContextMenu): fitID = self.mainFrame.getActiveFit() fit = sFit.getFit(fitID) - for mod in self.selection: - pos = fit.modules.index(mod) - sFit.changeModule(fitID, pos, item.ID) + for selected_item in self.selection: + if isinstance(selected_item, Module): + pos = fit.modules.index(selected_item) + sFit.changeModule(fitID, pos, item.ID) + + elif isinstance(selected_item, Drone): + drone_count = None + + for idx, drone_stack in enumerate(fit.drones): + if drone_stack is selected_item: + drone_count = drone_stack.amount + sFit.removeDrone(fitID, idx, drone_count) + break + + if drone_count: + sFit.addDrone(fitID, item.ID, drone_count) + + elif isinstance(selected_item, Fighter): + fighter_count = None + + for idx, fighter_stack in enumerate(fit.fighters): + # Right now fighters always will have max stack size. + # Including this for future improvement, so if adjustable + # fighter stacks get added we're ready for it. + if fighter_stack is selected_item: + if fighter_stack.amount > 0: + fighter_count = fighter_stack.amount + elif fighter_stack.amount == -1: + fighter_count = fighter_stack.amountActive + else: + fighter_count.amount = 0 + + sFit.removeFighter(fitID, idx) + break + + sFit.addFighter(fitID, item.ID) + + elif isinstance(selected_item, Booster): + for idx, booster_stack in enumerate(fit.boosters): + if booster_stack is selected_item: + sFit.removeBooster(fitID, idx) + sFit.addBooster(fitID, item.ID) + break + + elif isinstance(selected_item, Implant): + for idx, implant_stack in enumerate(fit.implants): + if implant_stack is selected_item: + sFit.removeImplant(fitID, idx, False) + sFit.addImplant(fitID, item.ID, True) + break wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) diff --git a/gui/builtinContextMenus/moduleAmmoPicker.py b/gui/builtinContextMenus/moduleAmmoPicker.py index e69aac4cd..1af970190 100644 --- a/gui/builtinContextMenus/moduleAmmoPicker.py +++ b/gui/builtinContextMenus/moduleAmmoPicker.py @@ -1,14 +1,16 @@ # coding: utf-8 +# noinspection PyPackageRequirements import wx from service.fit import Fit from service.market import Market -from eos.types import Hardpoint +from eos.saveddata.module import Hardpoint import gui.mainFrame import gui.globalEvents as GE from gui.contextMenu import ContextMenu from gui.bitmapLoader import BitmapLoader +from service.settings import ContextMenuSettings class ModuleAmmoPicker(ContextMenu): @@ -17,8 +19,12 @@ class ModuleAmmoPicker(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('moduleAmmoPicker'): + return False + if self.mainFrame.getActiveFit() is None or srcContext not in ("fittingModule", "projectedModule"): return False @@ -96,7 +102,8 @@ class ModuleAmmoPicker(ContextMenu): return chargeDamageType, totalDamage - def numericConverter(self, string): + @staticmethod + def numericConverter(string): return int(string) if string.isdigit() else string def nameSorter(self, charge): @@ -117,7 +124,8 @@ class ModuleAmmoPicker(ContextMenu): return item - def addSeperator(self, m, text): + @staticmethod + def addSeperator(m, text): id_ = ContextMenu.nextID() m.Append(id_, u'─ %s ─' % text) m.Enable(id_, False) @@ -157,7 +165,7 @@ class ModuleAmmoPicker(ContextMenu): item = self.addCharge(rootMenu if msw else m, charge) items.append(item) else: - if sub is None: + if sub is None and item and base: sub = wx.Menu() sub.Bind(wx.EVT_MENU, self.handleAmmoSwitch) self.addSeperator(sub, "Less Damage") diff --git a/gui/builtinContextMenus/moduleGlobalAmmoPicker.py b/gui/builtinContextMenus/moduleGlobalAmmoPicker.py index 035109320..5e516e68f 100644 --- a/gui/builtinContextMenus/moduleGlobalAmmoPicker.py +++ b/gui/builtinContextMenus/moduleGlobalAmmoPicker.py @@ -1,15 +1,19 @@ # -*- coding: utf-8 -*- import gui.mainFrame +# noinspection PyPackageRequirements import wx import gui.globalEvents as GE from gui.builtinContextMenus.moduleAmmoPicker import ModuleAmmoPicker -import eos.db +from eos.db.saveddata.queries import getFit as db_getFit from service.fit import Fit +from service.settings import ContextMenuSettings class ModuleGlobalAmmoPicker(ModuleAmmoPicker): def __init__(self): + super(ModuleGlobalAmmoPicker, self).__init__() self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def getText(self, itmContext, selection): return "Charge (All)" @@ -26,7 +30,7 @@ class ModuleGlobalAmmoPicker(ModuleAmmoPicker): sFit = Fit.getInstance() fitID = self.mainFrame.getActiveFit() - fit = eos.db.getFit(fitID) + fit = db_getFit(fitID) selectedModule = self.modules[0] allModules = [] @@ -40,6 +44,9 @@ class ModuleGlobalAmmoPicker(ModuleAmmoPicker): wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) def display(self, srcContext, selection): + if not self.settings.get('moduleGlobalAmmoPicker'): + return False + try: selectionLen = len(selection) except: diff --git a/gui/builtinContextMenus/openFit.py b/gui/builtinContextMenus/openFit.py index fad0c2640..d13618132 100644 --- a/gui/builtinContextMenus/openFit.py +++ b/gui/builtinContextMenus/openFit.py @@ -1,14 +1,20 @@ from gui.contextMenu import ContextMenu import gui.mainFrame +# noinspection PyPackageRequirements import wx from gui.shipBrowser import FitSelected +from service.settings import ContextMenuSettings class OpenFit(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('openFit'): + return False + return srcContext == "projectedFit" def getText(self, itmContext, selection): diff --git a/gui/builtinContextMenus/priceClear.py b/gui/builtinContextMenus/priceClear.py index e61b7df7f..44093e662 100644 --- a/gui/builtinContextMenus/priceClear.py +++ b/gui/builtinContextMenus/priceClear.py @@ -1,15 +1,21 @@ from gui.contextMenu import ContextMenu import gui.mainFrame +# noinspection PyPackageRequirements import wx import gui.globalEvents as GE from service.market import Market +from service.settings import ContextMenuSettings class PriceClear(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('priceClear'): + return False + return srcContext == "priceViewFull" def getText(self, itmContext, selection): diff --git a/gui/builtinContextMenus/project.py b/gui/builtinContextMenus/project.py index 0fcae7864..f06c29152 100644 --- a/gui/builtinContextMenus/project.py +++ b/gui/builtinContextMenus/project.py @@ -1,15 +1,21 @@ from gui.contextMenu import ContextMenu import gui.mainFrame import gui.globalEvents as GE +# noinspection PyPackageRequirements import wx from service.fit import Fit +from service.settings import ContextMenuSettings class Project(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('project'): + return False + if srcContext not in ("marketItemGroup", "marketItemMisc") or self.mainFrame.getActiveFit() is None: return False diff --git a/gui/builtinContextMenus/shipJump.py b/gui/builtinContextMenus/shipJump.py index b743201a3..8f426ff1a 100644 --- a/gui/builtinContextMenus/shipJump.py +++ b/gui/builtinContextMenus/shipJump.py @@ -1,15 +1,21 @@ +# noinspection PyPackageRequirements import wx from gui.contextMenu import ContextMenu import gui.mainFrame from gui.shipBrowser import Stage3Selected from service.fit import Fit +from service.settings import ContextMenuSettings class ShipJump(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('shipJump'): + return False + return srcContext == "fittingShip" def getText(self, itmContext, selection): diff --git a/gui/builtinContextMenus/tacticalMode.py b/gui/builtinContextMenus/tacticalMode.py index 62abf309d..8b87dd10b 100644 --- a/gui/builtinContextMenus/tacticalMode.py +++ b/gui/builtinContextMenus/tacticalMode.py @@ -1,16 +1,22 @@ +# noinspection PyPackageRequirements import wx from gui.contextMenu import ContextMenu import gui.mainFrame import gui.globalEvents as GE from service.fit import Fit +from service.settings import ContextMenuSettings class TacticalMode(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('tacticalMode'): + return False + if self.mainFrame.getActiveFit() is None or srcContext != "fittingShip": return False diff --git a/gui/builtinContextMenus/targetResists.py b/gui/builtinContextMenus/targetResists.py index f23125f43..95468ecd0 100644 --- a/gui/builtinContextMenus/targetResists.py +++ b/gui/builtinContextMenus/targetResists.py @@ -1,22 +1,28 @@ from gui.contextMenu import ContextMenu import gui.mainFrame import gui.globalEvents as GE +# noinspection PyPackageRequirements import wx from gui.bitmapLoader import BitmapLoader from service.targetResists import TargetResists as svc_TargetResists from service.fit import Fit +from service.settings import ContextMenuSettings try: from collections import OrderedDict except ImportError: - from gui.utils.compat import OrderedDict + from utils.compat import OrderedDict class TargetResists(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('targetResists'): + return False + if self.mainFrame.getActiveFit() is None or srcContext != "firepowerViewFull": return False diff --git a/gui/builtinContextMenus/whProjector.py b/gui/builtinContextMenus/whProjector.py index 0e3bfed93..a677ceabf 100644 --- a/gui/builtinContextMenus/whProjector.py +++ b/gui/builtinContextMenus/whProjector.py @@ -1,16 +1,22 @@ from gui.contextMenu import ContextMenu import gui.mainFrame import gui.globalEvents as GE +# noinspection PyPackageRequirements import wx from service.market import Market from service.fit import Fit +from service.settings import ContextMenuSettings class WhProjector(ContextMenu): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): + if not self.settings.get('whProjector'): + return False + return srcContext == "projected" def getText(self, itmContext, selection): diff --git a/gui/builtinPreferenceViews/__init__.py b/gui/builtinPreferenceViews/__init__.py index eb7f3c970..8b61beb13 100644 --- a/gui/builtinPreferenceViews/__init__.py +++ b/gui/builtinPreferenceViews/__init__.py @@ -1,7 +1,16 @@ +# noinspection PyPackageRequirements import wx -__all__ = ["pyfaGeneralPreferences", "pyfaHTMLExportPreferences", "pyfaUpdatePreferences", - "pyfaNetworkPreferences"] # noqa +__all__ = [ + "pyfaGeneralPreferences", + "pyfaHTMLExportPreferences", + "pyfaUpdatePreferences", + "pyfaNetworkPreferences", + "pyfaDatabasePreferences", + "pyfaLoggingPreferences", + "pyfaEnginePreferences", + "pyfaStatViewPreferences", +] if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)): __all__.append("pyfaCrestPreferences") diff --git a/gui/builtinPreferenceViews/dummyView.py b/gui/builtinPreferenceViews/dummyView.py index fb46db87e..5bded0d05 100644 --- a/gui/builtinPreferenceViews/dummyView.py +++ b/gui/builtinPreferenceViews/dummyView.py @@ -17,6 +17,7 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from gui.preferenceView import PreferenceView diff --git a/gui/builtinPreferenceViews/pyfaContextMenuPreferences.py b/gui/builtinPreferenceViews/pyfaContextMenuPreferences.py new file mode 100644 index 000000000..58ed81556 --- /dev/null +++ b/gui/builtinPreferenceViews/pyfaContextMenuPreferences.py @@ -0,0 +1,114 @@ +import wx + +from gui.preferenceView import PreferenceView +from gui.bitmapLoader import BitmapLoader +import gui.mainFrame +from service.settings import ContextMenuSettings + + +class PFContextMenuPref(PreferenceView): + title = "Context Menu Panel" + + def populatePanel(self, panel): + self.settings = ContextMenuSettings.getInstance() + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + + self.dirtySettings = False + mainSizer = wx.BoxSizer(wx.VERTICAL) + + self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0) + self.stTitle.Wrap(-1) + self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString)) + + mainSizer.Add(self.stTitle, 0, wx.ALL, 5) + + self.stSubTitle = wx.StaticText(panel, wx.ID_ANY, + u"Disabling context menus can improve responsiveness.", + wx.DefaultPosition, wx.DefaultSize, 0) + self.stSubTitle.Wrap(-1) + mainSizer.Add(self.stSubTitle, 0, wx.ALL, 5) + + # Row 1 + self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL) + mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.ALL, 5) + + rbSizerRow1 = wx.BoxSizer(wx.HORIZONTAL) + + self.rbBox1 = wx.RadioBox(panel, -1, "Set as Damage Pattern", wx.DefaultPosition, wx.DefaultSize, ['Disabled', 'Enabled'], 1, wx.RA_SPECIFY_COLS) + self.rbBox1.SetSelection(self.settings.get('ammoPattern')) + rbSizerRow1.Add(self.rbBox1, 1, wx.TOP | wx.RIGHT, 5) + self.rbBox1.Bind(wx.EVT_RADIOBOX, self.OnSetting1Change) + + self.rbBox2 = wx.RadioBox(panel, -1, "Change Skills", wx.DefaultPosition, wx.DefaultSize, ['Disabled', 'Enabled'], 1, wx.RA_SPECIFY_COLS) + self.rbBox2.SetSelection(self.settings.get('changeAffectingSkills')) + rbSizerRow1.Add(self.rbBox2, 1, wx.ALL, 5) + self.rbBox2.Bind(wx.EVT_RADIOBOX, self.OnSetting2Change) + + self.rbBox3 = wx.RadioBox(panel, -1, "Factor in Reload Time", wx.DefaultPosition, wx.DefaultSize, ['Disabled', 'Enabled'], 1, wx.RA_SPECIFY_COLS) + self.rbBox3.SetSelection(self.settings.get('factorReload')) + rbSizerRow1.Add(self.rbBox3, 1, wx.ALL, 5) + self.rbBox3.Bind(wx.EVT_RADIOBOX, self.OnSetting3Change) + + mainSizer.Add(rbSizerRow1, 1, wx.ALL | wx.EXPAND, 0) + + # Row 2 + rbSizerRow2 = wx.BoxSizer(wx.HORIZONTAL) + + self.rbBox4 = wx.RadioBox(panel, -1, "Variations", wx.DefaultPosition, wx.DefaultSize, ['Disabled', 'Enabled'], 1, wx.RA_SPECIFY_COLS) + self.rbBox4.SetSelection(self.settings.get('metaSwap')) + rbSizerRow2.Add(self.rbBox4, 1, wx.TOP | wx.RIGHT, 5) + self.rbBox4.Bind(wx.EVT_RADIOBOX, self.OnSetting4Change) + + ''' + self.rbBox5 = wx.RadioBox(panel, -1, "Charge", wx.DefaultPosition, wx.DefaultSize, ['Disabled', 'Enabled'], 1, wx.RA_SPECIFY_COLS) + self.rbBox5.SetSelection(self.settings.get('moduleAmmoPicker')) + rbSizerRow2.Add(self.rbBox5, 1, wx.ALL, 5) + self.rbBox5.Bind(wx.EVT_RADIOBOX, self.OnSetting5Change) + ''' + + self.rbBox6 = wx.RadioBox(panel, -1, "Charge (All)", wx.DefaultPosition, wx.DefaultSize, ['Disabled', 'Enabled'], 1, wx.RA_SPECIFY_COLS) + self.rbBox6.SetSelection(self.settings.get('moduleGlobalAmmoPicker')) + rbSizerRow2.Add(self.rbBox6, 1, wx.ALL, 5) + self.rbBox6.Bind(wx.EVT_RADIOBOX, self.OnSetting6Change) + + mainSizer.Add(rbSizerRow2, 1, wx.ALL | wx.EXPAND, 0) + + # Row 3 + rbSizerRow3 = wx.BoxSizer(wx.HORIZONTAL) + + self.rbBox7 = wx.RadioBox(panel, -1, "Project onto Fit", wx.DefaultPosition, wx.DefaultSize, ['Disabled', 'Enabled'], 1, wx.RA_SPECIFY_COLS) + self.rbBox7.SetSelection(self.settings.get('project')) + rbSizerRow3.Add(self.rbBox7, 1, wx.TOP | wx.RIGHT, 5) + self.rbBox7.Bind(wx.EVT_RADIOBOX, self.OnSetting7Change) + + mainSizer.Add(rbSizerRow3, 1, wx.ALL | wx.EXPAND, 0) + + panel.SetSizer(mainSizer) + panel.Layout() + + def OnSetting1Change(self, event): + self.settings.set('ammoPattern', event.GetInt()) + + def OnSetting2Change(self, event): + self.settings.set('changeAffectingSkills', event.GetInt()) + + def OnSetting3Change(self, event): + self.settings.set('factorReload', event.GetInt()) + + def OnSetting4Change(self, event): + self.settings.set('metaSwap', event.GetInt()) + + def OnSetting5Change(self, event): + self.settings.set('moduleAmmoPicker', event.GetInt()) + + def OnSetting6Change(self, event): + self.settings.set('moduleGlobalAmmoPicker', event.GetInt()) + + def OnSetting7Change(self, event): + self.settings.set('project', event.GetInt()) + + def getImage(self): + return BitmapLoader.getBitmap("settings_menu", "gui") + + +PFContextMenuPref.register() diff --git a/gui/builtinPreferenceViews/pyfaCrestPreferences.py b/gui/builtinPreferenceViews/pyfaCrestPreferences.py index 7a54dbc83..4a9208d0a 100644 --- a/gui/builtinPreferenceViews/pyfaCrestPreferences.py +++ b/gui/builtinPreferenceViews/pyfaCrestPreferences.py @@ -1,3 +1,4 @@ +# noinspection PyPackageRequirements import wx from gui.preferenceView import PreferenceView @@ -7,6 +8,7 @@ import gui.mainFrame from service.settings import CRESTSettings +# noinspection PyPackageRequirements from wx.lib.intctrl import IntCtrl if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)): diff --git a/gui/builtinPreferenceViews/pyfaDatabasePreferences.py b/gui/builtinPreferenceViews/pyfaDatabasePreferences.py new file mode 100644 index 000000000..b8647ef2f --- /dev/null +++ b/gui/builtinPreferenceViews/pyfaDatabasePreferences.py @@ -0,0 +1,112 @@ +import wx + +from gui.preferenceView import PreferenceView +from gui.bitmapLoader import BitmapLoader +import config + +import logging + +logger = logging.getLogger(__name__) + + +class PFGeneralPref(PreferenceView): + title = "Database" + + def populatePanel(self, panel): + self.dirtySettings = False + # self.openFitsSettings = service.SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits", {"enabled": False, "pyfaOpenFits": []}) + + mainSizer = wx.BoxSizer(wx.VERTICAL) + + self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0) + self.stTitle.Wrap(-1) + self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString)) + mainSizer.Add(self.stTitle, 0, wx.ALL, 5) + + self.stSubTitle = wx.StaticText(panel, wx.ID_ANY, u"(Cannot be changed while pyfa is running. Set via command line switches.)", + wx.DefaultPosition, wx.DefaultSize, 0) + self.stSubTitle.Wrap(-1) + mainSizer.Add(self.stSubTitle, 0, wx.ALL, 3) + + self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL) + mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5) + + # Save in Root + self.cbsaveInRoot = wx.CheckBox(panel, wx.ID_ANY, u"Using Executable Path for Saved Fit Database and Settings", wx.DefaultPosition, wx.DefaultSize, 0) + mainSizer.Add(self.cbsaveInRoot, 0, wx.ALL | wx.EXPAND, 5) + + # Database path + self.stSetUserPath = wx.StaticText(panel, wx.ID_ANY, u"pyfa User Path:", wx.DefaultPosition, wx.DefaultSize, 0) + self.stSetUserPath.Wrap(-1) + mainSizer.Add(self.stSetUserPath, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) + self.inputUserPath = wx.TextCtrl(panel, wx.ID_ANY, config.savePath, wx.DefaultPosition, wx.DefaultSize, 0) + self.inputUserPath.SetEditable(False) + self.inputUserPath.SetBackgroundColour((200, 200, 200)) + mainSizer.Add(self.inputUserPath, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5) + + # Save DB + self.stFitDB = wx.StaticText(panel, wx.ID_ANY, u"Fitting Database:", wx.DefaultPosition, wx.DefaultSize, 0) + self.stFitDB.Wrap(-1) + mainSizer.Add(self.stFitDB, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) + + self.inputFitDB = wx.TextCtrl(panel, wx.ID_ANY, config.saveDB, wx.DefaultPosition, wx.DefaultSize, 0) + self.inputFitDB.SetEditable(False) + self.inputFitDB.SetBackgroundColour((200, 200, 200)) + mainSizer.Add(self.inputFitDB, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5) + + # Game Data DB + self.stGameDB = wx.StaticText(panel, wx.ID_ANY, u"Game Database:", wx.DefaultPosition, wx.DefaultSize, 0) + self.stGameDB.Wrap(-1) + mainSizer.Add(self.stGameDB, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) + + self.inputGameDB = wx.TextCtrl(panel, wx.ID_ANY, config.gameDB, wx.DefaultPosition, wx.DefaultSize, 0) + self.inputGameDB.SetEditable(False) + self.inputGameDB.SetBackgroundColour((200, 200, 200)) + mainSizer.Add(self.inputGameDB, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5) + + self.cbsaveInRoot.SetValue(config.saveInRoot) + self.cbsaveInRoot.Bind(wx.EVT_CHECKBOX, self.onCBsaveInRoot) + + self.inputUserPath.Bind(wx.EVT_LEAVE_WINDOW, self.OnWindowLeave) + self.inputFitDB.Bind(wx.EVT_LEAVE_WINDOW, self.OnWindowLeave) + self.inputGameDB.Bind(wx.EVT_LEAVE_WINDOW, self.OnWindowLeave) + + panel.SetSizer(mainSizer) + panel.Layout() + + def onCBsaveInRoot(self, event): + # We don't want users to be able to actually change this, + # so if they try and change it, set it back to the current setting + self.cbsaveInRoot.SetValue(config.saveInRoot) + + # If we ever enable it might need this. + ''' + config.saveInRoot = self.cbsaveInRoot.GetValue() + ''' + + def getImage(self): + return BitmapLoader.getBitmap("settings_database", "gui") + + def OnWindowLeave(self, event): + # We don't want to do anything when they leave, + # but in the future we'd want to make sure settings + # changed get saved. + pass + + ''' + #Set database path + config.defPaths(self.inputFitDBPath.GetValue()) + + logger.debug("Running database import") + if self.cbimportDefaults is True: + # Import default database values + # Import values that must exist otherwise Pyfa breaks + DefaultDatabaseValues.importRequiredDefaults() + # Import default values for damage profiles + DefaultDatabaseValues.importDamageProfileDefaults() + # Import default values for target resist profiles + DefaultDatabaseValues.importResistProfileDefaults() + ''' + + +PFGeneralPref.register() diff --git a/gui/builtinPreferenceViews/pyfaEnginePreferences.py b/gui/builtinPreferenceViews/pyfaEnginePreferences.py new file mode 100644 index 000000000..7e7ebd72f --- /dev/null +++ b/gui/builtinPreferenceViews/pyfaEnginePreferences.py @@ -0,0 +1,84 @@ +import logging + +import wx + +from service.fit import Fit +from gui.bitmapLoader import BitmapLoader +from gui.preferenceView import PreferenceView + +logger = logging.getLogger(__name__) + + +class PFFittingEnginePref(PreferenceView): + title = "Fitting Engine" + + def __init__(self): + self.dirtySettings = False + + def refreshPanel(self, fit): + pass + + # noinspection PyAttributeOutsideInit + def populatePanel(self, panel): + # self.openFitsSettings = service.SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits", {"enabled": False, "pyfaOpenFits": []}) + + mainSizer = wx.BoxSizer(wx.VERTICAL) + + self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0) + self.stTitle.Wrap(-1) + self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString)) + mainSizer.Add(self.stTitle, 0, wx.ALL, 5) + + self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL) + mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5) + + self.cbGlobalForceReload = wx.CheckBox(panel, wx.ID_ANY, u"Factor in reload time when calculating capacitor usage, damage, and tank.", + wx.DefaultPosition, wx.DefaultSize, 0) + mainSizer.Add(self.cbGlobalForceReload, 0, wx.ALL | wx.EXPAND, 5) + + # Future code once new cap sim is implemented + ''' + self.cbGlobalForceReactivationTimer = wx.CheckBox( panel, wx.ID_ANY, u"Factor in reactivation timer", wx.DefaultPosition, wx.DefaultSize, 0 ) + mainSizer.Add( self.cbGlobalForceReactivationTimer, 0, wx.ALL|wx.EXPAND, 5 ) + + text = u" Ignores reactivation timer when calculating capacitor usage,\n damage, and tank." + self.cbGlobalForceReactivationTimerText = wx.StaticText( panel, wx.ID_ANY, text, wx.DefaultPosition, wx.DefaultSize, 0 ) + self.cbGlobalForceReactivationTimerText.Wrap( -1 ) + self.cbGlobalForceReactivationTimerText.SetFont( wx.Font( 10, 70, 90, 90, False, wx.EmptyString ) ) + mainSizer.Add( self.cbGlobalForceReactivationTimerText, 0, wx.ALL, 5 ) + ''' + + # Future code for mining laser crystal + ''' + self.cbGlobalMiningSpecialtyCrystal = wx.CheckBox( panel, wx.ID_ANY, u"Factor in reactivation timer", wx.DefaultPosition, wx.DefaultSize, 0 ) + mainSizer.Add( self.cbGlobalMiningSpecialtyCrystal, 0, wx.ALL|wx.EXPAND, 5 ) + + text = u" If enabled, displays the Specialty Crystal mining amount.\n This is the amount mined when using crystals and mining the matching asteroid." + self.cbGlobalMiningSpecialtyCrystalText = wx.StaticText( panel, wx.ID_ANY, text, wx.DefaultPosition, wx.DefaultSize, 0 ) + self.cbGlobalMiningSpecialtyCrystalText.Wrap( -1 ) + self.cbGlobalMiningSpecialtyCrystalText.SetFont( wx.Font( 10, 70, 90, 90, False, wx.EmptyString ) ) + mainSizer.Add( self.cbGlobalMiningSpecialtyCrystalText, 0, wx.ALL, 5 ) + ''' + + self.sFit = Fit.getInstance() + + self.cbGlobalForceReload.SetValue(self.sFit.serviceFittingOptions["useGlobalForceReload"]) + + self.cbGlobalForceReload.Bind(wx.EVT_CHECKBOX, self.OnCBGlobalForceReloadStateChange) + + panel.SetSizer(mainSizer) + panel.Layout() + + def OnCBGlobalForceReloadStateChange(self, event): + self.sFit.serviceFittingOptions["useGlobalForceReload"] = self.cbGlobalForceReload.GetValue() + + def getImage(self): + return BitmapLoader.getBitmap("settings_fitting", "gui") + + def OnWindowLeave(self, event): + # We don't want to do anything when they leave, + # but in the future we might. + pass + + +PFFittingEnginePref.register() diff --git a/gui/builtinPreferenceViews/pyfaGaugePreferences.py b/gui/builtinPreferenceViews/pyfaGaugePreferences.py index 88c1e1313..5f6509dc0 100644 --- a/gui/builtinPreferenceViews/pyfaGaugePreferences.py +++ b/gui/builtinPreferenceViews/pyfaGaugePreferences.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- +# noinspection PyPackageRequirements import wx import copy @@ -425,7 +426,8 @@ class PFGaugePref(PreferenceView): self.SetColours() event.Skip() - def OnOk(self, event): + @staticmethod + def OnOk(event): # Apply New Settings event.Skip() diff --git a/gui/builtinPreferenceViews/pyfaGeneralPreferences.py b/gui/builtinPreferenceViews/pyfaGeneralPreferences.py index 0e5a18f93..8a278a048 100644 --- a/gui/builtinPreferenceViews/pyfaGeneralPreferences.py +++ b/gui/builtinPreferenceViews/pyfaGeneralPreferences.py @@ -1,3 +1,4 @@ +# noinspection PyPackageRequirements import wx from gui.preferenceView import PreferenceView @@ -7,6 +8,8 @@ import gui.mainFrame import gui.globalEvents as GE from service.settings import SettingsProvider from service.fit import Fit +from service.price import Price +from service.market import Market class PFGeneralPref(PreferenceView): @@ -37,10 +40,6 @@ class PFGeneralPref(PreferenceView): wx.DefaultSize, 0) mainSizer.Add(self.cbGlobalDmgPattern, 0, wx.ALL | wx.EXPAND, 5) - self.cbGlobalForceReload = wx.CheckBox(panel, wx.ID_ANY, u"Factor in reload time", wx.DefaultPosition, - wx.DefaultSize, 0) - mainSizer.Add(self.cbGlobalForceReload, 0, wx.ALL | wx.EXPAND, 5) - self.cbCompactSkills = wx.CheckBox(panel, wx.ID_ANY, u"Compact skills needed tooltip", wx.DefaultPosition, wx.DefaultSize, 0) mainSizer.Add(self.cbCompactSkills, 0, wx.ALL | wx.EXPAND, 5) @@ -79,13 +78,21 @@ class PFGeneralPref(PreferenceView): wx.DefaultPosition, wx.DefaultSize, 0) mainSizer.Add(self.cbOpenFitInNew, 0, wx.ALL | wx.EXPAND, 5) - wx.BoxSizer(wx.HORIZONTAL) + priceSizer = wx.BoxSizer(wx.HORIZONTAL) + + self.stDefaultSystem = wx.StaticText(panel, wx.ID_ANY, u"Default Market Prices:", wx.DefaultPosition, wx.DefaultSize, 0) + self.stDefaultSystem.Wrap(-1) + priceSizer.Add(self.stDefaultSystem, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) + + self.chPriceSystem = wx.Choice(panel, choices=Price.systemsList.keys()) + priceSizer.Add(self.chPriceSystem, 1, wx.ALL | wx.EXPAND, 5) + + mainSizer.Add(priceSizer, 0, wx.ALL | wx.EXPAND, 0) self.sFit = Fit.getInstance() self.cbGlobalChar.SetValue(self.sFit.serviceFittingOptions["useGlobalCharacter"]) self.cbGlobalDmgPattern.SetValue(self.sFit.serviceFittingOptions["useGlobalDamagePattern"]) - self.cbGlobalForceReload.SetValue(self.sFit.serviceFittingOptions["useGlobalForceReload"]) self.cbFitColorSlots.SetValue(self.sFit.serviceFittingOptions["colorFitBySlot"] or False) self.cbRackSlots.SetValue(self.sFit.serviceFittingOptions["rackSlots"] or False) self.cbRackLabels.SetValue(self.sFit.serviceFittingOptions["rackLabels"] or False) @@ -96,10 +103,10 @@ class PFGeneralPref(PreferenceView): self.cbGaugeAnimation.SetValue(self.sFit.serviceFittingOptions["enableGaugeAnimation"]) self.cbExportCharges.SetValue(self.sFit.serviceFittingOptions["exportCharges"]) self.cbOpenFitInNew.SetValue(self.sFit.serviceFittingOptions["openFitInNew"]) + self.chPriceSystem.SetStringSelection(self.sFit.serviceFittingOptions["priceSystem"]) self.cbGlobalChar.Bind(wx.EVT_CHECKBOX, self.OnCBGlobalCharStateChange) self.cbGlobalDmgPattern.Bind(wx.EVT_CHECKBOX, self.OnCBGlobalDmgPatternStateChange) - self.cbGlobalForceReload.Bind(wx.EVT_CHECKBOX, self.OnCBGlobalForceReloadStateChange) self.cbFitColorSlots.Bind(wx.EVT_CHECKBOX, self.onCBGlobalColorBySlot) self.cbRackSlots.Bind(wx.EVT_CHECKBOX, self.onCBGlobalRackSlots) self.cbRackLabels.Bind(wx.EVT_CHECKBOX, self.onCBGlobalRackLabels) @@ -110,6 +117,7 @@ class PFGeneralPref(PreferenceView): self.cbGaugeAnimation.Bind(wx.EVT_CHECKBOX, self.onCBGaugeAnimation) self.cbExportCharges.Bind(wx.EVT_CHECKBOX, self.onCBExportCharges) self.cbOpenFitInNew.Bind(wx.EVT_CHECKBOX, self.onCBOpenFitInNew) + self.chPriceSystem.Bind(wx.EVT_CHOICE, self.onPriceSelection) self.cbRackLabels.Enable(self.sFit.serviceFittingOptions["rackSlots"] or False) @@ -138,13 +146,6 @@ class PFGeneralPref(PreferenceView): wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) event.Skip() - def OnCBGlobalForceReloadStateChange(self, event): - self.sFit.serviceFittingOptions["useGlobalForceReload"] = self.cbGlobalForceReload.GetValue() - fitID = self.mainFrame.getActiveFit() - self.sFit.refreshFit(fitID) - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) - event.Skip() - def OnCBGlobalCharStateChange(self, event): self.sFit.serviceFittingOptions["useGlobalCharacter"] = self.cbGlobalChar.GetValue() event.Skip() @@ -181,5 +182,18 @@ class PFGeneralPref(PreferenceView): def getImage(self): return BitmapLoader.getBitmap("prefs_settings", "gui") + def onPriceSelection(self, event): + system = self.chPriceSystem.GetString(self.chPriceSystem.GetSelection()) + self.sFit.serviceFittingOptions["priceSystem"] = system + + fitID = self.mainFrame.getActiveFit() + + sMkt = Market.getInstance() + sMkt.clearPriceCache() + + self.sFit.refreshFit(fitID) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) + event.Skip() + PFGeneralPref.register() diff --git a/gui/builtinPreferenceViews/pyfaHTMLExportPreferences.py b/gui/builtinPreferenceViews/pyfaHTMLExportPreferences.py index c6428d8b7..01f00409d 100644 --- a/gui/builtinPreferenceViews/pyfaHTMLExportPreferences.py +++ b/gui/builtinPreferenceViews/pyfaHTMLExportPreferences.py @@ -1,3 +1,4 @@ +# noinspection PyPackageRequirements import wx import os diff --git a/gui/builtinPreferenceViews/pyfaLoggingPreferences.py b/gui/builtinPreferenceViews/pyfaLoggingPreferences.py new file mode 100644 index 000000000..82f3b0b83 --- /dev/null +++ b/gui/builtinPreferenceViews/pyfaLoggingPreferences.py @@ -0,0 +1,59 @@ +import wx + +from gui.preferenceView import PreferenceView +from gui.bitmapLoader import BitmapLoader +import config + + +class PFGeneralPref(PreferenceView): + title = "Logging" + + def populatePanel(self, panel): + self.dirtySettings = False + # self.openFitsSettings = service.SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits", {"enabled": False, "pyfaOpenFits": []}) + + mainSizer = wx.BoxSizer(wx.VERTICAL) + + self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0) + self.stTitle.Wrap(-1) + self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString)) + mainSizer.Add(self.stTitle, 0, wx.ALL, 5) + + self.stSubTitle = wx.StaticText(panel, wx.ID_ANY, u"(Cannot be changed while pyfa is running. Set via command line switches.)", + wx.DefaultPosition, wx.DefaultSize, 0) + self.stSubTitle.Wrap(-1) + mainSizer.Add(self.stSubTitle, 0, wx.ALL, 3) + + self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL) + mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5) + + # Debug Logging + self.cbdebugLogging = wx.CheckBox(panel, wx.ID_ANY, u"Debug Logging Enabled", wx.DefaultPosition, wx.DefaultSize, 0) + mainSizer.Add(self.cbdebugLogging, 0, wx.ALL | wx.EXPAND, 5) + + self.cbdebugLogging.SetValue(config.debug) + self.cbdebugLogging.Bind(wx.EVT_CHECKBOX, self.onCBdebugLogging) + + panel.SetSizer(mainSizer) + panel.Layout() + + def onCBdebugLogging(self, event): + # We don't want users to be able to actually change this, + # so if they try and change it, set it back to the current setting + self.cbdebugLogging.SetValue(config.debug) + + # In case we do, down there road, here's a bit of a start. + ''' + if self.cbdebugLogging.GetValue() is True: + self.cbdebugLogging.SetValue(False) + config.Debug = self.cbdebugLogging.GetValue() + else: + self.cbdebugLogging.SetValue(True) + config.Debug = self.cbdebugLogging.GetValue() + ''' + + def getImage(self): + return BitmapLoader.getBitmap("settings_log", "gui") + + +PFGeneralPref.register() diff --git a/gui/builtinPreferenceViews/pyfaNetworkPreferences.py b/gui/builtinPreferenceViews/pyfaNetworkPreferences.py index 8c93b1a5f..e20f8a01d 100644 --- a/gui/builtinPreferenceViews/pyfaNetworkPreferences.py +++ b/gui/builtinPreferenceViews/pyfaNetworkPreferences.py @@ -1,3 +1,4 @@ +# noinspection PyPackageRequirements import wx from gui.preferenceView import PreferenceView diff --git a/gui/builtinPreferenceViews/pyfaStatViewPreferences.py b/gui/builtinPreferenceViews/pyfaStatViewPreferences.py new file mode 100644 index 000000000..64182a82e --- /dev/null +++ b/gui/builtinPreferenceViews/pyfaStatViewPreferences.py @@ -0,0 +1,158 @@ +# noinspection PyPackageRequirements +import wx + +from gui.preferenceView import PreferenceView +from gui.bitmapLoader import BitmapLoader +from service.settings import StatViewSettings + + +class PFStatViewPref(PreferenceView): + title = "Statistics Panel" + + def __init__(self): + self.dirtySettings = False + self.settings = StatViewSettings.getInstance() + + def refreshPanel(self, fit): + pass + + # noinspection PyAttributeOutsideInit + def populatePanel(self, panel): + mainSizer = wx.BoxSizer(wx.VERTICAL) + + self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0) + self.stTitle.Wrap(-1) + self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString)) + + mainSizer.Add(self.stTitle, 0, wx.ALL, 5) + + self.stSubTitle = wx.StaticText(panel, wx.ID_ANY, + u"Changes require restart of pyfa to take effect.", + wx.DefaultPosition, wx.DefaultSize, 0) + self.stSubTitle.Wrap(-1) + mainSizer.Add(self.stSubTitle, 0, wx.ALL, 3) + + # Row 1 + self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL) + mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.ALL, 5) + + rbSizerRow1 = wx.BoxSizer(wx.HORIZONTAL) + + self.rbResources = wx.RadioBox(panel, -1, "Resources", wx.DefaultPosition, wx.DefaultSize, ['None', 'Minimal', 'Full'], 1, wx.RA_SPECIFY_COLS) + # Disable minimal as we don't have a view for this yet + self.rbResources.EnableItem(1, False) + self.rbResources.SetSelection(self.settings.get('resources')) + rbSizerRow1.Add(self.rbResources, 1, wx.TOP | wx.RIGHT, 5) + self.rbResources.Bind(wx.EVT_RADIOBOX, self.OnResourcesChange) + + self.rbResistances = wx.RadioBox(panel, -1, "Resistances", wx.DefaultPosition, wx.DefaultSize, ['None', 'Minimal', 'Full'], 1, wx.RA_SPECIFY_COLS) + # Disable minimal as we don't have a view for this yet + self.rbResistances.EnableItem(1, False) + self.rbResistances.SetSelection(self.settings.get('resistances')) + rbSizerRow1.Add(self.rbResistances, 1, wx.ALL, 5) + self.rbResistances.Bind(wx.EVT_RADIOBOX, self.OnResistancesChange) + + self.rbRecharge = wx.RadioBox(panel, -1, "Shield/Armor Tank", wx.DefaultPosition, wx.DefaultSize, ['None', 'Minimal', 'Full'], 1, wx.RA_SPECIFY_COLS) + # Disable minimal as we don't have a view for this yet + self.rbRecharge.EnableItem(1, False) + self.rbRecharge.SetSelection(self.settings.get('recharge')) + rbSizerRow1.Add(self.rbRecharge, 1, wx.ALL, 5) + self.rbRecharge.Bind(wx.EVT_RADIOBOX, self.OnRechargeChange) + + mainSizer.Add(rbSizerRow1, 1, wx.ALL | wx.EXPAND, 0) + + # Row 2 + rbSizerRow2 = wx.BoxSizer(wx.HORIZONTAL) + + self.rbFirepower = wx.RadioBox(panel, -1, "Firepower", wx.DefaultPosition, wx.DefaultSize, ['None', 'Minimal', 'Full'], 1, wx.RA_SPECIFY_COLS) + # Disable minimal as we don't have a view for this yet + self.rbFirepower.EnableItem(1, False) + self.rbFirepower.SetSelection(self.settings.get('firepower')) + rbSizerRow2.Add(self.rbFirepower, 1, wx.TOP | wx.RIGHT, 5) + self.rbFirepower.Bind(wx.EVT_RADIOBOX, self.OnFirepowerChange) + + self.rbCapacitor = wx.RadioBox(panel, -1, "Capacitor", wx.DefaultPosition, wx.DefaultSize, ['None', 'Minimal', 'Full'], 1, wx.RA_SPECIFY_COLS) + # Disable minimal as we don't have a view for this yet + self.rbCapacitor.EnableItem(1, False) + self.rbCapacitor.SetSelection(self.settings.get('capacitor')) + rbSizerRow2.Add(self.rbCapacitor, 1, wx.ALL, 5) + self.rbCapacitor.Bind(wx.EVT_RADIOBOX, self.OnCapacitorChange) + + self.rbMisc = wx.RadioBox(panel, -1, "Misc", wx.DefaultPosition, wx.DefaultSize, ['None', 'Minimal', 'Full'], 1, wx.RA_SPECIFY_COLS) + # Disable full as we don't have a view for this yet + self.rbMisc.EnableItem(2, False) + self.rbMisc.SetSelection(self.settings.get('targetingMisc')) + rbSizerRow2.Add(self.rbMisc, 1, wx.ALL, 5) + self.rbMisc.Bind(wx.EVT_RADIOBOX, self.OnTargetingMiscChange) + + mainSizer.Add(rbSizerRow2, 1, wx.ALL | wx.EXPAND, 0) + + # Row 3 + rbSizerRow3 = wx.BoxSizer(wx.HORIZONTAL) + + self.rbPrice = wx.RadioBox(panel, -1, "Price", wx.DefaultPosition, wx.DefaultSize, ['None', 'Minimal', 'Full'], 1, wx.RA_SPECIFY_COLS) + # Disable minimal as we don't have a view for this yet + self.rbPrice.EnableItem(1, False) + self.rbPrice.SetSelection(self.settings.get('price')) + rbSizerRow3.Add(self.rbPrice, 1, wx.TOP | wx.RIGHT, 5) + self.rbPrice.Bind(wx.EVT_RADIOBOX, self.OnPriceChange) + + self.rbOutgoing = wx.RadioBox(panel, -1, "Remote Reps", wx.DefaultPosition, wx.DefaultSize, ['None', 'Minimal', 'Full'], 1, wx.RA_SPECIFY_COLS) + self.rbOutgoing.SetSelection(self.settings.get('outgoing')) + rbSizerRow3.Add(self.rbOutgoing, 1, wx.TOP | wx.RIGHT, 5) + self.rbOutgoing.Bind(wx.EVT_RADIOBOX, self.OnOutgoingChange) + # We don't have views for these.....yet + ''' + self.rbMining = wx.RadioBox(panel, -1, "Mining", wx.DefaultPosition, wx.DefaultSize, + ['None', 'Minimal', 'Full'], 1, wx.RA_SPECIFY_COLS) + self.rbMining.SetSelection(self.settings.get('miningyield')) + rbSizerRow3.Add(self.rbMining, 1, wx.ALL, 5) + self.rbMining.Bind(wx.EVT_RADIOBOX, self.OnMiningYieldChange) + + self.rbDrones = wx.RadioBox(panel, -1, "Drones", wx.DefaultPosition, wx.DefaultSize, + ['None', 'Minimal', 'Full'], 1, wx.RA_SPECIFY_COLS) + self.rbDrones.SetSelection(self.settings.get('drones')) + rbSizerRow3.Add(self.rbDrones, 1, wx.ALL, 5) + self.rbDrones.Bind(wx.EVT_RADIOBOX, self.OnDroneChange) + ''' + + mainSizer.Add(rbSizerRow3, 1, wx.ALL | wx.EXPAND, 0) + + panel.SetSizer(mainSizer) + panel.Layout() + + def OnResourcesChange(self, event): + self.settings.set('resources', event.GetInt()) + + def OnResistancesChange(self, event): + self.settings.set('resistances', event.GetInt()) + + def OnRechargeChange(self, event): + self.settings.set('recharge', event.GetInt()) + + def OnFirepowerChange(self, event): + self.settings.set('firepower', event.GetInt()) + + def OnCapacitorChange(self, event): + self.settings.set('capacitor', event.GetInt()) + + def OnTargetingMiscChange(self, event): + self.settings.set('targetingMisc', event.GetInt()) + + def OnPriceChange(self, event): + self.settings.set('price', event.GetInt()) + + def OnOutgoingChange(self, event): + self.settings.set('outgoing', event.GetInt()) + + def OnMiningYieldChange(self, event): + self.settings.set('miningyield', event.GetInt()) + + def OnDroneChange(self, event): + self.settings.set('drones', event.GetInt()) + + def getImage(self): + return BitmapLoader.getBitmap("settings_stats", "gui") + + +PFStatViewPref.register() diff --git a/gui/builtinPreferenceViews/pyfaUpdatePreferences.py b/gui/builtinPreferenceViews/pyfaUpdatePreferences.py index 48e2a79cc..cfc1bef11 100644 --- a/gui/builtinPreferenceViews/pyfaUpdatePreferences.py +++ b/gui/builtinPreferenceViews/pyfaUpdatePreferences.py @@ -1,3 +1,4 @@ +# noinspection PyPackageRequirements import wx from gui.preferenceView import PreferenceView @@ -39,11 +40,11 @@ class PFUpdatePref(PreferenceView): mainSizer.Add(self.suppressPrerelease, 0, wx.ALL | wx.EXPAND, 5) - if (self.UpdateSettings.get('version')): + if self.UpdateSettings.get('version'): self.versionSizer = wx.BoxSizer(wx.VERTICAL) self.versionTitle = wx.StaticText(panel, wx.ID_ANY, "Suppressing {0} Notifications".format( - self.UpdateSettings.get('version')), wx.DefaultPosition, wx.DefaultSize, 0) + self.UpdateSettings.get('version')), wx.DefaultPosition, wx.DefaultSize, 0) self.versionTitle.Wrap(-1) self.versionTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString)) diff --git a/gui/builtinStatsViews/__init__.py b/gui/builtinStatsViews/__init__.py index 5f2ca646e..be310c2ac 100644 --- a/gui/builtinStatsViews/__init__.py +++ b/gui/builtinStatsViews/__init__.py @@ -1,3 +1,11 @@ -__all__ = ["resourcesViewFull", "resistancesViewFull", - "rechargeViewFull", "firepowerViewFull", "capacitorViewFull", - "targetingMiscViewFull", "priceViewFull", "miningyieldViewFull"] +__all__ = [ + "resourcesViewFull", + "resistancesViewFull", + "rechargeViewFull", + "firepowerViewFull", + "capacitorViewFull", + "outgoingViewFull", + "outgoingViewMinimal", + "targetingMiscViewMinimal", + "priceViewFull", +] diff --git a/gui/builtinStatsViews/capacitorViewFull.py b/gui/builtinStatsViews/capacitorViewFull.py index a09b2ff91..f85b35e4c 100644 --- a/gui/builtinStatsViews/capacitorViewFull.py +++ b/gui/builtinStatsViews/capacitorViewFull.py @@ -17,6 +17,7 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from gui.statsView import StatsView from gui.bitmapLoader import BitmapLoader @@ -130,8 +131,8 @@ class CapacitorViewFull(StatsView): capStable = fit.capStable if fit is not None else False lblNameTime = "label%sCapacitorTime" lblNameState = "label%sCapacitorState" - if isinstance(capState, tuple): - t = "%.1f%%-%.1f%%" % capState + if isinstance(capState, tuple) and len(capState) >= 2: + t = ("{0}%-{1}%", capState[0], capState[1]) s = "" else: if capStable: diff --git a/gui/builtinStatsViews/firepowerViewFull.py b/gui/builtinStatsViews/firepowerViewFull.py index 9c31fefe2..618ca52de 100644 --- a/gui/builtinStatsViews/firepowerViewFull.py +++ b/gui/builtinStatsViews/firepowerViewFull.py @@ -17,6 +17,7 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx import gui.mainFrame from gui.statsView import StatsView diff --git a/gui/builtinStatsViews/miningyieldViewFull.py b/gui/builtinStatsViews/miningyieldViewFull.py index 545b47c88..be69be316 100644 --- a/gui/builtinStatsViews/miningyieldViewFull.py +++ b/gui/builtinStatsViews/miningyieldViewFull.py @@ -17,6 +17,7 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx import gui.mainFrame from gui.statsView import StatsView diff --git a/gui/builtinStatsViews/outgoingViewFull.py b/gui/builtinStatsViews/outgoingViewFull.py new file mode 100644 index 000000000..346aacc7a --- /dev/null +++ b/gui/builtinStatsViews/outgoingViewFull.py @@ -0,0 +1,106 @@ +# =============================================================================== +# Copyright (C) 2014 Alexandros Kosiaris +# +# This file is part of pyfa. +# +# pyfa is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# pyfa is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with pyfa. If not, see . +# =============================================================================== + +# noinspection PyPackageRequirements +import wx +from gui.statsView import StatsView +from gui.bitmapLoader import BitmapLoader +from gui.utils.numberFormatter import formatAmount + + +class OutgoingViewFull(StatsView): + name = "outgoingViewFull" + + def __init__(self, parent): + StatsView.__init__(self) + self.parent = parent + self._cachedValues = [] + + def getHeaderText(self, fit): + return "Remote Reps" + + def getTextExtentW(self, text): + width, height = self.parent.GetTextExtent(text) + return width + + def populatePanel(self, contentPanel, headerPanel): + contentSizer = contentPanel.GetSizer() + parent = self.panel = contentPanel + self.headerPanel = headerPanel + + sizerOutgoing = wx.GridSizer(1, 4) + + contentSizer.Add(sizerOutgoing, 0, wx.EXPAND, 0) + + counter = 0 + + rr_list = [ + ("RemoteCapacitor", "Capacitor:", "capacitorInfo", "Capacitor GJ/s per second transferred remotely."), + ("RemoteShield", "Shield:", "shieldActive", "Shield hitpoints per second repaired remotely."), + ("RemoteArmor", "Armor:", "armorActive", "Armor hitpoints per second repaired remotely."), + ("RemoteHull", "Hull:", "hullActive", "Hull hitpoints per second repaired remotely."), + ] + + for outgoingType, label, image, tooltip in rr_list: + baseBox = wx.BoxSizer(wx.VERTICAL) + + baseBox.Add(BitmapLoader.getStaticBitmap("%s_big" % image, parent, "gui"), 0, wx.ALIGN_CENTER) + + if "Capacitor" in outgoingType: + lbl = wx.StaticText(parent, wx.ID_ANY, u"0 GJ/s") + else: + lbl = wx.StaticText(parent, wx.ID_ANY, u"0 HP/s") + + lbl.SetToolTip(wx.ToolTip(tooltip)) + + setattr(self, "label%s" % outgoingType, lbl) + + baseBox.Add(lbl, 0, wx.ALIGN_CENTER) + self._cachedValues.append(0) + counter += 1 + + sizerOutgoing.Add(baseBox, 1, wx.ALIGN_LEFT) + + def refreshPanel(self, fit): + # If we did anything intresting, we'd update our labels to reflect the new fit's stats here + + stats = [ + ("labelRemoteArmor", lambda: fit.remoteReps["Armor"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteShield", lambda: fit.remoteReps["Shield"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteHull", lambda: fit.remoteReps["Hull"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteCapacitor", lambda: fit.remoteReps["Capacitor"], 3, 0, 0, u"%s GJ/s", None), + ] + + counter = 0 + for labelName, value, prec, lowest, highest, valueFormat, altFormat in stats: + label = getattr(self, labelName) + value = value() if fit is not None else 0 + value = value if value is not None else 0 + if self._cachedValues[counter] != value: + valueStr = formatAmount(value, prec, lowest, highest) + label.SetLabel(valueFormat % valueStr) + tipStr = valueFormat % valueStr if altFormat is None else altFormat % value + label.SetToolTip(wx.ToolTip(tipStr)) + self._cachedValues[counter] = value + counter += 1 + self.panel.Layout() + self.headerPanel.Layout() + + +OutgoingViewFull.register() diff --git a/gui/builtinStatsViews/outgoingViewMinimal.py b/gui/builtinStatsViews/outgoingViewMinimal.py new file mode 100644 index 000000000..d2bf2c118 --- /dev/null +++ b/gui/builtinStatsViews/outgoingViewMinimal.py @@ -0,0 +1,105 @@ +# =============================================================================== +# Copyright (C) 2014 Alexandros Kosiaris +# +# This file is part of pyfa. +# +# pyfa is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# pyfa is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with pyfa. If not, see . +# =============================================================================== + +# noinspection PyPackageRequirements +import wx +from gui.statsView import StatsView +from gui.utils.numberFormatter import formatAmount + + +class OutgoingViewMinimal(StatsView): + name = "outgoingViewMinimal" + + def __init__(self, parent): + StatsView.__init__(self) + self.parent = parent + self._cachedValues = [] + + def getHeaderText(self, fit): + return "Remote Reps" + + def getTextExtentW(self, text): + width, height = self.parent.GetTextExtent(text) + return width + + def populatePanel(self, contentPanel, headerPanel): + contentSizer = contentPanel.GetSizer() + parent = self.panel = contentPanel + self.headerPanel = headerPanel + + sizerOutgoing = wx.GridSizer(1, 4) + + contentSizer.Add(sizerOutgoing, 0, wx.EXPAND, 0) + + counter = 0 + + rr_list = [ + ("RemoteCapacitor", "Capacitor:", "capacitorInfo", "Capacitor GJ/s per second transferred remotely."), + ("RemoteShield", "Shield:", "shieldActive", "Shield hitpoints per second repaired remotely."), + ("RemoteArmor", "Armor:", "armorActive", "Armor hitpoints per second repaired remotely."), + ("RemoteHull", "Hull:", "hullActive", "Hull hitpoints per second repaired remotely."), + ] + + for outgoingType, label, image, tooltip in rr_list: + baseBox = wx.BoxSizer(wx.VERTICAL) + + baseBox.Add(wx.StaticText(contentPanel, wx.ID_ANY, label), 0, wx.ALIGN_CENTER) + + if "Capacitor" in outgoingType: + lbl = wx.StaticText(parent, wx.ID_ANY, u"0 GJ/s") + else: + lbl = wx.StaticText(parent, wx.ID_ANY, u"0 HP/s") + + lbl.SetToolTip(wx.ToolTip(tooltip)) + + setattr(self, "label%s" % outgoingType, lbl) + + baseBox.Add(lbl, 0, wx.ALIGN_CENTER) + self._cachedValues.append(0) + counter += 1 + + sizerOutgoing.Add(baseBox, 1, wx.ALIGN_LEFT) + + def refreshPanel(self, fit): + # If we did anything intresting, we'd update our labels to reflect the new fit's stats here + + stats = [ + ("labelRemoteArmor", lambda: fit.remoteReps["Armor"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteShield", lambda: fit.remoteReps["Shield"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteHull", lambda: fit.remoteReps["Hull"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteCapacitor", lambda: fit.remoteReps["Capacitor"], 3, 0, 0, u"%s GJ/s", None), + ] + + counter = 0 + for labelName, value, prec, lowest, highest, valueFormat, altFormat in stats: + label = getattr(self, labelName) + value = value() if fit is not None else 0 + value = value if value is not None else 0 + if self._cachedValues[counter] != value: + valueStr = formatAmount(value, prec, lowest, highest) + label.SetLabel(valueFormat % valueStr) + tipStr = valueFormat % valueStr if altFormat is None else altFormat % value + label.SetToolTip(wx.ToolTip(tipStr)) + self._cachedValues[counter] = value + counter += 1 + self.panel.Layout() + self.headerPanel.Layout() + + +OutgoingViewMinimal.register() diff --git a/gui/builtinStatsViews/priceViewFull.py b/gui/builtinStatsViews/priceViewFull.py index bb222d94a..0fbd24ff0 100644 --- a/gui/builtinStatsViews/priceViewFull.py +++ b/gui/builtinStatsViews/priceViewFull.py @@ -17,11 +17,13 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from gui.statsView import StatsView from gui.bitmapLoader import BitmapLoader from gui.utils.numberFormatter import formatAmount from service.market import Market +from service.price import Price class PriceViewFull(StatsView): @@ -73,23 +75,8 @@ class PriceViewFull(StatsView): def refreshPanel(self, fit): if fit is not None: self.fit = fit - # Compose a list of all the data we need & request it - typeIDs = [] - typeIDs.append(fit.ship.item.ID) - for mod in fit.modules: - if not mod.isEmpty: - typeIDs.append(mod.itemID) - - for drone in fit.drones: - typeIDs.append(drone.itemID) - - for fighter in fit.fighters: - if fighter.amountActive > 0: - typeIDs.append(fighter.itemID) - - for cargo in fit.cargo: - typeIDs.append(cargo.itemID) + typeIDs = Price.fitItemsList(fit) sMkt = Market.getInstance() sMkt.getPrices(typeIDs, self.processPrices) diff --git a/gui/builtinStatsViews/rechargeViewFull.py b/gui/builtinStatsViews/rechargeViewFull.py index a285c04cb..21399602e 100644 --- a/gui/builtinStatsViews/rechargeViewFull.py +++ b/gui/builtinStatsViews/rechargeViewFull.py @@ -17,12 +17,13 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from gui.statsView import StatsView from gui.bitmapLoader import BitmapLoader from gui.utils.numberFormatter import formatAmount import gui.mainFrame -import gui.builtinStatsViews.resistancesViewFull as rvf +from gui.builtinStatsViews.resistancesViewFull import EFFECTIVE_HP_TOGGLED from service.fit import Fit @@ -33,7 +34,7 @@ class RechargeViewFull(StatsView): StatsView.__init__(self) self.parent = parent self.mainFrame = gui.mainFrame.MainFrame.getInstance() - self.mainFrame.Bind(rvf.EFFECTIVE_HP_TOGGLED, self.toggleEffective) + self.mainFrame.Bind(EFFECTIVE_HP_TOGGLED, self.toggleEffective) self.effective = True def getHeaderText(self, fit): diff --git a/gui/builtinStatsViews/resistancesViewFull.py b/gui/builtinStatsViews/resistancesViewFull.py index 16f8cb5a5..9946310ec 100644 --- a/gui/builtinStatsViews/resistancesViewFull.py +++ b/gui/builtinStatsViews/resistancesViewFull.py @@ -17,10 +17,11 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from gui.statsView import StatsView from gui.bitmapLoader import BitmapLoader -from gui import pygauge as PG +from gui.pygauge import PyGauge from gui.utils.numberFormatter import formatAmount import gui.mainFrame import gui.globalEvents as GE @@ -132,7 +133,7 @@ class ResistancesViewFull(StatsView): bc = pgColour[1] currGColour += 1 - lbl = PG.PyGauge(contentPanel, wx.ID_ANY, 100) + lbl = PyGauge(contentPanel, wx.ID_ANY, 100) lbl.SetMinSize((48, 16)) lbl.SetBackgroundColour(wx.Colour(bc[0], bc[1], bc[2])) lbl.SetBarColour(wx.Colour(fc[0], fc[1], fc[2])) diff --git a/gui/builtinStatsViews/resourcesViewFull.py b/gui/builtinStatsViews/resourcesViewFull.py index 39bb0b62a..3171aaa4b 100644 --- a/gui/builtinStatsViews/resourcesViewFull.py +++ b/gui/builtinStatsViews/resourcesViewFull.py @@ -17,14 +17,15 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from gui.statsView import StatsView from gui.bitmapLoader import BitmapLoader -from gui import pygauge as PG +from gui.pygauge import PyGauge import gui.mainFrame -import gui.chromeTabs +from gui.chromeTabs import EVT_NOTEBOOK_PAGE_CHANGED -from eos.types import Hardpoint +from eos.saveddata.module import Hardpoint from gui.utils.numberFormatter import formatAmount @@ -37,7 +38,7 @@ class ResourcesViewFull(StatsView): StatsView.__init__(self) self.parent = parent self.mainFrame = gui.mainFrame.MainFrame.getInstance() - self.mainFrame.additionsPane.notebook.Bind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged) + self.mainFrame.additionsPane.notebook.Bind(EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged) def pageChanged(self, event): page = self.mainFrame.additionsPane.getName(event.GetSelection()) @@ -175,7 +176,7 @@ class ResourcesViewFull(StatsView): # Gauges modif. - Darriele - gauge = PG.PyGauge(parent, wx.ID_ANY, 1) + gauge = PyGauge(parent, wx.ID_ANY, 1) gauge.SetValueRange(0, 0) gauge.SetMinSize((self.getTextExtentW("1.999M/1.99M MW"), 23)) gauge.SetFractionDigits(2) @@ -216,52 +217,61 @@ class ResourcesViewFull(StatsView): ("label%sTotalCargoBay", lambda: fit.ship.getModifiedItemAttr("capacity"), 3, 0, 9), ) panel = "Full" + usedTurretHardpoints = 0 + labelUTH = "" totalTurretHardpoints = 0 + labelTTH = "" usedLauncherHardpoints = 0 + labelULH = "" totalLauncherHardPoints = 0 + labelTLH = "" + usedDronesActive = 0 + labelUDA = "" + totalDronesActive = 0 + labelTDA = "" + usedFighterTubes = 0 + labelUFT = "" + totalFighterTubes = 0 + labelTFT = "" + usedCalibrationPoints = 0 + labelUCP = "" + totalCalibrationPoints = 0 + labelTCP = "" for labelName, value, prec, lowest, highest in stats: label = getattr(self, labelName % panel) value = value() if fit is not None else 0 value = value if value is not None else 0 + if labelName % panel == "label%sUsedTurretHardpoints" % panel: usedTurretHardpoints = value labelUTH = label - - if labelName % panel == "label%sTotalTurretHardpoints" % panel: + elif labelName % panel == "label%sTotalTurretHardpoints" % panel: totalTurretHardpoints = value labelTTH = label - - if labelName % panel == "label%sUsedLauncherHardpoints" % panel: + elif labelName % panel == "label%sUsedLauncherHardpoints" % panel: usedLauncherHardpoints = value labelULH = label - - if labelName % panel == "label%sTotalLauncherHardpoints" % panel: + elif labelName % panel == "label%sTotalLauncherHardpoints" % panel: totalLauncherHardPoints = value labelTLH = label - - if labelName % panel == "label%sUsedDronesActive" % panel: + elif labelName % panel == "label%sUsedDronesActive" % panel: usedDronesActive = value labelUDA = label - - if labelName % panel == "label%sTotalDronesActive" % panel: + elif labelName % panel == "label%sTotalDronesActive" % panel: totalDronesActive = value labelTDA = label - - if labelName % panel == "label%sUsedFighterTubes" % panel: + elif labelName % panel == "label%sUsedFighterTubes" % panel: usedFighterTubes = value labelUFT = label - - if labelName % panel == "label%sTotalFighterTubes" % panel: + elif labelName % panel == "label%sTotalFighterTubes" % panel: totalFighterTubes = value labelTFT = label - - if labelName % panel == "label%sUsedCalibrationPoints" % panel: + elif labelName % panel == "label%sUsedCalibrationPoints" % panel: usedCalibrationPoints = value labelUCP = label - - if labelName % panel == "label%sTotalCalibrationPoints" % panel: + elif labelName % panel == "label%sTotalCalibrationPoints" % panel: totalCalibrationPoints = value labelTCP = label @@ -316,6 +326,8 @@ class ResourcesViewFull(StatsView): lambda: fit.ship.getModifiedItemAttr("droneBandwidth"), lambda: fit.ship.getModifiedItemAttr("capacity"), ) + else: + resMax = None i = 0 for resourceType in ("cpu", "pg", "droneBay", "fighterBay", "droneBandwidth", "cargoBay"): diff --git a/gui/builtinStatsViews/targetingMiscViewFull.py b/gui/builtinStatsViews/targetingMiscViewFull.py index aab2bf25e..1fa235ba0 100644 --- a/gui/builtinStatsViews/targetingMiscViewFull.py +++ b/gui/builtinStatsViews/targetingMiscViewFull.py @@ -17,6 +17,7 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from gui.statsView import StatsView from gui.utils.numberFormatter import formatAmount @@ -28,7 +29,7 @@ except ImportError: class TargetingMiscViewFull(StatsView): - name = "targetingmiscViewFull" + name = "targetingMiscViewFull" def __init__(self, parent): StatsView.__init__(self) @@ -202,16 +203,14 @@ class TargetingMiscViewFull(StatsView): label.SetToolTip( wx.ToolTip("Type: %s\n%.1f%% Chance of Jam" % (fit.scanType, fit.jamChance))) else: - label.SetToolTip(wx.ToolTip("Type: %s" % (fit.scanType))) + label.SetToolTip(wx.ToolTip("Type: %s" % fit.scanType)) elif labelName == "labelFullAlignTime": alignTime = "Align:\t%.3fs" % mainValue mass = 'Mass:\t{:,.0f}kg'.format(fit.ship.getModifiedItemAttr("mass")) agility = "Agility:\t%.3fx" % (fit.ship.getModifiedItemAttr("agility") or 0) label.SetToolTip(wx.ToolTip("%s\n%s\n%s" % (alignTime, mass, agility))) elif labelName == "labelFullCargo": - tipLines = [] - tipLines.append( - u"Cargohold: {:,.2f}m\u00B3 / {:,.2f}m\u00B3".format(fit.cargoBayUsed, newValues["main"])) + tipLines = [u"Cargohold: {:,.2f}m\u00B3 / {:,.2f}m\u00B3".format(fit.cargoBayUsed, newValues["main"])] for attrName, tipAlias in cargoNamesOrder.items(): if newValues[attrName] > 0: tipLines.append(u"{}: {:,.2f}m\u00B3".format(tipAlias, newValues[attrName])) @@ -231,7 +230,7 @@ class TargetingMiscViewFull(StatsView): if fit.jamChance > 0: label.SetToolTip(wx.ToolTip("Type: %s\n%.1f%% Chance of Jam" % (fit.scanType, fit.jamChance))) else: - label.SetToolTip(wx.ToolTip("Type: %s" % (fit.scanType))) + label.SetToolTip(wx.ToolTip("Type: %s" % fit.scanType)) else: label.SetToolTip(wx.ToolTip("")) elif labelName == "labelFullCargo": @@ -239,9 +238,7 @@ class TargetingMiscViewFull(StatsView): cachedCargo = self._cachedValues[counter] # if you add stuff to cargo, the capacity doesn't change and thus it is still cached # This assures us that we force refresh of cargo tooltip - tipLines = [] - tipLines.append( - u"Cargohold: {:,.2f}m\u00B3 / {:,.2f}m\u00B3".format(fit.cargoBayUsed, cachedCargo["main"])) + tipLines = [u"Cargohold: {:,.2f}m\u00B3 / {:,.2f}m\u00B3".format(fit.cargoBayUsed, cachedCargo["main"])] for attrName, tipAlias in cargoNamesOrder.items(): if cachedCargo[attrName] > 0: tipLines.append(u"{}: {:,.2f}m\u00B3".format(tipAlias, cachedCargo[attrName])) diff --git a/gui/builtinStatsViews/targetingMiscViewMinimal.py b/gui/builtinStatsViews/targetingMiscViewMinimal.py new file mode 100644 index 000000000..4dffc9e40 --- /dev/null +++ b/gui/builtinStatsViews/targetingMiscViewMinimal.py @@ -0,0 +1,256 @@ +# ============================================================================= +# Copyright (C) 2010 Diego Duclos +# +# This file is part of pyfa. +# +# pyfa is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# pyfa is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with pyfa. If not, see . +# ============================================================================= + +# noinspection PyPackageRequirements +import wx +from gui.statsView import StatsView +from gui.utils.numberFormatter import formatAmount + +try: + from collections import OrderedDict +except ImportError: + from utils.compat import OrderedDict + + +class TargetingMiscViewMinimal(StatsView): + name = "targetingMiscViewMinimal" + + def __init__(self, parent): + StatsView.__init__(self) + self.parent = parent + self._cachedValues = [] + + def getHeaderText(self, fit): + return "Targeting && Misc" + + def getTextExtentW(self, text): + width, height = self.parent.GetTextExtent(text) + return width + + def populatePanel(self, contentPanel, headerPanel): + contentSizer = contentPanel.GetSizer() + + self.panel = contentPanel + self.headerPanel = headerPanel + gridTargetingMisc = wx.FlexGridSizer(1, 3) + contentSizer.Add(gridTargetingMisc, 0, wx.EXPAND | wx.ALL, 0) + gridTargetingMisc.AddGrowableCol(0) + gridTargetingMisc.AddGrowableCol(2) + # Targeting + + gridTargeting = wx.FlexGridSizer(5, 2) + gridTargeting.AddGrowableCol(1) + + gridTargetingMisc.Add(gridTargeting, 0, wx.ALIGN_LEFT | wx.ALL, 5) + + labels = (("Targets", "Targets", ""), + ("Range", "Range", "km"), + ("Scan res.", "ScanRes", "mm"), + ("Sensor str.", "SensorStr", ""), + ("Drone range", "CtrlRange", "km")) + + for header, labelShort, unit in labels: + gridTargeting.Add(wx.StaticText(contentPanel, wx.ID_ANY, "%s: " % header), 0, wx.ALIGN_LEFT) + + box = wx.BoxSizer(wx.HORIZONTAL) + gridTargeting.Add(box, 0, wx.ALIGN_LEFT) + + lbl = wx.StaticText(contentPanel, wx.ID_ANY, "0 %s" % unit) + setattr(self, "label%s" % labelShort, lbl) + box.Add(lbl, 0, wx.ALIGN_LEFT) + + self._cachedValues.append({"main": 0}) + + # Misc + gridTargetingMisc.Add(wx.StaticLine(contentPanel, wx.ID_ANY, style=wx.VERTICAL), 0, wx.EXPAND, 3) + gridMisc = wx.FlexGridSizer(5, 2) + gridMisc.AddGrowableCol(1) + gridTargetingMisc.Add(gridMisc, 0, wx.ALIGN_LEFT | wx.ALL, 5) + + labels = (("Speed", "Speed", "m/s"), + ("Align time", "AlignTime", "s"), + ("Signature", "SigRadius", "m"), + ("Warp Speed", "WarpSpeed", "AU/s"), + ("Cargo", "Cargo", u"m\u00B3")) + + for header, labelShort, unit in labels: + gridMisc.Add(wx.StaticText(contentPanel, wx.ID_ANY, "%s: " % header), 0, wx.ALIGN_LEFT) + + box = wx.BoxSizer(wx.HORIZONTAL) + gridMisc.Add(box, 0, wx.ALIGN_LEFT) + + lbl = wx.StaticText(contentPanel, wx.ID_ANY, "0 %s" % unit) + setattr(self, "labelFull%s" % labelShort, lbl) + box.Add(lbl, 0, wx.ALIGN_LEFT) + + self._cachedValues.append({"main": 0}) + + def refreshPanel(self, fit): + # If we did anything interesting, we'd update our labels to reflect the new fit's stats here + + cargoNamesOrder = OrderedDict(( + ("fleetHangarCapacity", "Fleet hangar"), + ("shipMaintenanceBayCapacity", "Maintenance bay"), + ("specialAmmoHoldCapacity", "Ammo hold"), + ("specialFuelBayCapacity", "Fuel bay"), + ("specialShipHoldCapacity", "Ship hold"), + ("specialSmallShipHoldCapacity", "Small ship hold"), + ("specialMediumShipHoldCapacity", "Medium ship hold"), + ("specialLargeShipHoldCapacity", "Large ship hold"), + ("specialIndustrialShipHoldCapacity", "Industrial ship hold"), + ("specialOreHoldCapacity", "Ore hold"), + ("specialMineralHoldCapacity", "Mineral hold"), + ("specialMaterialBayCapacity", "Material bay"), + ("specialGasHoldCapacity", "Gas hold"), + ("specialSalvageHoldCapacity", "Salvage hold"), + ("specialCommandCenterHoldCapacity", "Command center hold"), + ("specialPlanetaryCommoditiesHoldCapacity", "Planetary goods hold"), + ("specialQuafeHoldCapacity", "Quafe hold") + )) + + cargoValues = { + "main": lambda: fit.ship.getModifiedItemAttr("capacity"), + "fleetHangarCapacity": lambda: fit.ship.getModifiedItemAttr("fleetHangarCapacity"), + "shipMaintenanceBayCapacity": lambda: fit.ship.getModifiedItemAttr("shipMaintenanceBayCapacity"), + "specialAmmoHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialAmmoHoldCapacity"), + "specialFuelBayCapacity": lambda: fit.ship.getModifiedItemAttr("specialFuelBayCapacity"), + "specialShipHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialShipHoldCapacity"), + "specialSmallShipHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialSmallShipHoldCapacity"), + "specialMediumShipHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialMediumShipHoldCapacity"), + "specialLargeShipHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialLargeShipHoldCapacity"), + "specialIndustrialShipHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialIndustrialShipHoldCapacity"), + "specialOreHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialOreHoldCapacity"), + "specialMineralHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialMineralHoldCapacity"), + "specialMaterialBayCapacity": lambda: fit.ship.getModifiedItemAttr("specialMaterialBayCapacity"), + "specialGasHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialGasHoldCapacity"), + "specialSalvageHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialSalvageHoldCapacity"), + "specialCommandCenterHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialCommandCenterHoldCapacity"), + "specialPlanetaryCommoditiesHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialPlanetaryCommoditiesHoldCapacity"), + "specialQuafeHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialQuafeHoldCapacity") + } + + stats = (("labelTargets", {"main": lambda: fit.maxTargets}, 3, 0, 0, ""), + ("labelRange", {"main": lambda: fit.maxTargetRange / 1000}, 3, 0, 0, "km"), + ("labelScanRes", {"main": lambda: fit.ship.getModifiedItemAttr("scanResolution")}, 3, 0, 0, "mm"), + ("labelSensorStr", {"main": lambda: fit.scanStrength}, 3, 0, 0, ""), + ("labelCtrlRange", {"main": lambda: fit.extraAttributes["droneControlRange"] / 1000}, 3, 0, 0, "km"), + ("labelFullSpeed", {"main": lambda: fit.maxSpeed}, 3, 0, 0, "m/s"), + ("labelFullAlignTime", {"main": lambda: fit.alignTime}, 3, 0, 0, "s"), + ("labelFullSigRadius", {"main": lambda: fit.ship.getModifiedItemAttr("signatureRadius")}, 3, 0, 9, ""), + ("labelFullWarpSpeed", {"main": lambda: fit.warpSpeed}, 3, 0, 0, "AU/s"), + ("labelFullCargo", cargoValues, 4, 0, 9, u"m\u00B3")) + + counter = 0 + RADII = [("Pod", 25), ("Interceptor", 33), ("Frigate", 38), + ("Destroyer", 83), ("Cruiser", 130), + ("Battlecruiser", 265), ("Battleship", 420), + ("Carrier", 3000)] + for labelName, valueDict, prec, lowest, highest, unit in stats: + label = getattr(self, labelName) + newValues = {} + for valueAlias, value in valueDict.items(): + value = value() if fit is not None else 0 + value = value if value is not None else 0 + newValues[valueAlias] = value + if self._cachedValues[counter] != newValues: + mainValue = newValues["main"] + otherValues = dict((k, newValues[k]) for k in filter(lambda k: k != "main", newValues)) + if labelName == "labelFullCargo": + # Get sum of all cargoholds except for maintenance bay + additionalCargo = sum(otherValues.values()) + if additionalCargo > 0: + label.SetLabel("%s+%s %s" % (formatAmount(mainValue, prec, lowest, highest), + formatAmount(additionalCargo, prec, lowest, highest), + unit)) + else: + label.SetLabel("%s %s" % (formatAmount(mainValue, prec, lowest, highest), unit)) + else: + label.SetLabel("%s %s" % (formatAmount(mainValue, prec, lowest, highest), unit)) + # Tooltip stuff + if fit: + if labelName == "labelScanRes": + lockTime = "%s\n" % "Lock Times".center(30) + for size, radius in RADII: + left = "%.1fs" % fit.calculateLockTime(radius) + right = "%s [%d]" % (size, radius) + lockTime += "%5s\t%s\n" % (left, right) + label.SetToolTip(wx.ToolTip(lockTime)) + elif labelName == "labelFullWarpSpeed": + label.SetToolTip(wx.ToolTip("Max Warp Distance: %.1f AU" % fit.maxWarpDistance)) + elif labelName == "labelSensorStr": + if fit.jamChance > 0: + label.SetToolTip(wx.ToolTip("Type: %s\n%.1f%% Chance of Jam" % (fit.scanType, fit.jamChance))) + else: + label.SetToolTip(wx.ToolTip("Type: %s" % fit.scanType)) + elif labelName == "labelFullAlignTime": + alignTime = "Align:\t%.3fs" % mainValue + mass = 'Mass:\t{:,.0f}kg'.format(fit.ship.getModifiedItemAttr("mass")) + agility = "Agility:\t%.3fx" % (fit.ship.getModifiedItemAttr("agility") or 0) + label.SetToolTip(wx.ToolTip("%s\n%s\n%s" % (alignTime, mass, agility))) + elif labelName == "labelFullCargo": + tipLines = [u"Cargohold: {:,.2f}m\u00B3 / {:,.2f}m\u00B3".format(fit.cargoBayUsed, newValues["main"])] + for attrName, tipAlias in cargoNamesOrder.items(): + if newValues[attrName] > 0: + tipLines.append(u"{}: {:,.2f}m\u00B3".format(tipAlias, newValues[attrName])) + label.SetToolTip(wx.ToolTip(u"\n".join(tipLines))) + else: + label.SetToolTip(wx.ToolTip("%.1f" % mainValue)) + else: + label.SetToolTip(wx.ToolTip("")) + self._cachedValues[counter] = newValues + elif labelName == "labelFullWarpSpeed": + if fit: + label.SetToolTip(wx.ToolTip("Max Warp Distance: %.1f AU" % fit.maxWarpDistance)) + else: + label.SetToolTip(wx.ToolTip("")) + elif labelName == "labelSensorStr": + if fit: + if fit.jamChance > 0: + label.SetToolTip(wx.ToolTip("Type: %s\n%.1f%% Chance of Jam" % (fit.scanType, fit.jamChance))) + else: + label.SetToolTip(wx.ToolTip("Type: %s" % fit.scanType)) + else: + label.SetToolTip(wx.ToolTip("")) + elif labelName == "labelFullCargo": + if fit: + cachedCargo = self._cachedValues[counter] + # if you add stuff to cargo, the capacity doesn't change and thus it is still cached + # This assures us that we force refresh of cargo tooltip + tipLines = [u"Cargohold: {:,.2f}m\u00B3 / {:,.2f}m\u00B3".format(fit.cargoBayUsed, cachedCargo["main"])] + for attrName, tipAlias in cargoNamesOrder.items(): + if cachedCargo[attrName] > 0: + tipLines.append(u"{}: {:,.2f}m\u00B3".format(tipAlias, cachedCargo[attrName])) + label.SetToolTip(wx.ToolTip(u"\n".join(tipLines))) + else: + label.SetToolTip(wx.ToolTip("")) + + # forces update of probe size, since this stat is used by both sig radius and sensor str + if labelName == "labelFullSigRadius": + print "labelName" + if fit: + label.SetToolTip(wx.ToolTip("Probe Size: %.3f" % (fit.probeSize or 0))) + else: + label.SetToolTip(wx.ToolTip("")) + + counter += 1 + self.panel.Layout() + self.headerPanel.Layout() + + +TargetingMiscViewMinimal.register() diff --git a/gui/builtinViewColumns/abilities.py b/gui/builtinViewColumns/abilities.py index e42a2eed3..69b7ece97 100644 --- a/gui/builtinViewColumns/abilities.py +++ b/gui/builtinViewColumns/abilities.py @@ -18,8 +18,9 @@ # ============================================================================= +# noinspection PyPackageRequirements import wx -from eos.types import Fighter +from eos.saveddata.fighter import Fighter from gui.viewColumn import ViewColumn import gui.mainFrame diff --git a/gui/builtinViewColumns/ammo.py b/gui/builtinViewColumns/ammo.py index 4cd6a0ba7..069328a32 100644 --- a/gui/builtinViewColumns/ammo.py +++ b/gui/builtinViewColumns/ammo.py @@ -17,8 +17,9 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx -from eos.types import Fighter +from eos.saveddata.fighter import Fighter from gui.viewColumn import ViewColumn from gui.bitmapLoader import BitmapLoader diff --git a/gui/builtinViewColumns/ammoIcon.py b/gui/builtinViewColumns/ammoIcon.py index f4f6f7af1..7459db6a4 100644 --- a/gui/builtinViewColumns/ammoIcon.py +++ b/gui/builtinViewColumns/ammoIcon.py @@ -18,8 +18,9 @@ # ============================================================================= from gui.viewColumn import ViewColumn +# noinspection PyPackageRequirements import wx -from eos.types import Module +from eos.saveddata.module import Module class AmmoIcon(ViewColumn): diff --git a/gui/builtinViewColumns/attributeDisplay.py b/gui/builtinViewColumns/attributeDisplay.py index 26994a956..855bfe2a1 100644 --- a/gui/builtinViewColumns/attributeDisplay.py +++ b/gui/builtinViewColumns/attributeDisplay.py @@ -17,6 +17,7 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from gui.viewColumn import ViewColumn @@ -82,7 +83,7 @@ class AttributeDisplay(ViewColumn): if self.info.name == "volume": str_ = (formatAmount(attr, 3, 0, 3)) if hasattr(mod, "amount"): - str_ = str_ + u"m\u00B3 (%s m\u00B3)" % (formatAmount(attr * mod.amount, 3, 0, 3)) + str_ += u"m\u00B3 (%s m\u00B3)" % (formatAmount(attr * mod.amount, 3, 0, 3)) attr = str_ if isinstance(attr, (float, int)): diff --git a/gui/builtinViewColumns/baseIcon.py b/gui/builtinViewColumns/baseIcon.py index 7f9b16296..8c09a9fa3 100644 --- a/gui/builtinViewColumns/baseIcon.py +++ b/gui/builtinViewColumns/baseIcon.py @@ -1,5 +1,9 @@ +# noinspection PyPackageRequirements import wx -from eos.types import Drone, Fit, Module, Slot, Rack, Implant +from eos.saveddata.implant import Implant +from eos.saveddata.drone import Drone +from eos.saveddata.module import Module, Slot, Rack +from eos.saveddata.fit import Fit from gui.viewColumn import ViewColumn diff --git a/gui/builtinViewColumns/baseName.py b/gui/builtinViewColumns/baseName.py index 973219b2c..70d0c65a7 100644 --- a/gui/builtinViewColumns/baseName.py +++ b/gui/builtinViewColumns/baseName.py @@ -18,9 +18,15 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx -from eos.types import Drone, Cargo, Module, Slot, Rack, Implant, Fighter -from service.fit import Fit +from eos.saveddata.cargo import Cargo +from eos.saveddata.implant import Implant +from eos.saveddata.drone import Drone +from eos.saveddata.fighter import Fighter +from eos.saveddata.module import Module, Slot, Rack +from eos.saveddata.fit import Fit +from service.fit import Fit as FitSvc from gui.viewColumn import ViewColumn import gui.mainFrame @@ -53,7 +59,7 @@ class BaseName(ViewColumn): else: return "%s (%s)" % (stuff.name, stuff.ship.item.name) elif isinstance(stuff, Rack): - if Fit.getInstance().serviceFittingOptions["rackLabels"]: + if FitSvc.getInstance().serviceFittingOptions["rackLabels"]: if stuff.slot == Slot.MODE: return u'─ Tactical Mode ─' else: @@ -70,7 +76,7 @@ class BaseName(ViewColumn): else: item = getattr(stuff, "item", stuff) - if Fit.getInstance().serviceFittingOptions["showMarketShortcuts"]: + if FitSvc.getInstance().serviceFittingOptions["showMarketShortcuts"]: marketShortcut = getattr(item, "marketShortcut", None) if marketShortcut: diff --git a/gui/builtinViewColumns/capacitorUse.py b/gui/builtinViewColumns/capacitorUse.py index 692911400..5d0287375 100644 --- a/gui/builtinViewColumns/capacitorUse.py +++ b/gui/builtinViewColumns/capacitorUse.py @@ -17,9 +17,10 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx -from eos.types import Mode +from eos.saveddata.mode import Mode from service.attribute import Attribute from gui.utils.numberFormatter import formatAmount from gui.viewColumn import ViewColumn diff --git a/gui/builtinViewColumns/maxRange.py b/gui/builtinViewColumns/maxRange.py index ea26d4d67..d4b3367da 100644 --- a/gui/builtinViewColumns/maxRange.py +++ b/gui/builtinViewColumns/maxRange.py @@ -17,9 +17,10 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx -from eos.types import Mode +from eos.saveddata.mode import Mode from service.attribute import Attribute from gui.viewColumn import ViewColumn from gui.bitmapLoader import BitmapLoader @@ -73,7 +74,7 @@ class MaxRange(ViewColumn): return -1 def getParameters(self): - return (("displayName", bool, False), ("showIcon", bool, True)) + return ("displayName", bool, False), ("showIcon", bool, True) def getToolTip(self, mod): return "Optimal + Falloff" diff --git a/gui/builtinViewColumns/misc.py b/gui/builtinViewColumns/misc.py index 080614a3b..c1e12f29c 100644 --- a/gui/builtinViewColumns/misc.py +++ b/gui/builtinViewColumns/misc.py @@ -17,6 +17,7 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from service.fit import Fit @@ -58,7 +59,7 @@ class Miscellanea(ViewColumn): return -1 def getParameters(self): - return (("displayName", bool, False), ("showIcon", bool, True)) + return ("displayName", bool, False), ("showIcon", bool, True) def __getData(self, stuff): item = stuff.item @@ -450,30 +451,69 @@ class Miscellanea(ViewColumn): return text, item.name else: return "", None - elif itemGroup in ("Ancillary Armor Repairer", "Ancillary Shield Booster"): - hp = stuff.hpBeforeReload - cycles = stuff.numShots - cycleTime = stuff.rawCycleTime + elif itemGroup in ( + "Ancillary Armor Repairer", + "Ancillary Shield Booster", + "Capacitor Booster", + "Ancillary Remote Armor Repairer", + "Ancillary Remote Shield Booster", + ): + if "Armor" in itemGroup or "Shield" in itemGroup: + boosted_attribute = "HP" + reload_time = item.getAttribute("reloadTime", 0) / 1000 + elif "Capacitor" in itemGroup: + boosted_attribute = "Cap" + reload_time = 10 + else: + boosted_attribute = "" + reload_time = 0 + + cycles = max(stuff.numShots, 0) + cycleTime = max(stuff.rawCycleTime, 0) + + # Get HP or boosted amount + stuff_hp = max(stuff.hpBeforeReload, 0) + armor_hp = stuff.getModifiedItemAttr("armorDamageAmount", 0) + capacitor_hp = stuff.getModifiedChargeAttr("capacitorBonus", 0) + shield_hp = stuff.getModifiedItemAttr("shieldBonus", 0) + hp = max(stuff_hp, armor_hp * cycles, capacitor_hp * cycles, shield_hp * cycles, 0) + if not hp or not cycleTime or not cycles: return "", None + fit = Fit.getInstance().getFit(self.mainFrame.getActiveFit()) ehpTotal = fit.ehp hpTotal = fit.hp useEhp = self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective - tooltip = "HP restored over duration using charges" - if useEhp: - if itemGroup == "Ancillary Armor Repairer": + tooltip = "{0} restored over duration using charges (plus reload)".format(boosted_attribute) + + if useEhp and boosted_attribute == "HP" and "Remote" not in itemGroup: + if "Ancillary Armor Repairer" in itemGroup: hpRatio = ehpTotal["armor"] / hpTotal["armor"] else: hpRatio = ehpTotal["shield"] / hpTotal["shield"] tooltip = "E{0}".format(tooltip) else: hpRatio = 1 - if itemGroup == "Ancillary Armor Repairer": - hpRatio *= 3 + + if "Ancillary" in itemGroup and "Armor" in itemGroup: + hpRatio *= stuff.getModifiedItemAttr("chargedArmorDamageMultiplier", 1) + ehp = hp * hpRatio + duration = cycles * cycleTime / 1000 - text = "{0} / {1}s".format(formatAmount(ehp, 3, 0, 9), formatAmount(duration, 3, 0, 3)) + for number_of_cycles in {5, 10, 25}: + tooltip = "{0}\n{1} charges lasts {2} seconds ({3} cycles)".format( + tooltip, + formatAmount(number_of_cycles * cycles, 3, 0, 3), + formatAmount((duration + reload_time) * number_of_cycles, 3, 0, 3), + formatAmount(number_of_cycles, 3, 0, 3) + ) + text = "{0} / {1}s (+{2}s)".format( + formatAmount(ehp, 3, 0, 9), + formatAmount(duration, 3, 0, 3), + formatAmount(reload_time, 3, 0, 3) + ) return text, tooltip elif itemGroup == "Armor Resistance Shift Hardener": diff --git a/gui/builtinViewColumns/price.py b/gui/builtinViewColumns/price.py index 68ad87e1e..194aa594d 100644 --- a/gui/builtinViewColumns/price.py +++ b/gui/builtinViewColumns/price.py @@ -17,9 +17,11 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx -from eos.types import Drone, Cargo +from eos.saveddata.cargo import Cargo +from eos.saveddata.drone import Drone from service.market import Market from gui.viewColumn import ViewColumn from gui.bitmapLoader import BitmapLoader diff --git a/gui/builtinViewColumns/propertyDisplay.py b/gui/builtinViewColumns/propertyDisplay.py index 1972cfae1..b4faa177a 100644 --- a/gui/builtinViewColumns/propertyDisplay.py +++ b/gui/builtinViewColumns/propertyDisplay.py @@ -56,7 +56,7 @@ class PropertyDisplay(ViewColumn): def getText(self, stuff): attr = getattr(stuff, self.propertyName, None) if attr: - return (formatAmount(attr, 3, 0, 3)) + return formatAmount(attr, 3, 0, 3) else: return "" diff --git a/gui/builtinViewColumns/state.py b/gui/builtinViewColumns/state.py index 920562087..aa3f79ebe 100644 --- a/gui/builtinViewColumns/state.py +++ b/gui/builtinViewColumns/state.py @@ -18,10 +18,13 @@ # ============================================================================= +# noinspection PyPackageRequirements import wx -from eos.types import Drone, Module, Rack, Fit, Implant -from eos.types import State as State_ +from eos.saveddata.fit import Fit +from eos.saveddata.implant import Implant +from eos.saveddata.drone import Drone +from eos.saveddata.module import Module, State as State_, Rack from gui.viewColumn import ViewColumn import gui.mainFrame diff --git a/gui/builtinViews/emptyView.py b/gui/builtinViews/emptyView.py index 0dc8d958e..ebf667726 100644 --- a/gui/builtinViews/emptyView.py +++ b/gui/builtinViews/emptyView.py @@ -1,6 +1,7 @@ +# noinspection PyPackageRequirements import wx import gui.globalEvents as GE -import gui.chromeTabs +from gui.chromeTabs import EVT_NOTEBOOK_PAGE_CHANGED import gui.mainFrame @@ -11,13 +12,13 @@ class BlankPage(wx.Panel): self.mainFrame = gui.mainFrame.MainFrame.getInstance() self.parent = parent - self.parent.Bind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged) + self.parent.Bind(EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged) self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=None)) def Destroy(self): - self.parent.Unbind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, handler=self.pageChanged) + self.parent.Unbind(EVT_NOTEBOOK_PAGE_CHANGED, handler=self.pageChanged) wx.Panel.Destroy(self) def pageChanged(self, event): diff --git a/gui/builtinViews/entityEditor.py b/gui/builtinViews/entityEditor.py index b77efe8a5..ecbe065c6 100644 --- a/gui/builtinViews/entityEditor.py +++ b/gui/builtinViews/entityEditor.py @@ -1,3 +1,4 @@ +# noinspection PyPackageRequirements import wx from gui.bitmapLoader import BitmapLoader diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index 3260ab116..0b64d9d53 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -17,7 +17,9 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx +# noinspection PyPackageRequirements import wx.lib.newevent import gui.mainFrame import gui.marketBrowser @@ -25,19 +27,21 @@ import gui.display as d from gui.contextMenu import ContextMenu import gui.shipBrowser import gui.multiSwitch -from eos.types import Slot, Rack, Module, Mode +from eos.saveddata.mode import Mode +from eos.saveddata.module import Module, Slot, Rack from gui.builtinViewColumns.state import State from gui.bitmapLoader import BitmapLoader import gui.builtinViews.emptyView from gui.utils.exportHtml import exportHtml -from logging import getLogger, Formatter +from logbook import Logger +from gui.chromeTabs import EVT_NOTEBOOK_PAGE_CHANGED from service.fit import Fit from service.market import Market import gui.globalEvents as GE -logger = getLogger(__name__) +pyfalog = Logger(__name__) # Tab spawning handler @@ -51,14 +55,16 @@ class FitSpawner(gui.multiSwitch.TabSpawner): def fitSelected(self, event): count = -1 for index, page in enumerate(self.multiSwitch.pages): - try: - if page.activeFitID == event.fitID: - count += 1 - self.multiSwitch.SetSelection(index) - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=event.fitID)) - break - except: - pass + if not isinstance(page, gui.builtinViews.emptyView.BlankPage): # Don't try and process it if it's a blank page. + try: + if page.activeFitID == event.fitID: + count += 1 + self.multiSwitch.SetSelection(index) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=event.fitID)) + break + except Exception as e: + pyfalog.critical("Caught exception in fitSelected") + pyfalog.critical(e) if count < 0: startup = getattr(event, "startup", False) # see OpenFitsThread in gui.mainFrame sFit = Fit.getInstance() @@ -96,8 +102,8 @@ FitSpawner.register() # Drag'n'drop handler class FittingViewDrop(wx.PyDropTarget): - def __init__(self, dropFn): - wx.PyDropTarget.__init__(self) + def __init__(self, dropFn, *args, **kwargs): + super(FittingViewDrop, self).__init__(*args, **kwargs) self.dropFn = dropFn # this is really transferring an EVE itemID self.dropData = wx.PyTextDataObject() @@ -144,7 +150,6 @@ class FittingView(d.Display): self.activeFitID = None self.FVsnapshot = None self.itemCount = 0 - self.itemRect = 0 self.hoveredRow = None self.hoveredColumn = None @@ -156,7 +161,7 @@ class FittingView(d.Display): self.Bind(wx.EVT_SHOW, self.OnShow) self.Bind(wx.EVT_MOTION, self.OnMouseMove) self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow) - self.parent.Bind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged) + self.parent.Bind(EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged) def OnLeaveWindow(self, event): self.SetToolTip(None) @@ -184,13 +189,13 @@ class FittingView(d.Display): event.Skip() def handleListDrag(self, x, y, data): - ''' + """ Handles dragging of items from various pyfa displays which support it data is list with two items: data[0] is hard-coded str of originating source data[1] is typeID or index of data we want to manipulate - ''' + """ if data[0] == "fitting": self.swapItems(x, y, int(data[1])) @@ -205,7 +210,7 @@ class FittingView(d.Display): wx.PostEvent(self.mainFrame, gui.shipBrowser.FitSelected(fitID=fitID)) def Destroy(self): - self.parent.Unbind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, handler=self.pageChanged) + self.parent.Unbind(EVT_NOTEBOOK_PAGE_CHANGED, handler=self.pageChanged) self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.fitChanged) self.mainFrame.Unbind(gui.shipBrowser.EVT_FIT_RENAMED, handler=self.fitRenamed) self.mainFrame.Unbind(gui.shipBrowser.EVT_FIT_REMOVED, handler=self.fitRemoved) @@ -258,11 +263,11 @@ class FittingView(d.Display): event.Skip() def fitRemoved(self, event): - ''' + """ If fit is removed and active, the page is deleted. We also refresh the fit of the new current page in case delete fit caused change in stats (projected) - ''' + """ fitID = event.fitID if fitID == self.getActiveFit(): @@ -274,6 +279,7 @@ class FittingView(d.Display): sFit.refreshFit(self.getActiveFit()) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.activeFitID)) except wx._core.PyDeadObjectError: + pyfalog.warning("Caught dead object") pass event.Skip() @@ -354,7 +360,7 @@ class FittingView(d.Display): wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.activeFitID)) def addModule(self, x, y, srcIdx): - '''Add a module from the market browser''' + """Add a module from the market browser""" dstRow, _ = self.HitTest((x, y)) if dstRow != -1 and dstRow not in self.blanks: @@ -367,7 +373,7 @@ class FittingView(d.Display): wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) def swapCargo(self, x, y, srcIdx): - '''Swap a module from cargo to fitting window''' + """Swap a module from cargo to fitting window""" mstate = wx.GetMouseState() dstRow, _ = self.HitTest((x, y)) @@ -381,7 +387,7 @@ class FittingView(d.Display): wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) def swapItems(self, x, y, srcIdx): - '''Swap two modules in fitting window''' + """Swap two modules in fitting window""" mstate = wx.GetMouseState() sFit = Fit.getInstance() fit = sFit.getFit(self.activeFitID) @@ -402,20 +408,23 @@ class FittingView(d.Display): if mod1.slot != mod2.slot: return - if clone and mod2.isEmpty: - sFit.cloneModule(self.mainFrame.getActiveFit(), srcIdx, mod2.modPosition) - else: - sFit.swapModules(self.mainFrame.getActiveFit(), srcIdx, mod2.modPosition) + if getattr(mod2, "modPosition") is not None: + if clone and mod2.isEmpty: + sFit.cloneModule(self.mainFrame.getActiveFit(), srcIdx, mod2.modPosition) + else: + sFit.swapModules(self.mainFrame.getActiveFit(), srcIdx, mod2.modPosition) - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) + else: + pyfalog.error("Missing module position for: {0}", str(getattr(mod2, "ID", "Unknown"))) def generateMods(self): - ''' + """ Generate module list. This also injects dummy modules to visually separate racks. These modules are only known to the display, and not the backend, so it's safe. - ''' + """ sFit = Fit.getInstance() fit = sFit.getFit(self.activeFitID) @@ -424,7 +433,7 @@ class FittingView(d.Display): if fit is not None: self.mods = fit.modules[:] - self.mods.sort(key=lambda mod: (slotOrder.index(mod.slot), mod.position)) + self.mods.sort(key=lambda _mod: (slotOrder.index(_mod.slot), _mod.position)) # Blanks is a list of indexes that mark non-module positions (such # as Racks and tactical Modes. This allows us to skip over common @@ -476,7 +485,7 @@ class FittingView(d.Display): self.Show(self.activeFitID is not None and self.activeFitID == event.fitID) except wx._core.PyDeadObjectError: - pass + pyfalog.warning("Caught dead object") finally: event.Skip() @@ -535,13 +544,13 @@ class FittingView(d.Display): self.PopupMenu(menu) def click(self, event): - ''' + """ Handle click event on modules. This is only useful for the State column. If multiple items are selected, and we have clicked the State column, iterate through the selections and change State - ''' + """ row, _, col = self.HitTestSubItem(event.Position) # only do State column and ignore invalid rows @@ -583,12 +592,12 @@ class FittingView(d.Display): return self.slotColourMap.get(slot) or self.GetBackgroundColour() def refresh(self, stuff): - ''' + """ Displays fitting Sends data to d.Display.refresh where the rows and columns are set up, then does a bit of post-processing (colors) - ''' + """ self.Freeze() d.Display.refresh(self, stuff) @@ -624,25 +633,27 @@ class FittingView(d.Display): self.Thaw() self.itemCount = self.GetItemCount() - self.itemRect = self.GetItemRect(0) if 'wxMac' in wx.PlatformInfo: try: self.MakeSnapshot() - except: - pass + except Exception as e: + pyfalog.critical("Failed to make snapshot") + pyfalog.critical(e) def OnShow(self, event): if event.GetShow(): try: self.MakeSnapshot() - except: - pass + except Exception as e: + pyfalog.critical("Failed to make snapshot") + pyfalog.critical(e) event.Skip() def Snapshot(self): return self.FVsnapshot + # noinspection PyPropertyAccess def MakeSnapshot(self, maxColumns=1337): if self.FVsnapshot: @@ -661,8 +672,9 @@ class FittingView(d.Display): sFit = Fit.getInstance() try: fit = sFit.getFit(self.activeFitID) - except: - return + except Exception as e: + pyfalog.critical("Failed to get fit") + pyfalog.critical(e) if fit is None: return @@ -676,7 +688,6 @@ class FittingView(d.Display): isize = 16 headerSize = max(isize, tdc.GetTextExtent("W")[0]) + padding * 2 - maxWidth = 0 maxRowHeight = isize rows = 0 for st in self.mods: @@ -740,7 +751,7 @@ class FittingView(d.Display): maxWidth += columnsWidths[i] mdc = wx.MemoryDC() - mbmp = wx.EmptyBitmap(maxWidth, (maxRowHeight) * rows + padding * 4 + headerSize) + mbmp = wx.EmptyBitmap(maxWidth, maxRowHeight * rows + padding * 4 + headerSize) mdc.SelectObject(mbmp) @@ -770,8 +781,7 @@ class FittingView(d.Display): bmp = col.bitmap opts.m_labelBitmap = bmp - width = render.DrawHeaderButton(self, mdc, (cx, padding, columnsWidths[i], headerSize), wx.CONTROL_CURRENT, - sortArrow=wx.HDR_SORT_ICON_NONE, params=opts) + render.DrawHeaderButton(self, mdc, (cx, padding, columnsWidths[i], headerSize), wx.CONTROL_CURRENT, sortArrow=wx.HDR_SORT_ICON_NONE, params=opts) cx += columnsWidths[i] diff --git a/gui/builtinViews/implantEditor.py b/gui/builtinViews/implantEditor.py index 8b56833df..bb9c125e7 100644 --- a/gui/builtinViews/implantEditor.py +++ b/gui/builtinViews/implantEditor.py @@ -1,4 +1,6 @@ +# noinspection PyPackageRequirements import wx +# noinspection PyPackageRequirements from wx.lib.buttons import GenBitmapButton from service.market import Market diff --git a/gui/cachingImageList.py b/gui/cachingImageList.py index 0762d1687..4bbef1e23 100644 --- a/gui/cachingImageList.py +++ b/gui/cachingImageList.py @@ -18,6 +18,7 @@ # ============================================================================= +# noinspection PyPackageRequirements import wx from gui.bitmapLoader import BitmapLoader diff --git a/gui/cargoView.py b/gui/cargoView.py index 6fe9e3c9e..d997afa79 100644 --- a/gui/cargoView.py +++ b/gui/cargoView.py @@ -17,6 +17,7 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx import gui.display as d from gui.builtinViewColumns.state import State @@ -27,8 +28,8 @@ from service.market import Market class CargoViewDrop(wx.PyDropTarget): - def __init__(self, dropFn): - wx.PyDropTarget.__init__(self) + def __init__(self, dropFn, *args, **kwargs): + super(CargoViewDrop, self).__init__(*args, **kwargs) self.dropFn = dropFn # this is really transferring an EVE itemID self.dropData = wx.PyTextDataObject() @@ -66,13 +67,13 @@ class CargoView(d.Display): self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu) def handleListDrag(self, x, y, data): - ''' + """ Handles dragging of items from various pyfa displays which support it data is list with two indices: data[0] is hard-coded str of originating source data[1] is typeID or index of data we want to manipulate - ''' + """ if data[0] == "fitting": self.swapModule(x, y, int(data[1])) @@ -104,7 +105,7 @@ class CargoView(d.Display): event.Skip() def swapModule(self, x, y, modIdx): - '''Swap a module from fitting window with cargo''' + """Swap a module from fitting window with cargo""" sFit = Fit.getInstance() fit = sFit.getFit(self.mainFrame.getActiveFit()) dstRow, _ = self.HitTest((x, y)) diff --git a/gui/characterEditor.py b/gui/characterEditor.py index 421ed8bbc..8006fa56a 100644 --- a/gui/characterEditor.py +++ b/gui/characterEditor.py @@ -17,9 +17,12 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx +# noinspection PyPackageRequirements import wx.lib.newevent +# noinspection PyPackageRequirements import wx.gizmos from gui.bitmapLoader import BitmapLoader from gui.contextMenu import ContextMenu @@ -30,6 +33,8 @@ from service.fit import Fit from service.character import Character from service.network import AuthenticationError, TimeoutError from service.market import Market +from logbook import Logger +pyfalog = Logger(__name__) class CharacterTextValidor(BaseValidator): @@ -52,6 +57,7 @@ class CharacterTextValidor(BaseValidator): return True except ValueError, e: + pyfalog.error(e) wx.MessageBox(u"{}".format(e), "Error") textCtrl.SetFocus() return False @@ -626,10 +632,15 @@ class APIView(wx.Panel): activeChar = self.charEditor.entityEditor.getActiveEntity() list = sChar.apiCharList(activeChar.ID, self.inputID.GetLineText(0), self.inputKey.GetLineText(0)) except AuthenticationError, e: - self.stStatus.SetLabel("Authentication failure. Please check keyID and vCode combination.") + msg = "Authentication failure. Please check keyID and vCode combination." + pyfalog.info(msg) + self.stStatus.SetLabel(msg) except TimeoutError, e: - self.stStatus.SetLabel("Request timed out. Please check network connectivity and/or proxy settings.") + msg = "Request timed out. Please check network connectivity and/or proxy settings." + pyfalog.info(msg) + self.stStatus.SetLabel(msg) except Exception, e: + pyfalog.error(e) self.stStatus.SetLabel("Error:\n%s" % e.message) else: self.charChoice.Clear() @@ -652,6 +663,7 @@ class APIView(wx.Panel): sChar.apiFetch(activeChar.ID, charName) self.stStatus.SetLabel("Successfully fetched %s\'s skills from EVE API." % charName) except Exception, e: + pyfalog.error("Unable to retrieve {0}\'s skills. Error message:\n{1}", charName, e) self.stStatus.SetLabel("Unable to retrieve %s\'s skills. Error message:\n%s" % (charName, e)) diff --git a/gui/characterSelection.py b/gui/characterSelection.py index b63f87475..3ee531d8f 100644 --- a/gui/characterSelection.py +++ b/gui/characterSelection.py @@ -17,12 +17,15 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from gui.bitmapLoader import BitmapLoader import gui.globalEvents as GE import gui.mainFrame from service.character import Character from service.fit import Fit +from logbook import Logger +pyfalog = Logger(__name__) class CharacterSelection(wx.Panel): @@ -111,9 +114,10 @@ class CharacterSelection(wx.Panel): if charName: try: sChar.apiFetch(self.getActiveCharacter(), charName) - except: + except Exception as e: # can we do a popup, notifying user of API error? - pass + pyfalog.error("API fetch error") + pyfalog.error(e) self.refreshCharacterList() def charChanged(self, event): diff --git a/gui/chromeTabs.py b/gui/chromeTabs.py index 00998eb87..89ad9327b 100644 --- a/gui/chromeTabs.py +++ b/gui/chromeTabs.py @@ -17,15 +17,19 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx +# noinspection PyPackageRequirements import wx.lib.newevent import gui.utils.colorUtils as colorUtils import gui.utils.drawUtils as drawUtils import gui.utils.fonts as fonts from gui.bitmapLoader import BitmapLoader - +from logbook import Logger from service.fit import Fit +pyfalog = Logger(__name__) + _PageChanging, EVT_NOTEBOOK_PAGE_CHANGING = wx.lib.newevent.NewEvent() _PageChanged, EVT_NOTEBOOK_PAGE_CHANGED = wx.lib.newevent.NewEvent() _PageAdding, EVT_NOTEBOOK_PAGE_ADDING = wx.lib.newevent.NewEvent() @@ -34,7 +38,7 @@ PageAdded, EVT_NOTEBOOK_PAGE_ADDED = wx.lib.newevent.NewEvent() PageClosed, EVT_NOTEBOOK_PAGE_CLOSED = wx.lib.newevent.NewEvent() -class VetoAble(): +class VetoAble(object): def __init__(self): self.__vetoed = False @@ -45,7 +49,7 @@ class VetoAble(): return self.__vetoed -class NotebookTabChangeEvent(): +class NotebookTabChangeEvent(object): def __init__(self, old, new): self.__old = old self.__new = new @@ -146,7 +150,8 @@ class PFNotebook(wx.Panel): if self.activePage == page: self.ShowActive() - def GetBorders(self): + @staticmethod + def GetBorders(): """Gets border widths to better determine page size in ShowActive()""" bx = wx.SystemSettings_GetMetric(wx.SYS_BORDER_X) @@ -335,7 +340,7 @@ class PFNotebook(wx.Panel): event.Skip() -class PFTabRenderer: +class PFTabRenderer(object): def __init__(self, size=(36, 24), text=wx.EmptyString, img=None, inclination=6, closeButton=True): """ Renders a new tab @@ -438,7 +443,8 @@ class PFTabRenderer: def SetTabImage(self, img): self.tabImg = img - def CopyRegion(self, region): + @staticmethod + def CopyRegion(region): rect = region.GetBox() newRegion = wx.Region(rect.X, rect.Y, rect.Width, rect.Height) @@ -527,8 +533,8 @@ class PFTabRenderer: self.tabRegion = wx.RegionFromBitmap(self.tabBackBitmap) self.closeBtnRegion = wx.RegionFromBitmap(self.ctabCloseBmp) self.closeBtnRegion.Offset( - self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth() / 2, - (self.tabHeight - self.ctabCloseBmp.GetHeight()) / 2 + self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth() / 2, + (self.tabHeight - self.ctabCloseBmp.GetHeight()) / 2 ) def InitColors(self): @@ -591,9 +597,9 @@ class PFTabRenderer: cbmp = wx.BitmapFromImage(cimg) mdc.DrawBitmap( - cbmp, - self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth() / 2, - (height - self.ctabCloseBmp.GetHeight()) / 2, + cbmp, + self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth() / 2, + (height - self.ctabCloseBmp.GetHeight()) / 2, ) mdc.SelectObject(wx.NullBitmap) @@ -609,11 +615,11 @@ class PFTabRenderer: def __repr__(self): return "PFTabRenderer(text={}, disabled={}) at {}".format( - self.text, self.disabled, hex(id(self)) + self.text, self.disabled, hex(id(self)) ) -class PFAddRenderer: +class PFAddRenderer(object): def __init__(self): """Renders the add tab button""" self.addImg = BitmapLoader.getImage("ctabadd", "gui") @@ -652,7 +658,8 @@ class PFAddRenderer: region = wx.RegionFromBitmap(self.tbmp) return region - def CopyRegion(self, region): + @staticmethod + def CopyRegion(region): rect = region.GetBox() newRegion = wx.Region(rect.X, rect.Y, rect.Width, rect.Height) @@ -973,7 +980,8 @@ class PFTabsContainer(wx.Panel): return tab return None - def TabHitTest(self, tab, x, y): + @staticmethod + def TabHitTest(tab, x, y): tabRegion = tab.GetTabRegion() tabPos = tab.GetPosition() tabPosX, tabPosY = tabPos @@ -1087,8 +1095,9 @@ class PFTabsContainer(wx.Panel): self.previewTab = tab self.previewTimer.Start(500, True) break - except: - pass + except Exception as e: + pyfalog.critical("Exception caught in CheckTabPreview.") + pyfalog.critical(e) def CheckAddHighlighted(self, x, y): """ @@ -1117,13 +1126,13 @@ class PFTabsContainer(wx.Panel): else: mdc = wx.BufferedPaintDC(self) - selected = 0 - if 'wxMac' in wx.PlatformInfo and wx.VERSION < (3, 0): color = wx.Colour(0, 0, 0) brush = wx.Brush(color) + # noinspection PyPackageRequirements,PyUnresolvedReferences,PyUnresolvedReferences,PyUnresolvedReferences from Carbon.Appearance import kThemeBrushDialogBackgroundActive + # noinspection PyUnresolvedReferences brush.MacSetTheme(kThemeBrushDialogBackgroundActive) else: color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE) @@ -1253,7 +1262,7 @@ class PFTabsContainer(wx.Panel): if self.tabMinWidth < 1: self.tabMinWidth = 1 for tab in self.tabs: - w, h = tab.GetSize() + tab.GetSize() tab.SetSize((self.tabMinWidth, self.height)) if self.GetTabsCount() > 0: @@ -1268,6 +1277,7 @@ class PFTabsContainer(wx.Panel): pos = tabsWidth selected = None + selpos = None for i in range(len(self.tabs) - 1, -1, -1): tab = self.tabs[i] width = tab.tabWidth - self.inclination * 2 diff --git a/gui/commandView.py b/gui/commandView.py index 20a7a33a9..38dec46c9 100644 --- a/gui/commandView.py +++ b/gui/commandView.py @@ -17,6 +17,7 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx import gui.display as d import gui.globalEvents as GE @@ -28,20 +29,20 @@ from service.fit import Fit from eos.saveddata.drone import Drone as es_Drone -class DummyItem: +class DummyItem(object): def __init__(self, txt): self.name = txt self.icon = None -class DummyEntry: +class DummyEntry(object): def __init__(self, txt): self.item = DummyItem(txt) class CommandViewDrop(wx.PyDropTarget): - def __init__(self, dropFn): - wx.PyDropTarget.__init__(self) + def __init__(self, dropFn, *args, **kwargs): + super(CommandViewDrop, self).__init__(*args, **kwargs) self.dropFn = dropFn # this is really transferring an EVE itemID self.dropData = wx.PyTextDataObject() @@ -78,14 +79,15 @@ class CommandView(d.Display): self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag) self.SetDropTarget(CommandViewDrop(self.handleListDrag)) - def handleListDrag(self, x, y, data): - ''' + @staticmethod + def handleListDrag(x, y, data): + """ Handles dragging of items from various pyfa displays which support it data is list with two indices: data[0] is hard-coded str of originating source data[1] is typeID or index of data we want to manipulate - ''' + """ pass def kbEvent(self, event): @@ -118,7 +120,8 @@ class CommandView(d.Display): dropSource.SetData(data) dropSource.DoDragDrop() - def fitSort(self, fit): + @staticmethod + def fitSort(fit): return fit.name def fitChanged(self, event): @@ -151,7 +154,7 @@ class CommandView(d.Display): self.deselectItems() # todo: verify - if stuff == []: + if not stuff: stuff = [DummyEntry("Drag a fit to this area")] self.update(stuff) @@ -159,7 +162,7 @@ class CommandView(d.Display): def get(self, row): numFits = len(self.fits) - if (numFits) == 0: + if numFits == 0: return None return self.fits[row] @@ -191,7 +194,7 @@ class CommandView(d.Display): fitSrcContext = "commandFit" fitItemContext = item.name context = ((fitSrcContext, fitItemContext),) - context = context + (("command",),) + context += ("command",), menu = ContextMenu.getMenu((item,), *context) elif sel == -1: fitID = self.mainFrame.getActiveFit() diff --git a/gui/contextMenu.py b/gui/contextMenu.py index 520ad8065..a35c73282 100644 --- a/gui/contextMenu.py +++ b/gui/contextMenu.py @@ -17,10 +17,11 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx -import logging +from logbook import Logger -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class ContextMenu(object): @@ -58,7 +59,7 @@ class ContextMenu(object): rootMenu.selection = (selection,) if not hasattr(selection, "__iter__") else selection empty = True for i, fullContext in enumerate(fullContexts): - amount = 0 + display_amount = 0 srcContext = fullContext[0] try: itemContext = fullContext[1] @@ -68,7 +69,7 @@ class ContextMenu(object): # loop through registered menus m = menuHandler() if m.display(srcContext, selection): - amount += 1 + display_amount += 1 texts = m.getText(itemContext, selection) if isinstance(texts, basestring): @@ -115,12 +116,12 @@ class ContextMenu(object): empty = False - if amount > 0 and i != len(fullContexts) - 1: + if display_amount > 0 and i != len(fullContexts) - 1: rootMenu.AppendSeparator() debug_end = len(cls._ids) - if (debug_end - debug_start): - logger.debug("%d new IDs created for this menu" % (debug_end - debug_start)) + if debug_end - debug_start: + pyfalog.debug("{0} new IDs created for this menu", (debug_end - debug_start)) return rootMenu if empty is False else None @@ -177,4 +178,31 @@ class ContextMenu(object): return None -from gui.builtinContextMenus import * # noqa +# noinspection PyUnresolvedReferences +from gui.builtinContextMenus import ( # noqa: E402,F401 + openFit, + moduleGlobalAmmoPicker, + moduleAmmoPicker, + itemStats, + damagePattern, + marketJump, + droneSplit, + itemRemove, + droneRemoveStack, + ammoPattern, + project, + factorReload, + whProjector, + cargo, + shipJump, + changeAffectingSkills, + tacticalMode, + targetResists, + priceClear, + amount, + cargoAmmo, + droneStack, + metaSwap, + implantSets, + fighterAbilities, +) diff --git a/gui/copySelectDialog.py b/gui/copySelectDialog.py index bb5a6e601..57ce48f47 100644 --- a/gui/copySelectDialog.py +++ b/gui/copySelectDialog.py @@ -18,6 +18,7 @@ # ============================================================================= +# noinspection PyPackageRequirements import wx @@ -53,7 +54,7 @@ class CopySelectDialog(wx.Dialog): mainSizer.Add(selector, 0, wx.EXPAND | wx.ALL, 5) buttonSizer = self.CreateButtonSizer(wx.OK | wx.CANCEL) - if (buttonSizer): + if buttonSizer: mainSizer.Add(buttonSizer, 0, wx.EXPAND | wx.ALL, 5) self.SetSizer(mainSizer) diff --git a/gui/crestFittings.py b/gui/crestFittings.py index 6b62f3d5e..0f1911206 100644 --- a/gui/crestFittings.py +++ b/gui/crestFittings.py @@ -1,18 +1,22 @@ import time import webbrowser import json +# noinspection PyPackageRequirements import wx import requests from service.port import Port from service.fit import Fit -from eos.types import Cargo +from eos.saveddata.cargo import Cargo from eos.db import getItem -import gui.display as d +from gui.display import Display import gui.globalEvents as GE +from logbook import Logger +pyfalog = Logger(__name__) + if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)): from service.crest import Crest, CrestModes @@ -144,10 +148,11 @@ class CrestFittings(wx.Frame): self.updateCacheStatus(None) self.cacheTimer.Start(1000) self.fitTree.populateSkillTree(fittings) - except requests.exceptions.ConnectionError: - self.statusbar.SetStatusText("Connection error, please check your internet connection") - finally: del waitDialog + except requests.exceptions.ConnectionError: + msg = "Connection error, please check your internet connection" + pyfalog.error(msg) + self.statusbar.SetStatusText(msg) def importFitting(self, event): selection = self.fitView.fitSelection @@ -173,7 +178,9 @@ class CrestFittings(wx.Frame): try: sCrest.delFitting(self.getActiveCharacter(), data['fittingID']) except requests.exceptions.ConnectionError: - self.statusbar.SetStatusText("Connection error, please check your internet connection") + msg = "Connection error, please check your internet connection" + pyfalog.error(msg) + self.statusbar.SetStatusText(msg) class ExportToEve(wx.Frame): @@ -281,9 +288,12 @@ class ExportToEve(wx.Frame): text = json.loads(res.text) self.statusbar.SetStatusText(text['message'], 1) except ValueError: + pyfalog.warning("Value error on loading JSON.") self.statusbar.SetStatusText("", 1) except requests.exceptions.ConnectionError: - self.statusbar.SetStatusText("Connection error, please check your internet connection", 1) + msg = "Connection error, please check your internet connection" + pyfalog.error(msg) + self.statusbar.SetStatusText(msg) class CrestMgmt(wx.Dialog): @@ -340,7 +350,8 @@ class CrestMgmt(wx.Dialog): self.lcCharacters.SetColumnWidth(0, wx.LIST_AUTOSIZE) self.lcCharacters.SetColumnWidth(1, wx.LIST_AUTOSIZE) - def addChar(self, event): + @staticmethod + def addChar(event): sCrest = Crest.getInstance() uri = sCrest.startServer() webbrowser.open(uri) @@ -404,17 +415,18 @@ class FittingsTreeView(wx.Panel): cargo = Cargo(getItem(item['type']['id'])) cargo.amount = item['quantity'] list.append(cargo) - except: - pass + except Exception as e: + pyfalog.critical("Exception caught in displayFit") + pyfalog.critical(e) self.parent.fitView.fitSelection = selection self.parent.fitView.update(list) -class FitView(d.Display): +class FitView(Display): DEFAULT_COLS = ["Base Icon", "Base Name"] def __init__(self, parent): - d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL) + Display.__init__(self, parent, style=wx.LC_SINGLE_SEL) self.fitSelection = None diff --git a/gui/display.py b/gui/display.py index 0d9e0308f..2ae83aa44 100644 --- a/gui/display.py +++ b/gui/display.py @@ -18,6 +18,7 @@ # ============================================================================= import sys +# noinspection PyPackageRequirements import wx import gui.mainFrame from gui.viewColumn import ViewColumn @@ -25,6 +26,8 @@ from gui.cachingImageList import CachingImageList class Display(wx.ListCtrl): + DEFAULT_COLS = None + def __init__(self, parent, size=wx.DefaultSize, style=0): wx.ListCtrl.__init__(self, parent, size=size, style=wx.LC_REPORT | style) @@ -64,6 +67,7 @@ class Display(wx.ListCtrl): i += 1 info = wx.ListItem() + # noinspection PyPropertyAccess info.m_mask = wx.LIST_MASK_WIDTH self.InsertColumnInfo(i, info) self.SetColumnWidth(i, 0) @@ -88,11 +92,11 @@ class Display(wx.ListCtrl): # Did the point hit any item? if (flags & wx.LIST_HITTEST_ONITEM) == 0: - return (-1, 0, -1) + return -1, 0, -1 # If it did hit an item and we are not in report mode, it must be the primary cell if not self.InReportView(): - return (rowIndex, wx.LIST_HITTEST_ONITEM, 0) + return rowIndex, wx.LIST_HITTEST_ONITEM, 0 # Find which subitem is hit right = 0 @@ -105,9 +109,9 @@ class Display(wx.ListCtrl): flag = wx.LIST_HITTEST_ONITEMICON else: flag = wx.LIST_HITTEST_ONITEMLABEL - return (rowIndex, flag, i) + return rowIndex, flag, i - return (rowIndex, 0, -1) + return rowIndex, 0, -1 def OnEraseBk(self, event): if self.GetItemCount() > 0: @@ -143,6 +147,7 @@ class Display(wx.ListCtrl): else: event.Skip() + # noinspection PyPropertyAccess def addColumn(self, i, col): self.activeColumns.append(col) info = wx.ListItem() @@ -217,7 +222,7 @@ class Display(wx.ListCtrl): self.InsertStringItem(sys.maxint, "") if listItemCount > stuffItemCount: - if listItemCount - stuffItemCount > 20 and stuffItemCount < 20: + if listItemCount - stuffItemCount > 20 > stuffItemCount: self.DeleteAllItems() for i in range(stuffItemCount): self.InsertStringItem(sys.maxint, "") diff --git a/gui/droneView.py b/gui/droneView.py index 4d389e8ea..e506c278d 100644 --- a/gui/droneView.py +++ b/gui/droneView.py @@ -17,11 +17,12 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx import gui.globalEvents as GE -import gui.marketBrowser as mb -import gui.display as d +from gui.marketBrowser import ITEM_SELECTED, ItemSelected +from gui.display import Display from gui.builtinViewColumns.state import State from gui.contextMenu import ContextMenu from service.fit import Fit @@ -29,8 +30,8 @@ from service.market import Market class DroneViewDrop(wx.PyDropTarget): - def __init__(self, dropFn): - wx.PyDropTarget.__init__(self) + def __init__(self, dropFn, *args, **kwargs): + super(DroneViewDrop, self).__init__(*args, **kwargs) self.dropFn = dropFn # this is really transferring an EVE itemID self.dropData = wx.PyTextDataObject() @@ -43,7 +44,7 @@ class DroneViewDrop(wx.PyDropTarget): return t -class DroneView(d.Display): +class DroneView(Display): DEFAULT_COLS = [ "State", # "Base Icon", @@ -56,7 +57,7 @@ class DroneView(d.Display): ] def __init__(self, parent): - d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE) + Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE) self.lastFitId = None @@ -64,7 +65,7 @@ class DroneView(d.Display): self.hoveredColumn = None self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged) - self.mainFrame.Bind(mb.ITEM_SELECTED, self.addItem) + self.mainFrame.Bind(ITEM_SELECTED, self.addItem) self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem) self.Bind(wx.EVT_LEFT_DOWN, self.click) self.Bind(wx.EVT_KEY_UP, self.kbEvent) @@ -128,24 +129,25 @@ class DroneView(d.Display): dropSource.DoDragDrop() def handleDragDrop(self, x, y, data): - ''' + """ Handles dragging of items from various pyfa displays which support it data is list with two indices: data[0] is hard-coded str of originating source data[1] is typeID or index of data we want to manipulate - ''' + """ if data[0] == "drone": # we want to merge drones srcRow = int(data[1]) dstRow, _ = self.HitTest((x, y)) if srcRow != -1 and dstRow != -1: self._merge(srcRow, dstRow) elif data[0] == "market": - wx.PostEvent(self.mainFrame, mb.ItemSelected(itemID=int(data[1]))) + wx.PostEvent(self.mainFrame, ItemSelected(itemID=int(data[1]))) def _merge(self, src, dst): sFit = Fit.getInstance() fitID = self.mainFrame.getActiveFit() + if sFit.mergeDrones(fitID, self.drones[src], self.drones[dst]): wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) diff --git a/gui/errorDialog.py b/gui/errorDialog.py new file mode 100644 index 000000000..469eb9e63 --- /dev/null +++ b/gui/errorDialog.py @@ -0,0 +1,94 @@ +# =============================================================================== +# Copyright (C) 2010 Diego Duclos +# +# This file is part of pyfa. +# +# pyfa is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# pyfa is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with pyfa. If not, see . +# =============================================================================== + +import wx +import sys +import gui.utils.fonts as fonts +import config + + +class ErrorFrame(wx.Frame): + + def __init__(self, exception, tb): + wx.Frame.__init__(self, None, id=wx.ID_ANY, title="pyfa error", pos=wx.DefaultPosition, size=wx.Size(500, 400), + style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER | wx.STAY_ON_TOP) + + desc = "pyfa has experienced an unexpected error. Below is the " \ + "Traceback that contains crucial information about how this " \ + "error was triggered. Please contact the developers with " \ + "the information provided through the EVE Online forums " \ + "or file a GitHub issue." + + self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize) + + if 'wxMSW' in wx.PlatformInfo: + self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)) + + mainSizer = wx.BoxSizer(wx.VERTICAL) + headSizer = wx.BoxSizer(wx.HORIZONTAL) + + self.headingText = wx.StaticText(self, wx.ID_ANY, "Error!", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_CENTRE) + self.headingText.SetFont(wx.Font(14, 74, 90, 92, False)) + + headSizer.Add(self.headingText, 1, wx.ALL, 5) + mainSizer.Add(headSizer, 0, wx.EXPAND, 5) + + mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0, wx.EXPAND | wx.ALL, 5) + + descSizer = wx.BoxSizer(wx.HORIZONTAL) + self.descText = wx.TextCtrl(self, wx.ID_ANY, desc, wx.DefaultPosition, wx.DefaultSize, + wx.TE_AUTO_URL | wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE | wx.TRANSPARENT_WINDOW) + self.descText.SetFont(wx.Font(fonts.BIG, wx.SWISS, wx.NORMAL, wx.NORMAL)) + descSizer.Add(self.descText, 1, wx.ALL, 5) + mainSizer.Add(descSizer, 1, wx.EXPAND, 5) + + self.eveForums = wx.HyperlinkCtrl(self, wx.ID_ANY, "EVE Forums Thread", "https://forums.eveonline.com/default.aspx?g=posts&t=466425", + wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE) + + mainSizer.Add(self.eveForums, 0, wx.ALL, 2) + + self.eveForums = wx.HyperlinkCtrl(self, wx.ID_ANY, "Github Issues", "https://github.com/pyfa-org/Pyfa/issues", + wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE) + + mainSizer.Add(self.eveForums, 0, wx.ALL, 2) + + # mainSizer.AddSpacer((0, 5), 0, wx.EXPAND, 5) + + self.errorTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition, wx.DefaultSize, wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH2 | wx.TE_DONTWRAP) + self.errorTextCtrl.SetFont(wx.Font(8, wx.FONTFAMILY_TELETYPE, wx.NORMAL, wx.NORMAL)) + mainSizer.Add(self.errorTextCtrl, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + self.errorTextCtrl.AppendText("pyfa root: ") + self.errorTextCtrl.AppendText(config.pyfaPath or "Unknown") + self.errorTextCtrl.AppendText('\n') + self.errorTextCtrl.AppendText("save path: ") + self.errorTextCtrl.AppendText(config.savePath or "Unknown") + self.errorTextCtrl.AppendText('\n') + self.errorTextCtrl.AppendText("fs encoding: ") + self.errorTextCtrl.AppendText(sys.getfilesystemencoding()) + self.errorTextCtrl.AppendText('\n\n') + self.errorTextCtrl.AppendText(tb) + + self.SetSizer(mainSizer) + mainSizer.Layout() + self.Layout() + + self.Centre(wx.BOTH) + + self.Show() diff --git a/gui/fighterView.py b/gui/fighterView.py index 083901460..6332817fe 100644 --- a/gui/fighterView.py +++ b/gui/fighterView.py @@ -17,22 +17,23 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx import gui.globalEvents as GE -import gui.marketBrowser as mb +import gui.marketBrowser as marketBrowser import gui.mainFrame import gui.display as d from gui.builtinViewColumns.state import State -from eos.types import Slot +from eos.saveddata.module import Slot from gui.contextMenu import ContextMenu from service.fit import Fit from service.market import Market class FighterViewDrop(wx.PyDropTarget): - def __init__(self, dropFn): - wx.PyDropTarget.__init__(self) + def __init__(self, dropFn, *args, **kwargs): + super(FighterViewDrop, self).__init__(*args, **kwargs) self.dropFn = dropFn # this is really transferring an EVE itemID self.dropData = wx.PyTextDataObject() @@ -126,7 +127,7 @@ class FighterDisplay(d.Display): self.hoveredColumn = None self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged) - self.mainFrame.Bind(mb.ITEM_SELECTED, self.addItem) + self.mainFrame.Bind(marketBrowser.ITEM_SELECTED, self.addItem) self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem) self.Bind(wx.EVT_LEFT_DOWN, self.click) self.Bind(wx.EVT_KEY_UP, self.kbEvent) @@ -190,22 +191,23 @@ class FighterDisplay(d.Display): dropSource.DoDragDrop() def handleDragDrop(self, x, y, data): - ''' + """ Handles dragging of items from various pyfa displays which support it data is list with two indices: data[0] is hard-coded str of originating source data[1] is typeID or index of data we want to manipulate - ''' + """ if data[0] == "fighter": # we want to merge fighters srcRow = int(data[1]) dstRow, _ = self.HitTest((x, y)) if srcRow != -1 and dstRow != -1: self._merge(srcRow, dstRow) elif data[0] == "market": - wx.PostEvent(self.mainFrame, mb.ItemSelected(itemID=int(data[1]))) + wx.PostEvent(self.mainFrame, marketBrowser.ItemSelected(itemID=int(data[1]))) - def _merge(self, src, dst): + @staticmethod + def _merge(src, dst): return ''' diff --git a/gui/globalEvents.py b/gui/globalEvents.py index 18f91d348..1c1cc7e38 100644 --- a/gui/globalEvents.py +++ b/gui/globalEvents.py @@ -1,3 +1,4 @@ +# noinspection PyPackageRequirements import wx.lib.newevent FitChanged, FIT_CHANGED = wx.lib.newevent.NewEvent() diff --git a/gui/graph.py b/gui/graph.py index 720e10cb8..a2b2239de 100644 --- a/gui/graph.py +++ b/gui/graph.py @@ -35,4 +35,5 @@ class Graph(object): return None -from gui.builtinGraphs import * # noqa +# noinspection PyUnresolvedReferences +from gui.builtinGraphs import fitDps # noqa: E402, F401 diff --git a/gui/graphFrame.py b/gui/graphFrame.py index 7b56c0ed0..2abeadbab 100644 --- a/gui/graphFrame.py +++ b/gui/graphFrame.py @@ -18,9 +18,9 @@ # ============================================================================= import os -import logging -import imp +from logbook import Logger +# noinspection PyPackageRequirements import wx from service.fit import Fit @@ -29,39 +29,53 @@ import gui.mainFrame import gui.globalEvents as GE from gui.graph import Graph from gui.bitmapLoader import BitmapLoader -from config import parsePath +import traceback + +pyfalog = Logger(__name__) -# Don't actually import the thing, since it takes for fucking ever try: - imp.find_module('matplotlib') - enabled = True -except ImportError: - enabled = False + import matplotlib as mpl -mplImported = False + mpl_version = int(mpl.__version__[0]) or -1 + if mpl_version >= 2: + mpl.use('wxagg') + mplImported = True + else: + mplImported = False + from matplotlib.patches import Patch -logger = logging.getLogger(__name__) -if not enabled: - logger.info("Problems importing matplotlib; continuing without graphs") + from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas + from matplotlib.figure import Figure + + graphFrame_enabled = True + mplImported = True +except ImportError as e: + pyfalog.warning("Matplotlib failed to import. Likely missing or incompatible version.") + mpl_version = -1 + Patch = mpl = Canvas = Figure = None + graphFrame_enabled = False + mplImported = False +except Exception: + # We can get exceptions deep within matplotlib. Catch those. See GH #1046 + tb = traceback.format_exc() + pyfalog.critical("Exception when importing Matplotlib. Continuing without importing.") + pyfalog.critical(tb) + mpl_version = -1 + Patch = mpl = Canvas = Figure = None + graphFrame_enabled = False + mplImported = False class GraphFrame(wx.Frame): def __init__(self, parent, style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT): - - global enabled + global graphFrame_enabled global mplImported - - # Import here - try: - import matplotlib as mpl - from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas - from matplotlib.figure import Figure - enabled = True - except ImportError: - enabled = False + global mpl_version self.legendFix = False - if not enabled: + + if not graphFrame_enabled: + pyfalog.warning("Matplotlib is not enabled. Skipping initialization.") return try: @@ -69,7 +83,7 @@ class GraphFrame(wx.Frame): except: cache_dir = os.path.expanduser(os.path.join("~", ".matplotlib")) - cache_file = parsePath(cache_dir, 'fontList.cache') + cache_file = os.path.join(cache_dir, 'fontList.cache') if os.access(cache_dir, os.W_OK | os.X_OK) and os.path.isfile(cache_file): # remove matplotlib font cache, see #234 @@ -77,8 +91,8 @@ class GraphFrame(wx.Frame): if not mplImported: mpl.use('wxagg') - enabled = True - if mpl.__version__[0] != "1": + graphFrame_enabled = True + if int(mpl.__version__[0]) < 1: print("pyfa: Found matplotlib version ", mpl.__version__, " - activating OVER9000 workarounds") print("pyfa: Recommended minimum matplotlib version is 1.0.0") self.legendFix = True @@ -213,6 +227,8 @@ class GraphFrame(wx.Frame): self.draw() def draw(self, event=None): + global mpl_version + values = self.getValues() view = self.getView() self.subplot.clear() @@ -232,25 +248,54 @@ class GraphFrame(wx.Frame): self.subplot.plot(x, y) legend.append(fit.name) except: + pyfalog.warning("Invalid values in '{0}'", fit.name) self.SetStatusText("Invalid values in '%s'" % fit.name) self.canvas.draw() return - if self.legendFix and len(legend) > 0: - leg = self.subplot.legend(tuple(legend), "upper right", shadow=False) - for t in leg.get_texts(): - t.set_fontsize('small') + if mpl_version < 2: + if self.legendFix and len(legend) > 0: + leg = self.subplot.legend(tuple(legend), "upper right", shadow=False) + for t in leg.get_texts(): + t.set_fontsize('small') - for l in leg.get_lines(): - l.set_linewidth(1) + for l in leg.get_lines(): + l.set_linewidth(1) - elif not self.legendFix and len(legend) > 0: - leg = self.subplot.legend(tuple(legend), "upper right", shadow=False, frameon=False) - for t in leg.get_texts(): - t.set_fontsize('small') + elif not self.legendFix and len(legend) > 0: + leg = self.subplot.legend(tuple(legend), "upper right", shadow=False, frameon=False) + for t in leg.get_texts(): + t.set_fontsize('small') - for l in leg.get_lines(): - l.set_linewidth(1) + for l in leg.get_lines(): + l.set_linewidth(1) + elif mpl_version >= 2: + legend2 = [] + legend_colors = { + 0: "blue", + 1: "orange", + 2: "green", + 3: "red", + 4: "purple", + 5: "brown", + 6: "pink", + 7: "grey", + } + + for i, i_name in enumerate(legend): + try: + selected_color = legend_colors[i] + except: + selected_color = None + legend2.append(Patch(color=selected_color, label=i_name), ) + + if len(legend2) > 0: + leg = self.subplot.legend(handles=legend2) + for t in leg.get_texts(): + t.set_fontsize('small') + + for l in leg.get_lines(): + l.set_linewidth(1) self.canvas.draw() self.SetStatusText("") diff --git a/gui/implantView.py b/gui/implantView.py index 3de27f1bc..86b9afd96 100644 --- a/gui/implantView.py +++ b/gui/implantView.py @@ -17,14 +17,15 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx import gui.display as d -import gui.marketBrowser as mb +import gui.marketBrowser as marketBrowser import gui.mainFrame from gui.builtinViewColumns.state import State from gui.contextMenu import ContextMenu import globalEvents as GE -from eos.types import ImplantLocation +from eos.saveddata.fit import ImplantLocation from service.fit import Fit from service.market import Market @@ -89,7 +90,7 @@ class ImplantDisplay(d.Display): self.lastFitId = None self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged) - self.mainFrame.Bind(mb.ITEM_SELECTED, self.addItem) + self.mainFrame.Bind(marketBrowser.ITEM_SELECTED, self.addItem) self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem) self.Bind(wx.EVT_LEFT_DOWN, self.click) self.Bind(wx.EVT_KEY_UP, self.kbEvent) diff --git a/gui/itemStats.py b/gui/itemStats.py index 97adfb32d..325793e86 100644 --- a/gui/itemStats.py +++ b/gui/itemStats.py @@ -23,12 +23,24 @@ import csv import sys import subprocess +# noinspection PyPackageRequirements import wx +# noinspection PyPackageRequirements import wx.html +# noinspection PyPackageRequirements import wx.lib.mixins.listctrl as listmix import config -from eos.types import Fit, Ship, Citadel, Module, Skill, Booster, Implant, Drone, Mode, Fighter +from eos.saveddata.mode import Mode +from eos.saveddata.character import Skill +from eos.saveddata.implant import Implant +from eos.saveddata.booster import Booster +from eos.saveddata.drone import Drone +from eos.saveddata.fighter import Fighter +from eos.saveddata.module import Module +from eos.saveddata.ship import Ship +from eos.saveddata.citadel import Citadel +from eos.saveddata.fit import Fit from service.market import Market from service.attribute import Attribute import gui.mainFrame @@ -50,13 +62,13 @@ class ItemStatsDialog(wx.Dialog): ): wx.Dialog.__init__( - self, - gui.mainFrame.MainFrame.getInstance(), - wx.ID_ANY, - title="Item stats", - pos=pos, - size=size, - style=wx.CAPTION | wx.CLOSE_BOX | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU + self, + gui.mainFrame.MainFrame.getInstance(), + wx.ID_ANY, + title="Item stats", + pos=pos, + size=size, + style=wx.CAPTION | wx.CLOSE_BOX | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU ) empty = getattr(victim, "isEmpty", False) @@ -185,6 +197,10 @@ class ItemStatsContainer(wx.Panel): self.affectedby = ItemAffectedBy(self.nbContainer, stuff, item) self.nbContainer.AddPage(self.affectedby, "Affected by") + if config.debug: + self.properties = ItemProperties(self.nbContainer, stuff, item, context) + self.nbContainer.AddPage(self.properties, "Properties") + self.nbContainer.Bind(wx.EVT_LEFT_DOWN, self.mouseHit) self.SetSizer(mainSizer) self.Layout() @@ -244,7 +260,7 @@ class ItemDescription(wx.Panel): # Strip URLs desc = re.sub("<( *)a(.*?)>(?P.*?)<( *)/( *)a( *)>", "\g", desc) desc = "" + desc + "" + wx.C2S_HTML_SYNTAX) + "' >" + desc + "" self.description.SetPage(desc) @@ -346,13 +362,13 @@ class ItemParams(wx.Panel): writer = csv.writer(exportFile, delimiter=',') writer.writerow( - [ - "ID", - "Internal Name", - "Friendly Name", - "Modified Value", - "Base Value", - ] + [ + "ID", + "Internal Name", + "Friendly Name", + "Modified Value", + "Base Value", + ] ) for attribute in self.attrValues: @@ -383,13 +399,13 @@ class ItemParams(wx.Panel): attribute_modified_value = self.attrValues[attribute] writer.writerow( - [ - attribute_id, - attribute_name, - attribute_displayname, - attribute_modified_value, - attribute_value, - ] + [ + attribute_id, + attribute_name, + attribute_displayname, + attribute_modified_value, + attribute_value, + ] ) def PopulateList(self): @@ -470,7 +486,8 @@ class ItemParams(wx.Panel): self.totalAttrsLabel.SetLabel("%d attributes. " % idCount) self.Layout() - def TranslateValueUnit(self, value, unitName, unitDisplayName): + @staticmethod + def TranslateValueUnit(value, unitName, unitDisplayName): def itemIDCallback(): item = Market.getInstance().getItem(value) return "%s (%d)" % (item.name, value) if item is not None else str(value) @@ -483,17 +500,19 @@ class ItemParams(wx.Panel): attribute = Attribute.getInstance().getAttributeInfo(value) return "%s (%d)" % (attribute.name.capitalize(), value) - trans = {"Inverse Absolute Percent": (lambda: (1 - value) * 100, unitName), - "Inversed Modifier Percent": (lambda: (1 - value) * 100, unitName), - "Modifier Percent": ( - lambda: ("%+.2f" if ((value - 1) * 100) % 1 else "%+d") % ((value - 1) * 100), unitName), - "Volume": (lambda: value, u"m\u00B3"), - "Sizeclass": (lambda: value, ""), - "Absolute Percent": (lambda: (value * 100), unitName), - "Milliseconds": (lambda: value / 1000.0, unitName), - "typeID": (itemIDCallback, ""), - "groupID": (groupIDCallback, ""), - "attributeID": (attributeIDCallback, "")} + trans = { + "Inverse Absolute Percent" : (lambda: (1 - value) * 100, unitName), + "Inversed Modifier Percent": (lambda: (1 - value) * 100, unitName), + "Modifier Percent" : ( + lambda: ("%+.2f" if ((value - 1) * 100) % 1 else "%+d") % ((value - 1) * 100), unitName), + "Volume" : (lambda: value, u"m\u00B3"), + "Sizeclass" : (lambda: value, ""), + "Absolute Percent" : (lambda: (value * 100), unitName), + "Milliseconds" : (lambda: value / 1000.0, unitName), + "typeID" : (itemIDCallback, ""), + "groupID" : (groupIDCallback, ""), + "attributeID" : (attributeIDCallback, "") + } override = trans.get(unitDisplayName) if override is not None: @@ -616,17 +635,17 @@ class ItemCompare(wx.Panel): if sort is not None: if sort == 0: # Name sort - func = lambda x: x.name + func = lambda _val: _val.name else: try: # Remember to reduce by 1, because the attrs array # starts at 0 while the list has the item name as column 0. attr = str(self.attrs.keys()[sort - 1]) - func = lambda x: x.attributes[attr].value if attr in x.attributes else None + func = lambda _val: _val.attributes[attr].value if attr in _val.attributes else None except IndexError: # Clicked on a column that's not part of our array (price most likely) self.sortReverse = False - func = lambda x: x.attributes['metaLevel'].value if 'metaLevel' in x.attributes else None + func = lambda _val: _val.attributes['metaLevel'].value if 'metaLevel' in _val.attributes else None self.items = sorted(self.items, key=func, reverse=self.sortReverse) @@ -652,7 +671,7 @@ class ItemCompare(wx.Panel): value = item.attributes[attr].value if self.toggleView != 1: valueUnit = str(value) - if info and info.unit: + elif info and info.unit and self.toggleView == 1: valueUnit = self.TranslateValueUnit(value, info.unit.displayName, info.unit.name) else: valueUnit = formatAmount(value, 3, 0, 0) @@ -662,7 +681,8 @@ class ItemCompare(wx.Panel): self.paramList.RefreshRows() self.Layout() - def TranslateValueUnit(self, value, unitName, unitDisplayName): + @staticmethod + def TranslateValueUnit(value, unitName, unitDisplayName): def itemIDCallback(): item = Market.getInstance().getItem(value) return "%s (%d)" % (item.name, value) if item is not None else str(value) @@ -675,17 +695,18 @@ class ItemCompare(wx.Panel): attribute = Attribute.getInstance().getAttributeInfo(value) return "%s (%d)" % (attribute.name.capitalize(), value) - trans = {"Inverse Absolute Percent": (lambda: (1 - value) * 100, unitName), - "Inversed Modifier Percent": (lambda: (1 - value) * 100, unitName), - "Modifier Percent": ( - lambda: ("%+.2f" if ((value - 1) * 100) % 1 else "%+d") % ((value - 1) * 100), unitName), - "Volume": (lambda: value, u"m\u00B3"), - "Sizeclass": (lambda: value, ""), - "Absolute Percent": (lambda: (value * 100), unitName), - "Milliseconds": (lambda: value / 1000.0, unitName), - "typeID": (itemIDCallback, ""), - "groupID": (groupIDCallback, ""), - "attributeID": (attributeIDCallback, "")} + trans = { + "Inverse Absolute Percent" : (lambda: (1 - value) * 100, unitName), + "Inversed Modifier Percent": (lambda: (1 - value) * 100, unitName), + "Modifier Percent" : (lambda: ("%+.2f" if ((value - 1) * 100) % 1 else "%+d") % ((value - 1) * 100), unitName), + "Volume" : (lambda: value, u"m\u00B3"), + "Sizeclass" : (lambda: value, ""), + "Absolute Percent" : (lambda: (value * 100), unitName), + "Milliseconds" : (lambda: value / 1000.0, unitName), + "typeID" : (itemIDCallback, ""), + "groupID" : (groupIDCallback, ""), + "attributeID" : (attributeIDCallback, "") + } override = trans.get(unitDisplayName) if override is not None: @@ -828,13 +849,14 @@ class ItemEffects(wx.Panel): self.RefreshValues(event) - def OnRightClick(self, event): + @staticmethod + def OnRightClick(event): """ Debug use: open effect file with default application. If effect file does not exist, create it """ - file_ = config.getPyfaPath(os.path.join("eos", "effects", "%s.py" % event.GetText().lower())) + file_ = os.path.join(config.pyfaPath, "eos", "effects", "%s.py" % event.GetText().lower()) if not os.path.isfile(file_): open(file_, 'a').close() @@ -1052,7 +1074,7 @@ class ItemAffectedBy(wx.Panel): item = afflictor.item items[attrName].append( - (type(afflictor), afflictor, item, modifier, amount, getattr(afflictor, "projected", False))) + (type(afflictor), afflictor, item, modifier, amount, getattr(afflictor, "projected", False))) # Make sure projected fits are on top rootOrder = container.keys() @@ -1280,3 +1302,97 @@ class ItemAffectedBy(wx.Panel): treeitem = self.affectedBy.AppendItem(child, display, attrIcon) self.affectedBy.SetPyData(treeitem, saved) self.treeItems.append(treeitem) + + +class ItemProperties(wx.Panel): + def __init__(self, parent, stuff, item, context=None): + wx.Panel.__init__(self, parent) + mainSizer = wx.BoxSizer(wx.VERTICAL) + + self.paramList = AutoListCtrl(self, wx.ID_ANY, + style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES | wx.NO_BORDER) + mainSizer.Add(self.paramList, 1, wx.ALL | wx.EXPAND, 0) + self.SetSizer(mainSizer) + + self.toggleView = 1 + self.stuff = stuff + self.item = item + self.attrInfo = {} + self.attrValues = {} + self._fetchValues() + + self.m_staticline = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL) + mainSizer.Add(self.m_staticline, 0, wx.EXPAND) + bSizer = wx.BoxSizer(wx.HORIZONTAL) + + self.totalAttrsLabel = wx.StaticText(self, wx.ID_ANY, u" ", wx.DefaultPosition, wx.DefaultSize, 0) + bSizer.Add(self.totalAttrsLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT) + + mainSizer.Add(bSizer, 0, wx.ALIGN_RIGHT) + + self.PopulateList() + + def _fetchValues(self): + if self.stuff is None: + self.attrInfo.clear() + self.attrValues.clear() + self.attrInfo.update(self.item.attributes) + self.attrValues.update(self.item.attributes) + elif self.stuff.item == self.item: + self.attrInfo.clear() + self.attrValues.clear() + self.attrInfo.update(self.stuff.item.attributes) + self.attrValues.update(self.stuff.itemModifiedAttributes) + elif self.stuff.charge == self.item: + self.attrInfo.clear() + self.attrValues.clear() + self.attrInfo.update(self.stuff.charge.attributes) + self.attrValues.update(self.stuff.chargeModifiedAttributes) + # When item for stats window no longer exists, don't change anything + else: + return + + def PopulateList(self): + self.paramList.InsertColumn(0, "Attribute") + self.paramList.InsertColumn(1, "Current Value") + self.paramList.SetColumnWidth(0, 110) + self.paramList.SetColumnWidth(1, 1500) + self.paramList.setResizeColumn(0) + + if self.stuff: + names = dir(self.stuff) + else: + names = dir(self.item) + + names = [a for a in names if not (a.startswith('__') and a.endswith('__'))] + + idNameMap = {} + idCount = 0 + for name in names: + try: + if self.stuff: + attrName = name.title() + value = getattr(self.stuff, name) + else: + attrName = name.title() + value = getattr(self.item, name) + except Exception as e: + # TODO: Add logging to this. + # We couldn't get a property for some reason. Skip it for now. + print(e) + continue + + index = self.paramList.InsertStringItem(sys.maxint, attrName) + # index = self.paramList.InsertImageStringItem(sys.maxint, attrName) + idNameMap[idCount] = attrName + self.paramList.SetItemData(index, idCount) + idCount += 1 + + valueUnit = str(value) + + self.paramList.SetStringItem(index, 1, valueUnit) + + self.paramList.SortItems(lambda id1, id2: cmp(idNameMap[id1], idNameMap[id2])) + self.paramList.RefreshRows() + self.totalAttrsLabel.SetLabel("%d attributes. " % idCount) + self.Layout() diff --git a/gui/mainFrame.py b/gui/mainFrame.py index e33c8bac9..7af37d875 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -19,22 +19,27 @@ import sys import os.path -import logging +from logbook import Logger import sqlalchemy +# noinspection PyPackageRequirements import wx +# noinspection PyPackageRequirements +from wx._core import PyDeadObjectError +# noinspection PyPackageRequirements +from wx.lib.wordwrap import wordwrap +# noinspection PyPackageRequirements +from wx.lib.inspection import InspectionTool import time from codecs import open -from wx.lib.wordwrap import wordwrap - import config from eos.config import gamedata_version import gui.aboutData -import gui.chromeTabs +from gui.chromeTabs import PFNotebook import gui.globalEvents as GE from gui.bitmapLoader import BitmapLoader @@ -54,7 +59,8 @@ from gui.graphFrame import GraphFrame from gui.copySelectDialog import CopySelectDialog from gui.utils.clipboard import toClipboard, fromClipboard from gui.updateDialog import UpdateDialog -from gui.builtinViews import * # TODO: unsure if this is needed here +# noinspection PyUnresolvedReferences +from gui.builtinViews import emptyView, entityEditor, fittingView, implantEditor # noqa: F401 from gui import graphFrame from service.settings import SettingsProvider @@ -65,7 +71,7 @@ from service.update import Update # import this to access override setting from eos.modifiedAttributeDict import ModifiedAttributeDict from eos.db.saveddata.loadDefaultDatabaseValues import DefaultDatabaseValues -from eos import db +from eos.db.saveddata.queries import getFit as db_getFit from service.port import Port from service.settings import HTMLExportSettings @@ -79,15 +85,16 @@ if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION from service.crest import CrestModes from gui.crestFittings import CrestFittings, ExportToEve, CrestMgmt - try: - from gui.propertyEditor import AttributeEditor +disableOverrideEditor = False - disableOverrideEditor = False - except ImportError as e: - print("Error loading Attribute Editor: %s.\nAccess to Attribute Editor is disabled." % e.message) - disableOverrideEditor = True +try: + from gui.propertyEditor import AttributeEditor +except ImportError as e: + AttributeEditor = None + print("Error loading Attribute Editor: %s.\nAccess to Attribute Editor is disabled." % e.message) + disableOverrideEditor = True -logger = logging.getLogger("pyfa.gui.mainFrame") +pyfalog = Logger(__name__) # dummy panel(no paint no erasebk) @@ -137,7 +144,8 @@ class MainFrame(wx.Frame): def getInstance(cls): return cls.__instance if cls.__instance is not None else MainFrame() - def __init__(self, title): + def __init__(self, title="pyfa"): + pyfalog.debug("Initialize MainFrame") self.title = title wx.Frame.__init__(self, None, wx.ID_ANY, self.title) @@ -167,7 +175,7 @@ class MainFrame(wx.Frame): self.fitMultiSwitch = MultiSwitch(self.fitting_additions_split) self.additionsPane = AdditionsPane(self.fitting_additions_split) - self.notebookBrowsers = gui.chromeTabs.PFNotebook(self.browser_fitting_split, False) + self.notebookBrowsers = PFNotebook(self.browser_fitting_split, False) marketImg = BitmapLoader.getImage("market_small", "gui") shipBrowserImg = BitmapLoader.getImage("ship_small", "gui") @@ -349,6 +357,13 @@ class MainFrame(wx.Frame): info = wx.AboutDialogInfo() info.Name = "pyfa" info.Version = gui.aboutData.versionString + + try: + import matplotlib + matplotlib_version = matplotlib.__version__ + except: + matplotlib_version = None + info.Description = wordwrap(gui.aboutData.description + "\n\nDevelopers:\n\t" + "\n\t".join(gui.aboutData.developers) + "\n\nAdditional credits:\n\t" + @@ -358,7 +373,8 @@ class MainFrame(wx.Frame): "\n\nEVE Data: \t" + gamedata_version + "\nPython: \t\t" + '{}.{}.{}'.format(v.major, v.minor, v.micro) + "\nwxPython: \t" + wx.__version__ + - "\nSQLAlchemy: \t" + sqlalchemy.__version__, + "\nSQLAlchemy: \t" + sqlalchemy.__version__ + + "\nmatplotlib: \t {}".format(matplotlib_version if matplotlib_version else "Not Installed"), 500, wx.ClientDC(self)) if "__WXGTK__" in wx.PlatformInfo: forumUrl = "http://forums.eveonline.com/default.aspx?g=posts&t=466425" @@ -381,7 +397,10 @@ class MainFrame(wx.Frame): def showDamagePatternEditor(self, event): dlg = DmgPatternEditorDlg(self) dlg.ShowModal() - dlg.Destroy() + try: + dlg.Destroy() + except PyDeadObjectError: + pyfalog.error("Tried to destroy an object that doesn't exist in .") def showImplantSetEditor(self, event): ImplantSetEditorDlg(self) @@ -406,26 +425,35 @@ class MainFrame(wx.Frame): path += ".xml" else: print("oops, invalid fit format %d" % format_) - dlg.Destroy() + try: + dlg.Destroy() + except PyDeadObjectError: + pyfalog.error("Tried to destroy an object that doesn't exist in .") return with open(path, "w", encoding="utf-8") as openfile: openfile.write(output) openfile.close() - dlg.Destroy() + try: + dlg.Destroy() + except PyDeadObjectError: + pyfalog.error("Tried to destroy an object that doesn't exist in .") def showPreferenceDialog(self, event): dlg = PreferenceDialog(self) dlg.ShowModal() - def goWiki(self, event): + @staticmethod + def goWiki(event): webbrowser.open('https://github.com/pyfa-org/Pyfa/wiki') - def goForums(self, event): + @staticmethod + def goForums(event): webbrowser.open('https://forums.eveonline.com/default.aspx?g=posts&t=466425') - def loadDatabaseDefaults(self, event): + @staticmethod + def loadDatabaseDefaults(event): # Import values that must exist otherwise Pyfa breaks DefaultDatabaseValues.importRequiredDefaults() # Import default values for damage profiles @@ -679,27 +707,27 @@ class MainFrame(wx.Frame): self.marketBrowser.search.Focus() def clipboardEft(self): - fit = db.getFit(self.getActiveFit()) + fit = db_getFit(self.getActiveFit()) toClipboard(Port.exportEft(fit)) def clipboardEftImps(self): - fit = db.getFit(self.getActiveFit()) + fit = db_getFit(self.getActiveFit()) toClipboard(Port.exportEftImps(fit)) def clipboardDna(self): - fit = db.getFit(self.getActiveFit()) + fit = db_getFit(self.getActiveFit()) toClipboard(Port.exportDna(fit)) def clipboardCrest(self): - fit = db.getFit(self.getActiveFit()) + fit = db_getFit(self.getActiveFit()) toClipboard(Port.exportCrest(fit)) def clipboardXml(self): - fit = db.getFit(self.getActiveFit()) + fit = db_getFit(self.getActiveFit()) toClipboard(Port.exportXml(None, fit)) def clipboardMultiBuy(self): - fit = db.getFit(self.getActiveFit()) + fit = db_getFit(self.getActiveFit()) toClipboard(Port.exportMultiBuy(fit)) def importFromClipboard(self, event): @@ -707,7 +735,7 @@ class MainFrame(wx.Frame): try: fits = Port().importFitFromBuffer(clipboard, self.getActiveFit()) except: - logger.error("Attempt to import failed:\n%s", clipboard) + pyfalog.error("Attempt to import failed:\n{0}", clipboard) else: self._openAfterImport(fits) @@ -724,7 +752,10 @@ class MainFrame(wx.Frame): CopySelectDict[selected]() - dlg.Destroy() + try: + dlg.Destroy() + except PyDeadObjectError: + pyfalog.error("Tried to destroy an object that doesn't exist in .") def exportSkillsNeeded(self, event): """ Exports skills needed for active fit and active character """ @@ -768,7 +799,7 @@ class MainFrame(wx.Frame): "All Files (*)|*"), style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE ) - if (dlg.ShowModal() == wx.ID_OK): + if dlg.ShowModal() == wx.ID_OK: self.progressDialog = wx.ProgressDialog( "Importing fits", " " * 100, # set some arbitrary spacing to create width in window @@ -778,7 +809,10 @@ class MainFrame(wx.Frame): self.progressDialog.message = None sPort.importFitsThreaded(dlg.GetPaths(), self.fileImportCallback) self.progressDialog.ShowModal() - dlg.Destroy() + try: + dlg.Destroy() + except PyDeadObjectError: + pyfalog.error("Tried to destroy an object that doesn't exist in .") def backupToXml(self, event): """ Back up all fits to EVE XML file """ @@ -919,13 +953,12 @@ class MainFrame(wx.Frame): if not self.graphFrame: self.graphFrame = GraphFrame(self) - if graphFrame.enabled: + if graphFrame.graphFrame_enabled: self.graphFrame.Show() - else: + elif graphFrame.graphFrame_enabled: self.graphFrame.SetFocus() def openWXInspectTool(self, event): - from wx.lib.inspection import InspectionTool if not InspectionTool().initialized: InspectionTool().Init() diff --git a/gui/mainMenuBar.py b/gui/mainMenuBar.py index 5e28da949..00402a7a3 100644 --- a/gui/mainMenuBar.py +++ b/gui/mainMenuBar.py @@ -17,14 +17,18 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx import config from service.character import Character -#import gui.graphFrame +import gui.graphFrame import gui.globalEvents as GE from gui.bitmapLoader import BitmapLoader +from logbook import Logger +pyfalog = Logger(__name__) + if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)): from service.crest import Crest from service.crest import CrestModes @@ -32,6 +36,7 @@ if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION class MainMenuBar(wx.MenuBar): def __init__(self, mainFrame): + pyfalog.debug("Initialize MainMenuBar") self.characterEditorId = wx.NewId() self.damagePatternEditorId = wx.NewId() self.targetResistsEditorId = wx.NewId() @@ -116,6 +121,9 @@ class MainMenuBar(wx.MenuBar): graphFrameItem.SetBitmap(BitmapLoader.getBitmap("graphs_small", "gui")) windowMenu.AppendItem(graphFrameItem) + if not gui.graphFrame.graphFrame_enabled: + self.Enable(self.graphFrameId, False) + preferencesShortCut = "CTRL+," if 'wxMac' in wx.PlatformInfo else "CTRL+P" preferencesItem = wx.MenuItem(windowMenu, wx.ID_PREFERENCES, "Preferences\t" + preferencesShortCut) preferencesItem.SetBitmap(BitmapLoader.getBitmap("preferences_small", "gui")) @@ -162,6 +170,7 @@ class MainMenuBar(wx.MenuBar): self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged) def fitChanged(self, event): + pyfalog.debug("fitChanged triggered") enable = event.fitID is not None self.Enable(wx.ID_SAVEAS, enable) self.Enable(wx.ID_COPY, enable) diff --git a/gui/marketBrowser.py b/gui/marketBrowser.py index 213e0520d..4047507da 100644 --- a/gui/marketBrowser.py +++ b/gui/marketBrowser.py @@ -17,14 +17,18 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from service.market import Market from service.attribute import Attribute -import gui.display as d +from gui.display import Display import gui.PFSearchBox as SBox from gui.cachingImageList import CachingImageList from gui.contextMenu import ContextMenu from gui.bitmapLoader import BitmapLoader +from logbook import Logger + +pyfalog = Logger(__name__) ItemSelected, ITEM_SELECTED = wx.lib.newevent.NewEvent() @@ -55,6 +59,7 @@ class MetaButton(wx.ToggleButton): class MarketBrowser(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) + pyfalog.debug("Initialize marketBrowser") vbox = wx.BoxSizer(wx.VERTICAL) self.SetSizer(vbox) @@ -82,6 +87,7 @@ class MarketBrowser(wx.Panel): p.SetSizer(box) vbox.Add(p, 0, wx.EXPAND) self.metaButtons = [] + btn = None for name in self.sMkt.META_MAP.keys(): btn = MetaButton(p, wx.ID_ANY, name.capitalize(), style=wx.BU_EXACTFIT) setattr(self, name, btn) @@ -132,6 +138,7 @@ class SearchBox(SBox.PFSearchBox): class MarketTree(wx.TreeCtrl): def __init__(self, parent, marketBrowser): wx.TreeCtrl.__init__(self, parent, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT) + pyfalog.debug("Initialize marketTree") self.root = self.AddRoot("root") self.imageList = CachingImageList(16, 16) @@ -180,7 +187,9 @@ class MarketTree(wx.TreeCtrl): iconId = self.addImage(sMkt.getIconByMarketGroup(childMktGrp)) try: childId = self.AppendItem(root, childMktGrp.name, iconId, data=wx.TreeItemData(childMktGrp.ID)) - except: + except Exception as e: + pyfalog.debug("Error appending item.") + pyfalog.debug(e) continue if sMkt.marketGroupHasTypesCheck(childMktGrp) is False: self.AppendItem(childId, "dummy") @@ -216,14 +225,15 @@ class MarketTree(wx.TreeCtrl): self.marketBrowser.itemView.selectionMade() -class ItemView(d.Display): +class ItemView(Display): DEFAULT_COLS = ["Base Icon", "Base Name", "attr:power,,,True", "attr:cpu,,,True"] def __init__(self, parent, marketBrowser): - d.Display.__init__(self, parent) + Display.__init__(self, parent) + pyfalog.debug("Initialize ItemView") marketBrowser.Bind(wx.EVT_TREE_SEL_CHANGED, self.selectionMade) self.unfilteredStore = set() @@ -250,6 +260,7 @@ class ItemView(d.Display): self.metaMap = self.makeReverseMetaMap() # Fill up recently used modules set + pyfalog.debug("Fill up recently used modules set") for itemID in self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]: self.recentlyUsedModules.add(self.sMkt.getItem(itemID)) @@ -398,7 +409,7 @@ class ItemView(d.Display): metagrpid = sMkt.getMetaGroupIdByItem(item) metatab = self.metaMap.get(metagrpid) metalvl = self.metalvls.get(item.ID, 0) - return (catname, mktgrpid, parentname, metatab, metalvl, item.name) + return catname, mktgrpid, parentname, metatab, metalvl, item.name def contextMenu(self, event): # Check if something is selected, if so, spawn the menu for it @@ -429,7 +440,7 @@ class ItemView(d.Display): # Mark current item list as active self.active = items # Show them - d.Display.populate(self, items) + Display.populate(self, items) def refresh(self, items): if len(items) > 1: @@ -445,7 +456,7 @@ class ItemView(d.Display): # set shortcut info for first 9 modules item.marketShortcut = i + 1 - d.Display.refresh(self, items) + Display.refresh(self, items) def makeReverseMetaMap(self): """ diff --git a/gui/multiSwitch.py b/gui/multiSwitch.py index 766524a61..2efe80bc0 100644 --- a/gui/multiSwitch.py +++ b/gui/multiSwitch.py @@ -17,13 +17,13 @@ # along with pyfa. If not, see . # ============================================================================= -import gui.chromeTabs +from gui.chromeTabs import PFNotebook import gui.builtinViews.emptyView -class MultiSwitch(gui.chromeTabs.PFNotebook): +class MultiSwitch(PFNotebook): def __init__(self, parent): - gui.chromeTabs.PFNotebook.__init__(self, parent) + PFNotebook.__init__(self, parent) # self.AddPage() # now handled by mainFrame self.handlers = handlers = [] for type in TabSpawner.tabTypes: @@ -40,10 +40,10 @@ class MultiSwitch(gui.chromeTabs.PFNotebook): tabWnd = gui.builtinViews.emptyView.BlankPage(self) tabWnd.handleDrag = lambda type, info: self.handleDrag(type, info) - gui.chromeTabs.PFNotebook.AddPage(self, tabWnd, tabTitle, tabImage, True) + PFNotebook.AddPage(self, tabWnd, tabTitle, tabImage, True) def DeletePage(self, n, *args, **kwargs): - gui.chromeTabs.PFNotebook.DeletePage(self, n, *args, **kwargs) + PFNotebook.DeletePage(self, n, *args, **kwargs) if self.GetPageCount() == 0: self.AddPage() diff --git a/gui/notesView.py b/gui/notesView.py index f607efb0b..d4f8703cc 100644 --- a/gui/notesView.py +++ b/gui/notesView.py @@ -1,3 +1,4 @@ +# noinspection PyPackageRequirements import wx from service.fit import Fit diff --git a/gui/patternEditor.py b/gui/patternEditor.py index 9d11a5ab9..879683373 100644 --- a/gui/patternEditor.py +++ b/gui/patternEditor.py @@ -17,12 +17,17 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from gui.bitmapLoader import BitmapLoader +# noinspection PyPackageRequirements from wx.lib.intctrl import IntCtrl from gui.utils.clipboard import toClipboard, fromClipboard from gui.builtinViews.entityEditor import EntityEditor, BaseValidator from service.damagePattern import DamagePattern, ImportError +from logbook import Logger + +pyfalog = Logger(__name__) class DmgPatternTextValidor(BaseValidator): @@ -45,6 +50,7 @@ class DmgPatternTextValidor(BaseValidator): return True except ValueError as e: + pyfalog.error(e) wx.MessageBox(u"{}".format(e), "Error") textCtrl.SetFocus() return False @@ -254,9 +260,13 @@ class DmgPatternEditorDlg(wx.Dialog): sDP.importPatterns(text) self.stNotice.SetLabel("Patterns successfully imported from clipboard") except ImportError as e: + pyfalog.error(e) self.stNotice.SetLabel(str(e)) - except Exception: - self.stNotice.SetLabel("Could not import from clipboard: unknown errors") + except Exception as e: + msg = "Could not import from clipboard: unknown errors" + pyfalog.warning(msg) + pyfalog.error(e) + self.stNotice.SetLabel(msg) finally: self.entityEditor.refreshEntityList() else: diff --git a/gui/preferenceDialog.py b/gui/preferenceDialog.py index 1d36d0d03..2ed0f829a 100644 --- a/gui/preferenceDialog.py +++ b/gui/preferenceDialog.py @@ -17,6 +17,7 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from gui.preferenceView import PreferenceView from gui.bitmapLoader import BitmapLoader @@ -65,12 +66,12 @@ class PreferenceDialog(wx.Dialog): # Set the height based on a condition. Can all the panels fit in the current height? # If not, use the .GetBestVirtualSize() to ensure that all content is available. - minHeight = 360 + minHeight = 550 bestFit = self.GetBestVirtualSize() if minHeight > bestFit[1]: - self.SetSizeWH(450, minHeight) + self.SetSizeWH(650, minHeight) else: - self.SetSizeWH(450, bestFit[1]) + self.SetSizeWH(650, bestFit[1]) self.Layout() diff --git a/gui/preferenceView.py b/gui/preferenceView.py index 06e7d10e2..a52a720e4 100644 --- a/gui/preferenceView.py +++ b/gui/preferenceView.py @@ -17,6 +17,7 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx @@ -37,4 +38,16 @@ class PreferenceView(object): return wx.NullBitmap -from gui.builtinPreferenceViews import * # noqa +# noinspection PyUnresolvedReferences +from gui.builtinPreferenceViews import ( # noqa: E402, F401 + pyfaGeneralPreferences, + pyfaNetworkPreferences, + pyfaHTMLExportPreferences, + pyfaCrestPreferences, + pyfaContextMenuPreferences, + pyfaStatViewPreferences, + pyfaUpdatePreferences, + pyfaEnginePreferences, + pyfaDatabasePreferences, + pyfaLoggingPreferences +) diff --git a/gui/projectedView.py b/gui/projectedView.py index f9c666f60..091c4a94d 100644 --- a/gui/projectedView.py +++ b/gui/projectedView.py @@ -17,6 +17,7 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx import gui.display as d import gui.globalEvents as GE @@ -30,20 +31,20 @@ from eos.saveddata.fighter import Fighter as es_Fighter from eos.saveddata.module import Module as es_Module -class DummyItem: +class DummyItem(object): def __init__(self, txt): self.name = txt self.icon = None -class DummyEntry: +class DummyEntry(object): def __init__(self, txt): self.item = DummyItem(txt) class ProjectedViewDrop(wx.PyDropTarget): - def __init__(self, dropFn): - wx.PyDropTarget.__init__(self) + def __init__(self, dropFn, *args, **kwargs): + super(ProjectedViewDrop, self).__init__(*args, **kwargs) self.dropFn = dropFn # this is really transferring an EVE itemID self.dropData = wx.PyTextDataObject() @@ -85,13 +86,13 @@ class ProjectedView(d.Display): self.SetDropTarget(ProjectedViewDrop(self.handleListDrag)) def handleListDrag(self, x, y, data): - ''' + """ Handles dragging of items from various pyfa displays which support it data is list with two indices: data[0] is hard-coded str of originating source data[1] is typeID or index of data we want to manipulate - ''' + """ if data[0] == "projected": # if source is coming from projected, we are trying to combine drones. @@ -146,10 +147,12 @@ class ProjectedView(d.Display): if sFit.mergeDrones(fitID, self.get(src), dstDrone, True): wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) - def moduleSort(self, module): + @staticmethod + def moduleSort(module): return module.item.name - def fighterSort(self, fighter): + @staticmethod + def fighterSort(fighter): return fighter.item.name def droneSort(self, drone): @@ -160,7 +163,8 @@ class ProjectedView(d.Display): return (self.droneView.DRONE_ORDER.index(item.marketGroup.name), drone.item.name) - def fitSort(self, fit): + @staticmethod + def fitSort(fit): return fit.name def fitChanged(self, event): @@ -203,7 +207,7 @@ class ProjectedView(d.Display): self.deselectItems() - if stuff == []: + if not stuff: stuff = [DummyEntry("Drag an item or fit, or use right-click menu for system effects")] self.update(stuff) @@ -276,7 +280,7 @@ class ProjectedView(d.Display): fitSrcContext = "projectedFit" fitItemContext = item.name context = ((fitSrcContext, fitItemContext),) - context = context + (("projected",),) + context += ("projected",), menu = ContextMenu.getMenu((item,), *context) elif sel == -1: fitID = self.mainFrame.getActiveFit() diff --git a/gui/propertyEditor.py b/gui/propertyEditor.py index 1129545a6..3416d591a 100644 --- a/gui/propertyEditor.py +++ b/gui/propertyEditor.py @@ -1,9 +1,11 @@ import csv -import logging +from logbook import Logger +# noinspection PyPackageRequirements import wx try: + # noinspection PyPackageRequirements import wx.propgrid as wxpg except: if wx.VERSION < (2, 9): @@ -11,7 +13,7 @@ except: else: raise -import eos.db +from eos.db.gamedata.queries import getItem, getAttributeInfo from service.market import Market import gui.display as d import gui.globalEvents as GE @@ -19,7 +21,7 @@ import gui.PFSearchBox as SBox from gui.marketBrowser import SearchBox from gui.bitmapLoader import BitmapLoader -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class AttributeEditor(wx.Frame): @@ -98,14 +100,14 @@ class AttributeEditor(wx.Frame): dlg = wx.FileDialog(self, "Import pyfa override file", wildcard="pyfa override file (*.csv)|*.csv", style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) - if (dlg.ShowModal() == wx.ID_OK): + if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() with open(path, 'rb') as csvfile: spamreader = csv.reader(csvfile) for row in spamreader: itemID, attrID, value = row - item = eos.db.getItem(int(itemID)) - attr = eos.db.getAttributeInfo(int(attrID)) + item = getItem(int(itemID)) + attr = getAttributeInfo(int(attrID)) item.setOverride(attr, float(value)) self.itemView.updateItems(True) @@ -268,7 +270,7 @@ class AttributeGrid(wxpg.PropertyGrid): self.itemView.updateItems() - logger.debug('%s changed to "%s"' % (p.GetName(), p.GetValueAsString())) + pyfalog.debug('{0} changed to "{1}"', p.GetName(), p.GetValueAsString()) def OnPropGridSelect(self, event): pass diff --git a/gui/pyfatogglepanel.py b/gui/pyfatogglepanel.py index db37216ba..cdd4398bb 100644 --- a/gui/pyfatogglepanel.py +++ b/gui/pyfatogglepanel.py @@ -21,6 +21,7 @@ # Notes: leave the commented code as it is, those line will be removed someday ########################################################################### +# noinspection PyPackageRequirements import wx from gui.bitmapLoader import BitmapLoader @@ -145,7 +146,7 @@ class TogglePanel(wx.Panel): """ Handles the status changes (collapsing/expanding). - :param `sz`: an instance of `wx.Size`. + :param sz: an instance of `wx.Size`. """ # minimal size has priority over the best size so set here our min size diff --git a/gui/pygauge.py b/gui/pygauge.py index 602304e13..dbb0c4531 100644 --- a/gui/pygauge.py +++ b/gui/pygauge.py @@ -11,6 +11,7 @@ PyfaGauge is a generic Gauge implementation tailored for PYFA (Python Fitting As It uses the easeOutQuad equation from caurina.transitions.Tweener to do the animation stuff """ +# noinspection PyPackageRequirements import wx import copy @@ -143,7 +144,7 @@ class PyGauge(wx.PyWindow): """ Sets the bar gradient. This overrides the BarColour. - :param `gradient`: a tuple containing the gradient start and end colours. + :param gradient: a tuple containing the gradient start and end colours. """ if gradient is None: self._barGradient = None @@ -162,7 +163,7 @@ class PyGauge(wx.PyWindow): """ Sets the border padding. - :param `padding`: pixels between the border and the progress bar. + :param padding: pixels between the border and the progress bar. """ self._border_padding = padding @@ -188,7 +189,8 @@ class PyGauge(wx.PyWindow): Sets the range of the gauge. The gauge length is its value as a proportion of the range. - :param `range`: The maximum value of the gauge. + :param reinit: + :param range: The maximum value of the gauge. """ if self._range == range: @@ -262,11 +264,12 @@ class PyGauge(wx.PyWindow): self.Animate() self._tooltip.SetTip("%.2f/%.2f" % (self._value, self._range if self._range > 0.01 else 0)) - def OnEraseBackground(self, event): + @staticmethod + def OnEraseBackground(event): """ Handles the ``wx.EVT_ERASE_BACKGROUND`` event for L{PyGauge}. - :param `event`: a `wx.EraseEvent` event to be processed. + :param event: a `wx.EraseEvent` event to be processed. :note: This method is intentionally empty to reduce flicker. """ @@ -277,7 +280,7 @@ class PyGauge(wx.PyWindow): """ Handles the ``wx.EVT_PAINT`` event for L{PyGauge}. - :param `event`: a `wx.PaintEvent` event to be processed. + :param event: a `wx.PaintEvent` event to be processed. """ dc = wx.BufferedPaintDC(self) @@ -320,8 +323,6 @@ class PyGauge(wx.PyWindow): # time on them if not needed. See GH issue #282 pv = value - xv = 1 - transition = 0 if pv <= 100: xv = pv / 100 @@ -408,7 +409,7 @@ class PyGauge(wx.PyWindow): """ Handles the ``wx.EVT_TIMER`` event for L{PyfaGauge}. - :param `event`: a timer event + :param event: a timer event """ oldValue = self._oldPercentage value = self._percentage diff --git a/gui/resistsEditor.py b/gui/resistsEditor.py index 84f7bf98b..c8bab84bb 100644 --- a/gui/resistsEditor.py +++ b/gui/resistsEditor.py @@ -17,11 +17,15 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from service.targetResists import TargetResists from gui.bitmapLoader import BitmapLoader from gui.utils.clipboard import toClipboard, fromClipboard from gui.builtinViews.entityEditor import EntityEditor, BaseValidator +from logbook import Logger + +pyfalog = Logger(__name__) class TargetResistsTextValidor(BaseValidator): @@ -44,6 +48,7 @@ class TargetResistsTextValidor(BaseValidator): return True except ValueError as e: + pyfalog.error(e) wx.MessageBox(u"{}".format(e), "Error") textCtrl.SetFocus() return False @@ -188,15 +193,17 @@ class ResistsEditorDlg(wx.Dialog): self.Destroy() def ValuesUpdated(self, event=None): - ''' + """ Event that is fired when resists values change. Iterates through all resist edit fields. If blank, sets it to 0.0. If it is not a proper decimal value, sets text color to red and refuses to save changes until issue is resolved - ''' + """ if self.block: return + editObj = None + try: p = self.entityEditor.getActiveEntity() @@ -227,15 +234,19 @@ class ResistsEditorDlg(wx.Dialog): except ValueError: editObj.SetForegroundColour(wx.RED) - self.stNotice.SetLabel("Incorrect Formatting (decimals only)") + msg = "Incorrect Formatting (decimals only)" + pyfalog.warning(msg) + self.stNotice.SetLabel(msg) except AssertionError: editObj.SetForegroundColour(wx.RED) - self.stNotice.SetLabel("Incorrect Range (must be 0-100)") + msg = "Incorrect Range (must be 0-100)" + pyfalog.warning(msg) + self.stNotice.SetLabel(msg) finally: # Refresh for color changes to take effect immediately self.Refresh() def patternChanged(self, event=None): - "Event fired when user selects pattern. Can also be called from script" + """Event fired when user selects pattern. Can also be called from script""" if not self.entityEditor.checkEntitiesExist(): self.Destroy() @@ -259,7 +270,7 @@ class ResistsEditorDlg(wx.Dialog): pass def importPatterns(self, event): - "Event fired when import from clipboard button is clicked" + """Event fired when import from clipboard button is clicked""" text = fromClipboard() if text: @@ -268,16 +279,20 @@ class ResistsEditorDlg(wx.Dialog): sTR.importPatterns(text) self.stNotice.SetLabel("Patterns successfully imported from clipboard") except ImportError as e: + pyfalog.error(e) self.stNotice.SetLabel(str(e)) - except Exception: - self.stNotice.SetLabel("Could not import from clipboard: unknown errors") + except Exception as e: + msg = "Could not import from clipboard:" + pyfalog.warning(msg) + pyfalog.error(e) + self.stNotice.SetLabel(msg) finally: self.entityEditor.refreshEntityList() else: self.stNotice.SetLabel("Could not import from clipboard") def exportPatterns(self, event): - "Event fired when export to clipboard button is clicked" + """Event fired when export to clipboard button is clicked""" sTR = TargetResists.getInstance() toClipboard(sTR.exportPatterns()) self.stNotice.SetLabel("Patterns exported to clipboard") diff --git a/gui/setEditor.py b/gui/setEditor.py index 0118fbe03..d199c1cc2 100644 --- a/gui/setEditor.py +++ b/gui/setEditor.py @@ -17,7 +17,8 @@ # along with pyfa. If not, see . # ============================================================================= -import logging +from logbook import Logger +# noinspection PyPackageRequirements import wx from service.implantSet import ImplantSets @@ -25,7 +26,7 @@ from gui.builtinViews.implantEditor import BaseImplantEditorView from gui.utils.clipboard import toClipboard, fromClipboard from gui.builtinViews.entityEditor import EntityEditor, BaseValidator -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class ImplantTextValidor(BaseValidator): @@ -48,6 +49,7 @@ class ImplantTextValidor(BaseValidator): return True except ValueError as e: + pyfalog.error(e) wx.MessageBox(u"{}".format(e), "Error") textCtrl.SetFocus() return False @@ -187,7 +189,7 @@ class ImplantSetEditorDlg(wx.Dialog): pass def importPatterns(self, event): - "Event fired when import from clipboard button is clicked" + """Event fired when import from clipboard button is clicked""" text = fromClipboard() if text: @@ -197,9 +199,10 @@ class ImplantSetEditorDlg(wx.Dialog): self.stNotice.SetLabel("Patterns successfully imported from clipboard") self.showInput(False) except ImportError as e: + pyfalog.error(e) self.stNotice.SetLabel(str(e)) except Exception as e: - logging.exception("Unhandled Exception") + pyfalog.error(e) self.stNotice.SetLabel("Could not import from clipboard: unknown errors") finally: self.updateChoices() @@ -207,7 +210,7 @@ class ImplantSetEditorDlg(wx.Dialog): self.stNotice.SetLabel("Could not import from clipboard") def exportPatterns(self, event): - "Event fired when export to clipboard button is clicked" + """Event fired when export to clipboard button is clicked""" sIS = ImplantSets.getInstance() toClipboard(sIS.exportSets()) diff --git a/gui/sfBrowserItem.py b/gui/sfBrowserItem.py index 047c04bc6..de9eb4001 100644 --- a/gui/sfBrowserItem.py +++ b/gui/sfBrowserItem.py @@ -1,3 +1,4 @@ +# noinspection PyPackageRequirements import wx import gui.utils.drawUtils as drawUtils @@ -57,7 +58,7 @@ class PFBaseButton(object): def GetSize(self): w = self.normalBmp.GetWidth() h = self.normalBmp.GetHeight() - return (w, h) + return w, h def GetBitmap(self): return self.normalBmp @@ -136,7 +137,6 @@ class PFToolbar(object): return doRefresh def MouseClick(self, event): - mx, my = event.GetPosition() bx = self.toolbarX for button in self.buttons: if not button.IsVisible(): @@ -196,11 +196,12 @@ class PFToolbar(object): return height - def HitTest(self, target, position, area): + @staticmethod + def HitTest(target, position, area): x, y = target px, py = position aX, aY = area - if (px > x and px < x + aX) and (py > y and py < y + aY): + if (x < px < x + aX) and (y < py < y + aY): return True return False @@ -354,7 +355,8 @@ class SFBrowserItem(wx.Window): event.Skip() - def GetType(self): + @staticmethod + def GetType(): return -1 def SetSelected(self, select=True): diff --git a/gui/shipBrowser.py b/gui/shipBrowser.py index a9e12a110..33561de5b 100644 --- a/gui/shipBrowser.py +++ b/gui/shipBrowser.py @@ -3,7 +3,9 @@ import re import time +# noinspection PyPackageRequirements import wx +# noinspection PyPackageRequirements from wx.lib.buttons import GenBitmapButton from service.fit import Fit @@ -19,6 +21,8 @@ import gui.utils.animEffects as animEffects from gui.PFListPane import PFListPane from gui.contextMenu import ContextMenu from gui.bitmapLoader import BitmapLoader +from logbook import Logger +pyfalog = Logger(__name__) FitRenamed, EVT_FIT_RENAMED = wx.lib.newevent.NewEvent() FitSelected, EVT_FIT_SELECTED = wx.lib.newevent.NewEvent() @@ -195,7 +199,7 @@ class RaceSelector(wx.Window): padding = self.buttonsPadding for bmp in self.raceBmps: - if (mx > x and mx < x + bmp.GetWidth()) and (my > y and my < y + bmp.GetHeight()): + if (x < mx < x + bmp.GetWidth()) and (y < my < y + bmp.GetHeight()): return self.raceBmps.index(bmp) if self.layout == wx.VERTICAL: y += bmp.GetHeight() + padding @@ -352,7 +356,9 @@ class NavigationPanel(SFItem.SFBrowserItem): self.btnSwitch = self.toolbar.AddButton(self.switchBmpD, "Hide empty ship groups", clickCallback=self.ToggleEmptyGroupsView, hoverBitmap=self.switchBmpH, show=False) - self.toolbar.AddButton(self.searchBmp, "Search fittings", clickCallback=self.ToggleSearchBox, + + modifier = "CTRL" if 'wxMac' not in wx.PlatformInfo else "CMD" + self.toolbar.AddButton(self.searchBmp, "Search fittings ({}+F)".format(modifier), clickCallback=self.ToggleSearchBox, hoverBitmap=self.searchBmpH) self.padding = 4 @@ -456,7 +462,8 @@ class NavigationPanel(SFItem.SFBrowserItem): stage, data = self.shipBrowser.browseHist.pop() self.gotoStage(stage, data) - def AdjustChannels(self, bitmap): + @staticmethod + def AdjustChannels(bitmap): img = wx.ImageFromBitmap(bitmap) img = img.AdjustChannels(1.05, 1.05, 1.05, 1) return wx.BitmapFromImage(img) @@ -626,7 +633,6 @@ class ShipBrowser(wx.Panel): event.Skip() def SizeRefreshList(self, event): - ewidth, eheight = event.GetSize() self.Layout() self.lpane.Layout() self.lpane.RefreshList(True) @@ -680,15 +686,17 @@ class ShipBrowser(wx.Panel): self.lpane.Freeze() self.lpane.RemoveAllChildren() + pyfalog.debug("Populate ship category list.") if len(self.categoryList) == 0: # set cache of category list self.categoryList = list(sMkt.getShipRoot()) - self.categoryList.sort(key=lambda ship: ship.name) + self.categoryList.sort(key=lambda _ship: _ship.name) # set map & cache of fittings per category for cat in self.categoryList: itemIDs = [x.ID for x in cat.items] - self.categoryFitCache[cat.ID] = sFit.countFitsWithShip(itemIDs) > 1 + num = sFit.countFitsWithShip(itemIDs) + self.categoryFitCache[cat.ID] = num > 0 for ship in self.categoryList: if self.filterShipsWithNoFits and not self.categoryFitCache[ship.ID]: @@ -798,7 +806,8 @@ class ShipBrowser(wx.Panel): self.navpanel.ShowNewFitButton(False) self.navpanel.ShowSwitchEmptyGroupsButton(True) - def nameKey(self, info): + @staticmethod + def nameKey(info): return info[1] def stage3(self, event): @@ -925,7 +934,7 @@ class ShipBrowser(wx.Panel): fits = event.fits # sort by ship name, then fit name - fits.sort(key=lambda fit: (fit.ship.item.name, fit.name)) + fits.sort(key=lambda _fit: (_fit.ship.item.name, _fit.name)) self.lastdata = fits self.lpane.Freeze() @@ -933,7 +942,7 @@ class ShipBrowser(wx.Panel): if fits: for fit in fits: - shipTrait = fit.ship.traits.traitText if (fit.ship.traits is not None) else "" + shipTrait = fit.ship.item.traits.traitText if (fit.ship.item.traits is not None) else "" # empty string if no traits self.lpane.AddWidget(FitItem( @@ -970,7 +979,8 @@ class PFStaticText(wx.Panel): self.SetSizer(mainSizer) self.Layout() - def GetType(self): + @staticmethod + def GetType(): return -1 @@ -1029,7 +1039,8 @@ class CategoryItem(SFItem.SFBrowserItem): self.animTimer.Stop() self.Refresh() - def OUT_QUAD(self, t, b, c, d): + @staticmethod + def OUT_QUAD(t, b, c, d): t = float(t) b = float(b) c = float(c) @@ -1189,8 +1200,7 @@ class ShipItem(SFItem.SFBrowserItem): def OnShowPopup(self, event): pos = event.GetPosition() pos = self.ScreenToClient(pos) - contexts = [] - contexts.append(("baseShip", "Ship Basic")) + contexts = [("baseShip", "Ship Basic")] menu = ContextMenu.getMenu(self.baseItem, *contexts) self.PopupMenu(menu, pos) @@ -1203,7 +1213,8 @@ class ShipItem(SFItem.SFBrowserItem): self.animTimer.Stop() self.Refresh() - def OUT_QUAD(self, t, b, c, d): + @staticmethod + def OUT_QUAD(t, b, c, d): t = float(t) b = float(b) c = float(c) @@ -1269,17 +1280,17 @@ class ShipItem(SFItem.SFBrowserItem): self.toolbarx = rect.width - self.toolbar.GetWidth() - self.padding self.toolbary = (rect.height - self.toolbar.GetHeight()) / 2 - self.toolbarx = self.toolbarx + self.animCount + self.toolbarx += self.animCount self.shipEffx = self.padding + (rect.height - self.shipEffBk.GetWidth()) / 2 self.shipEffy = (rect.height - self.shipEffBk.GetHeight()) / 2 - self.shipEffx = self.shipEffx - self.animCount + self.shipEffx -= self.animCount self.shipBmpx = self.padding + (rect.height - self.shipBmp.GetWidth()) / 2 self.shipBmpy = (rect.height - self.shipBmp.GetHeight()) / 2 - self.shipBmpx = self.shipBmpx - self.animCount + self.shipBmpx -= self.animCount self.raceBmpx = self.shipEffx + self.shipEffBk.GetWidth() + self.padding self.raceBmpy = (rect.height - self.raceBmp.GetHeight()) / 2 @@ -1544,6 +1555,10 @@ class FitItem(SFItem.SFBrowserItem): self.selTimer.Start(100) self.Bind(wx.EVT_RIGHT_UP, self.OnContextMenu) + self.Bind(wx.EVT_MIDDLE_UP, self.OpenNewTab) + + def OpenNewTab(self, evt): + self.selectFit(newTab=True) def OnToggleBooster(self, event): sFit = Fit.getInstance() @@ -1573,7 +1588,7 @@ class FitItem(SFItem.SFBrowserItem): self.mainFrame.additionsPane.select("Command") def OnMouseCaptureLost(self, event): - ''' Destroy drag information (GH issue #479)''' + """ Destroy drag information (GH issue #479)""" if self.dragging and self.dragged: self.dragging = False self.dragged = False @@ -1583,7 +1598,7 @@ class FitItem(SFItem.SFBrowserItem): self.dragWindow = None def OnContextMenu(self, event): - ''' Handles context menu for fit. Dragging is handled by MouseLeftUp() ''' + """ Handles context menu for fit. Dragging is handled by MouseLeftUp() """ sFit = Fit.getInstance() fit = sFit.getFit(self.mainFrame.getActiveFit()) @@ -1608,6 +1623,9 @@ class FitItem(SFItem.SFBrowserItem): # menu.AppendSubMenu(boosterMenu, 'Set Booster') if fit: + newTabItem = menu.Append(wx.ID_ANY, "Open in new tab") + self.Bind(wx.EVT_MENU, self.OpenNewTab, newTabItem) + projectedItem = menu.Append(wx.ID_ANY, "Project onto Active Fit") self.Bind(wx.EVT_MENU, self.OnProjectToFit, projectedItem) @@ -1643,10 +1661,12 @@ class FitItem(SFItem.SFBrowserItem): self.animTimer.Stop() self.Refresh() - def CalculateDelta(self, start, end, delta): + @staticmethod + def CalculateDelta(start, end, delta): return start + (end - start) * delta - def OUT_QUAD(self, t, b, c, d): + @staticmethod + def OUT_QUAD(t, b, c, d): t = float(t) b = float(b) c = float(c) @@ -1799,8 +1819,11 @@ class FitItem(SFItem.SFBrowserItem): self.dragWindow.SetPosition(pos) return - def selectFit(self, event=None): - wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fitID)) + def selectFit(self, event=None, newTab=False): + if newTab: + wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fitID, startup=2)) + else: + wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fitID)) def RestoreEditButton(self): self.tcFitName.Show(False) @@ -1813,17 +1836,17 @@ class FitItem(SFItem.SFBrowserItem): self.toolbarx = rect.width - self.toolbar.GetWidth() - self.padding self.toolbary = (rect.height - self.toolbar.GetHeight()) / 2 - self.toolbarx = self.toolbarx + self.animCount + self.toolbarx += self.animCount self.shipEffx = self.padding + (rect.height - self.shipEffBk.GetWidth()) / 2 self.shipEffy = (rect.height - self.shipEffBk.GetHeight()) / 2 - self.shipEffx = self.shipEffx - self.animCount + self.shipEffx -= self.animCount self.shipBmpx = self.padding + (rect.height - self.shipBmp.GetWidth()) / 2 self.shipBmpy = (rect.height - self.shipBmp.GetHeight()) / 2 - self.shipBmpx = self.shipBmpx - self.animCount + self.shipBmpx -= self.animCount self.textStartx = self.shipEffx + self.shipEffBk.GetWidth() + self.padding @@ -1863,8 +1886,6 @@ class FitItem(SFItem.SFBrowserItem): mdc.DrawBitmap(self.shipBmp, self.shipBmpx, self.shipBmpy, 0) - shipName, shipTrait, fittings, booster, timestamp = self.shipFittingInfo - mdc.SetFont(self.fontNormal) fitDate = time.localtime(self.timestamp) diff --git a/gui/statsPane.py b/gui/statsPane.py index 5d20f22ef..ce09e2e62 100644 --- a/gui/statsPane.py +++ b/gui/statsPane.py @@ -17,9 +17,11 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx from service.fit import Fit +from service.settings import StatViewSettings import gui.mainFrame import gui.builtinStatsViews import gui.globalEvents as GE @@ -27,12 +29,44 @@ import gui.globalEvents as GE from gui.statsView import StatsView from gui.contextMenu import ContextMenu from gui.pyfatogglepanel import TogglePanel +from logbook import Logger + +pyfalog = Logger(__name__) class StatsPane(wx.Panel): - DEFAULT_VIEWS = ["resourcesViewFull", "resistancesViewFull", "rechargeViewFull", "firepowerViewFull", - "capacitorViewFull", "targetingmiscViewFull", - "priceViewFull"] + AVAILIBLE_VIEWS = [ + "resources", + "resistances", + "recharge", + "firepower", + "outgoing", + "capacitor", + "targetingMisc", + "price", + ] + + # Don't have these....yet.... + ''' + "miningyield", "drones" + ] + ''' + + DEFAULT_VIEWS = [] + + settings = StatViewSettings.getInstance() + + for aView in AVAILIBLE_VIEWS: + if settings.get(aView) == 2: + DEFAULT_VIEWS.extend(["%sViewFull" % aView]) + pyfalog.debug("Setting full view for: {0}", aView) + elif settings.get(aView) == 1: + DEFAULT_VIEWS.extend(["%sViewMinimal" % aView]) + pyfalog.debug("Setting minimal view for: {0}", aView) + elif settings.get(aView) == 0: + pyfalog.debug("Setting disabled view for: {0}", aView) + else: + pyfalog.error("Unknown setting for view: {0}", aView) def fitChanged(self, event): sFit = Fit.getInstance() @@ -65,7 +99,12 @@ class StatsPane(wx.Panel): contentPanel = tp.GetContentPane() contentPanel.viewName = viewName - view = StatsView.getView(viewName)(self) + try: + view = StatsView.getView(viewName)(self) + pyfalog.debug("Load view: {0}", viewName) + except KeyError: + pyfalog.error("Attempted to load an invalid view: {0}", viewName) + self.nameViewMap[viewName] = view self.views.append(view) @@ -92,7 +131,8 @@ class StatsPane(wx.Panel): self.mainFrame = gui.mainFrame.MainFrame.getInstance() self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged) - def contextHandler(self, contentPanel): + @staticmethod + def contextHandler(contentPanel): viewName = contentPanel.viewName def handler(event): diff --git a/gui/statsView.py b/gui/statsView.py index 2cd8db548..464359695 100644 --- a/gui/statsView.py +++ b/gui/statsView.py @@ -42,4 +42,16 @@ class StatsView(object): raise NotImplementedError() -from gui.builtinStatsViews import * # noqa +# noinspection PyUnresolvedReferences +from gui.builtinStatsViews import ( # noqa: E402, F401 + resourcesViewFull, + resistancesViewFull, + firepowerViewFull, + miningyieldViewFull, + capacitorViewFull, + rechargeViewFull, + targetingMiscViewMinimal, + priceViewFull, + outgoingViewFull, + outgoingViewMinimal, +) diff --git a/gui/updateDialog.py b/gui/updateDialog.py index 155d5a6a9..019901819 100644 --- a/gui/updateDialog.py +++ b/gui/updateDialog.py @@ -17,7 +17,9 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx +# noinspection PyPackageRequirements import dateutil.parser from service.settings import UpdateSettings as svc_UpdateSettings @@ -48,7 +50,7 @@ class UpdateDialog(wx.Dialog): versionSizer = wx.BoxSizer(wx.HORIZONTAL) - if (self.releaseInfo['prerelease']): + if self.releaseInfo['prerelease']: self.releaseText = wx.StaticText(self, wx.ID_ANY, "Pre-release", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_RIGHT) self.releaseText.SetFont(wx.Font(12, 74, 90, 92, False)) @@ -118,7 +120,7 @@ class UpdateDialog(wx.Dialog): self.Close() def SuppressChange(self, e): - if (self.supressCheckbox.IsChecked()): + if self.supressCheckbox.IsChecked(): self.UpdateSettings.set('version', self.releaseInfo['tag_name']) else: self.UpdateSettings.set('version', None) diff --git a/gui/utils/animEffects.py b/gui/utils/animEffects.py index a705374a0..beb1b30aa 100644 --- a/gui/utils/animEffects.py +++ b/gui/utils/animEffects.py @@ -42,7 +42,7 @@ def IN_CUBIC(t, b, c, d): c = float(c) d = float(d) - t = t / d + t /= d return c * t * t * t + b diff --git a/gui/utils/animUtils.py b/gui/utils/animUtils.py index cefd3938b..4003e7760 100644 --- a/gui/utils/animUtils.py +++ b/gui/utils/animUtils.py @@ -1,3 +1,4 @@ +# noinspection PyPackageRequirements import wx import gui.utils.colorUtils as colorUtils @@ -59,7 +60,7 @@ class LoadAnimation(wx.Window): barColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT) shadeColor = colorUtils.GetSuitableColor(barColor, 0.75) - barWidth = (rect.width) / self.bars + barWidth = rect.width / self.bars barHeight = rect.height - self.padding * 2 x = self.padding diff --git a/gui/utils/clipboard.py b/gui/utils/clipboard.py index 4fa05e1f3..2ca2345e4 100644 --- a/gui/utils/clipboard.py +++ b/gui/utils/clipboard.py @@ -1,3 +1,4 @@ +# noinspection PyPackageRequirements import wx diff --git a/gui/utils/colorUtils.py b/gui/utils/colorUtils.py index a8d560159..d2f10336b 100644 --- a/gui/utils/colorUtils.py +++ b/gui/utils/colorUtils.py @@ -1,3 +1,4 @@ +# noinspection PyPackageRequirements import wx import math @@ -42,7 +43,7 @@ def GetBrightnessO1(color): # Calculates the brightness of a color, different options r, g, b = color - return (0.299 * r + 0.587 * g + 0.114 * b) + return 0.299 * r + 0.587 * g + 0.114 * b def GetBrightnessO2(color): diff --git a/gui/utils/compat.py b/gui/utils/compat.py deleted file mode 100644 index e0d336b22..000000000 --- a/gui/utils/compat.py +++ /dev/null @@ -1,259 +0,0 @@ -# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. -# Passes Python2.7's test suite and incorporates all the latest updates. - -try: - from thread import get_ident as _get_ident -except ImportError: - from dummy_thread import get_ident as _get_ident - -try: - from _abcoll import KeysView, ValuesView, ItemsView -except ImportError: - pass - - -class OrderedDict(dict): - 'Dictionary that remembers insertion order' - - # An inherited dict maps keys to values. - # The inherited dict provides __getitem__, __len__, __contains__, and get. - # The remaining methods are order-aware. - # Big-O running times for all methods are the same as for regular dictionaries. - - # The internal self.__map dictionary maps keys to links in a doubly linked list. - # The circular doubly linked list starts and ends with a sentinel element. - # The sentinel element never gets deleted (this simplifies the algorithm). - # Each link is stored as a list of length three: [PREV, NEXT, KEY]. - - def __init__(self, *args, **kwds): - '''Initialize an ordered dictionary. Signature is the same as for - regular dictionaries, but keyword arguments are not recommended - because their insertion order is arbitrary. - - ''' - if len(args) > 1: - raise TypeError('expected at most 1 arguments, got %d' % len(args)) - try: - self.__root - except AttributeError: - self.__root = root = [] # sentinel node - root[:] = [root, root, None] - self.__map = {} - self.__update(*args, **kwds) - - def __setitem__(self, key, value, dict_setitem=dict.__setitem__): - 'od.__setitem__(i, y) <==> od[i]=y' - # Setting a new item creates a new link which goes at the end of the linked - # list, and the inherited dictionary is updated with the new key/value pair. - if key not in self: - root = self.__root - last = root[0] - last[1] = root[0] = self.__map[key] = [last, root, key] - dict_setitem(self, key, value) - - def __delitem__(self, key, dict_delitem=dict.__delitem__): - 'od.__delitem__(y) <==> del od[y]' - # Deleting an existing item uses self.__map to find the link which is - # then removed by updating the links in the predecessor and successor nodes. - dict_delitem(self, key) - link_prev, link_next, key = self.__map.pop(key) - link_prev[1] = link_next - link_next[0] = link_prev - - def __iter__(self): - 'od.__iter__() <==> iter(od)' - root = self.__root - curr = root[1] - while curr is not root: - yield curr[2] - curr = curr[1] - - def __reversed__(self): - 'od.__reversed__() <==> reversed(od)' - root = self.__root - curr = root[0] - while curr is not root: - yield curr[2] - curr = curr[0] - - def clear(self): - 'od.clear() -> None. Remove all items from od.' - try: - for node in self.__map.itervalues(): - del node[:] - root = self.__root - root[:] = [root, root, None] - self.__map.clear() - except AttributeError: - pass - dict.clear(self) - - def popitem(self, last=True): - '''od.popitem() -> (k, v), return and remove a (key, value) pair. - Pairs are returned in LIFO order if last is true or FIFO order if false. - - ''' - if not self: - raise KeyError('dictionary is empty') - root = self.__root - if last: - link = root[0] - link_prev = link[0] - link_prev[1] = root - root[0] = link_prev - else: - link = root[1] - link_next = link[1] - root[1] = link_next - link_next[0] = root - key = link[2] - del self.__map[key] - value = dict.pop(self, key) - return key, value - - # -- the following methods do not depend on the internal structure -- - - def keys(self): - 'od.keys() -> list of keys in od' - return list(self) - - def values(self): - 'od.values() -> list of values in od' - return [self[key] for key in self] - - def items(self): - 'od.items() -> list of (key, value) pairs in od' - return [(key, self[key]) for key in self] - - def iterkeys(self): - 'od.iterkeys() -> an iterator over the keys in od' - return iter(self) - - def itervalues(self): - 'od.itervalues -> an iterator over the values in od' - for k in self: - yield self[k] - - def iteritems(self): - 'od.iteritems -> an iterator over the (key, value) items in od' - for k in self: - yield (k, self[k]) - - def update(*args, **kwds): - '''od.update(E, **F) -> None. Update od from dict/iterable E and F. - - If E is a dict instance, does: for k in E: od[k] = E[k] - If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] - Or if E is an iterable of items, does: for k, v in E: od[k] = v - In either case, this is followed by: for k, v in F.items(): od[k] = v - - ''' - if len(args) > 2: - raise TypeError('update() takes at most 2 positional ' - 'arguments (%d given)' % (len(args),)) - elif not args: - raise TypeError('update() takes at least 1 argument (0 given)') - self = args[0] - # Make progressively weaker assumptions about "other" - other = () - if len(args) == 2: - other = args[1] - if isinstance(other, dict): - for key in other: - self[key] = other[key] - elif hasattr(other, 'keys'): - for key in other.keys(): - self[key] = other[key] - else: - for key, value in other: - self[key] = value - for key, value in kwds.items(): - self[key] = value - - __update = update # let subclasses override update without breaking __init__ - - __marker = object() - - def pop(self, key, default=__marker): - '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. - If key is not found, d is returned if given, otherwise KeyError is raised. - - ''' - if key in self: - result = self[key] - del self[key] - return result - if default is self.__marker: - raise KeyError(key) - return default - - def setdefault(self, key, default=None): - 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' - if key in self: - return self[key] - self[key] = default - return default - - def __repr__(self, _repr_running={}): - 'od.__repr__() <==> repr(od)' - call_key = id(self), _get_ident() - if call_key in _repr_running: - return '...' - _repr_running[call_key] = 1 - try: - if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, self.items()) - finally: - del _repr_running[call_key] - - def __reduce__(self): - 'Return state information for pickling' - items = [[k, self[k]] for k in self] - inst_dict = vars(self).copy() - for k in vars(OrderedDict()): - inst_dict.pop(k, None) - if inst_dict: - return (self.__class__, (items,), inst_dict) - return self.__class__, (items,) - - def copy(self): - 'od.copy() -> a shallow copy of od' - return self.__class__(self) - - @classmethod - def fromkeys(cls, iterable, value=None): - '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S - and values equal to v (which defaults to None). - - ''' - d = cls() - for key in iterable: - d[key] = value - return d - - def __eq__(self, other): - '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive - while comparison to a regular mapping is order-insensitive. - - ''' - if isinstance(other, OrderedDict): - return len(self) == len(other) and self.items() == other.items() - return dict.__eq__(self, other) - - def __ne__(self, other): - return not self == other - - # -- the following methods are only used in Python 2.7 -- - - def viewkeys(self): - "od.viewkeys() -> a set-like object providing a view on od's keys" - return KeysView(self) - - def viewvalues(self): - "od.viewvalues() -> an object providing a view on od's values" - return ValuesView(self) - - def viewitems(self): - "od.viewitems() -> a set-like object providing a view on od's items" - return ItemsView(self) diff --git a/gui/utils/drawUtils.py b/gui/utils/drawUtils.py index 559dac395..d7034ece7 100644 --- a/gui/utils/drawUtils.py +++ b/gui/utils/drawUtils.py @@ -1,3 +1,4 @@ +# noinspection PyPackageRequirements import wx import gui.utils.colorUtils as colorUtils @@ -32,6 +33,7 @@ def DrawFilledBitmap(width, height, color): return canvas +# noinspection PyPropertyAccess def DrawGradientBar(width, height, gStart, gEnd, gMid=None, fillRatio=4): # we need to have dimensions to draw # assert width > 0 and height > 0 diff --git a/gui/utils/exportHtml.py b/gui/utils/exportHtml.py index 41fa7584d..ba075a35f 100644 --- a/gui/utils/exportHtml.py +++ b/gui/utils/exportHtml.py @@ -1,12 +1,18 @@ import threading import time +# noinspection PyPackageRequirements import wx from service.settings import HTMLExportSettings from service.fit import Fit +from service.port import Port from service.market import Market +from logbook import Logger +from eos.db import getFit + +pyfalog = Logger(__name__) -class exportHtml(): +class exportHtml(object): _instance = None @classmethod @@ -168,7 +174,7 @@ class exportHtmlThread(threading.Thread): """ % (time.time(), dnaUrl, localDate) HTML += '
    \n' categoryList = list(sMkt.getShipRoot()) - categoryList.sort(key=lambda ship: ship.name) + categoryList.sort(key=lambda _ship: _ship.name) count = 0 @@ -177,12 +183,13 @@ class exportHtmlThread(threading.Thread): HTMLgroup = '' ships = list(sMkt.getShipList(group.ID)) - ships.sort(key=lambda ship: ship.name) + ships.sort(key=lambda _ship: _ship.name) # Keep track of how many ships per group groupFits = 0 for ship in ships: fits = sFit.getFitsWithShip(ship.ID) + if len(fits) > 0: groupFits += len(fits) @@ -191,10 +198,11 @@ class exportHtmlThread(threading.Thread): return fit = fits[0] try: - dnaFit = sFit.exportDna(fit[0]) + dnaFit = Port.exportDna(getFit(fit[0])) HTMLgroup += '
  • ' + ship.name + ": " + \ fit[1] + '
  • \n' except: + pyfalog.warning("Failed to export line") pass finally: if self.callback: @@ -213,10 +221,12 @@ class exportHtmlThread(threading.Thread): if self.stopRunning: return try: - dnaFit = sFit.exportDna(fit[0]) + dnaFit = Port.exportDna(getFit(fit[0])) + print dnaFit HTMLship += '
  • ' + fit[ 1] + '
  • \n' except: + pyfalog.warning("Failed to export line") continue finally: if self.callback: @@ -230,7 +240,7 @@ class exportHtmlThread(threading.Thread): HTML += ( '
  • \n' '

    ' + group.groupName + ' ' + str(groupFits) + '

    \n' - '
      \n' + HTMLgroup + + '
        \n' + HTMLgroup + '
      \n' ' ' ) @@ -247,7 +257,7 @@ class exportHtmlThread(threading.Thread): def generateMinimalHTML(self, sMkt, sFit, dnaUrl): """ Generate a minimal HTML version of the fittings, without any javascript or styling""" categoryList = list(sMkt.getShipRoot()) - categoryList.sort(key=lambda ship: ship.name) + categoryList.sort(key=lambda _ship: _ship.name) count = 0 HTML = '' @@ -255,9 +265,9 @@ class exportHtmlThread(threading.Thread): # init market group string to give ships something to attach to ships = list(sMkt.getShipList(group.ID)) - ships.sort(key=lambda ship: ship.name) + ships.sort(key=lambda _ship: _ship.name) - ships.sort(key=lambda ship: ship.name) + ships.sort(key=lambda _ship: _ship.name) for ship in ships: fits = sFit.getFitsWithShip(ship.ID) @@ -265,10 +275,11 @@ class exportHtmlThread(threading.Thread): if self.stopRunning: return try: - dnaFit = sFit.exportDna(fit[0]) + dnaFit = Port.exportDna(getFit(fit[0])) HTML += '' + ship.name + ': ' + \ fit[1] + '
      \n' except: + pyfalog.error("Failed to export line") continue finally: if self.callback: diff --git a/gui/utils/fonts.py b/gui/utils/fonts.py index eb2dd95f5..6f8e109d3 100644 --- a/gui/utils/fonts.py +++ b/gui/utils/fonts.py @@ -1,8 +1,9 @@ -''' +""" Font file to handle the differences in font calculations between different wxPython versions -''' +""" +# noinspection PyPackageRequirements import wx if 'wxMac' in wx.PlatformInfo: diff --git a/gui/utils/numberFormatter.py b/gui/utils/numberFormatter.py index cd8140dce..46aaf7d5a 100644 --- a/gui/utils/numberFormatter.py +++ b/gui/utils/numberFormatter.py @@ -67,7 +67,7 @@ def formatAmount(val, prec=3, lowest=0, highest=0, currency=False, forceSign=Fal except IndexError: nextKey = 0 # Check if mantissa with next suffix is in range [1, 1000) - if abs(val) < 10 ** (nextKey) and key >= lowest: + if abs(val) < 10 ** nextKey and key >= lowest: mantissa, suffix = val / float(10 ** key), negSuffixMap[key] # Do additional step to eliminate results like 0.9999 => 1000m # Check if the key we're potentially switching to is greater than our diff --git a/gui/viewColumn.py b/gui/viewColumn.py index 9afca36e7..34c3c89ce 100644 --- a/gui/viewColumn.py +++ b/gui/viewColumn.py @@ -17,15 +17,16 @@ # along with pyfa. If not, see . # ============================================================================= +# noinspection PyPackageRequirements import wx class ViewColumn(object): - ''' + """ Abstract class that columns can inherit from. Once the missing methods are correctly implemented, they can be used as columns in a view. - ''' + """ columns = {} def __init__(self, fittingView): @@ -65,4 +66,18 @@ class ViewColumn(object): raise NotImplementedError() -from gui.builtinViewColumns import * # noqa +# noinspection PyUnresolvedReferences +from gui.builtinViewColumns import ( # noqa: E402, F401 + abilities, + ammo, + ammoIcon, + attributeDisplay, + baseIcon, + baseName, + capacitorUse, + maxRange, + misc, + price, + propertyDisplay, + state +) diff --git a/imgs/gui/settings_database.png b/imgs/gui/settings_database.png new file mode 100644 index 000000000..373a0adb0 Binary files /dev/null and b/imgs/gui/settings_database.png differ diff --git a/imgs/gui/settings_fitting.png b/imgs/gui/settings_fitting.png new file mode 100644 index 000000000..60026f35b Binary files /dev/null and b/imgs/gui/settings_fitting.png differ diff --git a/imgs/gui/settings_log.png b/imgs/gui/settings_log.png new file mode 100644 index 000000000..041f8ebb8 Binary files /dev/null and b/imgs/gui/settings_log.png differ diff --git a/imgs/gui/settings_menu.png b/imgs/gui/settings_menu.png new file mode 100644 index 000000000..c1ccc619d Binary files /dev/null and b/imgs/gui/settings_menu.png differ diff --git a/imgs/gui/settings_stats.png b/imgs/gui/settings_stats.png new file mode 100644 index 000000000..088461479 Binary files /dev/null and b/imgs/gui/settings_stats.png differ diff --git a/pyfa.py b/pyfa.py index e465b0d5a..06f8632d1 100755 --- a/pyfa.py +++ b/pyfa.py @@ -19,11 +19,18 @@ # ============================================================================== import sys +import os +import os.path import re import config from optparse import OptionParser, BadOptionError, AmbiguousOptionError +import logbook +from logbook import TimedRotatingFileHandler, Logger, StreamHandler, NestedSetup, FingersCrossedHandler, NullHandler, \ + CRITICAL, ERROR, WARNING, DEBUG, INFO +pyfalog = Logger(__name__) + class PassThroughOptionParser(OptionParser): """ @@ -36,9 +43,30 @@ class PassThroughOptionParser(OptionParser): try: OptionParser._process_args(self, largs, rargs, values) except (BadOptionError, AmbiguousOptionError) as e: + pyfalog.error("Bad startup option passed.") largs.append(e.opt_str) +class LoggerWriter: + def __init__(self, level): + # self.level is really like using log.debug(message) + # at least in my case + self.level = level + + def write(self, message): + # if statement reduces the amount of newlines that are + # printed to the logger + if message not in {'\n', ' '}: + self.level(message.replace("\n", "")) + + def flush(self): + # create a flush method so things can be flushed when + # the system wants to. Not sure if simply 'printing' + # sys.stderr is the correct way to do it, but it seemed + # to work properly for me. + self.level(sys.stderr) + + # Parse command line options usage = "usage: %prog [--root]" parser = PassThroughOptionParser(usage=usage) @@ -47,9 +75,23 @@ parser.add_option("-w", "--wx28", action="store_true", dest="force28", help="For parser.add_option("-d", "--debug", action="store_true", dest="debug", help="Set logger to debug level.", default=False) parser.add_option("-t", "--title", action="store", dest="title", help="Set Window Title", default=None) parser.add_option("-s", "--savepath", action="store", dest="savepath", help="Set the folder for savedata", default=None) +parser.add_option("-l", "--logginglevel", action="store", dest="logginglevel", help="Set desired logging level [Critical|Error|Warning|Info|Debug]", default="Error") (options, args) = parser.parse_args() +if options.logginglevel == "Critical": + options.logginglevel = CRITICAL +elif options.logginglevel == "Error": + options.logginglevel = ERROR +elif options.logginglevel == "Warning": + options.logginglevel = WARNING +elif options.logginglevel == "Info": + options.logginglevel = INFO +elif options.logginglevel == "Debug": + options.logginglevel = DEBUG +else: + options.logginglevel = ERROR + if not hasattr(sys, 'frozen'): if sys.version_info < (2, 6) or sys.version_info > (3, 0): @@ -59,6 +101,7 @@ if not hasattr(sys, 'frozen'): try: import wxversion except ImportError: + wxversion = None print("Cannot find wxPython\nYou can download wxPython (2.8+) from http://www.wxpython.org/") sys.exit(1) @@ -82,22 +125,30 @@ if not hasattr(sys, 'frozen'): betaFlag = True if saMatch.group(3) == "b" else False saBuild = int(saMatch.group(4)) if not betaFlag else 0 if saMajor == 0 and (saMinor < 5 or (saMinor == 5 and saBuild < 8)): - print("Pyfa requires sqlalchemy 0.5.8 at least but current sqlalchemy version is %s\nYou can download sqlalchemy (0.5.8+) from http://www.sqlalchemy.org/".format(sqlalchemy.__version__)) + print("Pyfa requires sqlalchemy 0.5.8 at least but current sqlalchemy version is %s\n" + "You can download sqlalchemy (0.5.8+) from http://www.sqlalchemy.org/".format(sqlalchemy.__version__)) sys.exit(1) else: print("Unknown sqlalchemy version string format, skipping check") except ImportError: + sqlalchemy = None print("Cannot find sqlalchemy.\nYou can download sqlalchemy (0.6+) from http://www.sqlalchemy.org/") sys.exit(1) # check also for dateutil module installed. try: + # noinspection PyPackageRequirements import dateutil.parser # noqa - Copied import statement from service/update.py except ImportError: + dateutil = None print("Cannot find python-dateutil.\nYou can download python-dateutil from https://pypi.python.org/pypi/python-dateutil") sys.exit(1) + logVersion = logbook.__version__.split('.') + if int(logVersion[0]) < 1: + print ("Logbook version >= 1.0.0 is recommended. You may have some performance issues by continuing to use an earlier version.") + if __name__ == "__main__": # Configure paths @@ -109,30 +160,135 @@ if __name__ == "__main__": options.title = "pyfa %s%s - Python Fitting Assistant" % (config.version, "" if config.tag.lower() != 'git' else " (git)") config.debug = options.debug - # convert to unicode if it is set - if options.savepath is not None: - options.savepath = unicode(options.savepath) - config.defPaths(options.savepath) - - # Basic logging initialization - import logging - logging.basicConfig() # Import everything + # noinspection PyPackageRequirements import wx import os import os.path - import eos.db - import service.prefetch - from gui.mainFrame import MainFrame + try: + # convert to unicode if it is set + if options.savepath is not None: + options.savepath = unicode(options.savepath) + config.defPaths(options.savepath) - # Make sure the saveddata db exists - if not os.path.exists(config.savePath): - os.mkdir(config.savePath) + # Basic logging initialization - eos.db.saveddata_meta.create_all() + # Logging levels: + ''' + logbook.CRITICAL + logbook.ERROR + logbook.WARNING + logbook.INFO + logbook.DEBUG + logbook.NOTSET + ''' - pyfa = wx.App(False) - MainFrame(options.title) - pyfa.MainLoop() + if options.debug: + savePath_filename = "Pyfa_debug.log" + else: + savePath_filename = "Pyfa.log" + + savePath_Destination = os.path.join(config.savePath, savePath_filename) + + try: + if options.debug: + logging_mode = "Debug" + logging_setup = NestedSetup([ + # make sure we never bubble up to the stderr handler + # if we run out of setup handling + NullHandler(), + StreamHandler( + sys.stdout, + bubble=False, + level=options.logginglevel + ), + TimedRotatingFileHandler( + savePath_Destination, + level=0, + backup_count=3, + bubble=True, + date_format='%Y-%m-%d', + ), + ]) + else: + logging_mode = "User" + logging_setup = NestedSetup([ + # make sure we never bubble up to the stderr handler + # if we run out of setup handling + NullHandler(), + FingersCrossedHandler( + TimedRotatingFileHandler( + savePath_Destination, + level=0, + backup_count=3, + bubble=False, + date_format='%Y-%m-%d', + ), + action_level=ERROR, + buffer_size=1000, + # pull_information=True, + # reset=False, + ) + ]) + except: + logging_mode = "Console Only" + logging_setup = NestedSetup([ + # make sure we never bubble up to the stderr handler + # if we run out of setup handling + NullHandler(), + StreamHandler( + sys.stdout, + bubble=False + ) + ]) + + import eos.db + # noinspection PyUnresolvedReferences + import service.prefetch # noqa: F401 + + # Make sure the saveddata db exists + if not os.path.exists(config.savePath): + os.mkdir(config.savePath) + + eos.db.saveddata_meta.create_all() + + except Exception, e: + import traceback + from gui.errorDialog import ErrorFrame + + tb = traceback.format_exc() + + pyfa = wx.App(False) + ErrorFrame(e, tb) + pyfa.MainLoop() + sys.exit() + + with logging_setup.threadbound(): + # Don't redirect if frozen + if not hasattr(sys, 'frozen'): + # Output all stdout (print) messages as warnings + try: + sys.stdout = LoggerWriter(pyfalog.warning) + except ValueError, Exception: + pyfalog.critical("Cannot access log file. Continuing without writing stdout to log.") + + if not options.debug: + # Output all stderr (stacktrace) messages as critical + try: + sys.stderr = LoggerWriter(pyfalog.critical) + except ValueError, Exception: + pyfalog.critical("Cannot access log file. Continuing without writing stderr to log.") + + pyfalog.info("Starting Pyfa") + pyfalog.info("Running in logging mode: {0}", logging_mode) + + if hasattr(sys, 'frozen') and options.debug: + pyfalog.critical("Running in frozen mode with debug turned on. Forcing all output to be written to log.") + + from gui.mainFrame import MainFrame + + pyfa = wx.App(False) + MainFrame(options.title) + pyfa.MainLoop() diff --git a/requirements.txt b/requirements.txt index 2d8894113..d3bc33dde 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +logbook>=1.0.0 matplotlib PyYAML python-dateutil diff --git a/requirements_build_OSx.txt b/requirements_build_OSx.txt new file mode 100644 index 000000000..51f6135fd --- /dev/null +++ b/requirements_build_OSx.txt @@ -0,0 +1,9 @@ +PyInstaller >= 3.2.1 +cycler >= 0.10.0 +functools32 >= 3.2.3 +future >= 0.16.0 +numpy >= 1.12. +pyparsing >= 2.1.10 +pypiwin32 >= 219 +pytz >= 2016.10 +six >= 1.10.0 diff --git a/requirements_build_linux.txt b/requirements_build_linux.txt new file mode 100644 index 000000000..3a4640baf --- /dev/null +++ b/requirements_build_linux.txt @@ -0,0 +1,8 @@ +PyInstaller >= 3.2.1 +cycler >= 0.10.0 +functools32 >= 3.2.3 +future >= 0.16.0 +numpy >= 1.12. +pyparsing >= 2.1.10 +pytz >= 2016.10 +six diff --git a/requirements_build_windows.txt b/requirements_build_windows.txt new file mode 100644 index 000000000..0d5cfb0ac --- /dev/null +++ b/requirements_build_windows.txt @@ -0,0 +1,11 @@ +PyInstaller >= 3.2.1 +cx_freeze == 4.3.4 +cycler >= 0.10.0 +functools32 >= 3.2.3 +future >= 0.16.0 +numpy >= 1.12. +pyparsing >= 2.1.10 +pypiwin32 >= 219 +pytz >= 2016.10 +six >= 1.10.0 +tornado diff --git a/scripts/upx.exe b/scripts/upx.exe new file mode 100644 index 000000000..71f688acb Binary files /dev/null and b/scripts/upx.exe differ diff --git a/service/attribute.py b/service/attribute.py index ee4f43328..5b010bcc5 100644 --- a/service/attribute.py +++ b/service/attribute.py @@ -20,7 +20,7 @@ import eos.db -class Attribute(): +class Attribute(object): instance = None @classmethod @@ -30,7 +30,8 @@ class Attribute(): return cls.instance - def getAttributeInfo(self, identity): + @staticmethod + def getAttributeInfo(identity): if isinstance(identity, (int, basestring)): info = eos.db.getAttributeInfo(identity, eager=("icon", "unit")) elif isinstance(identity, (int, float)): diff --git a/service/character.py b/service/character.py index 25333edd6..1e5185b69 100644 --- a/service/character.py +++ b/service/character.py @@ -20,13 +20,14 @@ import copy import itertools import json -import logging +from logbook import Logger import threading from codecs import open from xml.etree import ElementTree from xml.dom import minidom import gzip +# noinspection PyPackageRequirements import wx import config @@ -38,7 +39,7 @@ from eos.saveddata.character import Character as es_Character from eos.saveddata.module import Slot as es_Slot, Module as es_Module from eos.saveddata.fighter import Fighter as es_Fighter -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class CharacterImportThread(threading.Thread): @@ -71,7 +72,7 @@ class CharacterImportThread(threading.Thread): charFile = open(path, mode='r').read() doc = minidom.parseString(charFile) if doc.documentElement.tagName not in ("SerializableCCPCharacter", "SerializableUriCharacter"): - logger.error("Incorrect EVEMon XML sheet") + pyfalog.error("Incorrect EVEMon XML sheet") raise RuntimeError("Incorrect EVEMon XML sheet") name = doc.getElementsByTagName("name")[0].firstChild.nodeValue skill_els = doc.getElementsByTagName("skill") @@ -83,16 +84,17 @@ class CharacterImportThread(threading.Thread): "level": int(skill.getAttribute("level")), }) else: - logger.error("Attempted to import unknown skill %s (ID: %s) (Level: %s)", - skill.getAttribute("name"), - skill.getAttribute("typeID"), - skill.getAttribute("level"), - ) + pyfalog.error( + "Attempted to import unknown skill {0} (ID: {1}) (Level: {2})", + skill.getAttribute("name"), + skill.getAttribute("typeID"), + skill.getAttribute("level"), + ) char = sCharacter.new(name + " (EVEMon)") sCharacter.apiUpdateCharSheet(char.ID, skills) except Exception, e: - logger.error("Exception on character import:") - logger.error(e) + pyfalog.error("Exception on character import:") + pyfalog.error(e) continue wx.CallAfter(self.callback) @@ -189,33 +191,42 @@ class Character(object): return prettydata - def backupSkills(self, path, saveFmt, activeFit, callback): + @staticmethod + def backupSkills(path, saveFmt, activeFit, callback): thread = SkillBackupThread(path, saveFmt, activeFit, callback) + pyfalog.debug("Starting backup skills thread.") thread.start() - def importCharacter(self, path, callback): + @staticmethod + def importCharacter(path, callback): thread = CharacterImportThread(path, callback) + pyfalog.debug("Starting import character thread.") thread.start() - def all0(self): + @staticmethod + def all0(): return es_Character.getAll0() def all0ID(self): return self.all0().ID - def all5(self): + @staticmethod + def all5(): return es_Character.getAll5() def all5ID(self): return self.all5().ID - def getAlphaCloneList(self): + @staticmethod + def getAlphaCloneList(): return eos.db.getAlphaCloneList() - def getCharacterList(self): + @staticmethod + def getCharacterList(): return eos.db.getCharacterList() - def getCharacter(self, charID): + @staticmethod + def getCharacter(charID): char = eos.db.getCharacter(charID) return char @@ -226,7 +237,8 @@ class Character(object): char = eos.db.getCharacter(charID) char.saveLevels() - def saveCharacterAs(self, charID, newName): + @staticmethod + def saveCharacterAs(charID, newName): """Save edited skills as a new character""" char = eos.db.getCharacter(charID) newChar = copy.deepcopy(char) @@ -236,12 +248,14 @@ class Character(object): # revert old char char.revertLevels() - def revertCharacter(self, charID): + @staticmethod + def revertCharacter(charID): """Rollback edited skills""" char = eos.db.getCharacter(charID) char.revertLevels() - def getSkillGroups(self): + @staticmethod + def getSkillGroups(): cat = eos.db.getCategory(16) groups = [] for grp in cat.groups: @@ -249,7 +263,8 @@ class Character(object): groups.append((grp.ID, grp.name)) return groups - def getSkills(self, groupID): + @staticmethod + def getSkills(groupID): group = eos.db.getGroup(groupID) skills = [] for skill in group.items: @@ -257,59 +272,71 @@ class Character(object): skills.append((skill.ID, skill.name)) return skills - def setAlphaClone(self, char, cloneID): + @staticmethod + def setAlphaClone(char, cloneID): char.alphaCloneID = cloneID eos.db.commit() - def getSkillDescription(self, itemID): + @staticmethod + def getSkillDescription(itemID): return eos.db.getItem(itemID).description - def getGroupDescription(self, groupID): + @staticmethod + def getGroupDescription(groupID): return eos.db.getMarketGroup(groupID).description - def getSkillLevel(self, charID, skillID): + @staticmethod + def getSkillLevel(charID, skillID): skill = eos.db.getCharacter(charID).getSkill(skillID) - return (skill.level if skill.learned else "Not learned", skill.isDirty) + return skill.level if skill.learned else "Not learned", skill.isDirty - def getDirtySkills(self, charID): + @staticmethod + def getDirtySkills(charID): return eos.db.getCharacter(charID).dirtySkills - def getCharName(self, charID): + @staticmethod + def getCharName(charID): return eos.db.getCharacter(charID).name - def new(self, name="New Character"): + @staticmethod + def new(name="New Character"): char = es_Character(name) eos.db.save(char) return char - def rename(self, char, newName): + @staticmethod + def rename(char, newName): if char.name in ("All 0", "All 5"): - logger.info("Cannot rename built in characters.") + pyfalog.info("Cannot rename built in characters.") else: char.name = newName eos.db.commit() - def copy(self, char): + @staticmethod + def copy(char): newChar = copy.deepcopy(char) eos.db.save(newChar) return newChar - def delete(self, char): + @staticmethod + def delete(char): eos.db.remove(char) - def getApiDetails(self, charID): + @staticmethod + def getApiDetails(charID): char = eos.db.getCharacter(charID) if char.chars is not None: chars = json.loads(char.chars) else: chars = None - return (char.apiID or "", char.apiKey or "", char.defaultChar or "", chars or []) + return char.apiID or "", char.apiKey or "", char.defaultChar or "", chars or [] def apiEnabled(self, charID): id_, key, default, _ = self.getApiDetails(charID) return id_ is not "" and key is not "" and default is not "" - def apiCharList(self, charID, userID, apiKey): + @staticmethod + def apiCharList(charID, userID, apiKey): char = eos.db.getCharacter(charID) char.apiID = userID @@ -323,7 +350,8 @@ class Character(object): char.chars = json.dumps(charList) return charList - def apiFetch(self, charID, charName): + @staticmethod + def apiFetch(charID, charName): dbChar = eos.db.getCharacter(charID) dbChar.defaultChar = charName @@ -343,12 +371,14 @@ class Character(object): dbChar.apiUpdateCharSheet(sheet.skills) eos.db.commit() - def apiUpdateCharSheet(self, charID, skills): + @staticmethod + def apiUpdateCharSheet(charID, skills): char = eos.db.getCharacter(charID) char.apiUpdateCharSheet(skills) eos.db.commit() - def changeLevel(self, charID, skillID, level, persist=False): + @staticmethod + def changeLevel(charID, skillID, level, persist=False): char = eos.db.getCharacter(charID) skill = char.getSkill(skillID) if isinstance(level, basestring) or level > 5 or level < 0: @@ -361,32 +391,37 @@ class Character(object): eos.db.commit() - def revertLevel(self, charID, skillID): + @staticmethod + def revertLevel(charID, skillID): char = eos.db.getCharacter(charID) skill = char.getSkill(skillID) skill.revert() - def saveSkill(self, charID, skillID): + @staticmethod + def saveSkill(charID, skillID): char = eos.db.getCharacter(charID) skill = char.getSkill(skillID) skill.saveLevel() - def addImplant(self, charID, itemID): + @staticmethod + def addImplant(charID, itemID): char = eos.db.getCharacter(charID) if char.ro: - logger.error("Trying to add implant to read-only character") + pyfalog.error("Trying to add implant to read-only character") return implant = es_Implant(eos.db.getItem(itemID)) char.implants.append(implant) eos.db.commit() - def removeImplant(self, charID, implant): + @staticmethod + def removeImplant(charID, implant): char = eos.db.getCharacter(charID) char.implants.remove(implant) eos.db.commit() - def getImplants(self, charID): + @staticmethod + def getImplants(charID): char = eos.db.getCharacter(charID) return char.implants diff --git a/service/crest.py b/service/crest.py index 74c74d311..27f5b6c5e 100644 --- a/service/crest.py +++ b/service/crest.py @@ -1,6 +1,6 @@ +# noinspection PyPackageRequirements import wx -import thread -import logging +from logbook import Logger import threading import copy import uuid @@ -8,13 +8,13 @@ import time import eos.db from eos.enum import Enum -from eos.types import CrestChar +from eos.saveddata.crestchar import CrestChar import gui.globalEvents as GE from service.settings import CRESTSettings from service.server import StoppableHTTPServer, AuthHandler from service.pycrest.eve import EVE -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class Servers(Enum): @@ -27,9 +27,9 @@ class CrestModes(Enum): USER = 1 -class Crest(): +class Crest(object): clientIDs = { - Servers.TQ: 'f9be379951c046339dc13a00e6be7704', + Servers.TQ : 'f9be379951c046339dc13a00e6be7704', Servers.SISI: 'af87365240d644f7950af563b8418bad' } @@ -77,11 +77,11 @@ class Crest(): # Base EVE connection that is copied to all characters self.eve = EVE( - client_id=self.settings.get('clientID') if self.settings.get( - 'mode') == CrestModes.USER else self.clientIDs.get(self.settings.get('server')), - api_key=self.settings.get('clientSecret') if self.settings.get('mode') == CrestModes.USER else None, - redirect_uri=self.clientCallback, - testing=self.isTestServer + client_id=self.settings.get('clientID') if self.settings.get( + 'mode') == CrestModes.USER else self.clientIDs.get(self.settings.get('server')), + api_key=self.settings.get('clientSecret') if self.settings.get('mode') == CrestModes.USER else None, + redirect_uri=self.clientCallback, + testing=self.isTestServer ) self.implicitCharacter = None @@ -152,42 +152,46 @@ class Crest(): def logout(self): """Logout of implicit character""" - logging.debug("Character logout") + pyfalog.debug("Character logout") self.implicitCharacter = None wx.PostEvent(self.mainFrame, GE.SsoLogout(type=self.settings.get('mode'))) def stopServer(self): - logging.debug("Stopping Server") + pyfalog.debug("Stopping Server") self.httpd.stop() self.httpd = None def startServer(self): - logging.debug("Starting server") + pyfalog.debug("Starting server") if self.httpd: self.stopServer() time.sleep(1) # we need this to ensure that the previous get_request finishes, and then the socket will close - self.httpd = StoppableHTTPServer(('', 6461), AuthHandler) - thread.start_new_thread(self.httpd.serve, (self.handleLogin,)) + self.httpd = StoppableHTTPServer(('localhost', 6461), AuthHandler) + + self.serverThread = threading.Thread(target=self.httpd.serve, args=(self.handleLogin,)) + self.serverThread.name = "CRESTServer" + self.serverThread.daemon = True + self.serverThread.start() self.state = str(uuid.uuid4()) return self.eve.auth_uri(scopes=self.scopes, state=self.state) def handleLogin(self, message): if not message: - return + raise Exception("Could not parse out querystring parameters.") if message['state'][0] != self.state: - logger.warn("OAUTH state mismatch") - return + pyfalog.warn("OAUTH state mismatch") + raise Exception("OAUTH State Mismatch.") - logger.debug("Handling CREST login with: %s" % message) + pyfalog.debug("Handling CREST login with: {0}", message) if 'access_token' in message: # implicit eve = copy.deepcopy(self.eve) eve.temptoken_authorize( - access_token=message['access_token'][0], - expires_in=int(message['expires_in'][0]) + access_token=message['access_token'][0], + expires_in=int(message['expires_in'][0]) ) self.ssoTimer = threading.Timer(int(message['expires_in'][0]), self.logout) self.ssoTimer.start() @@ -195,7 +199,7 @@ class Crest(): eve() info = eve.whoami() - logger.debug("Got character info: %s" % info) + pyfalog.debug("Got character info: {0}", info) self.implicitCharacter = CrestChar(info['CharacterID'], info['CharacterName']) self.implicitCharacter.eve = eve @@ -208,7 +212,7 @@ class Crest(): eve() info = eve.whoami() - logger.debug("Got character info: %s" % info) + pyfalog.debug("Got character info: {0}", info) # check if we have character already. If so, simply replace refresh_token char = self.getCrestCharacter(int(info['CharacterID'])) @@ -221,5 +225,3 @@ class Crest(): eos.db.save(char) wx.PostEvent(self.mainFrame, GE.SsoLogin(type=CrestModes.USER)) - - self.stopServer() diff --git a/service/damagePattern.py b/service/damagePattern.py index 2343693d3..5a169734c 100644 --- a/service/damagePattern.py +++ b/service/damagePattern.py @@ -27,7 +27,7 @@ class ImportError(Exception): pass -class DamagePattern(): +class DamagePattern(object): instance = None @classmethod @@ -37,31 +37,38 @@ class DamagePattern(): return cls.instance - def getDamagePatternList(self): + @staticmethod + def getDamagePatternList(): return eos.db.getDamagePatternList() - def getDamagePattern(self, name): + @staticmethod + def getDamagePattern(name): return eos.db.getDamagePattern(name) - def newPattern(self, name): + @staticmethod + def newPattern(name): p = es_DamagePattern(0, 0, 0, 0) p.name = name eos.db.save(p) return p - def renamePattern(self, p, newName): + @staticmethod + def renamePattern(p, newName): p.name = newName eos.db.save(p) - def deletePattern(self, p): + @staticmethod + def deletePattern(p): eos.db.remove(p) - def copyPattern(self, p): + @staticmethod + def copyPattern(p): newP = copy.deepcopy(p) eos.db.save(newP) return newP - def saveChanges(self, p): + @staticmethod + def saveChanges(p): eos.db.save(p) def importPatterns(self, text): diff --git a/service/eveapi.py b/service/eveapi.py index 67a238f47..c4ac681a0 100644 --- a/service/eveapi.py +++ b/service/eveapi.py @@ -712,6 +712,8 @@ class _Parser(object): class Element(object): + _name = None + # Element is a namespace for attributes and nested tags def __str__(self): return "" % self._name @@ -873,10 +875,10 @@ class Rowset(object): self._rows.sort(*args, **kw) def __str__(self): - return ("Rowset(columns=[%s], rows=%d)" % (','.join(self._cols), len(self))) + return "Rowset(columns=[%s], rows=%d)" % (','.join(self._cols), len(self)) def __getstate__(self): - return (self._cols, self._rows) + return self._cols, self._rows def __setstate__(self, state): self._cols, self._rows = state @@ -935,7 +937,7 @@ class IndexRowset(Rowset): self._items[row[self._ki]] = row def __getstate__(self): - return (Rowset.__getstate__(self), self._items, self._ki) + return Rowset.__getstate__(self), self._items, self._ki def __setstate__(self, state): state, self._items, self._ki = state @@ -1003,7 +1005,7 @@ class FilterRowset(object): return Rowset(self._cols, self._items[i]) def __getstate__(self): - return (self._cols, self._rows, self._items, self.key, self.key2) + return self._cols, self._rows, self._items, self.key, self.key2 def __setstate__(self, state): self._cols, self._rows, self._items, self.key, self.key2 = state diff --git a/service/fit.py b/service/fit.py index c8c97baf5..50955c6ae 100644 --- a/service/fit.py +++ b/service/fit.py @@ -18,7 +18,7 @@ # =============================================================================== import copy -import logging +from logbook import Logger import eos.db from eos.saveddata.booster import Booster as es_Booster @@ -29,15 +29,14 @@ from eos.saveddata.damagePattern import DamagePattern as es_DamagePattern from eos.saveddata.drone import Drone as es_Drone from eos.saveddata.fighter import Fighter as es_Fighter from eos.saveddata.implant import Implant as es_Implant -from eos.saveddata.module import Module as es_Module from eos.saveddata.ship import Ship as es_Ship -from eos.types import State, Slot, Fit as FitType +from eos.saveddata.module import Module as es_Module, State, Slot +from eos.saveddata.fit import Fit as FitType from service.character import Character from service.damagePattern import DamagePattern -from service.market import Market from service.settings import SettingsProvider -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) class Fit(object): @@ -51,6 +50,7 @@ class Fit(object): return cls.instance def __init__(self): + pyfalog.debug("Initialize Fit class") self.pattern = DamagePattern.getInstance().getDamagePattern("Uniform") self.targetResists = None self.character = saveddata_Character.getAll5() @@ -71,16 +71,19 @@ class Fit(object): "enableGaugeAnimation": True, "exportCharges": True, "openFitInNew": False, + "priceSystem": "Jita", } self.serviceFittingOptions = SettingsProvider.getInstance().getSettings( "pyfaServiceFittingOptions", serviceFittingDefaultOptions) - def getAllFits(self): + @staticmethod + def getAllFits(): fits = eos.db.getFitList() return fits - def getFitsWithShip(self, shipID): + @staticmethod + def getFitsWithShip(shipID): """ Lists fits of shipID, used with shipBrowser """ fits = eos.db.getFitsWithShip(shipID) names = [] @@ -89,7 +92,8 @@ class Fit(object): return names - def getBoosterFits(self): + @staticmethod + def getBoosterFits(): """ Lists fits flagged as booster """ fits = eos.db.getBoosterFits() names = [] @@ -98,14 +102,17 @@ class Fit(object): return names - def countAllFits(self): + @staticmethod + def countAllFits(): return eos.db.countAllFits() - def countFitsWithShip(self, stuff): + @staticmethod + def countFitsWithShip(stuff): count = eos.db.countFitsWithShip(stuff) return count - def getModule(self, fitID, pos): + @staticmethod + def getModule(fitID, pos): fit = eos.db.getFit(fitID) return fit.modules[pos] @@ -124,17 +131,20 @@ class Fit(object): self.recalc(fit) return fit.ID - def toggleBoostFit(self, fitID): + @staticmethod + def toggleBoostFit(fitID): fit = eos.db.getFit(fitID) fit.booster = not fit.booster eos.db.commit() - def renameFit(self, fitID, newName): + @staticmethod + def renameFit(fitID, newName): fit = eos.db.getFit(fitID) fit.name = newName eos.db.commit() - def deleteFit(self, fitID): + @staticmethod + def deleteFit(fitID): fit = eos.db.getFit(fitID) eos.db.remove(fit) @@ -145,13 +155,15 @@ class Fit(object): if projection.victim_fit in eos.db.saveddata_session: # GH issue #359 eos.db.saveddata_session.refresh(projection.victim_fit) - def copyFit(self, fitID): + @staticmethod + def copyFit(fitID): fit = eos.db.getFit(fitID) newFit = copy.deepcopy(fit) eos.db.save(newFit) return newFit.ID - def clearFit(self, fitID): + @staticmethod + def clearFit(fitID): if fitID is None: return None @@ -215,7 +227,8 @@ class Fit(object): fit.inited = True return fit - def searchFits(self, name): + @staticmethod + def searchFits(name): results = eos.db.searchFits(name) fits = [] for fit in results: @@ -233,6 +246,7 @@ class Fit(object): try: implant = es_Implant(item) except ValueError: + pyfalog.warning("Invalid item: {0}", itemID) return False fit.implants.append(implant) @@ -240,14 +254,15 @@ class Fit(object): self.recalc(fit) return True - def removeImplant(self, fitID, position): + def removeImplant(self, fitID, position, recalc=True): if fitID is None: return False fit = eos.db.getFit(fitID) implant = fit.implants[position] fit.implants.remove(implant) - self.recalc(fit) + if recalc: + self.recalc(fit) return True def addBooster(self, fitID, itemID): @@ -259,6 +274,7 @@ class Fit(object): try: booster = es_Booster(item) except ValueError: + pyfalog.warning("Invalid item: {0}", itemID) return False fit.boosters.append(booster) @@ -419,6 +435,7 @@ class Fit(object): try: m = es_Module(item) except ValueError: + pyfalog.warning("Invalid item: {0}", itemID) return False if m.item.category.name == "Subsystem": @@ -466,6 +483,7 @@ class Fit(object): try: m = es_Module(item) except ValueError: + pyfalog.warning("Invalid item: {0}", newItemID) return False if m.fits(fit): @@ -506,6 +524,7 @@ class Fit(object): if cargoP.isValidState(State.ACTIVE): cargoP.state = State.ACTIVE except: + pyfalog.warning("Invalid item: {0}", cargo.item) return if cargoP.slot != module.slot: # can't swap modules to different racks @@ -538,7 +557,8 @@ class Fit(object): eos.db.commit() self.recalc(fit) - def swapModules(self, fitID, src, dst): + @staticmethod + def swapModules(fitID, src, dst): fit = eos.db.getFit(fitID) # Gather modules srcMod = fit.modules[src] @@ -639,7 +659,7 @@ class Fit(object): total = fit.getNumSlots(fighter.slot) standardAttackActive = False for ability in fighter.abilities: - if (ability.effect.isImplemented and ability.effect.handlerName == u'fighterabilityattackm'): + if ability.effect.isImplemented and ability.effect.handlerName == u'fighterabilityattackm': # Activate "standard attack" if available ability.active = True standardAttackActive = True @@ -674,7 +694,7 @@ class Fit(object): self.recalc(fit) return True - def addDrone(self, fitID, itemID): + def addDrone(self, fitID, itemID, numDronesToAdd=1): if fitID is None: return False @@ -693,7 +713,7 @@ class Fit(object): fit.drones.append(drone) else: return False - drone.amount += 1 + drone.amount += numDronesToAdd eos.db.commit() self.recalc(fit) return True @@ -714,12 +734,19 @@ class Fit(object): fit.drones.remove(d1) d2.amount += d1.amount - d2.amountActive += d1.amountActive if d1.amountActive > 0 else -d2.amountActive + d2.amountActive += d1.amountActive + + # If we have less than the total number of drones active, make them all active. Fixes #728 + # This could be removed if we ever add an enhancement to make drone stacks partially active. + if d2.amount > d2.amountActive: + d2.amountActive = d2.amount + eos.db.commit() self.recalc(fit) return True - def splitDrones(self, fit, d, amount, l): + @staticmethod + def splitDrones(fit, d, amount, l): total = d.amount active = d.amountActive > 0 d.amount = amount @@ -823,7 +850,8 @@ class Fit(object): fit.character = self.character = eos.db.getCharacter(charID) self.recalc(fit) - def isAmmo(self, itemID): + @staticmethod + def isAmmo(itemID): return eos.db.getItem(itemID).category.name == "Charge" def setAmmo(self, fitID, ammoID, modules): @@ -839,7 +867,8 @@ class Fit(object): self.recalc(fit) - def getTargetResists(self, fitID): + @staticmethod + def getTargetResists(fitID): if fitID is None: return @@ -856,7 +885,8 @@ class Fit(object): self.recalc(fit) - def getDamagePattern(self, fitID): + @staticmethod + def getDamagePattern(fitID): if fitID is None: return @@ -904,13 +934,17 @@ class Fit(object): changed = False for mod in fit.modules: if mod != base: - if not mod.canHaveState(mod.state): + # fix for #529, where a module may be in incorrect state after CCP changes mechanics of module + if not mod.canHaveState(mod.state) or not mod.isValidState(mod.state): mod.state = State.ONLINE changed = True + for mod in fit.projectedModules: - if not mod.canHaveState(mod.state, fit): + # fix for #529, where a module may be in incorrect state after CCP changes mechanics of module + if not mod.canHaveState(mod.state, fit) or not mod.isValidState(mod.state): mod.state = State.OFFLINE changed = True + for drone in fit.projectedDrones: if drone.amountActive > 0 and not drone.canBeApplied(fit): drone.amountActive = 0 @@ -921,21 +955,27 @@ class Fit(object): self.recalc(fit) def toggleModulesState(self, fitID, base, modules, click): + changed = False proposedState = self.__getProposedState(base, click) + if proposedState != base.state: + changed = True base.state = proposedState for mod in modules: if mod != base: - mod.state = self.__getProposedState(mod, click, - proposedState) + p = self.__getProposedState(mod, click, proposedState) + mod.state = p + if p != mod.state: + changed = True - eos.db.commit() - fit = eos.db.getFit(fitID) + if changed: + eos.db.commit() + fit = eos.db.getFit(fitID) - # As some items may affect state-limiting attributes of the ship, calculate new attributes first - self.recalc(fit) - # Then, check states of all modules and change where needed. This will recalc if needed - self.checkStates(fit, base) + # As some items may affect state-limiting attributes of the ship, calculate new attributes first + self.recalc(fit) + # Then, check states of all modules and change where needed. This will recalc if needed + self.checkStates(fit, base) # Old state : New State localMap = { @@ -989,7 +1029,7 @@ class Fit(object): self.recalc(fit) def recalc(self, fit, withBoosters=True): - logger.debug("=" * 10 + "recalc" + "=" * 10) + pyfalog.info("=" * 10 + "recalc" + "=" * 10) if fit.factorReload is not self.serviceFittingOptions["useGlobalForceReload"]: fit.factorReload = self.serviceFittingOptions["useGlobalForceReload"] fit.clear() diff --git a/service/implantSet.py b/service/implantSet.py index f1da65aed..8d86c816d 100644 --- a/service/implantSet.py +++ b/service/implantSet.py @@ -39,44 +39,54 @@ class ImplantSets(object): return cls.instance - def getImplantSetList(self): + @staticmethod + def getImplantSetList(): return eos.db.getImplantSetList(None) - def getImplantSet(self, name): + @staticmethod + def getImplantSet(name): return eos.db.getImplantSet(name) - def getImplants(self, setID): + @staticmethod + def getImplants(setID): return eos.db.getImplantSet(setID).implants - def addImplant(self, setID, itemID): + @staticmethod + def addImplant(setID, itemID): implant_set = eos.db.getImplantSet(setID) implant = es_Implant(eos.db.getItem(itemID)) implant_set.implants.append(implant) eos.db.commit() - def removeImplant(self, setID, implant): + @staticmethod + def removeImplant(setID, implant): eos.db.getImplantSet(setID).implants.remove(implant) eos.db.commit() - def newSet(self, name): + @staticmethod + def newSet(name): implant_set = es_ImplantSet() implant_set.name = name eos.db.save(implant_set) return implant_set - def renameSet(self, implant_set, newName): + @staticmethod + def renameSet(implant_set, newName): implant_set.name = newName eos.db.save(implant_set) - def deleteSet(self, implant_set): + @staticmethod + def deleteSet(implant_set): eos.db.remove(implant_set) - def copySet(self, implant_set): + @staticmethod + def copySet(implant_set): newS = copy.deepcopy(implant_set) eos.db.save(newS) return newS - def saveChanges(self, implant_set): + @staticmethod + def saveChanges(implant_set): eos.db.save(implant_set) def importSets(self, text): diff --git a/service/market.py b/service/market.py index 6edb3d432..e311c94e5 100644 --- a/service/market.py +++ b/service/market.py @@ -19,9 +19,10 @@ import re import threading -import logging +from logbook import Logger import Queue +# noinspection PyPackageRequirements import wx from sqlalchemy.sql import or_ @@ -31,18 +32,16 @@ from service import conversions from service.settings import SettingsProvider from service.price import Price -# TODO: Convert eos.types over to eos.gamedata -# from eos.gamedata import Category as e_Category, Group as e_Group, Item as e_Item - -from eos.types import MarketGroup as types_MarketGroup, MetaGroup as types_MetaGroup, MetaType as types_MetaType, \ - Category as types_Category, Item as types_Item, Group as types_Group, Price as types_Price +from eos.gamedata import Category as types_Category, Group as types_Group, Item as types_Item, MarketGroup as types_MarketGroup, \ + MetaGroup as types_MetaGroup, MetaType as types_MetaType +from eos.saveddata.price import Price as types_Price try: from collections import OrderedDict except ImportError: from utils.compat import OrderedDict -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) # Event which tells threads dependent on Market that it's initialized mktRdy = threading.Event() @@ -51,6 +50,7 @@ mktRdy = threading.Event() class ShipBrowserWorkerThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) + pyfalog.debug("Initialize ShipBrowserWorkerThread.") self.name = "ShipBrowser" def run(self): @@ -74,24 +74,29 @@ class ShipBrowserWorkerThread(threading.Thread): cache[id_] = set_ wx.CallAfter(callback, (id_, set_)) - except: - pass + except Exception as e: + pyfalog.critical("Callback failed.") + pyfalog.critical(e) finally: try: queue.task_done() - except: - pass + except Exception as e: + pyfalog.critical("Queue task done failed.") + pyfalog.critical(e) class PriceWorkerThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.name = "PriceWorker" + pyfalog.debug("Initialize PriceWorkerThread.") def run(self): + pyfalog.debug("Run start") self.queue = Queue.Queue() self.wait = {} self.processUpdates() + pyfalog.debug("Run end") def processUpdates(self): queue = self.queue @@ -126,6 +131,7 @@ class SearchWorkerThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.name = "SearchWorker" + pyfalog.debug("Initialize SearchWorkerThread.") def run(self): self.cv = threading.Condition() @@ -170,7 +176,7 @@ class SearchWorkerThread(threading.Thread): self.cv.release() -class Market(): +class Market(object): instance = None def __init__(self): @@ -180,7 +186,7 @@ class Market(): serviceMarketRecentlyUsedModules = {"pyfaMarketRecentlyUsedModules": []} self.serviceMarketRecentlyUsedModules = SettingsProvider.getInstance().getSettings( - "pyfaMarketRecentlyUsedModules", serviceMarketRecentlyUsedModules) + "pyfaMarketRecentlyUsedModules", serviceMarketRecentlyUsedModules) # Start price fetcher self.priceWorkerThread = PriceWorkerThread() @@ -210,41 +216,41 @@ class Market(): self.les_grp.description = "" self.les_grp.icon = None self.ITEMS_FORCEGROUP = { - "Opux Luxury Yacht": self.les_grp, + "Opux Luxury Yacht" : self.les_grp, # One of those is wedding present at CCP fanfest, another was hijacked from ISD guy during an event - "Silver Magnate": self.les_grp, # Amarr Championship prize - "Gold Magnate": self.les_grp, # Amarr Championship prize - "Armageddon Imperial Issue": self.les_grp, # Amarr Championship prize - "Apocalypse Imperial Issue": self.les_grp, # Amarr Championship prize - "Guardian-Vexor": self.les_grp, # Illegal rewards for the Gallente Frontier Tour Lines event arc - "Megathron Federate Issue": self.les_grp, # Reward during Crielere event - "Raven State Issue": self.les_grp, # AT4 prize - "Tempest Tribal Issue": self.les_grp, # AT4 prize - "Apotheosis": self.les_grp, # 5th EVE anniversary present - "Zephyr": self.les_grp, # 2010 new year gift - "Primae": self.les_grp, # Promotion of planetary interaction - "Freki": self.les_grp, # AT7 prize - "Mimir": self.les_grp, # AT7 prize - "Utu": self.les_grp, # AT8 prize - "Adrestia": self.les_grp, # AT8 prize - "Echelon": self.les_grp, # 2011 new year gift - "Malice": self.les_grp, # AT9 prize - "Vangel": self.les_grp, # AT9 prize - "Cambion": self.les_grp, # AT10 prize - "Etana": self.les_grp, # AT10 prize - "Chremoas": self.les_grp, # AT11 prize :( - "Moracha": self.les_grp, # AT11 prize + "Silver Magnate" : self.les_grp, # Amarr Championship prize + "Gold Magnate" : self.les_grp, # Amarr Championship prize + "Armageddon Imperial Issue" : self.les_grp, # Amarr Championship prize + "Apocalypse Imperial Issue" : self.les_grp, # Amarr Championship prize + "Guardian-Vexor" : self.les_grp, # Illegal rewards for the Gallente Frontier Tour Lines event arc + "Megathron Federate Issue" : self.les_grp, # Reward during Crielere event + "Raven State Issue" : self.les_grp, # AT4 prize + "Tempest Tribal Issue" : self.les_grp, # AT4 prize + "Apotheosis" : self.les_grp, # 5th EVE anniversary present + "Zephyr" : self.les_grp, # 2010 new year gift + "Primae" : self.les_grp, # Promotion of planetary interaction + "Freki" : self.les_grp, # AT7 prize + "Mimir" : self.les_grp, # AT7 prize + "Utu" : self.les_grp, # AT8 prize + "Adrestia" : self.les_grp, # AT8 prize + "Echelon" : self.les_grp, # 2011 new year gift + "Malice" : self.les_grp, # AT9 prize + "Vangel" : self.les_grp, # AT9 prize + "Cambion" : self.les_grp, # AT10 prize + "Etana" : self.les_grp, # AT10 prize + "Chremoas" : self.les_grp, # AT11 prize :( + "Moracha" : self.les_grp, # AT11 prize "Stratios Emergency Responder": self.les_grp, # Issued for Somer Blink lottery - "Miasmos Quafe Ultra Edition": self.les_grp, # Gift to people who purchased FF HD stream - "InterBus Shuttle": self.les_grp, - "Leopard": self.les_grp, # 2013 new year gift - "Whiptail": self.les_grp, # AT12 prize - "Chameleon": self.les_grp, # AT12 prize - "Victorieux Luxury Yacht": self.les_grp, # Worlds Collide prize \o/ chinese getting owned - "Imp": self.les_grp, # AT13 prize - "Fiend": self.les_grp, # AT13 prize - "Caedes": self.les_grp, # AT14 prize - "Rabisu": self.les_grp, # AT14 prize + "Miasmos Quafe Ultra Edition" : self.les_grp, # Gift to people who purchased FF HD stream + "InterBus Shuttle" : self.les_grp, + "Leopard" : self.les_grp, # 2013 new year gift + "Whiptail" : self.les_grp, # AT12 prize + "Chameleon" : self.les_grp, # AT12 prize + "Victorieux Luxury Yacht" : self.les_grp, # Worlds Collide prize \o/ chinese getting owned + "Imp" : self.les_grp, # AT13 prize + "Fiend" : self.les_grp, # AT13 prize + "Caedes" : self.les_grp, # AT14 prize + "Rabisu" : self.les_grp, # AT14 prize } self.ITEMS_FORCEGROUP_R = self.__makeRevDict(self.ITEMS_FORCEGROUP) @@ -253,26 +259,26 @@ class Market(): # List of items which are forcibly published or hidden self.ITEMS_FORCEPUBLISHED = { - "Data Subverter I": False, # Not used in EVE, probably will appear with Dust link - "QA Cross Protocol Analyzer": False, # QA modules used by CCP internally - "QA Damage Module": False, - "QA ECCM": False, - "QA Immunity Module": False, - "QA Multiship Module - 10 Players": False, - "QA Multiship Module - 20 Players": False, - "QA Multiship Module - 40 Players": False, - "QA Multiship Module - 5 Players": False, + "Data Subverter I" : False, # Not used in EVE, probably will appear with Dust link + "QA Cross Protocol Analyzer" : False, # QA modules used by CCP internally + "QA Damage Module" : False, + "QA ECCM" : False, + "QA Immunity Module" : False, + "QA Multiship Module - 10 Players" : False, + "QA Multiship Module - 20 Players" : False, + "QA Multiship Module - 40 Players" : False, + "QA Multiship Module - 5 Players" : False, "QA Remote Armor Repair System - 5 Players": False, - "QA Shield Transporter - 5 Players": False, - "Goru's Shuttle": False, - "Guristas Shuttle": False, - "Mobile Decoy Unit": False, # Seems to be left over test mod for deployables - "Tournament Micro Jump Unit": False, # Normally seen only on tournament arenas - "Council Diplomatic Shuttle": False, # CSM X celebration - "Civilian Gatling Railgun": True, - "Civilian Gatling Pulse Laser": True, - "Civilian Gatling Autocannon": True, - "Civilian Light Electron Blaster": True, + "QA Shield Transporter - 5 Players" : False, + "Goru's Shuttle" : False, + "Guristas Shuttle" : False, + "Mobile Decoy Unit" : False, # Seems to be left over test mod for deployables + "Tournament Micro Jump Unit" : False, # Normally seen only on tournament arenas + "Council Diplomatic Shuttle" : False, # CSM X celebration + "Civilian Gatling Railgun" : True, + "Civilian Gatling Pulse Laser" : True, + "Civilian Gatling Autocannon" : True, + "Civilian Light Electron Blaster" : True, } # do not publish ships that we convert @@ -290,16 +296,18 @@ class Market(): # List of groups which are forcibly published self.GROUPS_FORCEPUBLISHED = { - "Prototype Exploration Ship": False} # We moved the only ship from this group to other group anyway + "Prototype Exploration Ship": False + } # We moved the only ship from this group to other group anyway # Dictionary of items with forced meta groups, uses following format: # Item name: (metagroup name, parent type name) self.ITEMS_FORCEDMETAGROUP = { - "'Habitat' Miner I": ("Storyline", "Miner I"), - "'Wild' Miner I": ("Storyline", "Miner I"), - "Medium Nano Armor Repair Unit I": ("Tech I", "Medium Armor Repairer I"), + "'Habitat' Miner I" : ("Storyline", "Miner I"), + "'Wild' Miner I" : ("Storyline", "Miner I"), + "Medium Nano Armor Repair Unit I" : ("Tech I", "Medium Armor Repairer I"), "Large 'Reprieve' Vestment Reconstructer I": ("Storyline", "Large Armor Repairer I"), - "Khanid Navy Torpedo Launcher": ("Faction", "Torpedo Launcher I"), } + "Khanid Navy Torpedo Launcher" : ("Faction", "Torpedo Launcher I"), + } # Parent type name: set(item names) self.ITEMS_FORCEDMETAGROUP_R = {} for item, value in self.ITEMS_FORCEDMETAGROUP.items(): @@ -310,57 +318,58 @@ class Market(): # Dictionary of items with forced market group (service assumes they have no # market group assigned in db, otherwise they'll appear in both original and forced groups) self.ITEMS_FORCEDMARKETGROUP = { - "'Alpha' Data Analyzer I": 714, + "'Alpha' Data Analyzer I" : 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners - "'Codex' Data Analyzer I": 714, + "'Codex' Data Analyzer I" : 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners - "'Daemon' Data Analyzer I": 714, + "'Daemon' Data Analyzer I" : 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners - "'Libram' Data Analyzer I": 714, + "'Libram' Data Analyzer I" : 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners - "Advanced Cerebral Accelerator": 977, # Implants & Boosters > Booster - "Civilian Damage Control": 615, # Ship Equipment > Hull & Armor > Damage Controls - "Civilian EM Ward Field": 1695, # Ship Equipment > Shield > Shield Hardeners > EM Shield Hardeners - "Civilian Explosive Deflection Field": 1694, + "Advanced Cerebral Accelerator" : 977, # Implants & Boosters > Booster + "Civilian Damage Control" : 615, # Ship Equipment > Hull & Armor > Damage Controls + "Civilian EM Ward Field" : 1695, + # Ship Equipment > Shield > Shield Hardeners > EM Shield Hardeners + "Civilian Explosive Deflection Field" : 1694, # Ship Equipment > Shield > Shield Hardeners > Explosive Shield Hardeners - "Civilian Hobgoblin": 837, # Drones > Combat Drones > Light Scout Drones - "Civilian Kinetic Deflection Field": 1693, + "Civilian Hobgoblin" : 837, # Drones > Combat Drones > Light Scout Drones + "Civilian Kinetic Deflection Field" : 1693, # Ship Equipment > Shield > Shield Hardeners > Kinetic Shield Hardeners - "Civilian Light Missile Launcher": 640, + "Civilian Light Missile Launcher" : 640, # Ship Equipment > Turrets & Bays > Missile Launchers > Light Missile Launchers - "Civilian Scourge Light Missile": 920, + "Civilian Scourge Light Missile" : 920, # Ammunition & Charges > Missiles > Light Missiles > Standard Light Missiles - "Civilian Small Remote Armor Repairer": 1059, + "Civilian Small Remote Armor Repairer" : 1059, # Ship Equipment > Hull & Armor > Remote Armor Repairers > Small - "Civilian Small Remote Shield Booster": 603, # Ship Equipment > Shield > Remote Shield Boosters > Small - "Civilian Stasis Webifier": 683, # Ship Equipment > Electronic Warfare > Stasis Webifiers - "Civilian Thermic Dissipation Field": 1692, + "Civilian Small Remote Shield Booster" : 603, # Ship Equipment > Shield > Remote Shield Boosters > Small + "Civilian Stasis Webifier" : 683, # Ship Equipment > Electronic Warfare > Stasis Webifiers + "Civilian Thermic Dissipation Field" : 1692, # Ship Equipment > Shield > Shield Hardeners > Thermal Shield Hardeners - "Civilian Warp Disruptor": 1935, # Ship Equipment > Electronic Warfare > Warp Disruptors - "Hardwiring - Zainou 'Sharpshooter' ZMX10": 1493, + "Civilian Warp Disruptor" : 1935, # Ship Equipment > Electronic Warfare > Warp Disruptors + "Hardwiring - Zainou 'Sharpshooter' ZMX10" : 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06 - "Hardwiring - Zainou 'Sharpshooter' ZMX100": 1493, + "Hardwiring - Zainou 'Sharpshooter' ZMX100" : 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06 "Hardwiring - Zainou 'Sharpshooter' ZMX1000": 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06 - "Hardwiring - Zainou 'Sharpshooter' ZMX11": 1493, + "Hardwiring - Zainou 'Sharpshooter' ZMX11" : 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06 - "Hardwiring - Zainou 'Sharpshooter' ZMX110": 1493, + "Hardwiring - Zainou 'Sharpshooter' ZMX110" : 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06 "Hardwiring - Zainou 'Sharpshooter' ZMX1100": 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06 - "Nugoehuvi Synth Blue Pill Booster": 977, # Implants & Boosters > Booster - "Prototype Cerebral Accelerator": 977, # Implants & Boosters > Booster - "Prototype Iris Probe Launcher": 712, # Ship Equipment > Turrets & Bays > Scan Probe Launchers - "Shadow": 1310, # Drones > Combat Drones > Fighter Bombers - "Sleeper Data Analyzer I": 714, + "Nugoehuvi Synth Blue Pill Booster" : 977, # Implants & Boosters > Booster + "Prototype Cerebral Accelerator" : 977, # Implants & Boosters > Booster + "Prototype Iris Probe Launcher" : 712, # Ship Equipment > Turrets & Bays > Scan Probe Launchers + "Shadow" : 1310, # Drones > Combat Drones > Fighter Bombers + "Sleeper Data Analyzer I" : 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners - "Standard Cerebral Accelerator": 977, # Implants & Boosters > Booster - "Talocan Data Analyzer I": 714, + "Standard Cerebral Accelerator" : 977, # Implants & Boosters > Booster + "Talocan Data Analyzer I" : 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners - "Terran Data Analyzer I": 714, + "Terran Data Analyzer I" : 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners - "Tetrimon Data Analyzer I": 714 + "Tetrimon Data Analyzer I" : 714 # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners } @@ -408,7 +417,8 @@ class Market(): cls.instance = Market() return cls.instance - def __makeRevDict(self, orig): + @staticmethod + def __makeRevDict(orig): """Creates reverse dictionary""" rev = {} for item, value in orig.items(): @@ -417,7 +427,8 @@ class Market(): rev[value].add(item) return rev - def getItem(self, identity, *args, **kwargs): + @staticmethod + def getItem(identity, *args, **kwargs): """Get item by its ID or name""" try: if isinstance(identity, types_Item): @@ -436,7 +447,7 @@ class Market(): else: raise TypeError("Need Item object, integer, float or string as argument") except: - logger.error("Could not get item: %s", identity) + pyfalog.error("Could not get item: {0}", identity) raise return item @@ -459,7 +470,8 @@ class Market(): else: raise TypeError("Need Group object, integer, float or string as argument") - def getCategory(self, identity, *args, **kwargs): + @staticmethod + def getCategory(identity, *args, **kwargs): """Get category by its ID or name""" if isinstance(identity, types_Category): category = identity @@ -472,7 +484,8 @@ class Market(): raise TypeError("Need Category object, integer, float or string as argument") return category - def getMetaGroup(self, identity, *args, **kwargs): + @staticmethod + def getMetaGroup(identity, *args, **kwargs): """Get meta group by its ID or name""" if isinstance(identity, types_MetaGroup): metaGroup = identity @@ -485,7 +498,8 @@ class Market(): raise TypeError("Need MetaGroup object, integer, float or string as argument") return metaGroup - def getMarketGroup(self, identity, *args, **kwargs): + @staticmethod + def getMarketGroup(identity, *args, **kwargs): """Get market group by its ID""" if isinstance(identity, types_MarketGroup): marketGroup = identity @@ -576,7 +590,40 @@ class Market(): parents = set() # Set-container for variables variations = set() + variations_limiter = set() for item in items: + if item.category.ID == 20: # Implants and Boosters + implant_remove_list = set() + implant_remove_list.add("Low-Grade ") + implant_remove_list.add("Low-grade ") + implant_remove_list.add("Mid-Grade ") + implant_remove_list.add("Mid-grade ") + implant_remove_list.add("High-Grade ") + implant_remove_list.add("High-grade ") + implant_remove_list.add("Limited ") + implant_remove_list.add(" - Advanced") + implant_remove_list.add(" - Basic") + implant_remove_list.add(" - Elite") + implant_remove_list.add(" - Improved") + implant_remove_list.add(" - Standard") + implant_remove_list.add("Copper ") + implant_remove_list.add("Gold ") + implant_remove_list.add("Silver ") + implant_remove_list.add("Advanced ") + implant_remove_list.add("Improved ") + implant_remove_list.add("Prototype ") + implant_remove_list.add("Standard ") + implant_remove_list.add("Strong ") + implant_remove_list.add("Synth ") + + for implant_prefix in ("-6", "-7", "-8", "-9", "-10"): + for i in range(50): + implant_remove_list.add(implant_prefix + str("%02d" % i)) + + for text_to_remove in implant_remove_list: + if text_to_remove in item.name: + variations_limiter.add(item.name.replace(text_to_remove, "")) + # Get parent item if alreadyparent is False: parent = self.getParentItemByItem(item) @@ -586,15 +633,24 @@ class Market(): parents.add(parent) # Check for overrides and add them if any if parent.name in self.ITEMS_FORCEDMETAGROUP_R: - for item in self.ITEMS_FORCEDMETAGROUP_R[parent.name]: - i = self.getItem(item) + for _item in self.ITEMS_FORCEDMETAGROUP_R[parent.name]: + i = self.getItem(_item) if i: variations.add(i) # Add all parents to variations set variations.update(parents) # Add all variations of parents to the set parentids = tuple(item.ID for item in parents) - variations.update(eos.db.getVariations(parentids)) + groupids = tuple(item.group.ID for item in parents) + variations_list = eos.db.getVariations(parentids, groupids) + + if variations_limiter: + for limit in variations_limiter: + trimmed_variations_list = [variation_item for variation_item in variations_list if limit in variation_item.name] + if trimmed_variations_list: + variations_list = trimmed_variations_list + + variations.update(variations_list) return variations def getGroupsByCategory(self, cat): @@ -603,7 +659,8 @@ class Market(): return groups - def getMarketGroupChildren(self, mg): + @staticmethod + def getMarketGroupChildren(mg): """Get the children marketGroups of marketGroup.""" children = set() for child in mg.children: @@ -618,7 +675,7 @@ class Market(): if hasattr(group, 'addItems'): groupItems.update(group.addItems) items = set( - filter(lambda item: self.getPublicityByItem(item) and self.getGroupByItem(item) == group, groupItems)) + filter(lambda item: self.getPublicityByItem(item) and self.getGroupByItem(item) == group, groupItems)) return items def getItemsByMarketGroup(self, mg, vars_=True): @@ -738,8 +795,6 @@ class Market(): """Get ships for given group id""" grp = self.getGroup(grpid, eager=("items", "items.group", "items.marketGroup")) ships = self.getItemsByGroup(grp) - for ship in ships: - ship.race return ships def getShipListDelayed(self, id_, callback): @@ -762,18 +817,20 @@ class Market(): """Find items according to given text pattern""" self.searchWorkerThread.scheduleSearch(name, callback, filterOn) - def getItemsWithOverrides(self): + @staticmethod + def getItemsWithOverrides(): overrides = eos.db.getAllOverrides() items = set() for x in overrides: - if (x.item is None): + if x.item is None: eos.db.saveddata_session.delete(x) eos.db.commit() else: items.add(x.item) return list(items) - def directAttrRequest(self, items, attribs): + @staticmethod + def directAttrRequest(items, attribs): try: itemIDs = tuple(map(lambda i: i.ID, items)) except TypeError: @@ -825,8 +882,9 @@ class Market(): def cb(): try: callback(requests) - except Exception: - pass + except Exception as e: + pyfalog.critical("Callback failed.") + pyfalog.critical(e) eos.db.commit() self.priceWorkerThread.trigger(requests, cb) @@ -841,8 +899,9 @@ class Market(): def cb(): try: callback(item) - except: - pass + except Exception as e: + pyfalog.critical("Callback failed.") + pyfalog.critical(e) self.priceWorkerThread.setToWait(item.ID, cb) diff --git a/service/network.py b/service/network.py index 481c77a41..a990fee23 100644 --- a/service/network.py +++ b/service/network.py @@ -21,10 +21,13 @@ import urllib2 import urllib import socket +from logbook import Logger import config from service.settings import NetworkSettings +pyfalog = Logger(__name__) + # network timeout, otherwise pyfa hangs for a long while if no internet connection timeout = 3 socket.setdefaulttimeout(timeout) @@ -51,7 +54,7 @@ class TimeoutError(StandardError): pass -class Network(): +class Network(object): # Request constants - every request must supply this, as it is checked if # enabled or not via settings ENABLED = 1 @@ -76,6 +79,7 @@ class Network(): access = NetworkSettings.getInstance().getAccess() if not self.ENABLED & access or not type & access: + pyfalog.warning("Access not enabled - please enable in Preferences > Network") raise Error("Access not enabled - please enable in Preferences > Network") # Set up some things for the request @@ -90,8 +94,10 @@ class Network(): # proxy_auth is a tuple of (login, password) or None if proxy_auth is not None: # add login:password@ in front of proxy address - proxy_handler = urllib2.ProxyHandler({'https': '{0}:{1}@{2}:{3}'.format( - proxy_auth[0], proxy_auth[1], proxy[0], proxy[1])}) + proxy_handler = urllib2.ProxyHandler({ + 'https': '{0}:{1}@{2}:{3}'.format( + proxy_auth[0], proxy_auth[1], proxy[0], proxy[1]) + }) else: # build proxy handler with no login/pass info proxy_handler = urllib2.ProxyHandler({'https': "{0}:{1}".format(proxy[0], proxy[1])}) @@ -111,6 +117,8 @@ class Network(): try: return urllib2.urlopen(request) except urllib2.HTTPError as error: + pyfalog.warning("HTTPError:") + pyfalog.warning(error) if error.code == 404: raise RequestError() elif error.code == 403: @@ -118,6 +126,8 @@ class Network(): elif error.code >= 500: raise ServerError() except urllib2.URLError as error: + pyfalog.warning("Timed out or other URL error:") + pyfalog.warning(error) if "timed out" in error.reason: raise TimeoutError() else: diff --git a/service/port.py b/service/port.py index c64293c1b..3e923ed0f 100644 --- a/service/port.py +++ b/service/port.py @@ -20,7 +20,7 @@ import re import os import xml.dom -import logging +from logbook import Logger import collections import json import threading @@ -33,15 +33,24 @@ import xml.parsers.expat from eos import db from service.fit import Fit as svcFit +# noinspection PyPackageRequirements import wx -from service.market import Market -from eos.types import State, Slot, Module, Cargo, Ship, Drone, Implant, Booster, Citadel, Fighter, Fit +from eos.saveddata.cargo import Cargo +from eos.saveddata.implant import Implant +from eos.saveddata.booster import Booster +from eos.saveddata.drone import Drone +from eos.saveddata.fighter import Fighter +from eos.saveddata.module import Module, State, Slot +from eos.saveddata.ship import Ship +from eos.saveddata.citadel import Citadel +from eos.saveddata.fit import Fit +from service.market import Market if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)): from service.crest import Crest -logger = logging.getLogger("pyfa.service.port") +pyfalog = Logger(__name__) try: from collections import OrderedDict @@ -72,15 +81,20 @@ class Port(object): return cls.instance - def backupFits(self, path, callback): + @staticmethod + def backupFits(path, callback): + pyfalog.debug("Starting backup fits thread.") thread = FitBackupThread(path, callback) thread.start() - def importFitsThreaded(self, paths, callback): + @staticmethod + def importFitsThreaded(paths, callback): + pyfalog.debug("Starting import fits thread.") thread = FitImportThread(paths, callback) thread.start() - def importFitFromFiles(self, paths, callback=None): + @staticmethod + def importFitFromFiles(paths, callback=None): """ Imports fits from file(s). First processes all provided paths and stores assembled fits into a list. This allows us to call back to the GUI as @@ -93,12 +107,14 @@ class Port(object): fits = [] for path in paths: if callback: # Pulse + pyfalog.debug("Processing file:\n{0}", path) wx.CallAfter(callback, 1, "Processing file:\n%s" % path) file_ = open(path, "r") srcString = file_.read() if len(srcString) == 0: # ignore blank files + pyfalog.debug("File is blank.") continue codec_found = None @@ -107,6 +123,8 @@ class Port(object): # codepage then fallback to utf-16, cp1252 if isinstance(srcString, str): + savebom = None + encoding_map = ( ('\xef\xbb\xbf', 'utf-8'), ('\xff\xfe\0\0', 'utf-32'), @@ -120,21 +138,21 @@ class Port(object): savebom = bom if codec_found is None: - logger.info("Unicode BOM not found in file %s.", path) + pyfalog.info("Unicode BOM not found in file {0}.", path) attempt_codecs = (defcodepage, "utf-8", "utf-16", "cp1252") for page in attempt_codecs: try: - logger.info("Attempting to decode file %s using %s page.", path, page) + pyfalog.info("Attempting to decode file {0} using {1} page.", path, page) srcString = unicode(srcString, page) codec_found = page - logger.info("File %s decoded using %s page.", path, page) + pyfalog.info("File {0} decoded using {1} page.", path, page) except UnicodeDecodeError: - logger.info("Error unicode decoding %s from page %s, trying next codec", path, page) + pyfalog.info("Error unicode decoding {0} from page {1}, trying next codec", path, page) else: break else: - logger.info("Unicode BOM detected in %s, using %s page.", path, codec_found) + pyfalog.info("Unicode BOM detected in {0}, using {1} page.", path, codec_found) srcString = unicode(srcString[len(savebom):], codec_found) else: @@ -151,10 +169,12 @@ class Port(object): _, fitsImport = Port.importAuto(srcString, path, callback=callback, encoding=codec_found) fits += fitsImport except xml.parsers.expat.ExpatError: + pyfalog.warning("Malformed XML in:\n{0}", path) return False, "Malformed XML in %s" % path - except Exception: - logger.exception("Unknown exception processing: %s", path) - return False, "Unknown Error while processing %s" % path + except Exception as e: + pyfalog.critical("Unknown exception processing: {0}", path) + pyfalog.critical(e) + return False, "Unknown Error while processing {0}" % path IDs = [] numFits = len(fits) @@ -166,6 +186,7 @@ class Port(object): db.save(fit) IDs.append(fit.ID) if callback: # Pulse + pyfalog.debug("Processing complete, saving fits to database: {0}/{1}", i + 1, numFits) wx.CallAfter( callback, 1, "Processing complete, saving fits to database\n(%d/%d)" % @@ -174,7 +195,8 @@ class Port(object): return True, fits - def importFitFromBuffer(self, bufferStr, activeFit=None): + @staticmethod + def importFitFromBuffer(bufferStr, activeFit=None): sFit = svcFit.getInstance() _, fits = Port.importAuto(bufferStr, activeFit=activeFit) for fit in fits: @@ -325,6 +347,7 @@ class Port(object): except ValueError: f.ship = Citadel(sMkt.getItem(fit['ship']['id'])) except: + pyfalog.warning("Caught exception in importCrest") return None items = fit['items'] @@ -350,6 +373,7 @@ class Port(object): m = Module(item) # When item can't be added to any slot (unknown item or just charge), ignore it except ValueError: + pyfalog.debug("Item can't be added to any slot (unknown item or just charge)") continue # Add subsystems before modules to make sure T3 cruisers have subsystems installed if item.category.name == "Subsystem": @@ -362,6 +386,7 @@ class Port(object): moduleList.append(m) except: + pyfalog.warning("Could not process module.") continue # Recalc to get slot numbers correct for T3 cruisers @@ -390,6 +415,7 @@ class Port(object): string = string[string.index(str(id_)):] break except: + pyfalog.warning("Exception caught in importDna") pass string = string[:string.index("::") + 2] info = string.split(":") @@ -407,7 +433,7 @@ class Port(object): return s_[:10] + "..." return s_ - logger.exception("Couldn't import ship data %r", [logtransform(s) for s in info]) + pyfalog.exception("Couldn't import ship data {0}", [logtransform(s) for s in info]) return None moduleList = [] @@ -434,6 +460,7 @@ class Port(object): try: m = Module(item) except: + pyfalog.warning("Exception caught in importDna") continue # Add subsystems before modules to make sure T3 cruisers have subsystems installed if item.category.name == "Subsystem": @@ -482,6 +509,7 @@ class Port(object): fit.ship = Citadel(ship) fit.name = fitName except: + pyfalog.warning("Exception caught in importEft") return # maintain map of drones and their quantities @@ -522,6 +550,7 @@ class Port(object): item = sMkt.getItem(modName, eager="group.category") except: # if no data can be found (old names) + pyfalog.warning("no data can be found (old names)") continue if item.category.name == "Drone": @@ -532,7 +561,7 @@ class Port(object): elif item.category.name == "Fighter": extraAmount = int(extraAmount) if extraAmount is not None else 1 fighterItem = Fighter(item) - if (extraAmount > fighterItem.fighterSquadronMaxSize): # Amount bigger then max fightergroup size + if extraAmount > fighterItem.fighterSquadronMaxSize: # Amount bigger then max fightergroup size extraAmount = fighterItem.fighterSquadronMaxSize if fighterItem.fits(fit): fit.fighters.append(fighterItem) @@ -548,7 +577,7 @@ class Port(object): elif "boosterness" in item.attributes: fit.boosters.append(Booster(item)) else: - logger.error("Failed to import implant: %s", line) + pyfalog.error("Failed to import implant: {0}", line) # elif item.category.name == "Subsystem": # try: # subsystem = Module(item) @@ -589,7 +618,7 @@ class Port(object): if m.fits(fit): m.owner = fit if not m.isValidState(m.state): - print("Error: Module", m, "cannot have state", m.state) + pyfalog.warning("Error: Module {0} cannot have state {1}", m, m.state) fit.modules.append(m) @@ -674,6 +703,7 @@ class Port(object): try: droneItem = sMkt.getItem(droneName, eager="group.category") except: + pyfalog.warning("Cannot get item.") continue if droneItem.category.name == "Drone": # Add drone to the fitting @@ -695,6 +725,7 @@ class Port(object): try: implantItem = sMkt.getItem(entityData, eager="group.category") except: + pyfalog.warning("Cannot get item.") continue if implantItem.category.name != "Implant": continue @@ -710,6 +741,7 @@ class Port(object): try: boosterItem = sMkt.getItem(entityData, eager="group.category") except: + pyfalog.warning("Cannot get item.") continue # All boosters have implant category if boosterItem.category.name != "Implant": @@ -730,6 +762,7 @@ class Port(object): try: item = sMkt.getItem(cargoName) except: + pyfalog.warning("Cannot get item.") continue # Add Cargo to the fitting c = Cargo(item) @@ -743,6 +776,7 @@ class Port(object): try: modItem = sMkt.getItem(modName) except: + pyfalog.warning("Cannot get item.") continue # Create module @@ -764,6 +798,7 @@ class Port(object): if chargeItem.category.name == "Charge": m.charge = chargeItem except: + pyfalog.warning("Cannot get item.") pass # Append module to fit moduleList.append(m) @@ -781,7 +816,9 @@ class Port(object): if callback: wx.CallAfter(callback, None) # Skip fit silently if we get an exception - except Exception: + except Exception as e: + pyfalog.error("Caught exception on fit.") + pyfalog.error(e) pass return fits @@ -805,7 +842,9 @@ class Port(object): f.ship = Ship(sMkt.getItem(shipType)) except ValueError: f.ship = Citadel(sMkt.getItem(shipType)) - except: + except Exception as e: + pyfalog.warning("Caught exception on importXml") + pyfalog.error(e) continue hardwares = fitting.getElementsByTagName("hardware") moduleList = [] @@ -814,7 +853,9 @@ class Port(object): moduleName = hardware.getAttribute("type") try: item = sMkt.getItem(moduleName, eager="group.category") - except: + except Exception as e: + pyfalog.warning("Caught exception on importXml") + pyfalog.error(e) continue if item: if item.category.name == "Drone": @@ -837,6 +878,7 @@ class Port(object): m = Module(item) # When item can't be added to any slot (unknown item or just charge), ignore it except ValueError: + pyfalog.warning("item can't be added to any slot (unknown item or just charge), ignore it") continue # Add subsystems before modules to make sure T3 cruisers have subsystems installed if item.category.name == "Subsystem": @@ -850,6 +892,7 @@ class Port(object): moduleList.append(m) except KeyboardInterrupt: + pyfalog.warning("Keyboard Interrupt") continue # Recalc to get slot numbers correct for T3 cruisers @@ -1081,7 +1124,7 @@ class Port(object): @staticmethod def exportMultiBuy(fit): - export = "%s\n" % (fit.ship.item.name) + export = "%s\n" % fit.ship.item.name stuff = {} sFit = svcFit.getInstance() for module in fit.modules: @@ -1156,7 +1199,7 @@ class FitImportThread(threading.Thread): success, result = sPort.importFitFromFiles(self.paths, self.callback) if not success: # there was an error during processing - logger.error("Error while processing file import: %s", result) + pyfalog.error("Error while processing file import: {0}", result) wx.CallAfter(self.callback, -2, result) else: # Send done signal to GUI wx.CallAfter(self.callback, -1, result) diff --git a/service/prefetch.py b/service/prefetch.py index cf40f90f8..2680b0184 100644 --- a/service/prefetch.py +++ b/service/prefetch.py @@ -17,7 +17,6 @@ # along with pyfa. If not, see . # ============================================================================= -import threading import os import config @@ -25,16 +24,10 @@ from eos import db from eos.db import migration from eos.db.saveddata.loadDefaultDatabaseValues import DefaultDatabaseValues from eos.db.saveddata.databaseRepair import DatabaseCleanup -from eos.saveddata.character import Character as es_Character -import logging +from logbook import Logger -logger = logging.getLogger(__name__) - -# The following code does not belong here, however until we rebuild skeletons -# to include modified pyfa.py, this is the best place to put it. See GH issue -# #176 -# @ todo: move this to pyfa.py +pyfalog = Logger(__name__) # Make sure the saveddata db exists if config.savePath and not os.path.exists(config.savePath): @@ -42,25 +35,31 @@ if config.savePath and not os.path.exists(config.savePath): if config.saveDB and os.path.isfile(config.saveDB): # If database exists, run migration after init'd database + pyfalog.debug("Run database migration.") db.saveddata_meta.create_all() migration.update(db.saveddata_engine) # Import default database values # Import values that must exist otherwise Pyfa breaks + pyfalog.debug("Import Required Database Values.") DefaultDatabaseValues.importRequiredDefaults() # Finds and fixes database corruption issues. - logging.debug("Starting database validation.") + pyfalog.debug("Starting database validation.") database_cleanup_instance = DatabaseCleanup() database_cleanup_instance.OrphanedCharacterSkills(db.saveddata_engine) database_cleanup_instance.OrphanedFitCharacterIDs(db.saveddata_engine) database_cleanup_instance.OrphanedFitDamagePatterns(db.saveddata_engine) database_cleanup_instance.NullDamagePatternNames(db.saveddata_engine) database_cleanup_instance.NullTargetResistNames(db.saveddata_engine) - logging.debug("Completed database validation.") + database_cleanup_instance.OrphanedFitIDItemID(db.saveddata_engine) + database_cleanup_instance.NullDamageTargetPatternValues(db.saveddata_engine) + database_cleanup_instance.DuplicateSelectedAmmoName(db.saveddata_engine) + pyfalog.debug("Completed database validation.") else: # If database does not exist, do not worry about migration. Simply # create and set version + pyfalog.debug("Existing database not found, creating new database.") db.saveddata_meta.create_all() db.saveddata_engine.execute('PRAGMA user_version = {}'.format(migration.getAppVersion())) # Import default database values diff --git a/service/price.py b/service/price.py index e3d39d734..b2466c4c4 100644 --- a/service/price.py +++ b/service/price.py @@ -23,6 +23,11 @@ from xml.dom import minidom from eos import db from service.network import Network, TimeoutError +from service.fit import Fit +from logbook import Logger + +pyfalog = Logger(__name__) + VALIDITY = 24 * 60 * 60 # Price validity period, 24 hours REREQUEST = 4 * 60 * 60 # Re-request delay for failed fetches, 4 hours @@ -30,6 +35,19 @@ TIMEOUT = 15 * 60 # Network timeout delay for connection issues, 15 minutes class Price(object): + systemsList = { + "Jita": 30000142, + "Amarr": 30002187, + "Dodixie": 30002659, + "Rens": 30002510, + "Hek": 30002053 + } + + @classmethod + def invalidPrices(cls, prices): + for price in prices: + price.time = 0 + @classmethod def fetchPrices(cls, prices): """Fetch all prices passed to this method""" @@ -63,9 +81,10 @@ class Price(object): # This will store POST data for eve-central data = [] + sFit = Fit.getInstance() # Base request URL baseurl = "https://eve-central.com/api/marketstat" - data.append(("usesystem", 30000142)) # Use Jita for market + data.append(("usesystem", cls.systemsList[sFit.serviceFittingOptions["priceSystem"]])) # Use Jita for market for typeID in toRequest: # Add all typeID arguments data.append(("typeid", typeID)) @@ -85,6 +104,7 @@ class Price(object): try: percprice = float(sell.getElementsByTagName("percentile").item(0).firstChild.data) except (TypeError, ValueError): + pyfalog.warning("Failed to get price for: {0}", type_) percprice = 0 # Fill price data @@ -99,6 +119,7 @@ class Price(object): # If getting or processing data returned any errors except TimeoutError: # Timeout error deserves special treatment + pyfalog.warning("Price fetch timout") for typeID in priceMap.keys(): priceobj = priceMap[typeID] priceobj.time = time.time() + TIMEOUT @@ -106,6 +127,7 @@ class Price(object): del priceMap[typeID] except: # all other errors will pass and continue onward to the REREQUEST delay + pyfalog.warning("Caught exception in fetchPrices") pass # if we get to this point, then we've got an error. Set to REREQUEST delay @@ -113,3 +135,23 @@ class Price(object): priceobj = priceMap[typeID] priceobj.time = time.time() + REREQUEST priceobj.failed = True + + @classmethod + def fitItemsList(cls, fit): + # Compose a list of all the data we need & request it + typeIDs = [fit.ship.item.ID] + + for mod in fit.modules: + if not mod.isEmpty: + typeIDs.append(mod.itemID) + + for drone in fit.drones: + typeIDs.append(drone.itemID) + + for fighter in fit.fighters: + typeIDs.append(fighter.itemID) + + for cargo in fit.cargo: + typeIDs.append(cargo.itemID) + + return typeIDs diff --git a/service/pycrest/__init__.py b/service/pycrest/__init__.py index f083e1f84..5820a7290 100644 --- a/service/pycrest/__init__.py +++ b/service/pycrest/__init__.py @@ -1,12 +1 @@ -import logging - - -class NullHandler(logging.Handler): - def emit(self, record): - pass - - -logger = logging.getLogger('pycrest') -logger.addHandler(NullHandler()) - version = "0.0.1" diff --git a/service/pycrest/eve.py b/service/pycrest/eve.py index b4ab03cd6..6a4799d74 100644 --- a/service/pycrest/eve.py +++ b/service/pycrest/eve.py @@ -1,5 +1,5 @@ import base64 -import logging +from logbook import Logger import os import re import time @@ -12,22 +12,15 @@ import config from service.pycrest.compat import bytes_, text_ from service.pycrest.errors import APIException -try: - from urllib.parse import urlparse, urlunparse, parse_qsl -except ImportError: # pragma: no cover - from urlparse import urlparse, urlunparse, parse_qsl +from urlparse import urlparse, urlunparse, parse_qsl try: import pickle except ImportError: # pragma: no cover + # noinspection PyPep8Naming import cPickle as pickle -try: - from urllib.parse import quote -except ImportError: # pragma: no cover - from urllib import quote - -logger = logging.getLogger("pycrest.eve") +pyfalog = Logger(__name__) cache_re = re.compile(r'max-age=([0-9]+)') @@ -50,7 +43,7 @@ class FileCache(APICache): os.mkdir(self.path, 0o700) def _getpath(self, key): - return config.parsePath(self.path, str(hash(key)) + '.cache') + return os.path.join(self.path, str(hash(key)) + '.cache') def put(self, key, value): with open(self._getpath(key), 'wb') as f: @@ -65,6 +58,7 @@ class FileCache(APICache): with open(self._getpath(key), 'rb') as f: return pickle.loads(zlib.decompress(f.read())) except IOError as ex: + pyfalog.debug("IO error opening zip file. (May not exist yet)") if ex.errno == 2: # file does not exist (yet) return None else: @@ -76,6 +70,8 @@ class FileCache(APICache): try: os.unlink(self._getpath(key)) except OSError as ex: + pyfalog.debug("Caught exception in invalidate") + pyfalog.debug(ex) if ex.errno == 2: # does not exist pass else: @@ -123,7 +119,7 @@ class APIConnection(object): self.cache = DictCache() def get(self, resource, params=None): - logger.debug('Getting resource %s', resource) + pyfalog.debug('Getting resource {0}', resource) if params is None: params = {} @@ -143,18 +139,18 @@ class APIConnection(object): key = (resource, frozenset(self._session.headers.items()), frozenset(prms.items())) cached = self.cache.get(key) if cached and cached['cached_until'] > time.time(): - logger.debug('Cache hit for resource %s (params=%s)', resource, prms) + pyfalog.debug('Cache hit for resource {0} (params={1})', resource, prms) return cached elif cached: - logger.debug('Cache stale for resource %s (params=%s)', resource, prms) + pyfalog.debug('Cache stale for resource {0} (params={1})', resource, prms) self.cache.invalidate(key) else: - logger.debug('Cache miss for resource %s (params=%s', resource, prms) + pyfalog.debug('Cache miss for resource {0} (params={1})', resource, prms) - logger.debug('Getting resource %s (params=%s)', resource, prms) + pyfalog.debug('Getting resource {0} (params={1})', resource, prms) res = self._session.get(resource, params=prms) if res.status_code != 200: - raise APIException("Got unexpected status code from server: %i" % res.status_code) + raise APIException("Got unexpected status code from server: {0}" % res.status_code) ret = res.json() @@ -166,7 +162,8 @@ class APIConnection(object): return ret - def _get_expires(self, response): + @staticmethod + def _get_expires(response): if 'Cache-Control' not in response.headers: return 0 if any([s in response.headers['Cache-Control'] for s in ['no-cache', 'no-store']]): diff --git a/service/pycrest/weak_ciphers.py b/service/pycrest/weak_ciphers.py index 48da3c909..b18a1a552 100644 --- a/service/pycrest/weak_ciphers.py +++ b/service/pycrest/weak_ciphers.py @@ -109,7 +109,7 @@ class WeakCiphersHTTPSConnectionPool(urllib3.connectionpool.HTTPSConnectionPool) class WeakCiphersPoolManager(urllib3.poolmanager.PoolManager): def _new_pool(self, scheme, host, port): if scheme == 'https': - return WeakCiphersHTTPSConnectionPool(host, port, **(self.connection_pool_kw)) + return WeakCiphersHTTPSConnectionPool(host, port, **self.connection_pool_kw) return super(WeakCiphersPoolManager, self)._new_pool(scheme, host, port) diff --git a/service/server.py b/service/server.py index 268637515..4d6566de9 100644 --- a/service/server.py +++ b/service/server.py @@ -1,14 +1,11 @@ import BaseHTTPServer import urlparse import socket -import thread -import logging - -import wx +import threading +from logbook import Logger from service.settings import CRESTSettings - -logger = logging.getLogger(__name__) +pyfalog = Logger(__name__) # noinspection PyPep8 HTML = ''' @@ -19,12 +16,13 @@ HTML = ''' pyfa Local Server @@ -33,26 +31,36 @@ HTML = '''

      pyfa

      -
      -

      If you see this message then it means you should be logged into CREST. You may close this window and return to the application.

      -
      + {0}
      + @@ -64,13 +72,34 @@ class AuthHandler(BaseHTTPServer.BaseHTTPRequestHandler): def do_GET(self): if self.path == "/favicon.ico": return + parsed_path = urlparse.urlparse(self.path) parts = urlparse.parse_qs(parsed_path.query) - self.send_response(200) - self.end_headers() - self.wfile.write(HTML) + msg = "" - wx.CallAfter(self.server.callback, parts) + step2 = 'step' in parts + + try: + if step2: + self.server.callback(parts) + pyfalog.info("Successfully logged into CREST.") + msg = "If you see this message then it means you should be logged into CREST. You may close this window and return to the application." + else: + # For implicit mode, we have to serve up the page which will take the hash and redirect useing a querystring + pyfalog.info("Processing response from EVE Online.") + msg = "Processing response from EVE Online" + except Exception, ex: + pyfalog.error("Error in CREST AuthHandler") + pyfalog.error(ex) + msg = "

      Error

      \n

      {}

      ".format(ex.message) + finally: + self.send_response(200) + self.end_headers() + self.wfile.write(HTML.format(msg)) + + if step2: + # Only stop once if we've received something in the querystring + self.server.stop() def log_message(self, format, *args): return @@ -84,9 +113,9 @@ class StoppableHTTPServer(BaseHTTPServer.HTTPServer): # Allow listening for x seconds sec = self.settings.get('timeout') - logger.debug("Running server for %d seconds", sec) + pyfalog.debug("Running server for {0} seconds", sec) - self.socket.settimeout(0.5) + self.socket.settimeout(1) self.max_tries = sec / self.socket.gettimeout() self.tries = 0 self.run = True @@ -96,32 +125,36 @@ class StoppableHTTPServer(BaseHTTPServer.HTTPServer): try: sock, addr = self.socket.accept() sock.settimeout(None) - return (sock, addr) + return sock, addr except socket.timeout: + pyfalog.warning("Server timed out waiting for connection") pass def stop(self): + pyfalog.warning("Setting CREST server to stop.") self.run = False def handle_timeout(self): - # logger.debug("Number of tries: %d"%self.tries) + pyfalog.debug("Number of tries: {0}", self.tries) self.tries += 1 if self.tries == self.max_tries: - logger.debug("Server timed out waiting for connection") + pyfalog.debug("Server timed out waiting for connection") self.stop() - def serve(self, callback): + def serve(self, callback=None): self.callback = callback while self.run: try: self.handle_request() except TypeError: + pyfalog.debug("Caught exception in serve") pass + self.server_close() if __name__ == "__main__": httpd = StoppableHTTPServer(('', 6461), AuthHandler) - thread.start_new_thread(httpd.serve, ()) + t = threading.Thread(target=httpd.serve) raw_input("Press to stop server\n") httpd.stop() diff --git a/service/settings.py b/service/settings.py index 1d5923985..cfc48fc4a 100644 --- a/service/settings.py +++ b/service/settings.py @@ -22,10 +22,14 @@ import os.path import urllib2 import config +import eos.config +from logbook import Logger + +pyfalog = Logger(__name__) class SettingsProvider(object): - BASE_PATH = config.getSavePath("settings") + BASE_PATH = os.path.join(config.savePath, 'settings') settings = {} _instance = None @@ -44,7 +48,7 @@ class SettingsProvider(object): s = self.settings.get(area) if s is None: - p = config.parsePath(self.BASE_PATH, area) + p = os.path.join(self.BASE_PATH, area) if not os.path.exists(p): info = {} @@ -87,7 +91,8 @@ class Settings(object): def __getitem__(self, k): try: return self.info[k] - except KeyError: + except KeyError as e: + pyfalog.warning("Failed to get setting for '{0}'. Exception: {1}", k, e) return None def __setitem__(self, k, v): @@ -133,17 +138,17 @@ class NetworkSettings(object): def __init__(self): serviceNetworkDefaultSettings = { - "mode": self.PROXY_MODE_AUTODETECT, - "type": "https", - "address": "", - "port": "", - "access": 15, - "login": None, + "mode" : self.PROXY_MODE_AUTODETECT, + "type" : "https", + "address" : "", + "port" : "", + "access" : 15, + "login" : None, "password": None } self.serviceNetworkSettings = SettingsProvider.getInstance().getSettings( - "pyfaServiceNetworkSettings", serviceNetworkDefaultSettings) + "pyfaServiceNetworkSettings", serviceNetworkDefaultSettings) def isEnabled(self, type): if type & self.serviceNetworkSettings["access"]: @@ -217,7 +222,7 @@ class NetworkSettings(object): if self.getMode() == self.PROXY_MODE_AUTODETECT: return self.autodetect() if self.getMode() == self.PROXY_MODE_MANUAL: - return (self.getAddress(), int(self.getPort())) + return self.getAddress(), int(self.getPort()) def getProxyAuthDetails(self): if self.getMode() == self.PROXY_MODE_NONE: @@ -225,7 +230,7 @@ class NetworkSettings(object): if (self.serviceNetworkSettings["login"] is None) or (self.serviceNetworkSettings["password"] is None): return None # in all other cases, return tuple of (login, password) - return (self.serviceNetworkSettings["login"], self.serviceNetworkSettings["password"]) + return self.serviceNetworkSettings["login"], self.serviceNetworkSettings["password"] def setProxyAuthDetails(self, login, password): if (login is None) or (password is None): @@ -256,12 +261,12 @@ class HTMLExportSettings(object): def __init__(self): serviceHTMLExportDefaultSettings = { "enabled": False, - "path": config.pyfaPath + os.sep + 'pyfaFits.html', + "path" : config.pyfaPath + os.sep + 'pyfaFits.html', "minimal": False } self.serviceHTMLExportSettings = SettingsProvider.getInstance().getSettings( - "pyfaServiceHTMLExportSettings", - serviceHTMLExportDefaultSettings + "pyfaServiceHTMLExportSettings", + serviceHTMLExportDefaultSettings ) def getEnabled(self): @@ -303,8 +308,8 @@ class UpdateSettings(object): # version - Set to release tag that user does not want notifications for serviceUpdateDefaultSettings = {"prerelease": True, 'version': None} self.serviceUpdateSettings = SettingsProvider.getInstance().getSettings( - "pyfaServiceUpdateSettings", - serviceUpdateDefaultSettings + "pyfaServiceUpdateSettings", + serviceUpdateDefaultSettings ) def get(self, type): @@ -331,8 +336,8 @@ class CRESTSettings(object): serviceCRESTDefaultSettings = {"mode": 0, "server": 0, "clientID": "", "clientSecret": "", "timeout": 60} self.serviceCRESTSettings = SettingsProvider.getInstance().getSettings( - "pyfaServiceCRESTSettings", - serviceCRESTDefaultSettings + "pyfaServiceCRESTSettings", + serviceCRESTDefaultSettings ) def get(self, type): @@ -341,4 +346,118 @@ class CRESTSettings(object): def set(self, type, value): self.serviceCRESTSettings[type] = value + +class StatViewSettings(object): + _instance = None + + @classmethod + def getInstance(cls): + if cls._instance is None: + cls._instance = StatViewSettings() + + return cls._instance + + def __init__(self): + # mode + # 0 - Do not show + # 1 - Minimal/Text Only View + # 2 - Full View + serviceStatViewDefaultSettings = { + "resources" : 2, + "resistances" : 2, + "recharge" : 2, + "firepower" : 2, + "capacitor" : 2, + "targetingMisc": 1, + "price" : 2, + "miningyield" : 2, + "drones" : 2, + "outgoing" : 2, + } + + # We don't have these....yet + ''' + "miningyield": 2, + "drones": 2 + ''' + + self.serviceStatViewDefaultSettings = SettingsProvider.getInstance().getSettings("pyfaServiceStatViewSettings", serviceStatViewDefaultSettings) + + def get(self, type): + return self.serviceStatViewDefaultSettings[type] + + def set(self, type, value): + self.serviceStatViewDefaultSettings[type] = value + + +class ContextMenuSettings(object): + _instance = None + + @classmethod + def getInstance(cls): + if cls._instance is None: + cls._instance = ContextMenuSettings() + + return cls._instance + + def __init__(self): + # mode + # 0 - Do not show + # 1 - Show + ContextMenuDefaultSettings = { + "ammoPattern" : 1, + "amount" : 1, + "cargo" : 1, + "cargoAmmo" : 1, + "changeAffectingSkills" : 1, + "damagePattern" : 1, + "droneRemoveStack" : 1, + "droneSplit" : 1, + "droneStack" : 1, + "factorReload" : 1, + "fighterAbilities" : 1, + "implantSets" : 1, + "itemStats" : 1, + "itemRemove" : 1, + "marketJump" : 1, + "metaSwap" : 1, + "moduleAmmoPicker" : 1, + "moduleGlobalAmmoPicker": 1, + "openFit" : 1, + "priceClear" : 1, + "project" : 1, + "shipJump" : 1, + "tacticalMode" : 1, + "targetResists" : 1, + "whProjector" : 1, + } + + self.ContextMenuDefaultSettings = SettingsProvider.getInstance().getSettings("pyfaContextMenuSettings", ContextMenuDefaultSettings) + + def get(self, type): + return self.ContextMenuDefaultSettings[type] + + def set(self, type, value): + self.ContextMenuDefaultSettings[type] = value + + +class EOSSettings(object): + _instance = None + + @classmethod + def getInstance(cls): + if cls._instance is None: + cls._instance = EOSSettings() + + return cls._instance + + def __init__(self): + self.EOSSettings = SettingsProvider.getInstance().getSettings("pyfaEOSSettings", eos.config.settings) + + def get(self, type): + return self.EOSSettings[type] + + def set(self, type, value): + self.EOSSettings[type] = value + # @todo: migrate fit settings (from fit service) here? diff --git a/service/targetResists.py b/service/targetResists.py index 2a4863c5d..06df8c8c6 100644 --- a/service/targetResists.py +++ b/service/targetResists.py @@ -37,31 +37,38 @@ class TargetResists(object): return cls.instance - def getTargetResistsList(self): + @staticmethod + def getTargetResistsList(): return db.getTargetResistsList() - def getTargetResists(self, name): + @staticmethod + def getTargetResists(name): return db.getTargetResists(name) - def newPattern(self, name): + @staticmethod + def newPattern(name): p = es_TargetResists(0.0, 0.0, 0.0, 0.0) p.name = name db.save(p) return p - def renamePattern(self, p, newName): + @staticmethod + def renamePattern(p, newName): p.name = newName db.save(p) - def deletePattern(self, p): + @staticmethod + def deletePattern(p): db.remove(p) - def copyPattern(self, p): + @staticmethod + def copyPattern(p): newP = copy.deepcopy(p) db.save(newP) return newP - def saveChanges(self, p): + @staticmethod + def saveChanges(p): db.save(p) def importPatterns(self, text): diff --git a/service/update.py b/service/update.py index 2c09910d7..7196b2a59 100644 --- a/service/update.py +++ b/service/update.py @@ -21,12 +21,17 @@ import threading import json import calendar +# noinspection PyPackageRequirements import wx +# noinspection PyPackageRequirements import dateutil.parser import config from service.network import Network from service.settings import UpdateSettings +from logbook import Logger + +pyfalog = Logger(__name__) class CheckUpdateThread(threading.Thread): @@ -50,7 +55,7 @@ class CheckUpdateThread(threading.Thread): for release in jsonResponse: # Suppress pre releases - if (release['prerelease'] and self.settings.get('prerelease')): + if release['prerelease'] and self.settings.get('prerelease'): continue # Handle use-case of updating to suppressed version @@ -58,7 +63,7 @@ class CheckUpdateThread(threading.Thread): self.settings.set('version', None) # Suppress version - if (release['tag_name'] == self.settings.get('version')): + if release['tag_name'] == self.settings.get('version'): break # Set the release version that we will be comparing with. @@ -80,18 +85,23 @@ class CheckUpdateThread(threading.Thread): if release['prerelease'] and rVersion > config.expansionVersion: wx.CallAfter(self.callback, release) # Singularity -> Singularity break - except: + except Exception as e: + pyfalog.error("Caught exception in run") + pyfalog.error(e) pass - def versiontuple(self, v): + @staticmethod + def versiontuple(v): return tuple(map(int, (v.split(".")))) -class Update(): +class Update(object): instance = None - def CheckUpdate(self, callback): + @staticmethod + def CheckUpdate(callback): thread = CheckUpdateThread(callback) + pyfalog.debug("Starting Check Update Thread.") thread.start() @classmethod diff --git a/setup.py b/setup.py index b4738824a..0d281bd89 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ import requests.certs # The modules that contain the bulk of teh source packages = ['eos', 'gui', 'service', 'utils'] # Extra files that will be copied into the root directory -include_files = ['eve.db', 'LICENSE', 'README.md', (requests.certs.where(),'cacert.pem')] +include_files = ['eve.db', 'LICENSE', 'README.md', (requests.certs.where(), 'cacert.pem')] # this is read by dist.py to package the icons icon_dirs = ['gui', 'icons', 'renders'] @@ -22,9 +22,27 @@ excludes = ['Tkinter', 'collections.abc', 'IPython', 'PyQt4', 'PIL', 'nose', 'to if __name__ == "__main__": import sys + # noinspection PyPackageRequirements,PyUnresolvedReferences from cx_Freeze import setup, Executable import config + import tempfile + import os + import zipfile + import shutil + tmpdir = tempfile.mkdtemp() + imagesFile = os.path.join(tmpdir, "imgs.zip") + + def zipdir(path, zip): + for root, dirs, files in os.walk(path): + for file in files: + zip.write(os.path.join(root, file)) + + os.chdir('imgs') + with zipfile.ZipFile(imagesFile, 'w') as images: + for dir in icon_dirs: + zipdir(dir, images) + os.chdir('..') app_name = 'pyfa' app_version = '{}'.format(config.version) @@ -33,7 +51,7 @@ if __name__ == "__main__": # Windows-specific options build_options_winexe = { 'packages': packages, - 'include_files': include_files, + 'include_files': include_files+[imagesFile], 'includes': includes, 'excludes': excludes, 'compressed': True, @@ -47,7 +65,6 @@ if __name__ == "__main__": 'initial_target_dir': r'[ProgramFilesFolder]\{}'.format(app_name), } - # Mac-specific options (untested) build_options_macapp = { 'iconfile': 'dist_assets/mac/pyfa.icns', @@ -59,13 +76,12 @@ if __name__ == "__main__": 'applications-shortcut': True, } - # Generic executable options executable_options = { 'script': 'pyfa.py', # Following are windows-specific options, they are stored # on a per-executable basis - 'base': 'Win32GUI' if sys.platform=='win32' else None, + 'base': 'Win32GUI' if sys.platform == 'win32' else None, 'icon': 'dist_assets/win/pyfa.ico', 'shortcutDir': 'DesktopFolder', 'shortcutName': app_name, @@ -75,7 +91,7 @@ if __name__ == "__main__": name=app_name, version=app_version, description=app_description, - options = { + options={ 'build_exe': build_options_winexe, 'bdist_msi': build_options_winmsi, 'bdist_mac': build_options_macapp, @@ -83,3 +99,5 @@ if __name__ == "__main__": }, executables=[Executable(**executable_options)] ) + + shutil.rmtree(tmpdir) diff --git a/tests/test_modules/gui/test_aboutData.py b/tests/test_modules/gui/test_aboutData.py new file mode 100644 index 000000000..8e7e862d6 --- /dev/null +++ b/tests/test_modules/gui/test_aboutData.py @@ -0,0 +1,9 @@ +from gui.aboutData import versionString, licenses, developers, credits, description + + +def test_aboutData(): + assert versionString.__len__() > 0 + assert licenses.__len__() > 0 + assert developers.__len__() > 0 + assert credits.__len__() > 0 + assert description.__len__() > 0 diff --git a/tests/test_modules/service/test_attribute.py b/tests/test_modules/service/test_attribute.py new file mode 100644 index 000000000..1ab44f2a8 --- /dev/null +++ b/tests/test_modules/service/test_attribute.py @@ -0,0 +1,42 @@ +from service.attribute import Attribute + + +def test_attribute(): + """ + We don't really have much to test here, to throw a generic attribute at it and validate we get the expected results + + :return: + """ + sAttr = Attribute.getInstance() + info = sAttr.getAttributeInfo("maxRange") + + assert info.attributeID == 54 + assert type(info.attributeID) is int + assert info.attributeName == 'maxRange' + assert type(info.attributeName) is unicode + assert info.defaultValue == 0.0 + assert type(info.defaultValue) is float + assert info.description == 'Distance below which range does not affect the to-hit equation.' + assert type(info.description) is unicode + assert info.displayName == 'Optimal Range' + assert type(info.displayName) is unicode + assert info.highIsGood is True + assert type(info.highIsGood) is bool + assert info.iconID == 1391 + assert type(info.iconID) is int + assert info.name == 'maxRange' + assert type(info.name) is unicode + assert info.published is True + assert type(info.published) is bool + assert info.unitID == 1 + assert type(info.unitID) is int + assert info.unit.ID == 1 + assert type(info.unit.ID) is int + assert info.unit.displayName == 'm' + assert type(info.unit.displayName) is unicode + assert info.unit.name == 'Length' + assert type(info.unit.name) is unicode + assert info.unit.unitID == 1 + assert type(info.unit.unitID) is int + assert info.unit.unitName == 'Length' + assert type(info.unit.unitName) is unicode diff --git a/tests/test_package.py b/tests/test_package.py index 19299a942..5f97967d7 100644 --- a/tests/test_package.py +++ b/tests/test_package.py @@ -2,9 +2,10 @@ import os import sys -import importlib +# import importlib -import pytest +# noinspection PyPackageRequirements +# import pytest script_dir = os.path.dirname(os.path.abspath(__file__)) diff --git a/tox.ini b/tox.ini index 2274602e3..b92d0b45b 100644 --- a/tox.ini +++ b/tox.ini @@ -12,4 +12,5 @@ commands = py.test -vv --cov Pyfa tests/ [testenv:pep8] deps = flake8 -commands = flake8 --exclude=.svn,CVS,.bzr,.hg,.git,__pycache__,venv,tests,.tox,build,dist,__init__.py --ignore=E126,E127,E128,E501,E731,F401,F403,F405 service gui eos utils config.py pyfa.py --max-line-length=130 +# TODO: Remove E731 and convert lambdas to defs +commands = flake8 --exclude=.svn,CVS,.bzr,.hg,.git,__pycache__,venv,tests,.tox,build,dist,__init__.py --ignore=E126,E127,E128,E203,E731 service gui eos utils config.py pyfa.py --max-line-length=165 diff --git a/utils/compat.py b/utils/compat.py index bf49eb4aa..8dcf8a4d9 100644 --- a/utils/compat.py +++ b/utils/compat.py @@ -9,11 +9,11 @@ except ImportError: try: from _abcoll import KeysView, ValuesView, ItemsView except ImportError: - pass + KeysView = ValuesView = ItemsView = None class OrderedDict(dict): - 'Dictionary that remembers insertion order' + """Dictionary that remembers insertion order""" # An inherited dict maps keys to values. # The inherited dict provides __getitem__, __len__, __contains__, and get. # The remaining methods are order-aware. @@ -25,11 +25,12 @@ class OrderedDict(dict): # Each link is stored as a list of length three: [PREV, NEXT, KEY]. def __init__(self, *args, **kwds): - '''Initialize an ordered dictionary. Signature is the same as for + """Initialize an ordered dictionary. Signature is the same as for regular dictionaries, but keyword arguments are not recommended because their insertion order is arbitrary. - ''' + """ + super(OrderedDict, self).__init__(**kwds) if len(args) > 1: raise TypeError('expected at most 1 arguments, got %d' % len(args)) try: @@ -41,7 +42,7 @@ class OrderedDict(dict): self.__update(*args, **kwds) def __setitem__(self, key, value, dict_setitem=dict.__setitem__): - 'od.__setitem__(i, y) <==> od[i]=y' + """od.__setitem__(i, y) <==> od[i]=y""" # Setting a new item creates a new link which goes at the end of the linked # list, and the inherited dictionary is updated with the new key/value pair. if key not in self: @@ -51,7 +52,7 @@ class OrderedDict(dict): dict_setitem(self, key, value) def __delitem__(self, key, dict_delitem=dict.__delitem__): - 'od.__delitem__(y) <==> del od[y]' + """od.__delitem__(y) <==> del od[y]""" # Deleting an existing item uses self.__map to find the link which is # then removed by updating the links in the predecessor and successor nodes. dict_delitem(self, key) @@ -60,7 +61,7 @@ class OrderedDict(dict): link_next[0] = link_prev def __iter__(self): - 'od.__iter__() <==> iter(od)' + """od.__iter__() <==> iter(od)""" root = self.__root curr = root[1] while curr is not root: @@ -68,7 +69,7 @@ class OrderedDict(dict): curr = curr[1] def __reversed__(self): - 'od.__reversed__() <==> reversed(od)' + """od.__reversed__() <==> reversed(od)""" root = self.__root curr = root[0] while curr is not root: @@ -76,7 +77,7 @@ class OrderedDict(dict): curr = curr[0] def clear(self): - 'od.clear() -> None. Remove all items from od.' + """od.clear() -> None. Remove all items from od.""" try: for node in self.__map.itervalues(): del node[:] @@ -88,10 +89,10 @@ class OrderedDict(dict): dict.clear(self) def popitem(self, last=True): - '''od.popitem() -> (k, v), return and remove a (key, value) pair. + """od.popitem() -> (k, v), return and remove a (key, value) pair. Pairs are returned in LIFO order if last is true or FIFO order if false. - ''' + """ if not self: raise KeyError('dictionary is empty') root = self.__root @@ -113,40 +114,40 @@ class OrderedDict(dict): # -- the following methods do not depend on the internal structure -- def keys(self): - 'od.keys() -> list of keys in od' + """od.keys() -> list of keys in od""" return list(self) def values(self): - 'od.values() -> list of values in od' + """od.values() -> list of values in od""" return [self[key] for key in self] def items(self): - 'od.items() -> list of (key, value) pairs in od' + """od.items() -> list of (key, value) pairs in od""" return [(key, self[key]) for key in self] def iterkeys(self): - 'od.iterkeys() -> an iterator over the keys in od' + """od.iterkeys() -> an iterator over the keys in od""" return iter(self) def itervalues(self): - 'od.itervalues -> an iterator over the values in od' + """od.itervalues -> an iterator over the values in od""" for k in self: yield self[k] def iteritems(self): - 'od.iteritems -> an iterator over the (key, value) items in od' + """od.iteritems -> an iterator over the (key, value) items in od""" for k in self: yield (k, self[k]) def update(*args, **kwds): - '''od.update(E, **F) -> None. Update od from dict/iterable E and F. + """od.update(E, **F) -> None. Update od from dict/iterable E and F. If E is a dict instance, does: for k in E: od[k] = E[k] If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] Or if E is an iterable of items, does: for k, v in E: od[k] = v In either case, this is followed by: for k, v in F.items(): od[k] = v - ''' + """ if len(args) > 2: raise TypeError('update() takes at most 2 positional ' 'arguments (%d given)' % (len(args),)) @@ -174,10 +175,10 @@ class OrderedDict(dict): __marker = object() def pop(self, key, default=__marker): - '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. + """od.pop(k[,d]) -> v, remove specified key and return the corresponding value. If key is not found, d is returned if given, otherwise KeyError is raised. - ''' + """ if key in self: result = self[key] del self[key] @@ -187,14 +188,16 @@ class OrderedDict(dict): return default def setdefault(self, key, default=None): - 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + """od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od""" if key in self: return self[key] self[key] = default return default - def __repr__(self, _repr_running={}): - 'od.__repr__() <==> repr(od)' + def __repr__(self, _repr_running=None): + """od.__repr__() <==> repr(od)""" + if _repr_running is None: + _repr_running = {} call_key = id(self), _get_ident() if call_key in _repr_running: return '...' @@ -207,35 +210,35 @@ class OrderedDict(dict): del _repr_running[call_key] def __reduce__(self): - 'Return state information for pickling' + """Return state information for pickling""" items = [[k, self[k]] for k in self] inst_dict = vars(self).copy() for k in vars(OrderedDict()): inst_dict.pop(k, None) if inst_dict: - return (self.__class__, (items,), inst_dict) + return self.__class__, (items,), inst_dict return self.__class__, (items,) def copy(self): - 'od.copy() -> a shallow copy of od' + """od.copy() -> a shallow copy of od""" return self.__class__(self) @classmethod def fromkeys(cls, iterable, value=None): - '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S + """OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S and values equal to v (which defaults to None). - ''' + """ d = cls() for key in iterable: d[key] = value return d def __eq__(self, other): - '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + """od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive while comparison to a regular mapping is order-insensitive. - ''' + """ if isinstance(other, OrderedDict): return len(self) == len(other) and self.items() == other.items() return dict.__eq__(self, other) @@ -246,13 +249,22 @@ class OrderedDict(dict): # -- the following methods are only used in Python 2.7 -- def viewkeys(self): - "od.viewkeys() -> a set-like object providing a view on od's keys" - return KeysView(self) + """od.viewkeys() -> a set-like object providing a view on od's keys""" + if KeysView: + return KeysView(self) + else: + return None def viewvalues(self): - "od.viewvalues() -> an object providing a view on od's values" - return ValuesView(self) + """od.viewvalues() -> an object providing a view on od's values""" + if ValuesView: + return ValuesView(self) + else: + return None def viewitems(self): - "od.viewitems() -> a set-like object providing a view on od's items" - return ItemsView(self) + """od.viewitems() -> a set-like object providing a view on od's items""" + if ItemsView: + return ItemsView(self) + else: + return None diff --git a/utils/timer.py b/utils/timer.py index 41b5f78b7..8139f9101 100644 --- a/utils/timer.py +++ b/utils/timer.py @@ -1,7 +1,7 @@ import time -class Timer(): +class Timer(object): def __init__(self, name='', logger=None): self.name = name self.start = time.time() @@ -18,10 +18,10 @@ class Timer(): def checkpoint(self, name=''): text = u'Timer - {timer} - {checkpoint} - {last:.2f}ms ({elapsed:.2f}ms elapsed)'.format( - timer=self.name, - checkpoint=unicode(name, "utf-8"), - last=self.last, - elapsed=self.elapsed + timer=self.name, + checkpoint=unicode(name, "utf-8"), + last=self.last, + elapsed=self.elapsed ).strip() self.__last = time.time() if self.logger: