Ticket #67: tools-i18n.patch

File tools-i18n.patch, 486.7 KB (added by Adrián Chaves, 11 years ago)

Tools internationalization (patch 3/3)

  • new file inaries/data/l10n/.tx/config

    diff --git a/binaries/data/l10n/.tx/config b/binaries/data/l10n/.tx/config
    new file mode 100644
    index 0000000..9695d34
    - +  
     1[main]
     2host = https://www.transifex.com
     3
     4[0ad.engine]
     5file_filter = <lang>.engine.po
     6source_file = engine.pot
     7source_lang = en
     8
  • new file inaries/data/l10n/messages.json

    diff --git a/binaries/data/l10n/messages.json b/binaries/data/l10n/messages.json
    new file mode 100644
    index 0000000..020a843
    - +  
     1[
     2    {
     3        "output": "engine.pot",
     4        "inputRoot": "../../../source",
     5        "project": "Pyrogenesis",
     6        "copyrightHolder": "Wildfire Games",
     7        "rules": [
     8            {
     9                "extractor": "cpp",
     10                "filemasks": ["**.cpp"],
     11                "options": {
     12                    "keywords": {
     13                        "translate": [1],
     14                        "translatePlural": [1, 2],
     15                        "translateWithContext": [[1], 2],
     16                        "translatePluralWithContext": [[1], 2, 3],
     17                        "markForTranslation": [1]
     18                    },
     19                    "commentTags": [
     20                        "Localization:"
     21                    ]
     22                }
     23            }
     24        ]
     25    }
     26]
  • new file inaries/data/mods/public/l10n/.tx/config

    diff --git a/binaries/data/mods/public/l10n/.tx/config b/binaries/data/mods/public/l10n/.tx/config
    new file mode 100644
    index 0000000..733e2ab
    - +  
     1[main]
     2host = https://www.transifex.com
     3
     4[0ad.public]
     5file_filter = <lang>.public.po
     6source_file = public.pot
     7source_lang = en
     8
  • new file inaries/data/mods/public/l10n/messages.json

    diff --git a/binaries/data/mods/public/l10n/messages.json b/binaries/data/mods/public/l10n/messages.json
    new file mode 100644
    index 0000000..3d1a5a1
    - +  
     1[
     2    {
     3        "output": "public.pot",
     4        "inputRoot": "..",
     5        "project": "0 A.D. — Empires Ascendant",
     6        "copyrightHolder": "Wildfire Games",
     7        "rules": [
     8            {
     9                "extractor": "javascript",
     10                "filemasks": ["**.js"],
     11                "options": {
     12                    "keywords": {
     13                        "translate": [1],
     14                        "translatePlural": [1, 2],
     15                        "translateWithContext": [[1], 2],
     16                        "translatePluralWithContext": [[1], 2, 3],
     17                        "markForTranslation": [1]
     18                    },
     19                    "commentTags": [
     20                        "Translation:"
     21                    ]
     22                }
     23            },
     24            {
     25                "extractor": "xml",
     26                "filemasks": ["gui/**.xml"],
     27                "options": {
     28                    "keywords": {
     29                        "translatableAttribute": {
     30                            "locationAttributes": ["id"]
     31                        },
     32                        "translate": {}
     33                    }
     34                }
     35            },
     36            {
     37                "extractor": "txt",
     38                "filemasks": [
     39                    "gui/manual/intro.txt",
     40                    "gui/manual/userreport.txt",
     41                    "gui/text/quotes.txt",
     42                    "gui/splashscreen/splashscreen.txt",
     43                    "gui/text/tips/**.txt"
     44                ]
     45            },
     46            {
     47                "extractor": "json",
     48                "filemasks": [
     49                    "simulation/data/game_speeds.json",
     50                    "simulation/data/player_defaults.json"
     51                ],
     52                "options": {
     53                    "keywords": [
     54                        "Name"
     55                    ]
     56                }
     57            },
     58            {
     59                "extractor": "json",
     60                "filemasks": [
     61                    "simulation/data/map_sizes.json"
     62                ],
     63                "options": {
     64                    "keywords": [
     65                        "Name",
     66                        "LongName"
     67                    ]
     68                }
     69            },
     70            {
     71                "extractor": "json",
     72                "filemasks": [
     73                    "civs/**.json"
     74                ],
     75                "options": {
     76                    "keywords": [
     77                        "Name",
     78                        "Description",
     79                        "History",
     80                        "Special",
     81                        "Formations",
     82                        "AINames"
     83                    ]
     84                }
     85            },
     86            {
     87                "extractor": "json",
     88                "filemasks": [
     89                    "maps/random/**.json"
     90                ],
     91                "options": {
     92                    "keywords": [
     93                        "Name",
     94                        "Description"
     95                    ]
     96                }
     97            },
     98            {
     99                "extractor": "json",
     100                "filemasks": [
     101                    "simulation/ai/**.json"
     102                ],
     103                "options": {
     104                    "keywords": [
     105                        "name",
     106                        "description"
     107                    ]
     108                }
     109            },
     110            {
     111                "extractor": "json",
     112                "filemasks": [
     113                    "simulation/data/technologies/**.json"
     114                ],
     115                "options": {
     116                    "keywords": [
     117                        "specificName",
     118                        "genericName",
     119                        "description",
     120                        "tooltip",
     121                        "requirementsTooltip"
     122                    ]
     123                }
     124            },
     125            {
     126                "extractor": "xml",
     127                "filemasks": ["simulation/templates/**.xml"],
     128                "options": {
     129                    "keywords": {
     130                        "GenericName": {},
     131                        "SpecificName": {},
     132                        "Tooltip": {}
     133                    }
     134                }
     135            },
     136            {
     137                "extractor": "xml",
     138                "filemasks": [
     139                    "maps/scenarios/**.xml",
     140                    "maps/skirmishes/**.xml"
     141                ],
     142                "options": {
     143                    "keywords": {
     144                        "ScriptSettings": {
     145                            "extractJson": {
     146                                "keywords": [
     147                                    "Name",
     148                                    "Description"
     149                                ]
     150                            }
     151                        }
     152                    }
     153                }
     154            }
     155        ]
     156    }
     157]
  • source/tools/LICENSE.txt

    diff --git a/source/tools/LICENSE.txt b/source/tools/LICENSE.txt
    index cdce0d2..dc2167a 100644
    a b in particular, let us know and we can try to clarify it.  
    4646    unspecified (FontLoader.py)
    4747    IBM CPL (Packer.py)
    4848
     49  i18n
     50    GPLv2
     51    BSD (potter, fork of babel.messages; see http://babel.edgewall.org/wiki/License)
     52
    4953  jsdebugger
    5054    GPL version 2 (or later)
    5155    Other - see js/lib/ace/LICENSE.TXT (js/lib/ace)
  • new file source/tools/i18n/generateLongStringTranslations.py

    diff --git a/source/tools/i18n/generateLongStringTranslations.py b/source/tools/i18n/generateLongStringTranslations.py
    new file mode 100644
    index 0000000..f09658d
    - +  
     1#!/usr/bin/env python
     2# -*- coding:utf-8 -*-
     3#
     4# Copyright (C) 2013 Wildfire Games.
     5# This file is part of 0 A.D.
     6#
     7# 0 A.D. is free software: you can redistribute it and/or modify
     8# it under the terms of the GNU General Public License as published by
     9# the Free Software Foundation, either version 2 of the License, or
     10# (at your option) any later version.
     11#
     12# 0 A.D. is distributed in the hope that it will be useful,
     13# but WITHOUT ANY WARRANTY; without even the implied warranty of
     14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15# GNU General Public License for more details.
     16#
     17# You should have received a copy of the GNU General Public License
     18# along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     19
     20from __future__ import absolute_import, division, print_function, unicode_literals
     21
     22import codecs, json, os, textwrap
     23
     24from potter.catalog import Catalog, Message
     25from potter.extract import getExtractorInstance
     26from potter.pofile import read_po, write_po
     27
     28
     29l10nToolsDirectory = os.path.dirname(os.path.realpath(__file__))
     30projectRootDirectory = os.path.abspath(os.path.join(l10nToolsDirectory, os.pardir, os.pardir, os.pardir))
     31l10nFolderName = "l10n"
     32
     33
     34#def getAverageExpansionForEnglishString(string):
     35    #"""
     36        #Based on http://www.w3.org/International/articles/article-text-size.en
     37    #"""
     38    #length = len(string)
     39    #if len <= 10:
     40        #return length*3     # 200–300%
     41    #if len <= 20:
     42        #return length*2     # 180–200%
     43    #if len <= 30:
     44        #return length*1.8   # 160–180%
     45    #if len <= 50:
     46        #return length*1.6   # 140–160%
     47    #if len <= 70:
     48        #return length*1.7   # 151-170%
     49
     50    #return length*1.3       # 130%
     51
     52
     53#def enlarge(string, surroundWithSpaces):
     54    #halfExpansion = int(getAverageExpansionForEnglishString(string)/2)
     55    #if surroundWithSpaces: halfExpansion -= 1
     56
     57    #outputString = "x"*halfExpansion
     58    #if surroundWithSpaces:
     59        #outputString += " "
     60
     61    #outputString += string
     62
     63    #if surroundWithSpaces:
     64        #outputString += " "
     65    #outputString += "x"*halfExpansion
     66
     67    #return outputString
     68
     69
     70def generateLongStringTranslationFromPotIntoPo(inputFilePath, outputFilePath):
     71
     72    with codecs.open(inputFilePath, 'r', 'utf-8') as fileObject:
     73        templateCatalog = read_po(fileObject)
     74
     75    longStringCatalog = Catalog()
     76
     77    # Fill catalog with English strings.
     78    for message in templateCatalog:
     79        if message.pluralizable:
     80            singularString, pluralString = message.id
     81            message.string = (singularString, pluralString)
     82        else:
     83            message.string = message.id
     84        longStringCatalog[message.id] = message
     85
     86    # Load existing translation catalogs.
     87    existingTranslationCatalogs = []
     88    l10nFolderPath = os.path.dirname(inputFilePath)
     89    for filename in os.listdir(l10nFolderPath):
     90        if len(filename) > 3 and filename[-3:] == ".po" and filename[:4] != "long":
     91            with codecs.open(os.path.join(l10nFolderPath, filename), 'r', 'utf-8') as fileObject:
     92                existingTranslationCatalogs.append(read_po(fileObject))
     93
     94    # If any existing translation has more characters than the average expansion, use that instead.
     95    for translationCatalog in existingTranslationCatalogs:
     96        for longStringCatalogMessage in longStringCatalog:
     97            translationMessage = translationCatalog.get(longStringCatalogMessage.id, longStringCatalogMessage.context)
     98            if translationMessage:
     99                if longStringCatalogMessage.pluralizable:
     100                    currentSingularString, currentPluralString = longStringCatalogMessage.string
     101                    longestSingularString = currentSingularString
     102                    longestPluralString = currentPluralString
     103
     104                    candidateSingularString = translationMessage.string[0]
     105                    candidatePluralString = "" # There might be between 0 and infinite plural forms.
     106                    for candidateString in translationMessage.string[1:]:
     107                        if len(candidateString) > len(candidatePluralString): candidatePluralString = candidateString
     108
     109                    changed = False
     110                    if len(candidateSingularString) > len(currentSingularString):
     111                        longestSingularString = candidateSingularString
     112                        changed = True
     113                    if len(candidatePluralString) > len(currentPluralString):
     114                        longestPluralString   = candidatePluralString
     115                        changed = True
     116
     117                    if changed:
     118                        longStringCatalogMessage.string = (longestSingularString, longestPluralString)
     119                        longStringCatalog[longStringCatalogMessage.id] = longStringCatalogMessage
     120
     121                else:
     122                    if len(translationMessage.string) > len(longStringCatalogMessage.string):
     123                        longStringCatalogMessage.string = translationMessage.string
     124                        longStringCatalog[longStringCatalogMessage.id] = longStringCatalogMessage
     125
     126
     127    with codecs.open(outputFilePath, 'w', 'utf-8') as fileObject:
     128        write_po(fileObject, longStringCatalog)
     129
     130
     131def main():
     132
     133    for root, folders, filenames in os.walk(projectRootDirectory):
     134        for filename in filenames:
     135            if len(filename) > 4 and filename[-4:] == ".pot" and os.path.basename(root) == "l10n":
     136                generateLongStringTranslationFromPotIntoPo(os.path.join(root, filename), os.path.join(root, "long." + filename[:-1]))
     137
     138
     139if __name__ == "__main__":
     140    main()
  • new file source/tools/i18n/potter/catalog.py

    diff --git a/source/tools/i18n/potter/__init__.py b/source/tools/i18n/potter/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/source/tools/i18n/potter/catalog.py b/source/tools/i18n/potter/catalog.py
    new file mode 100644
    index 0000000..248fcec
    - +  
     1# -*- coding: utf-8 -*-
     2#
     3# Copyright (C) 2007-2011 Edgewall Software
     4# Copyright (C) 2013 Wildfire Games
     5# All rights reserved.
     6#
     7# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
     8# following conditions are met:
     9#
     10#   Redistributions of source code must retain the above copyright notice, this list of conditions and the following
     11#   disclaimer.
     12#   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
     13#   disclaimer in the documentation and/or other materials provided with the distribution.
     14#   The name of the author may not be used to endorse or promote products derived from this software without specific
     15#   prior written permission.
     16#
     17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     18# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     22# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23#
     24# This software consists of voluntary contributions made by many
     25# individuals. For the exact contribution history, see the revision
     26# history and logs:
     27# • http://babel.edgewall.org/log/trunk/babel/messages
     28# • http://trac.wildfiregames.com/browser/ps/trunk/source/tools/i18n/potter
     29
     30"""Data structures for message catalogs."""
     31
     32from __future__ import absolute_import, division, print_function, unicode_literals
     33
     34from cgi import parse_header
     35from datetime import datetime, time as time_
     36from difflib import get_close_matches
     37from email import message_from_string
     38from copy import copy
     39import re
     40import time
     41
     42from collections import OrderedDict
     43
     44from potter.util import distinct, LOCALTZ, UTC, FixedOffsetTimezone
     45
     46
     47__all__ = ['Message', 'Catalog']
     48__docformat__ = 'restructuredtext en'
     49
     50
     51PYTHON_FORMAT = re.compile(r"""(?x)
     52    \%
     53        (?:\(([\w]*)\))?
     54        (
     55            [-#0\ +]?(?:\*|[\d]+)?
     56            (?:\.(?:\*|[\d]+))?
     57            [hlL]?
     58        )
     59        ([diouxXeEfFgGcrs%])
     60""")
     61
     62C_FORMAT = re.compile(r"""(?x)
     63    \%
     64        (\d+\$)?
     65        ([-+ 0#]+)?
     66        (v|\*(\d+\$)?v)?
     67        0*
     68        (\d+|\*(\d+\$)?)?
     69        (\.(\d*|\*(\d+\$)?))?
     70        [hlqLV]?
     71        ([%bcdefginopsuxDFOUX])
     72""")
     73
     74
     75class Message(object):
     76    """Representation of a single message in a catalog."""
     77
     78    def __init__(self, id, string=u'', locations=(), flags=(), auto_comments=(),
     79                 user_comments=(), previous_id=(), lineno=None, context=None):
     80        """Create the message object.
     81
     82        :param id: the message ID, or a ``(singular, plural)`` tuple for
     83                   pluralizable messages
     84        :param string: the translated message string, or a
     85                       ``(singular, plural)`` tuple for pluralizable messages
     86        :param locations: a sequence of ``(filenname, lineno)`` tuples
     87        :param flags: a set or sequence of flags
     88        :param auto_comments: a sequence of automatic comments for the message
     89        :param user_comments: a sequence of user comments for the message
     90        :param previous_id: the previous message ID, or a ``(singular, plural)``
     91                            tuple for pluralizable messages
     92        :param lineno: the line number on which the msgid line was found in the
     93                       PO file, if any
     94        :param context: the message context
     95        """
     96        self.id = id #: The message ID
     97        if not string and self.pluralizable:
     98            string = (u'', u'')
     99        self.string = string #: The message translation
     100        self.locations = list(distinct(locations))
     101        self.flags = set(flags)
     102        if id:
     103            formatFlag = self.guessFormatFlag();
     104            if formatFlag:
     105                self.flags.add(formatFlag)
     106        self.auto_comments = list(distinct(auto_comments))
     107        self.user_comments = list(distinct(user_comments))
     108        if isinstance(previous_id, str):
     109            self.previous_id = [previous_id]
     110        else:
     111            self.previous_id = list(previous_id)
     112        self.lineno = lineno
     113        self.context = context
     114
     115    def __repr__(self):
     116        return '<%s %r (flags: %r)>' % (type(self).__name__, self.id,
     117                                        list(self.flags))
     118
     119    def __cmp__(self, obj):
     120        """Compare Messages, taking into account plural ids"""
     121        def values_to_compare():
     122            if isinstance(obj, Message):
     123                plural = self.pluralizable
     124                obj_plural = obj.pluralizable
     125                if plural and obj_plural:
     126                    return self.id[0], obj.id[0]
     127                elif plural:
     128                    return self.id[0], obj.id
     129                elif obj_plural:
     130                    return self.id, obj.id[0]
     131            return self.id, obj.id
     132        this, other = values_to_compare()
     133        return cmp(this, other)
     134
     135    def __gt__(self, other):
     136        return self.__cmp__(other) > 0
     137
     138    def __lt__(self, other):
     139        return self.__cmp__(other) < 0
     140
     141    def __ge__(self, other):
     142        return self.__cmp__(other) >= 0
     143
     144    def __le__(self, other):
     145        return self.__cmp__(other) <= 0
     146
     147    def __eq__(self, other):
     148        return self.__cmp__(other) == 0
     149
     150    def __ne__(self, other):
     151        return self.__cmp__(other) != 0
     152
     153    def clone(self):
     154        return Message(*map(copy, (self.id, self.string, self.locations,
     155                                   self.flags, self.auto_comments,
     156                                   self.user_comments, self.previous_id,
     157                                   self.lineno, self.context)))
     158
     159    @property
     160    def pluralizable(self):
     161        """Whether the message is plurizable.
     162
     163        >>> Message('foo').pluralizable
     164        False
     165        >>> Message(('foo', 'bar')).pluralizable
     166        True
     167
     168        :type:  `bool`"""
     169        return isinstance(self.id, (list, tuple))
     170
     171    def guessFormatFlag(self):
     172        """ If the message contains parameters, this function returns a string with the flag that represents the format
     173            of those parameters.
     174
     175        :type:  `string`"""
     176        ids = self.id
     177        if not isinstance(ids, (list, tuple)):
     178            ids = [ids]
     179        if bool(filter(None, [C_FORMAT.search(id) for id in ids])):
     180            return "c-format"
     181        elif bool(filter(None, [PYTHON_FORMAT.search(id) for id in ids])):
     182            return "python-format"
     183        else:
     184            return None
     185
     186
     187DEFAULT_HEADER = u"""\
     188# Translation template for PROJECT.
     189# Copyright © YEAR ORGANIZATION
     190# This file is distributed under the same license as the PROJECT project.
     191#"""
     192
     193
     194class Catalog(object):
     195    """Representation of a message catalog."""
     196
     197    def __init__(self, locale=None, domain=None, header_comment=DEFAULT_HEADER,
     198                 project=None, version=None, copyright_holder=None,
     199                 msgid_bugs_address=None, creation_date=None,
     200                 revision_date=None, charset='utf-8'):
     201        """Initialize the catalog object.
     202
     203        :param domain: the message domain
     204        :param header_comment: the header comment as string, or `None` for the
     205                               default header
     206        :param project: the project's name
     207        :param version: the project's version
     208        :param copyright_holder: the copyright holder of the catalog
     209        :param msgid_bugs_address: the email address or URL to submit bug
     210                                   reports to
     211        :param creation_date: the date the catalog was created
     212        :param revision_date: the date the catalog was revised
     213        :param charset: the encoding to use in the output
     214        """
     215        self.domain = domain #: The message domain
     216        self._header_comment = header_comment
     217        self._messages = OrderedDict()
     218
     219        self.project = project or 'PROJECT' #: The project name
     220        self.version = version #: The project version
     221        self.copyright_holder = copyright_holder or 'ORGANIZATION'
     222        self.msgid_bugs_address = msgid_bugs_address or 'EMAIL@ADDRESS'
     223
     224        self.charset = charset or 'utf-8'
     225
     226        if creation_date is None:
     227            creation_date = datetime.now(LOCALTZ)
     228        elif isinstance(creation_date, datetime) and not creation_date.tzinfo:
     229            creation_date = creation_date.replace(tzinfo=LOCALTZ)
     230        self.creation_date = creation_date #: Creation date of the template
     231        if revision_date is None:
     232            revision_date = 'YEAR-MO-DA HO:MI+ZONE'
     233        elif isinstance(revision_date, datetime) and not revision_date.tzinfo:
     234            revision_date = revision_date.replace(tzinfo=LOCALTZ)
     235        self.revision_date = revision_date #: Last revision date of the catalog
     236
     237        self.obsolete = OrderedDict() #: Dictionary of obsolete messages
     238        self._num_plurals = None
     239        self._plural_expr = None
     240
     241    def _get_header_comment(self):
     242        comment = self._header_comment
     243        year = datetime.now(LOCALTZ).strftime('%Y')
     244        if hasattr(self.revision_date, 'strftime'):
     245            year = self.revision_date.strftime('%Y')
     246        comment = comment.replace('PROJECT', self.project) \
     247                         .replace('YEAR', year) \
     248                         .replace('ORGANIZATION', self.copyright_holder)
     249        return comment
     250
     251    def _set_header_comment(self, string):
     252        self._header_comment = string
     253
     254    header_comment = property(_get_header_comment, _set_header_comment, doc="""\
     255    The header comment for the catalog.
     256
     257    >>> catalog = Catalog(project='Foobar', version='1.0',
     258    ...                   copyright_holder='Foo Company')
     259    >>> print catalog.header_comment #doctest: +ELLIPSIS
     260    # Translations template for Foobar.
     261    # Copyright (C) ... Foo Company
     262    # This file is distributed under the same license as the Foobar project.
     263    # FIRST AUTHOR <EMAIL@ADDRESS>, ....
     264    #
     265
     266    The header can also be set from a string. Any known upper-case variables
     267    will be replaced when the header is retrieved again:
     268
     269    >>> catalog = Catalog(project='Foobar', version='1.0',
     270    ...                   copyright_holder='Foo Company')
     271    >>> catalog.header_comment = '''\\
     272    ... # The POT for my really cool PROJECT project.
     273    ... # Copyright (C) 1990-2003 ORGANIZATION
     274    ... # This file is distributed under the same license as the PROJECT
     275    ... # project.
     276    ... #'''
     277    >>> print catalog.header_comment
     278    # The POT for my really cool Foobar project.
     279    # Copyright (C) 1990-2003 Foo Company
     280    # This file is distributed under the same license as the Foobar
     281    # project.
     282    #
     283
     284    :type: `unicode`
     285    """)
     286
     287    def _get_mime_headers(self):
     288        headers = []
     289        projectIdVersion = self.project
     290        if self.version:
     291            projectIdVersion += " " + self.version
     292        headers.append(('Project-Id-Version', projectIdVersion))
     293        headers.append(('Report-Msgid-Bugs-To', self.msgid_bugs_address))
     294        headers.append(('POT-Creation-Date', self.creation_date.strftime('%Y-%m-%d %H:%M%z')))
     295        if isinstance(self.revision_date, (datetime, time_, int, float)):
     296            headers.append(('PO-Revision-Date', self.revision_date.strftime('%Y-%m-%d %H:%M%z')))
     297        else:
     298            headers.append(('PO-Revision-Date', self.revision_date))
     299        headers.append(('MIME-Version', '1.0'))
     300        headers.append(('Content-Type',
     301                        'text/plain; charset=%s' % self.charset))
     302        headers.append(('Content-Transfer-Encoding', '8bit'))
     303        headers.append(('Generated-By', 'Potter 1.0\n'))
     304        return headers
     305
     306    def _set_mime_headers(self, headers):
     307        for name, value in headers:
     308            name = name.lower()
     309            if name == 'project-id-version':
     310                parts = value.split(' ')
     311                self.project = u' '.join(parts[:-1])
     312                self.version = parts[-1]
     313            elif name == 'report-msgid-bugs-to':
     314                self.msgid_bugs_address = value
     315            elif name == 'content-type':
     316                mimetype, params = parse_header(value)
     317                if 'charset' in params:
     318                    self.charset = params['charset'].lower()
     319            elif name == 'plural-forms':
     320                _, params = parse_header(' ;' + value)
     321                try:
     322                    self._num_plurals = int(params.get('nplurals', 2))
     323                except ValueError:
     324                    self._num_plurals = 2
     325                self._plural_expr = params.get('plural', '(n != 1)')
     326            elif name == 'pot-creation-date':
     327                # FIXME: this should use dates.parse_datetime as soon as that
     328                #        is ready
     329                value, tzoffset, _ = re.split('([+-]\d{4})$', value, 1)
     330
     331                tt = time.strptime(value, '%Y-%m-%d %H:%M')
     332                ts = time.mktime(tt)
     333
     334                # Separate the offset into a sign component, hours, and minutes
     335                plus_minus_s, rest = tzoffset[0], tzoffset[1:]
     336                hours_offset_s, mins_offset_s = rest[:2], rest[2:]
     337
     338                # Make them all integers
     339                plus_minus = int(plus_minus_s + '1')
     340                hours_offset = int(hours_offset_s)
     341                mins_offset = int(mins_offset_s)
     342
     343                # Calculate net offset
     344                net_mins_offset = hours_offset * 60
     345                net_mins_offset += mins_offset
     346                net_mins_offset *= plus_minus
     347
     348                # Create an offset object
     349                tzoffset = FixedOffsetTimezone(net_mins_offset)
     350
     351                # Store the offset in a datetime object
     352                dt = datetime.fromtimestamp(ts)
     353                self.creation_date = dt.replace(tzinfo=tzoffset)
     354            elif name == 'po-revision-date':
     355                # Keep the value if it's not the default one
     356                if 'YEAR' not in value:
     357                    # FIXME: this should use dates.parse_datetime as soon as
     358                    #        that is ready
     359                    value, tzoffset, _ = re.split('([+-]\d{4})$', value, 1)
     360                    tt = time.strptime(value, '%Y-%m-%d %H:%M')
     361                    ts = time.mktime(tt)
     362
     363                    # Separate the offset into a sign component, hours, and
     364                    # minutes
     365                    plus_minus_s, rest = tzoffset[0], tzoffset[1:]
     366                    hours_offset_s, mins_offset_s = rest[:2], rest[2:]
     367
     368                    # Make them all integers
     369                    plus_minus = int(plus_minus_s + '1')
     370                    hours_offset = int(hours_offset_s)
     371                    mins_offset = int(mins_offset_s)
     372
     373                    # Calculate net offset
     374                    net_mins_offset = hours_offset * 60
     375                    net_mins_offset += mins_offset
     376                    net_mins_offset *= plus_minus
     377
     378                    # Create an offset object
     379                    tzoffset = FixedOffsetTimezone(net_mins_offset)
     380
     381                    # Store the offset in a datetime object
     382                    dt = datetime.fromtimestamp(ts)
     383                    self.revision_date = dt.replace(tzinfo=tzoffset)
     384
     385    mime_headers = property(_get_mime_headers, _set_mime_headers, doc="""\
     386    The MIME headers of the catalog, used for the special ``msgid ""`` entry.
     387
     388    Here's an example of the output for such a catalog template:
     389
     390    >>> created = datetime(1990, 4, 1, 15, 30, tzinfo=UTC)
     391    >>> catalog = Catalog(project='Foobar', version='1.0',
     392    ...                   creation_date=created)
     393    >>> for name, value in catalog.mime_headers:
     394    ...     print '%s: %s' % (name, value)
     395    Project-Id-Version: Foobar 1.0
     396    Report-Msgid-Bugs-To: EMAIL@ADDRESS
     397    POT-Creation-Date: 1990-04-01 15:30+0000
     398    PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE
     399    MIME-Version: 1.0
     400    Content-Type: text/plain; charset=utf-8
     401    Content-Transfer-Encoding: 8bit
     402    Generated-By: Potter ...
     403
     404    :type: `list`
     405    """)
     406
     407    def __contains__(self, id):
     408        """Return whether the catalog has a message with the specified ID."""
     409        return self._key_for(id) in self._messages
     410
     411    def __len__(self):
     412        """The number of messages in the catalog.
     413
     414        This does not include the special ``msgid ""`` entry."""
     415        return len(self._messages)
     416
     417    def __iter__(self):
     418        """Iterates through all the entries in the catalog, in the order they
     419        were added, yielding a `Message` object for every entry.
     420
     421        :rtype: ``iterator``"""
     422        buf = []
     423        for name, value in self.mime_headers:
     424            buf.append('%s: %s' % (name, value))
     425        yield Message(u'', '\n'.join(buf), flags=set())
     426        for key in self._messages:
     427            yield self._messages[key]
     428
     429    def __repr__(self):
     430        return '<%s %r>' % (type(self).__name__, self.domain)
     431
     432    def __delitem__(self, id):
     433        """Delete the message with the specified ID."""
     434        self.delete(id)
     435
     436    def __getitem__(self, id):
     437        """Return the message with the specified ID.
     438
     439        :param id: the message ID
     440        :return: the message with the specified ID, or `None` if no such
     441                 message is in the catalog
     442        :rtype: `Message`
     443        """
     444        return self.get(id)
     445
     446    def __setitem__(self, id, message):
     447        """Add or update the message with the specified ID.
     448
     449        >>> catalog = Catalog()
     450        >>> catalog[u'foo'] = Message(u'foo')
     451        >>> catalog[u'foo']
     452        <Message u'foo' (flags: [])>
     453
     454        If a message with that ID is already in the catalog, it is updated
     455        to include the locations and flags of the new message.
     456
     457        >>> catalog = Catalog()
     458        >>> catalog[u'foo'] = Message(u'foo', locations=[('main.py', 1)])
     459        >>> catalog[u'foo'].locations
     460        [('main.py', 1)]
     461        >>> catalog[u'foo'] = Message(u'foo', locations=[('utils.py', 5)])
     462        >>> catalog[u'foo'].locations
     463        [('main.py', 1), ('utils.py', 5)]
     464
     465        :param id: the message ID
     466        :param message: the `Message` object
     467        """
     468        assert isinstance(message, Message), 'expected a Message object'
     469        key = self._key_for(id, message.context)
     470        current = self._messages.get(key)
     471        if current:
     472            if message.pluralizable and not current.pluralizable:
     473                # The new message adds pluralization
     474                current.id = message.id
     475                current.string = message.string
     476            current.locations = list(distinct(current.locations + message.locations))
     477            current.auto_comments = list(distinct(current.auto_comments + message.auto_comments))
     478            current.user_comments = list(distinct(current.user_comments + message.user_comments))
     479            current.flags |= message.flags
     480            message = current
     481        elif id == '':
     482            # special treatment for the header message
     483            def _parse_header(header_string):
     484                # message_from_string only works for str, not for unicode
     485                headers = message_from_string(header_string.encode('utf8'))
     486                decoded_headers = {}
     487                for name, value in headers.items():
     488                    name = name.decode('utf8')
     489                    value = value.decode('utf8')
     490                    decoded_headers[name] = value
     491                return decoded_headers
     492            self.mime_headers = _parse_header(message.string).items()
     493            self.header_comment = '\n'.join(['# %s' % comment for comment
     494                                             in message.user_comments])
     495        else:
     496            if isinstance(id, (list, tuple)):
     497                assert isinstance(message.string, (list, tuple)), \
     498                    'Expected sequence but got %s' % type(message.string)
     499            self._messages[key] = message
     500
     501    def add(self, id, string=None, locations=(), flags=(), auto_comments=(),
     502            user_comments=(), previous_id=(), lineno=None, context=None):
     503        """Add or update the message with the specified ID.
     504
     505        >>> catalog = Catalog()
     506        >>> catalog.add(u'foo')
     507        <Message ...>
     508        >>> catalog[u'foo']
     509        <Message u'foo' (flags: [])>
     510
     511        This method simply constructs a `Message` object with the given
     512        arguments and invokes `__setitem__` with that object.
     513
     514        :param id: the message ID, or a ``(singular, plural)`` tuple for
     515                   pluralizable messages
     516        :param string: the translated message string, or a
     517                       ``(singular, plural)`` tuple for pluralizable messages
     518        :param locations: a sequence of strings that determine where a message was found
     519        :param flags: a set or sequence of flags
     520        :param auto_comments: a sequence of automatic comments
     521        :param user_comments: a sequence of user comments
     522        :param previous_id: the previous message ID, or a ``(singular, plural)``
     523                            tuple for pluralizable messages
     524        :param lineno: the line number on which the msgid line was found in the
     525                       PO file, if any
     526        :param context: the message context
     527        :return: the newly added message
     528        :rtype: `Message`
     529        """
     530        message = Message(id, string, locations, flags, auto_comments,
     531                          user_comments, previous_id, lineno=lineno,
     532                          context=context)
     533        self[id] = message
     534        return message
     535
     536    def get(self, id, context=None):
     537        """Return the message with the specified ID and context.
     538
     539        :param id: the message ID
     540        :param context: the message context, or ``None`` for no context
     541        :return: the message with the specified ID, or `None` if no such
     542                 message is in the catalog
     543        :rtype: `Message`
     544        """
     545        return self._messages.get(self._key_for(id, context))
     546
     547    def delete(self, id, context=None):
     548        """Delete the message with the specified ID and context.
     549
     550        :param id: the message ID
     551        :param context: the message context, or ``None`` for no context
     552        """
     553        key = self._key_for(id, context)
     554        if key in self._messages:
     555            del self._messages[key]
     556
     557    @property
     558    def num_plurals(self):
     559        if self._num_plurals is not None:
     560            return self._num_plurals
     561        else:
     562            return 2
     563
     564    def _key_for(self, id, context=None):
     565        """The key for a message is just the singular ID even for pluralizable
     566        messages, but is a ``(msgid, msgctxt)`` tuple for context-specific
     567        messages.
     568        """
     569        key = id
     570        if isinstance(key, (list, tuple)):
     571            key = id[0]
     572        if context is not None:
     573            key = (key, context)
     574        return key
  • new file source/tools/i18n/potter/extract.py

    diff --git a/source/tools/i18n/potter/extract.py b/source/tools/i18n/potter/extract.py
    new file mode 100644
    index 0000000..4b59691
    - +  
     1# -*- coding: utf-8 -*-
     2#
     3# Copyright (C) 2007-2011 Edgewall Software
     4# Copyright (C) 2013 Wildfire Games
     5# All rights reserved.
     6#
     7# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
     8# following conditions are met:
     9#
     10#   Redistributions of source code must retain the above copyright notice, this list of conditions and the following
     11#   disclaimer.
     12#   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
     13#   disclaimer in the documentation and/or other materials provided with the distribution.
     14#   The name of the author may not be used to endorse or promote products derived from this software without specific
     15#   prior written permission.
     16#
     17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     18# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     22# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23#
     24# This software consists of voluntary contributions made by many
     25# individuals. For the exact contribution history, see the revision
     26# history and logs:
     27# • http://babel.edgewall.org/log/trunk/babel/messages
     28# • http://trac.wildfiregames.com/browser/ps/trunk/source/tools/i18n/potter
     29
     30"""Basic infrastructure for extracting localizable messages from source files.
     31
     32This module defines an extensible system for collecting localizable message
     33strings from a variety of sources. A native extractor for Python source files
     34is builtin, extractors for other sources can be added using very simple plugins.
     35
     36The main entry points into the extraction functionality are the functions
     37`extract_from_dir` and `extract_from_file`.
     38"""
     39
     40from __future__ import absolute_import, division, print_function, unicode_literals
     41
     42__all__ = ['getExtractorInstance']
     43__docformat__ = 'restructuredtext en'
     44
     45
     46def getExtractorInstance(code, directoryPath, filemasks, options={}):
     47    extractorClass = getattr(__import__("potter.extractors", {}, {}, [code,]), code)
     48    return extractorClass(directoryPath, filemasks, options)
  • new file source/tools/i18n/potter/extractors.py

    diff --git a/source/tools/i18n/potter/extractors.py b/source/tools/i18n/potter/extractors.py
    new file mode 100644
    index 0000000..27187d5
    - +  
     1# -*- coding:utf-8 -*-
     2#
     3# Copyright (C) 2013 Wildfire Games
     4# All rights reserved.
     5#
     6# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
     7# following conditions are met:
     8#
     9#   Redistributions of source code must retain the above copyright notice, this list of conditions and the following
     10#   disclaimer.
     11#   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
     12#   disclaimer in the documentation and/or other materials provided with the distribution.
     13#   The name of the author may not be used to endorse or promote products derived from this software without specific
     14#   prior written permission.
     15#
     16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     17# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     18# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     19# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     20# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     21# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     22#
     23# This software consists of voluntary contributions made by many
     24# individuals. For the exact contribution history, see the revision
     25# history and logs:
     26# • http://babel.edgewall.org/log/trunk/babel/messages
     27# • http://trac.wildfiregames.com/browser/ps/trunk/source/tools/i18n/potter
     28
     29from __future__ import absolute_import, division, print_function, unicode_literals
     30
     31import codecs, os, sys
     32import json as jsonParser
     33
     34from tokenize import generate_tokens, COMMENT, NAME, OP, STRING
     35from textwrap import dedent
     36
     37from potter.util import parse_encoding, pathmatch, relpath
     38
     39
     40class Extractor(object):
     41
     42    def __init__(self, directoryPath, filemasks, options={}):
     43        self.directoryPath = directoryPath
     44        self.filemasks = filemasks
     45        self.options = options
     46
     47    def run(self):
     48        """ Extracts messages.
     49
     50        :return:    An iterator over ``(message, context, location, comment)`` tuples.
     51        :rtype:     ``iterator``
     52        """
     53        directoryAbsolutePath = os.path.abspath(self.directoryPath)
     54        for root, folders, filenames in os.walk(directoryAbsolutePath):
     55            for subdir in folders:
     56                if subdir.startswith('.') or subdir.startswith('_'):
     57                    folders.remove(subdir)
     58            folders.sort()
     59            filenames.sort()
     60            for filename in filenames:
     61                filename = relpath(os.path.join(root, filename).replace(os.sep, '/'), self.directoryPath)
     62                for filemask in self.filemasks:
     63                    if pathmatch(filemask, filename):
     64                        filepath = os.path.join(directoryAbsolutePath, filename)
     65                        for message, context, position, comments in self.extractFromFile(filepath):
     66                            yield message, context, filename + ":" + str(position), comments
     67
     68    def extractFromFile(self, filepath):
     69        """ Extracts messages from a specific file.
     70
     71        :return:    An iterator over ``(message, context, position, comments)`` tuples.
     72        :rtype:     ``iterator``
     73        """
     74        pass
     75
     76
     77class javascript(Extractor):
     78    """ Extract messages from JavaScript source code.
     79    """
     80
     81    empty_msgid_warning = ( '%s: warning: Empty msgid.  It is reserved by GNU gettext: gettext("") '
     82                            'returns the header entry with meta information, not the empty string.' )
     83
     84    def extractJavascriptFromFile(self, fileObject):
     85
     86        from potter.jslexer import tokenize, unquote_string
     87        funcname = message_lineno = None
     88        messages = []
     89        last_argument = None
     90        translator_comments = []
     91        concatenate_next = False
     92        last_token = None
     93        call_stack = -1
     94        comment_tags = self.options.get('commentTags', [])
     95        keywords = self.options.get('keywords', {}).keys()
     96
     97        for token in tokenize(fileObject.read()):
     98            if token.type == 'operator' and token.value == '(':
     99                if funcname:
     100                    message_lineno = token.lineno
     101                    call_stack += 1
     102
     103            elif call_stack == -1 and token.type == 'linecomment':
     104                value = token.value[2:].strip()
     105                if translator_comments and \
     106                translator_comments[-1][0] == token.lineno - 1:
     107                    translator_comments.append((token.lineno, value))
     108                    continue
     109
     110                for comment_tag in comment_tags:
     111                    if value.startswith(comment_tag):
     112                        translator_comments.append((token.lineno, value.strip()))
     113                        break
     114
     115            elif token.type == 'multilinecomment':
     116                # only one multi-line comment may preceed a translation
     117                translator_comments = []
     118                value = token.value[2:-2].strip()
     119                for comment_tag in comment_tags:
     120                    if value.startswith(comment_tag):
     121                        lines = value.splitlines()
     122                        if lines:
     123                            lines[0] = lines[0].strip()
     124                            lines[1:] = dedent('\n'.join(lines[1:])).splitlines()
     125                            for offset, line in enumerate(lines):
     126                                translator_comments.append((token.lineno + offset,
     127                                                            line))
     128                        break
     129
     130            elif funcname and call_stack == 0:
     131                if token.type == 'operator' and token.value == ')':
     132                    if last_argument is not None:
     133                        messages.append(last_argument)
     134                    if len(messages) > 1:
     135                        messages = tuple(messages)
     136                    elif messages:
     137                        messages = messages[0]
     138                    else:
     139                        messages = None
     140
     141                    # Comments don't apply unless they immediately precede the
     142                    # message
     143                    if translator_comments and \
     144                    translator_comments[-1][0] < message_lineno - 1:
     145                        translator_comments = []
     146
     147                    if messages is not None:
     148                        yield (message_lineno, funcname, messages,
     149                            [comment[1] for comment in translator_comments])
     150
     151                    funcname = message_lineno = last_argument = None
     152                    concatenate_next = False
     153                    translator_comments = []
     154                    messages = []
     155                    call_stack = -1
     156
     157                elif token.type == 'string':
     158                    new_value = unquote_string(token.value)
     159                    if concatenate_next:
     160                        last_argument = (last_argument or '') + new_value
     161                        concatenate_next = False
     162                    else:
     163                        last_argument = new_value
     164
     165                elif token.type == 'operator':
     166                    if token.value == ',':
     167                        if last_argument is not None:
     168                            messages.append(last_argument)
     169                            last_argument = None
     170                        else:
     171                            messages.append(None)
     172                        concatenate_next = False
     173                    elif token.value == '+':
     174                        concatenate_next = True
     175
     176            elif call_stack > 0 and token.type == 'operator' \
     177                and token.value == ')':
     178                call_stack -= 1
     179
     180            elif funcname and call_stack == -1:
     181                funcname = None
     182
     183            elif call_stack == -1 and token.type == 'name' and \
     184                token.value in keywords and \
     185                (last_token is None or last_token.type != 'name' or
     186                last_token.value != 'function'):
     187                funcname = token.value
     188
     189            last_token = token
     190
     191
     192    def extractFromFile(self, filepath):
     193
     194        with codecs.open(filepath, 'r', encoding='utf-8-sig') as fileObject:
     195            for lineno, funcname, messages, comments in self.extractJavascriptFromFile(fileObject):
     196                if funcname:
     197                    spec = self.options.get('keywords', {})[funcname] or (1,)
     198                else:
     199                    spec = (1,)
     200                if not isinstance(messages, (list, tuple)):
     201                    messages = [messages]
     202                if not messages:
     203                    continue
     204
     205                # Validate the messages against the keyword's specification
     206                context = None
     207                msgs = []
     208                invalid = False
     209                # last_index is 1 based like the keyword spec
     210                last_index = len(messages)
     211                for index in spec:
     212                    if isinstance(index, (list, tuple)):
     213                        context = messages[index[0] - 1]
     214                        continue
     215                    if last_index < index:
     216                        # Not enough arguments
     217                        invalid = True
     218                        break
     219                    message = messages[index - 1]
     220                    if message is None:
     221                        invalid = True
     222                        break
     223                    msgs.append(message)
     224                if invalid:
     225                    continue
     226
     227                # keyword spec indexes are 1 based, therefore '-1'
     228                if isinstance(spec[0], (tuple, list)):
     229                    # context-aware *gettext method
     230                    first_msg_index = spec[1] - 1
     231                else:
     232                    first_msg_index = spec[0] - 1
     233                if not messages[first_msg_index]:
     234                    # An empty string msgid isn't valid, emit a warning
     235                    where = '%s:%i' % (hasattr(fileObject, 'name') and \
     236                                        fileObject.name or '(unknown)', lineno)
     237                    print >> sys.stderr, self.empty_msgid_warning % where
     238                    continue
     239
     240                messages = tuple(msgs)
     241                if len(messages) == 1:
     242                    messages = messages[0]
     243
     244                yield messages, context, lineno, comments
     245
     246
     247class cpp(javascript):
     248    """ Extract messages from C++ source code.
     249    """
     250    pass
     251
     252
     253class txt(Extractor):
     254    """ Extract messages from plain text files.
     255    """
     256
     257    def extractFromFile(self, filepath):
     258        with codecs.open(filepath, "r", encoding='utf-8-sig') as fileObject:
     259            lineCount = 0
     260            for line in [line.strip() for line in fileObject.readlines()]:
     261                lineCount += 1
     262                if line:
     263                    yield line, None, str(lineCount), []
     264
     265
     266class json(Extractor):
     267    """ Extract messages from JSON files.
     268    """
     269
     270    def __init__(self, directoryPath, filemasks, options):
     271        super(json, self).__init__(directoryPath, filemasks, options)
     272        self.breadcrumbs = []
     273        self.keywords = self.options.get("keywords", {})
     274
     275    def setOptions(self, options):
     276        self.options = options
     277        self.keywords = self.options.get("keywords", {})
     278
     279    @staticmethod
     280    def formatBreadcrumbs(breadcrumbs):
     281        firstPiece = breadcrumbs[0]
     282        if isinstance(firstPiece, int): outputString = "[" + str(firstPiece) + "]"
     283        else: outputString = firstPiece
     284        for piece in breadcrumbs[1:]:
     285            if isinstance(piece, int): outputString += "[" + str(piece) + "]"
     286            else: outputString += "." + piece
     287        return outputString
     288
     289    def extractFromFile(self, filepath):
     290        with codecs.open(filepath, "r", encoding='utf-8-sig') as fileObject:
     291            for message, breadcrumbs in self.extractFromString(fileObject.read()): # 'utf-8-sig' avoids issues with BOM.
     292                yield message, None, self.formatBreadcrumbs(breadcrumbs), []
     293
     294    def extractFromString(self, string):
     295        self.breadcrumbs = []
     296        jsonDocument = jsonParser.loads(string)
     297        if isinstance(jsonDocument, list):
     298            for message, breadcrumbs in self.parseList(jsonDocument):
     299                if message: # Skip empty strings.
     300                    yield message, breadcrumbs
     301        elif isinstance(jsonDocument, dict):
     302            for message, breadcrumbs in self.parseDictionary(jsonDocument):
     303                if message: # Skip empty strings.
     304                    yield message, breadcrumbs
     305        else:
     306            raise Exception("Unexpected JSON document parent structure (not a list or a dictionary). You must extend the JSON extractor to support it.")
     307
     308    def parseList(self, itemsList):
     309        index = 0
     310        for listItem in itemsList:
     311            self.breadcrumbs.append(index)
     312            if isinstance(listItem, list):
     313                for message, breadcrumbs in self.parseList(listItem):
     314                    yield message, breadcrumbs
     315            elif isinstance(listItem, dict):
     316                for message, breadcrumbs in self.parseDictionary(listItem):
     317                    yield message, breadcrumbs
     318            del self.breadcrumbs[-1]
     319            index += 1
     320
     321    def parseDictionary(self, dictionary):
     322        for keyword in dictionary:
     323            self.breadcrumbs.append(keyword)
     324            if keyword in self.keywords:
     325                if isinstance(dictionary[keyword], str):
     326                    yield dictionary[keyword], self.breadcrumbs
     327                elif isinstance(dictionary[keyword], list):
     328                    for message, breadcrumbs in self.extractList(dictionary[keyword]):
     329                        yield message, breadcrumbs
     330                elif isinstance(dictionary[keyword], dict):
     331                    for message, breadcrumbs in self.extractDictionary(dictionary[keyword]):
     332                        yield message, breadcrumbs
     333            elif isinstance(dictionary[keyword], list):
     334                for message, breadcrumbs in self.parseList(dictionary[keyword]):
     335                    yield message, breadcrumbs
     336            elif isinstance(dictionary[keyword], dict):
     337                for message, breadcrumbs in self.parseDictionary(dictionary[keyword]):
     338                    yield message, breadcrumbs
     339            del self.breadcrumbs[-1]
     340
     341    def extractList(self, itemsList):
     342        index = 0
     343        for listItem in itemsList:
     344            self.breadcrumbs.append(index)
     345            if isinstance(listItem, str):
     346                yield listItem, self.breadcrumbs
     347            del self.breadcrumbs[-1]
     348            index += 1
     349
     350    def extractDictionary(self, dictionary):
     351        for keyword in dictionary:
     352            self.breadcrumbs.append(keyword)
     353            if isinstance(dictionary[keyword], str):
     354                yield dictionary[keyword], self.breadcrumbs
     355            del self.breadcrumbs[-1]
     356
     357
     358class xml(Extractor):
     359    """ Extract messages from XML files.
     360    """
     361
     362    def __init__(self, directoryPath, filemasks, options):
     363        super(xml, self).__init__(directoryPath, filemasks, options)
     364        self.keywords = self.options.get("keywords", {})
     365        self.jsonExtractor = None
     366
     367    def getJsonExtractor(self):
     368        if not self.jsonExtractor:
     369            self.jsonExtractor = json(None, None, {})
     370        return self.jsonExtractor
     371
     372    def extractFromFile(self, filepath):
     373        from lxml import etree
     374        with codecs.open(filepath, "r", encoding='utf-8-sig') as fileObject:
     375            xmlDocument = etree.parse(fileObject)
     376            for keyword in self.keywords:
     377                for element in xmlDocument.iter(keyword):
     378                    position = str(element.sourceline)
     379                    if "extractJson" in self.keywords[keyword]:
     380                        jsonExtractor = self.getJsonExtractor()
     381                        jsonExtractor.setOptions(self.keywords[keyword]["extractJson"])
     382                        #print("Yay!")
     383                        for message, breadcrumbs in jsonExtractor.extractFromString(element.text):
     384                            yield message, None, position + ":" + json.formatBreadcrumbs(breadcrumbs), []
     385                    else:
     386                        if "locationAttributes" in self.keywords[keyword]:
     387                            attributes = [element.get(attribute) for attribute in self.keywords[keyword]["locationAttributes"]]
     388                            position += " ({attributes})".format(attributes=", ".join(attributes))
     389                        yield element.text, None, position, []
  • new file source/tools/i18n/potter/jslexer.py

    diff --git a/source/tools/i18n/potter/jslexer.py b/source/tools/i18n/potter/jslexer.py
    new file mode 100644
    index 0000000..b215c61
    - +  
     1# -*- coding: utf-8 -*-
     2#
     3# Copyright (C) 2008-2011 Edgewall Software
     4# Copyright (C) 2013 Wildfire Games
     5# All rights reserved.
     6#
     7# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
     8# following conditions are met:
     9#
     10#   Redistributions of source code must retain the above copyright notice, this list of conditions and the following
     11#   disclaimer.
     12#   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
     13#   disclaimer in the documentation and/or other materials provided with the distribution.
     14#   The name of the author may not be used to endorse or promote products derived from this software without specific
     15#   prior written permission.
     16#
     17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     18# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     22# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23#
     24# This software consists of voluntary contributions made by many
     25# individuals. For the exact contribution history, see the revision
     26# history and logs:
     27# • http://babel.edgewall.org/log/trunk/babel/messages
     28# • http://trac.wildfiregames.com/browser/ps/trunk/source/tools/i18n/potter
     29
     30"""A simple JavaScript 1.5 lexer which is used for the JavaScript
     31extractor.
     32"""
     33
     34from __future__ import absolute_import, division, print_function, unicode_literals
     35
     36from operator import itemgetter
     37import re
     38
     39operators = [
     40    '+', '-', '*', '%', '!=', '==', '<', '>', '<=', '>=', '=',
     41    '+=', '-=', '*=', '%=', '<<', '>>', '>>>', '<<=', '>>=',
     42    '>>>=', '&', '&=', '|', '|=', '&&', '||', '^', '^=', '(', ')',
     43    '[', ']', '{', '}', '!', '--', '++', '~', ',', ';', '.', ':'
     44]
     45operators.sort(key=lambda x: -len(x))
     46
     47escapes = {'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t'}
     48
     49rules = [
     50    (None, re.compile(r'\s+(?u)')),
     51    (None, re.compile(r'<!--.*')),
     52    ('linecomment', re.compile(r'//.*')),
     53    ('multilinecomment', re.compile(r'/\*.*?\*/(?us)')),
     54    ('name', re.compile(r'(\$+\w*|[^\W\d]\w*)(?u)')),
     55    ('number', re.compile(r'''(?x)(
     56        (?:0|[1-9]\d*)
     57        (\.\d+)?
     58        ([eE][-+]?\d+)? |
     59        (0x[a-fA-F0-9]+)
     60    )''')),
     61    ('operator', re.compile(r'(%s)' % '|'.join(map(re.escape, operators)))),
     62    ('string', re.compile(r'''(?xs)(
     63        '(?:[^'\\]*(?:\\.[^'\\]*)*)'  |
     64        "(?:[^"\\]*(?:\\.[^"\\]*)*)"
     65    )'''))
     66]
     67
     68division_re = re.compile(r'/=?')
     69regex_re = re.compile(r'/(?:[^/\\]*(?:\\.[^/\\]*)*)/[a-zA-Z]*(?s)')
     70line_re = re.compile(r'(\r\n|\n|\r)')
     71line_join_re = re.compile(r'\\' + line_re.pattern)
     72uni_escape_re = re.compile(r'[a-fA-F0-9]{1,4}')
     73
     74
     75class Token(tuple):
     76    """Represents a token as returned by `tokenize`."""
     77    __slots__ = ()
     78
     79    def __new__(cls, type, value, lineno):
     80        return tuple.__new__(cls, (type, value, lineno))
     81
     82    type = property(itemgetter(0))
     83    value = property(itemgetter(1))
     84    lineno = property(itemgetter(2))
     85
     86
     87def indicates_division(token):
     88    """A helper function that helps the tokenizer to decide if the current
     89    token may be followed by a division operator.
     90    """
     91    if token.type == 'operator':
     92        return token.value in (')', ']', '}', '++', '--')
     93    return token.type in ('name', 'number', 'string', 'regexp')
     94
     95
     96def unquote_string(string):
     97    """Unquote a string with JavaScript rules.  The string has to start with
     98    string delimiters (``'`` or ``"``.)
     99
     100    :return: a string
     101    """
     102    assert string and string[0] == string[-1] and string[0] in '"\'', \
     103        'string provided is not properly delimited'
     104    string = line_join_re.sub('\\1', string[1:-1])
     105    result = []
     106    add = result.append
     107    pos = 0
     108
     109    while 1:
     110        # scan for the next escape
     111        escape_pos = string.find('\\', pos)
     112        if escape_pos < 0:
     113            break
     114        add(string[pos:escape_pos])
     115
     116        # check which character is escaped
     117        next_char = string[escape_pos + 1]
     118        if next_char in escapes:
     119            add(escapes[next_char])
     120
     121        # unicode escapes.  trie to consume up to four characters of
     122        # hexadecimal characters and try to interpret them as unicode
     123        # character point.  If there is no such character point, put
     124        # all the consumed characters into the string.
     125        elif next_char in 'uU':
     126            escaped = uni_escape_re.match(string, escape_pos + 2)
     127            if escaped is not None:
     128                escaped_value = escaped.group()
     129                if len(escaped_value) == 4:
     130                    try:
     131                        add(unichr(int(escaped_value, 16)))
     132                    except ValueError:
     133                        pass
     134                    else:
     135                        pos = escape_pos + 6
     136                        continue
     137                add(next_char + escaped_value)
     138                pos = escaped.end()
     139                continue
     140            else:
     141                add(next_char)
     142
     143        # bogus escape.  Just remove the backslash.
     144        else:
     145            add(next_char)
     146        pos = escape_pos + 2
     147
     148    if pos < len(string):
     149        add(string[pos:])
     150
     151    return u''.join(result)
     152
     153
     154def tokenize(source):
     155    """Tokenize a JavaScript source.
     156
     157    :return: generator of `Token`\s
     158    """
     159    may_divide = False
     160    pos = 0
     161    lineno = 1
     162    end = len(source)
     163
     164    while pos < end:
     165        # handle regular rules first
     166        for token_type, rule in rules:
     167            match = rule.match(source, pos)
     168            if match is not None:
     169                break
     170        # if we don't have a match we don't give up yet, but check for
     171        # division operators or regular expression literals, based on
     172        # the status of `may_divide` which is determined by the last
     173        # processed non-whitespace token using `indicates_division`.
     174        else:
     175            if may_divide:
     176                match = division_re.match(source, pos)
     177                token_type = 'operator'
     178            else:
     179                match = regex_re.match(source, pos)
     180                token_type = 'regexp'
     181            if match is None:
     182                # woops. invalid syntax. jump one char ahead and try again.
     183                pos += 1
     184                continue
     185
     186        token_value = match.group()
     187        if token_type is not None:
     188            token = Token(token_type, token_value, lineno)
     189            may_divide = indicates_division(token)
     190            yield token
     191        lineno += len(line_re.findall(token_value))
     192        pos = match.end()
  • new file source/tools/i18n/potter/mofile.py

    diff --git a/source/tools/i18n/potter/mofile.py b/source/tools/i18n/potter/mofile.py
    new file mode 100644
    index 0000000..1b798c2
    - +  
     1# -*- coding: utf-8 -*-
     2#
     3# Copyright (C) 2007-2011 Edgewall Software
     4# Copyright (C) 2013 Wildfire Games
     5# All rights reserved.
     6#
     7# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
     8# following conditions are met:
     9#
     10#   Redistributions of source code must retain the above copyright notice, this list of conditions and the following
     11#   disclaimer.
     12#   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
     13#   disclaimer in the documentation and/or other materials provided with the distribution.
     14#   The name of the author may not be used to endorse or promote products derived from this software without specific
     15#   prior written permission.
     16#
     17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     18# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     22# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23#
     24# This software consists of voluntary contributions made by many
     25# individuals. For the exact contribution history, see the revision
     26# history and logs:
     27# • http://babel.edgewall.org/log/trunk/babel/messages
     28# • http://trac.wildfiregames.com/browser/ps/trunk/source/tools/i18n/potter
     29
     30"""Writing of files in the ``gettext`` MO (machine object) format.
     31
     32:since: version 0.9
     33:see: `The Format of MO Files
     34       <http://www.gnu.org/software/gettext/manual/gettext.html#MO-Files>`_
     35"""
     36
     37import array
     38import struct
     39
     40from catalog import Catalog, Message
     41
     42__all__ = ['read_mo', 'write_mo']
     43__docformat__ = 'restructuredtext en'
     44
     45
     46LE_MAGIC = 0x950412deL
     47BE_MAGIC = 0xde120495L
     48
     49def read_mo(fileobj):
     50    """Read a binary MO file from the given file-like object and return a
     51    corresponding `Catalog` object.
     52   
     53    :param fileobj: the file-like object to read the MO file from
     54    :return: a catalog object representing the parsed MO file
     55    :rtype: `Catalog`
     56   
     57    :note: The implementation of this function is heavily based on the
     58           ``GNUTranslations._parse`` method of the ``gettext`` module in the
     59           standard library.
     60    """
     61    catalog = Catalog()
     62    headers = {}
     63
     64    filename = getattr(fileobj, 'name', '')
     65
     66    buf = fileobj.read()
     67    buflen = len(buf)
     68    unpack = struct.unpack
     69
     70    # Parse the .mo file header, which consists of 5 little endian 32
     71    # bit words.
     72    magic = unpack('<I', buf[:4])[0] # Are we big endian or little endian?
     73    if magic == LE_MAGIC:
     74        version, msgcount, origidx, transidx = unpack('<4I', buf[4:20])
     75        ii = '<II'
     76    elif magic == BE_MAGIC:
     77        version, msgcount, origidx, transidx = unpack('>4I', buf[4:20])
     78        ii = '>II'
     79    else:
     80        raise IOError(0, 'Bad magic number', filename)
     81
     82    # Now put all messages from the .mo file buffer into the catalog
     83    # dictionary
     84    for i in xrange(0, msgcount):
     85        mlen, moff = unpack(ii, buf[origidx:origidx + 8])
     86        mend = moff + mlen
     87        tlen, toff = unpack(ii, buf[transidx:transidx + 8])
     88        tend = toff + tlen
     89        if mend < buflen and tend < buflen:
     90            msg = buf[moff:mend]
     91            tmsg = buf[toff:tend]
     92        else:
     93            raise IOError(0, 'File is corrupt', filename)
     94
     95        # See if we're looking at GNU .mo conventions for metadata
     96        if mlen == 0:
     97            # Catalog description
     98            lastkey = key = None
     99            for item in tmsg.splitlines():
     100                item = item.strip()
     101                if not item:
     102                    continue
     103                if ':' in item:
     104                    key, value = item.split(':', 1)
     105                    lastkey = key = key.strip().lower()
     106                    headers[key] = value.strip()
     107                elif lastkey:
     108                    headers[lastkey] += '\n' + item
     109
     110        if '\x04' in msg: # context
     111            ctxt, msg = msg.split('\x04')
     112        else:
     113            ctxt = None
     114
     115        if '\x00' in msg: # plural forms
     116            msg = msg.split('\x00')
     117            tmsg = tmsg.split('\x00')
     118            if catalog.charset:
     119                msg = [x.decode(catalog.charset) for x in msg]
     120                tmsg = [x.decode(catalog.charset) for x in tmsg]
     121        else:
     122            if catalog.charset:
     123                msg = msg.decode(catalog.charset)
     124                tmsg = tmsg.decode(catalog.charset)
     125        catalog[msg] = Message(msg, tmsg, context=ctxt)
     126
     127        # advance to next entry in the seek tables
     128        origidx += 8
     129        transidx += 8
     130
     131    catalog.mime_headers = headers.items()
     132    return catalog
     133
     134def write_mo(fileobj, catalog, use_fuzzy=False):
     135    """Write a catalog to the specified file-like object using the GNU MO file
     136    format.
     137   
     138    >>> from babel.messages import Catalog
     139    >>> from gettext import GNUTranslations
     140    >>> from StringIO import StringIO
     141   
     142    >>> catalog = Catalog(locale='en_US')
     143    >>> catalog.add('foo', 'Voh')
     144    <Message ...>
     145    >>> catalog.add((u'bar', u'baz'), (u'Bahr', u'Batz'))
     146    <Message ...>
     147    >>> catalog.add('fuz', 'Futz', flags=['fuzzy'])
     148    <Message ...>
     149    >>> catalog.add('Fizz', '')
     150    <Message ...>
     151    >>> catalog.add(('Fuzz', 'Fuzzes'), ('', ''))
     152    <Message ...>
     153    >>> buf = StringIO()
     154   
     155    >>> write_mo(buf, catalog)
     156    >>> buf.seek(0)
     157    >>> translations = GNUTranslations(fp=buf)
     158    >>> translations.ugettext('foo')
     159    u'Voh'
     160    >>> translations.ungettext('bar', 'baz', 1)
     161    u'Bahr'
     162    >>> translations.ungettext('bar', 'baz', 2)
     163    u'Batz'
     164    >>> translations.ugettext('fuz')
     165    u'fuz'
     166    >>> translations.ugettext('Fizz')
     167    u'Fizz'
     168    >>> translations.ugettext('Fuzz')
     169    u'Fuzz'
     170    >>> translations.ugettext('Fuzzes')
     171    u'Fuzzes'
     172   
     173    :param fileobj: the file-like object to write to
     174    :param catalog: the `Catalog` instance
     175    :param use_fuzzy: whether translations marked as "fuzzy" should be included
     176                      in the output
     177    """
     178    messages = list(catalog)
     179    if not use_fuzzy:
     180        messages[1:] = [m for m in messages[1:] if not m.fuzzy]
     181    messages.sort()
     182
     183    ids = strs = ''
     184    offsets = []
     185
     186    for message in messages:
     187        # For each string, we need size and file offset.  Each string is NUL
     188        # terminated; the NUL does not count into the size.
     189        if message.pluralizable:
     190            msgid = '\x00'.join([
     191                msgid.encode(catalog.charset) for msgid in message.id
     192            ])
     193            msgstrs = []
     194            for idx, string in enumerate(message.string):
     195                if not string:
     196                    msgstrs.append(message.id[min(int(idx), 1)])
     197                else:
     198                    msgstrs.append(string)
     199            msgstr = '\x00'.join([
     200                msgstr.encode(catalog.charset) for msgstr in msgstrs
     201            ])
     202        else:
     203            msgid = message.id.encode(catalog.charset)
     204            if not message.string:
     205                msgstr = message.id.encode(catalog.charset)
     206            else:
     207                msgstr = message.string.encode(catalog.charset)
     208        if message.context:
     209            msgid = '\x04'.join([message.context.encode(catalog.charset),
     210                                 msgid])
     211        offsets.append((len(ids), len(msgid), len(strs), len(msgstr)))
     212        ids += msgid + '\x00'
     213        strs += msgstr + '\x00'
     214
     215    # The header is 7 32-bit unsigned integers.  We don't use hash tables, so
     216    # the keys start right after the index tables.
     217    keystart = 7 * 4 + 16 * len(messages)
     218    valuestart = keystart + len(ids)
     219
     220    # The string table first has the list of keys, then the list of values.
     221    # Each entry has first the size of the string, then the file offset.
     222    koffsets = []
     223    voffsets = []
     224    for o1, l1, o2, l2 in offsets:
     225        koffsets += [l1, o1 + keystart]
     226        voffsets += [l2, o2 + valuestart]
     227    offsets = koffsets + voffsets
     228
     229    fileobj.write(struct.pack('Iiiiiii',
     230        LE_MAGIC,                   # magic
     231        0,                          # version
     232        len(messages),              # number of entries
     233        7 * 4,                      # start of key index
     234        7 * 4 + len(messages) * 8,  # start of value index
     235        0, 0                        # size and offset of hash table
     236    ) + array.array("i", offsets).tostring() + ids + strs)
  • new file source/tools/i18n/potter/pofile.py

    diff --git a/source/tools/i18n/potter/pofile.py b/source/tools/i18n/potter/pofile.py
    new file mode 100644
    index 0000000..3cf8b85
    - +  
     1# -*- coding: utf-8 -*-
     2#
     3# Copyright (C) 2007-2011 Edgewall Software
     4# Copyright (C) 2013 Wildfire Games
     5# All rights reserved.
     6#
     7# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
     8# following conditions are met:
     9#
     10#   Redistributions of source code must retain the above copyright notice, this list of conditions and the following
     11#   disclaimer.
     12#   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
     13#   disclaimer in the documentation and/or other materials provided with the distribution.
     14#   The name of the author may not be used to endorse or promote products derived from this software without specific
     15#   prior written permission.
     16#
     17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     18# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     22# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23#
     24# This software consists of voluntary contributions made by many
     25# individuals. For the exact contribution history, see the revision
     26# history and logs:
     27# • http://babel.edgewall.org/log/trunk/babel/messages
     28# • http://trac.wildfiregames.com/browser/ps/trunk/source/tools/i18n/potter
     29
     30"""Reading and writing of files in the ``gettext`` PO (portable object)
     31format.
     32
     33:see: `The Format of PO Files
     34       <http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files>`_
     35"""
     36
     37from __future__ import absolute_import, division, print_function, unicode_literals
     38
     39from datetime import datetime
     40import os
     41import re
     42
     43from potter.util import wraptext
     44from potter.catalog import Catalog, Message
     45
     46__all__ = ['read_po', 'write_po']
     47__docformat__ = 'restructuredtext en'
     48
     49
     50
     51
     52def unescape(string):
     53    r"""Reverse `escape` the given string.
     54
     55    >>> print unescape('"Say:\\n  \\"hello, world!\\"\\n"')
     56    Say:
     57      "hello, world!"
     58    <BLANKLINE>
     59
     60    :param string: the string to unescape
     61    """
     62    def replace_escapes(match):
     63        m = match.group(1)
     64        if m == 'n':
     65            return '\n'
     66        elif m == 't':
     67            return '\t'
     68        elif m == 'r':
     69            return '\r'
     70        # m is \ or "
     71        return m
     72    return re.compile(r'\\([\\trn"])').sub(replace_escapes, string[1:-1])
     73
     74
     75def denormalize(string):
     76    r"""Reverse the normalization done by the `normalize` function.
     77
     78    >>> print denormalize(r'''""
     79    ... "Say:\n"
     80    ... "  \"hello, world!\"\n"''')
     81    Say:
     82      "hello, world!"
     83    <BLANKLINE>
     84
     85    >>> print denormalize(r'''""
     86    ... "Say:\n"
     87    ... "  \"Lorem ipsum dolor sit "
     88    ... "amet, consectetur adipisicing"
     89    ... " elit, \"\n"''')
     90    Say:
     91      "Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
     92    <BLANKLINE>
     93
     94    :param string: the string to denormalize
     95    """
     96    if '\n' in string:
     97        escaped_lines = string.splitlines()
     98        if string.startswith('""'):
     99            escaped_lines = escaped_lines[1:]
     100        lines = map(unescape, escaped_lines)
     101        return ''.join(lines)
     102    else:
     103        return unescape(string)
     104
     105def read_po(fileobj, locale=None, domain=None, ignore_obsolete=False, charset="utf-8"):
     106    """Read messages from a ``gettext`` PO (portable object) file from the given
     107    file-like object and return a `Catalog`.
     108
     109    >>> from datetime import datetime
     110    >>> from StringIO import StringIO
     111    >>> buf = StringIO('''
     112    ... #: main.py:1
     113    ... #, fuzzy, python-format
     114    ... msgid "foo %(name)s"
     115    ... msgstr "quux %(name)s"
     116    ...
     117    ... # A user comment
     118    ... #. An auto comment
     119    ... #: main.py:3
     120    ... msgid "bar"
     121    ... msgid_plural "baz"
     122    ... msgstr[0] "bar"
     123    ... msgstr[1] "baaz"
     124    ... ''')
     125    >>> catalog = read_po(buf)
     126    >>> catalog.revision_date = datetime(2007, 04, 01)
     127
     128    >>> for message in catalog:
     129    ...     if message.id:
     130    ...         print (message.id, message.string)
     131    ...         print ' ', (message.locations, message.flags)
     132    ...         print ' ', (message.user_comments, message.auto_comments)
     133    (u'foo %(name)s', u'quux %(name)s')
     134      ([(u'main.py', 1)], set([u'fuzzy', u'python-format']))
     135      ([], [])
     136    ((u'bar', u'baz'), (u'bar', u'baaz'))
     137      ([(u'main.py', 3)], set([]))
     138      ([u'A user comment'], [u'An auto comment'])
     139
     140    .. versionadded:: 1.0
     141       Added support for explicit charset argument.
     142
     143    :param fileobj: the file-like object to read the PO file from
     144    :param locale: the locale identifier or `Locale` object, or `None`
     145                   if the catalog is not bound to a locale (which basically
     146                   means it's a template)
     147    :param domain: the message domain
     148    :param ignore_obsolete: whether to ignore obsolete messages in the input
     149    :param charset: the character set of the catalog.
     150    """
     151    catalog = Catalog(locale=locale, domain=domain, charset=charset)
     152
     153    counter = [0]
     154    offset = [0]
     155    messages = []
     156    translations = []
     157    locations = []
     158    flags = []
     159    user_comments = []
     160    auto_comments = []
     161    obsolete = [False]
     162    context = []
     163    in_msgid = [False]
     164    in_msgstr = [False]
     165    in_msgctxt = [False]
     166
     167    def _add_message():
     168        translations.sort()
     169        if len(messages) > 1:
     170            msgid = tuple([denormalize(m) for m in messages])
     171        else:
     172            msgid = denormalize(messages[0])
     173        if isinstance(msgid, (list, tuple)):
     174            string = []
     175            for idx in range(catalog.num_plurals):
     176                try:
     177                    string.append(translations[idx])
     178                except IndexError:
     179                    string.append((idx, ''))
     180            string = tuple([denormalize(t[1]) for t in string])
     181        else:
     182            string = denormalize(translations[0][1])
     183        if context:
     184            msgctxt = denormalize('\n'.join(context))
     185        else:
     186            msgctxt = None
     187        message = Message(msgid, string, list(locations), set(flags),
     188                          auto_comments, user_comments, lineno=offset[0] + 1,
     189                          context=msgctxt)
     190        if obsolete[0]:
     191            if not ignore_obsolete:
     192                catalog.obsolete[msgid] = message
     193        else:
     194            catalog[msgid] = message
     195        del messages[:]; del translations[:]; del context[:]; del locations[:];
     196        del flags[:]; del auto_comments[:]; del user_comments[:];
     197        obsolete[0] = False
     198        counter[0] += 1
     199
     200    def _process_message_line(lineno, line):
     201        if line.startswith('msgid_plural'):
     202            in_msgid[0] = True
     203            msg = line[12:].lstrip()
     204            messages.append(msg)
     205        elif line.startswith('msgid'):
     206            in_msgid[0] = True
     207            offset[0] = lineno
     208            txt = line[5:].lstrip()
     209            if messages:
     210                _add_message()
     211            messages.append(txt)
     212        elif line.startswith('msgstr'):
     213            in_msgid[0] = False
     214            in_msgstr[0] = True
     215            msg = line[6:].lstrip()
     216            if msg.startswith('['):
     217                idx, msg = msg[1:].split(']', 1)
     218                translations.append([int(idx), msg.lstrip()])
     219            else:
     220                translations.append([0, msg])
     221        elif line.startswith('msgctxt'):
     222            if messages:
     223                _add_message()
     224            in_msgid[0] = in_msgstr[0] = False
     225            context.append(line[7:].lstrip())
     226        elif line.startswith('"'):
     227            if in_msgid[0]:
     228                messages[-1] += u'\n' + line.rstrip()
     229            elif in_msgstr[0]:
     230                translations[-1][1] += u'\n' + line.rstrip()
     231            elif in_msgctxt[0]:
     232                context.append(line.rstrip())
     233
     234    for lineno, line in enumerate(fileobj.readlines()):
     235        line = line.strip()
     236        if not isinstance(line, unicode):
     237            line = line.decode(catalog.charset)
     238        if line.startswith('#'):
     239            in_msgid[0] = in_msgstr[0] = False
     240            if messages and translations:
     241                _add_message()
     242            if line[1:].startswith(':'):
     243                for location in line[2:].lstrip().split():
     244                    pos = location.rfind(':')
     245                    if pos >= 0:
     246                        try:
     247                            lineno = int(location[pos + 1:])
     248                        except ValueError:
     249                            continue
     250                        locations.append((location[:pos], lineno))
     251            elif line[1:].startswith(','):
     252                for flag in line[2:].lstrip().split(','):
     253                    flags.append(flag.strip())
     254            elif line[1:].startswith('~'):
     255                obsolete[0] = True
     256                _process_message_line(lineno, line[2:].lstrip())
     257            elif line[1:].startswith('.'):
     258                # These are called auto-comments
     259                comment = line[2:].strip()
     260                if comment: # Just check that we're not adding empty comments
     261                    auto_comments.append(comment)
     262            else:
     263                # These are called user comments
     264                user_comments.append(line[1:].strip())
     265        else:
     266            _process_message_line(lineno, line)
     267
     268    if messages:
     269        _add_message()
     270
     271    # No actual messages found, but there was some info in comments, from which
     272    # we'll construct an empty header message
     273    elif not counter[0] and (flags or user_comments or auto_comments):
     274        messages.append(u'')
     275        translations.append([0, u''])
     276        _add_message()
     277
     278    return catalog
     279
     280WORD_SEP = re.compile('('
     281    r'\s+|'                                 # any whitespace
     282    r'[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|' # hyphenated words
     283    r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w)'   # em-dash
     284')')
     285
     286def escape(string):
     287    r"""Escape the given string so that it can be included in double-quoted
     288    strings in ``PO`` files.
     289
     290    >>> escape('''Say:
     291    ...   "hello, world!"
     292    ... ''')
     293    '"Say:\\n  \\"hello, world!\\"\\n"'
     294
     295    :param string: the string to escape
     296    :return: the escaped string
     297    :rtype: `str` or `unicode`
     298    """
     299    return '"%s"' % string.replace('\\', '\\\\') \
     300                          .replace('\t', '\\t') \
     301                          .replace('\r', '\\r') \
     302                          .replace('\n', '\\n') \
     303                          .replace('\"', '\\"')
     304
     305def normalize(string, prefix='', width=80):
     306    r"""Convert a string into a format that is appropriate for .po files.
     307
     308    >>> print normalize('''Say:
     309    ...   "hello, world!"
     310    ... ''', width=None)
     311    ""
     312    "Say:\n"
     313    "  \"hello, world!\"\n"
     314
     315    >>> print normalize('''Say:
     316    ...   "Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
     317    ... ''', width=32)
     318    ""
     319    "Say:\n"
     320    "  \"Lorem ipsum dolor sit "
     321    "amet, consectetur adipisicing"
     322    " elit, \"\n"
     323
     324    :param string: the string to normalize
     325    :param prefix: a string that should be prepended to every line
     326    :param width: the maximum line width; use `None`, 0, or a negative number
     327                  to completely disable line wrapping
     328    :return: the normalized string
     329    :rtype: `unicode`
     330    """
     331    if width and width > 0:
     332        prefixlen = len(prefix)
     333        lines = []
     334        for line in string.splitlines(True):
     335            if len(escape(line)) + prefixlen > width:
     336                chunks = WORD_SEP.split(line)
     337                chunks.reverse()
     338                while chunks:
     339                    buf = []
     340                    size = 2
     341                    while chunks:
     342                        l = len(escape(chunks[-1])) - 2 + prefixlen
     343                        if size + l < width:
     344                            buf.append(chunks.pop())
     345                            size += l
     346                        else:
     347                            if not buf:
     348                                # handle long chunks by putting them on a
     349                                # separate line
     350                                buf.append(chunks.pop())
     351                            break
     352                    lines.append(u''.join(buf))
     353            else:
     354                lines.append(line)
     355    else:
     356        lines = string.splitlines(True)
     357
     358    if len(lines) <= 1:
     359        return escape(string)
     360
     361    # Remove empty trailing line
     362    if lines and not lines[-1]:
     363        del lines[-1]
     364        lines[-1] += '\n'
     365    return u'""\n' + u'\n'.join([(prefix + escape(l)) for l in lines])
     366
     367def write_po(fileobj, catalog, width=80, no_location=False, omit_header=False,
     368             sort_output=False, sort_by_file=False, ignore_obsolete=False,
     369             include_previous=False):
     370    r"""Write a ``gettext`` PO (portable object) template file for a given
     371    message catalog to the provided file-like object.
     372
     373    >>> catalog = Catalog()
     374    >>> catalog.add(u'foo %(name)s', locations=['main.py:1',],
     375    ...             flags=('fuzzy',))
     376    <Message...>
     377    >>> catalog.add((u'bar', u'baz'), locations=['main.py:3',])
     378    <Message...>
     379    >>> from StringIO import StringIO
     380    >>> buf = StringIO()
     381    >>> write_po(buf, catalog, omit_header=True)
     382    >>> print buf.getvalue()
     383    #: main.py:1
     384    #, fuzzy, python-format
     385    msgid "foo %(name)s"
     386    msgstr ""
     387    <BLANKLINE>
     388    #: main.py:3
     389    msgid "bar"
     390    msgid_plural "baz"
     391    msgstr[0] ""
     392    msgstr[1] ""
     393    <BLANKLINE>
     394    <BLANKLINE>
     395
     396    :param fileobj: the file-like object to write to
     397    :param catalog: the `Catalog` instance
     398    :param width: the maximum line width for the generated output; use `None`,
     399                  0, or a negative number to completely disable line wrapping
     400    :param no_location: do not emit a location comment for every message
     401    :param omit_header: do not include the ``msgid ""`` entry at the top of the
     402                        output
     403    :param sort_output: whether to sort the messages in the output by msgid
     404    :param sort_by_file: whether to sort the messages in the output by their
     405                         locations
     406    :param ignore_obsolete: whether to ignore obsolete messages and not include
     407                            them in the output; by default they are included as
     408                            comments
     409    :param include_previous: include the old msgid as a comment when
     410                             updating the catalog
     411    """
     412    def _normalize(key, prefix=''):
     413        return normalize(key, prefix=prefix, width=width)
     414
     415    def _write(text):
     416        fileobj.write(text)
     417
     418    def _write_comment(comment, prefix=''):
     419        # xgettext always wraps comments even if --no-wrap is passed;
     420        # provide the same behaviour
     421        if width and width > 0:
     422            _width = width
     423        else:
     424            _width = 80
     425        if isinstance(comment, (tuple, list)):
     426            commentText = str(comment[0])
     427            for piece in comment[1:]:
     428                commentText += ":" + str(piece)
     429            comment = commentText
     430        for line in wraptext(comment, _width):
     431            _write('#%s %s\n' % (prefix, line.strip()))
     432
     433    def _write_message(message, prefix=''):
     434        if isinstance(message.id, (list, tuple)):
     435            if message.context:
     436                _write('%smsgctxt %s\n' % (prefix,
     437                                           _normalize(message.context, prefix)))
     438            _write('%smsgid %s\n' % (prefix, _normalize(message.id[0], prefix)))
     439            _write('%smsgid_plural %s\n' % (
     440                prefix, _normalize(message.id[1], prefix)
     441            ))
     442
     443            for idx in range(2):
     444                try:
     445                    string = message.string[idx]
     446                except IndexError:
     447                    string = ''
     448                _write('%smsgstr[%d] %s\n' % (
     449                    prefix, idx, _normalize(string, prefix)
     450                ))
     451        else:
     452            if message.context:
     453                _write('%smsgctxt %s\n' % (prefix,
     454                                           _normalize(message.context, prefix)))
     455            _write('%smsgid %s\n' % (prefix, _normalize(message.id, prefix)))
     456            _write('%smsgstr %s\n' % (
     457                prefix, _normalize(message.string or '', prefix)
     458            ))
     459
     460    messages = list(catalog)
     461    if sort_output:
     462        messages.sort()
     463    elif sort_by_file:
     464        messages.sort(lambda x,y: cmp(x.locations, y.locations))
     465
     466    for message in messages:
     467        if not message.id: # This is the header "message"
     468            if omit_header:
     469                continue
     470            comment_header = catalog.header_comment
     471            if width and width > 0:
     472                lines = []
     473                for line in comment_header.splitlines():
     474                    lines += wraptext(line, width=width,
     475                                      subsequent_indent='# ')
     476                comment_header = u'\n'.join(lines)
     477            _write(comment_header + u'\n')
     478
     479        for comment in message.user_comments:
     480            _write_comment(comment)
     481        for comment in message.auto_comments:
     482            _write_comment(comment, prefix='.')
     483
     484        if not no_location:
     485            for location in message.locations:
     486                _write_comment(location, prefix=':')
     487        if message.flags:
     488            _write('#%s\n' % ', '.join([''] + list(message.flags)))
     489
     490        if message.previous_id and include_previous:
     491            _write_comment('msgid %s' % _normalize(message.previous_id[0]),
     492                           prefix='|')
     493            if len(message.previous_id) > 1:
     494                _write_comment('msgid_plural %s' % _normalize(
     495                    message.previous_id[1]
     496                ), prefix='|')
     497
     498        _write_message(message)
     499        _write('\n')
     500
     501    if not ignore_obsolete:
     502        for message in catalog.obsolete.values():
     503            for comment in message.user_comments:
     504                _write_comment(comment)
     505            _write_message(message, prefix='#~ ')
     506            _write('\n')
  • new file source/tools/i18n/potter/util.py

    diff --git a/source/tools/i18n/potter/util.py b/source/tools/i18n/potter/util.py
    new file mode 100644
    index 0000000..63d8473
    - +  
     1# -*- coding: utf-8 -*-
     2#
     3# Copyright (C) 2007-2011 Edgewall Software
     4# Copyright (C) 2013 Wildfire Games
     5# All rights reserved.
     6#
     7# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
     8# following conditions are met:
     9#
     10#   Redistributions of source code must retain the above copyright notice, this list of conditions and the following
     11#   disclaimer.
     12#   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
     13#   disclaimer in the documentation and/or other materials provided with the distribution.
     14#   The name of the author may not be used to endorse or promote products derived from this software without specific
     15#   prior written permission.
     16#
     17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     18# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     22# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23#
     24# This software consists of voluntary contributions made by many
     25# individuals. For the exact contribution history, see the revision
     26# history and logs:
     27# • http://babel.edgewall.org/log/trunk/babel/messages
     28# • http://trac.wildfiregames.com/browser/ps/trunk/source/tools/i18n/potter
     29
     30"""Various utility classes and functions."""
     31
     32from __future__ import absolute_import, division, print_function, unicode_literals
     33
     34import codecs
     35from datetime import timedelta, tzinfo
     36import os
     37import re
     38import textwrap
     39import time
     40
     41try:
     42    from itertools import izip as zip
     43    from itertools import imap as map
     44except ImportError:
     45    pass # Python 3
     46
     47missing = object()
     48
     49__all__ = ['distinct', 'pathmatch', 'relpath', 'wraptext', 'UTC',
     50           'LOCALTZ']
     51__docformat__ = 'restructuredtext en'
     52
     53
     54def distinct(iterable):
     55    """Yield all items in an iterable collection that are distinct.
     56
     57    Unlike when using sets for a similar effect, the original ordering of the
     58    items in the collection is preserved by this function.
     59
     60    >>> print list(distinct([1, 2, 1, 3, 4, 4]))
     61    [1, 2, 3, 4]
     62    >>> print list(distinct('foobar'))
     63    ['f', 'o', 'b', 'a', 'r']
     64
     65    :param iterable: the iterable collection providing the data
     66    :return: the distinct items in the collection
     67    :rtype: ``iterator``
     68    """
     69    seen = set()
     70    for item in iter(iterable):
     71        if item not in seen:
     72            yield item
     73            seen.add(item)
     74
     75# Regexp to match python magic encoding line
     76PYTHON_MAGIC_COMMENT_re = re.compile(
     77    r'[ \t\f]* \# .* coding[=:][ \t]*([-\w.]+)', re.VERBOSE)
     78def parse_encoding(fp):
     79    """Deduce the encoding of a source file from magic comment.
     80
     81    It does this in the same way as the `Python interpreter`__
     82
     83    .. __: http://docs.python.org/ref/encodings.html
     84
     85    The ``fp`` argument should be a seekable file object.
     86
     87    (From Jeff Dairiki)
     88    """
     89    pos = fp.tell()
     90    fp.seek(0)
     91    try:
     92        line1 = fp.readline()
     93        has_bom = line1.startswith(codecs.BOM_UTF8)
     94        if has_bom:
     95            line1 = line1[len(codecs.BOM_UTF8):]
     96
     97        m = PYTHON_MAGIC_COMMENT_re.match(line1)
     98        if not m:
     99            try:
     100                import parser
     101                parser.suite(line1)
     102            except (ImportError, SyntaxError):
     103                # Either it's a real syntax error, in which case the source is
     104                # not valid python source, or line2 is a continuation of line1,
     105                # in which case we don't want to scan line2 for a magic
     106                # comment.
     107                pass
     108            else:
     109                line2 = fp.readline()
     110                m = PYTHON_MAGIC_COMMENT_re.match(line2)
     111
     112        if has_bom:
     113            if m:
     114                raise SyntaxError(
     115                    "python refuses to compile code with both a UTF8 "
     116                    "byte-order-mark and a magic encoding comment")
     117            return 'utf_8'
     118        elif m:
     119            return m.group(1)
     120        else:
     121            return None
     122    finally:
     123        fp.seek(pos)
     124
     125def pathmatch(pattern, filename):
     126    """Extended pathname pattern matching.
     127   
     128    This function is similar to what is provided by the ``fnmatch`` module in
     129    the Python standard library, but:
     130   
     131     * can match complete (relative or absolute) path names, and not just file
     132       names, and
     133     * also supports a convenience pattern ("**") to match files at any
     134       directory level.
     135   
     136    Examples:
     137   
     138    >>> pathmatch('**.py', 'bar.py')
     139    True
     140    >>> pathmatch('**.py', 'foo/bar/baz.py')
     141    True
     142    >>> pathmatch('**.py', 'templates/index.html')
     143    False
     144   
     145    >>> pathmatch('**/templates/*.html', 'templates/index.html')
     146    True
     147    >>> pathmatch('**/templates/*.html', 'templates/foo/bar.html')
     148    False
     149   
     150    :param pattern: the glob pattern
     151    :param filename: the path name of the file to match against
     152    :return: `True` if the path name matches the pattern, `False` otherwise
     153    :rtype: `bool`
     154    """
     155    symbols = {
     156        '?':   '[^/]',
     157        '?/':  '[^/]/',
     158        '*':   '[^/]+',
     159        '*/':  '[^/]+/',
     160        '**/': '(?:.+/)*?',
     161        '**':  '(?:.+/)*?[^/]+',
     162    }
     163    buf = []
     164    for idx, part in enumerate(re.split('([?*]+/?)', pattern)):
     165        if idx % 2:
     166            buf.append(symbols[part])
     167        elif part:
     168            buf.append(re.escape(part))
     169    match = re.match(''.join(buf) + '$', filename.replace(os.sep, '/'))
     170    return match is not None
     171
     172
     173class TextWrapper(textwrap.TextWrapper):
     174    wordsep_re = re.compile(
     175        r'(\s+|'                                  # any whitespace
     176        r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))'    # em-dash
     177    )
     178
     179
     180def wraptext(text, width=70, initial_indent='', subsequent_indent=''):
     181    """Simple wrapper around the ``textwrap.wrap`` function in the standard
     182    library. This version does not wrap lines on hyphens in words.
     183   
     184    :param text: the text to wrap
     185    :param width: the maximum line width
     186    :param initial_indent: string that will be prepended to the first line of
     187                           wrapped output
     188    :param subsequent_indent: string that will be prepended to all lines save
     189                              the first of wrapped output
     190    :return: a list of lines
     191    :rtype: `list`
     192    """
     193    wrapper = TextWrapper(width=width, initial_indent=initial_indent,
     194                          subsequent_indent=subsequent_indent,
     195                          break_long_words=False)
     196    return wrapper.wrap(text)
     197
     198
     199try:
     200    relpath = os.path.relpath
     201except AttributeError:
     202    def relpath(path, start='.'):
     203        """Compute the relative path to one path from another.
     204       
     205        >>> relpath('foo/bar.txt', '').replace(os.sep, '/')
     206        'foo/bar.txt'
     207        >>> relpath('foo/bar.txt', 'foo').replace(os.sep, '/')
     208        'bar.txt'
     209        >>> relpath('foo/bar.txt', 'baz').replace(os.sep, '/')
     210        '../foo/bar.txt'
     211       
     212        :return: the relative path
     213        :rtype: `basestring`
     214        """
     215        start_list = os.path.abspath(start).split(os.sep)
     216        path_list = os.path.abspath(path).split(os.sep)
     217
     218        # Work out how much of the filepath is shared by start and path.
     219        i = len(os.path.commonprefix([start_list, path_list]))
     220
     221        rel_list = [os.path.pardir] * (len(start_list) - i) + path_list[i:]
     222        return os.path.join(*rel_list)
     223
     224ZERO = timedelta(0)
     225
     226
     227class FixedOffsetTimezone(tzinfo):
     228    """Fixed offset in minutes east from UTC."""
     229
     230    def __init__(self, offset, name=None):
     231        self._offset = timedelta(minutes=offset)
     232        if name is None:
     233            name = 'Etc/GMT+%d' % offset
     234        self.zone = name
     235
     236    def __str__(self):
     237        return self.zone
     238
     239    def __repr__(self):
     240        return '<FixedOffset "%s" %s>' % (self.zone, self._offset)
     241
     242    def utcoffset(self, dt):
     243        return self._offset
     244
     245    def tzname(self, dt):
     246        return self.zone
     247
     248    def dst(self, dt):
     249        return ZERO
     250
     251
     252try:
     253    from pytz import UTC
     254except ImportError:
     255    UTC = FixedOffsetTimezone(0, 'UTC')
     256    """`tzinfo` object for UTC (Universal Time).
     257   
     258    :type: `tzinfo`
     259    """
     260
     261STDOFFSET = timedelta(seconds = -time.timezone)
     262if time.daylight:
     263    DSTOFFSET = timedelta(seconds = -time.altzone)
     264else:
     265    DSTOFFSET = STDOFFSET
     266
     267DSTDIFF = DSTOFFSET - STDOFFSET
     268
     269
     270class LocalTimezone(tzinfo):
     271
     272    def utcoffset(self, dt):
     273        if self._isdst(dt):
     274            return DSTOFFSET
     275        else:
     276            return STDOFFSET
     277
     278    def dst(self, dt):
     279        if self._isdst(dt):
     280            return DSTDIFF
     281        else:
     282            return ZERO
     283
     284    def tzname(self, dt):
     285        return time.tzname[self._isdst(dt)]
     286
     287    def _isdst(self, dt):
     288        tt = (dt.year, dt.month, dt.day,
     289              dt.hour, dt.minute, dt.second,
     290              dt.weekday(), 0, -1)
     291        stamp = time.mktime(tt)
     292        tt = time.localtime(stamp)
     293        return tt.tm_isdst > 0
     294
     295
     296LOCALTZ = LocalTimezone()
     297"""`tzinfo` object for local time-zone.
     298
     299:type: `tzinfo`
     300"""
  • new file source/tools/i18n/pullTranslations.py

    diff --git a/source/tools/i18n/pullTranslations.py b/source/tools/i18n/pullTranslations.py
    new file mode 100644
    index 0000000..696690c
    - +  
     1#!/usr/bin/env python2
     2# -*- coding:utf-8 -*-
     3#
     4# Copyright (C) 2013 Wildfire Games.
     5# This file is part of 0 A.D.
     6#
     7# 0 A.D. is free software: you can redistribute it and/or modify
     8# it under the terms of the GNU General Public License as published by
     9# the Free Software Foundation, either version 2 of the License, or
     10# (at your option) any later version.
     11#
     12# 0 A.D. is distributed in the hope that it will be useful,
     13# but WITHOUT ANY WARRANTY; without even the implied warranty of
     14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15# GNU General Public License for more details.
     16#
     17# You should have received a copy of the GNU General Public License
     18# along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     19
     20"""
     21    Although this script itself should work with both Python 2 and Python 3, it relies on the Transifex Client, which at
     22    this moment (2013-10-12) does not support Python 3.
     23
     24    As soon as Transifex Client supports Python 3, simply updating its folder should be enough to make this script work
     25    with Python 3 as well.
     26"""
     27
     28from __future__ import absolute_import, division, print_function, unicode_literals
     29
     30import os, sys
     31
     32# Python version check.
     33if sys.version_info[0] != 2:
     34    print(__doc__)
     35    sys.exit()
     36
     37from txclib.project import Project
     38
     39
     40def main():
     41
     42
     43    l10nToolsDirectory = os.path.dirname(os.path.realpath(__file__))
     44    projectRootDirectory = os.path.abspath(os.path.join(l10nToolsDirectory, os.pardir, os.pardir, os.pardir))
     45    l10nFolderName = "l10n"
     46    transifexClientFolder = ".tx"
     47
     48    for root, folders, filenames in os.walk(projectRootDirectory):
     49        for folder in folders:
     50            if folder == l10nFolderName:
     51                if os.path.exists(os.path.join(root, folder, transifexClientFolder)):
     52                    path = os.path.join(root, folder)
     53                    os.chdir(path)
     54                    project = Project(path)
     55                    project.pull(fetchall=True, force=True)
     56
     57
     58if __name__ == "__main__":
     59    main()
  • new file source/tools/i18n/tx

    diff --git a/source/tools/i18n/tx b/source/tools/i18n/tx
    new file mode 100755
    index 0000000..65e179a
    - +  
     1#!/usr/bin/env python
     2# -*- coding: utf-8 -*-
     3
     4from optparse import OptionParser, OptionValueError
     5import os
     6import sys
     7import ssl
     8import errno
     9from txclib import utils
     10from txclib import get_version
     11from txclib.log import set_log_level, logger
     12
     13reload(sys) # WTF? Otherwise setdefaultencoding doesn't work
     14
     15# This block ensures that ^C interrupts are handled quietly.
     16try:
     17    import signal
     18
     19    def exithandler(signum,frame):
     20        signal.signal(signal.SIGINT, signal.SIG_IGN)
     21        signal.signal(signal.SIGTERM, signal.SIG_IGN)
     22        sys.exit(1)
     23
     24    signal.signal(signal.SIGINT, exithandler)
     25    signal.signal(signal.SIGTERM, exithandler)
     26    if hasattr(signal, 'SIGPIPE'):
     27        signal.signal(signal.SIGPIPE, signal.SIG_DFL)
     28
     29except KeyboardInterrupt:
     30    sys.exit(1)
     31
     32# When we open file with f = codecs.open we specifi FROM what encoding to read
     33# This sets the encoding for the strings which are created with f.read()
     34sys.setdefaultencoding('utf-8')
     35
     36
     37def main(argv):
     38    """
     39    Here we parse the flags (short, long) and we instantiate the classes.
     40    """
     41    usage = "usage: %prog [options] command [cmd_options]"
     42    description = "This is the Transifex command line client which"\
     43        " allows you to manage your translations locally and sync"\
     44        " them with the master Transifex server.\nIf you'd like to"\
     45        " check the available commands issue `%prog help` or if you"\
     46        " just want help with a specific command issue `%prog help"\
     47        " command`"
     48
     49    parser = OptionParser(
     50        usage=usage, version=get_version(), description=description
     51    )
     52    parser.disable_interspersed_args()
     53    parser.add_option(
     54        "-d", "--debug", action="store_true", dest="debug",
     55        default=False, help=("enable debug messages")
     56    )
     57    parser.add_option(
     58        "-q", "--quiet", action="store_true", dest="quiet",
     59        default=False, help="don't print status messages to stdout"
     60    )
     61    parser.add_option(
     62        "-r", "--root", action="store", dest="root_dir", type="string",
     63        default=None, help="change root directory (default is cwd)"
     64    )
     65    parser.add_option(
     66        "--traceback", action="store_true", dest="trace", default=False,
     67        help="print full traceback on exceptions"
     68    )
     69    parser.add_option(
     70        "--disable-colors", action="store_true", dest="color_disable",
     71        default=(os.name == 'nt' or not sys.stdout.isatty()),
     72        help="disable colors in the output of commands"
     73    )
     74    (options, args) = parser.parse_args()
     75
     76    if len(args) < 1:
     77        parser.error("No command was given")
     78
     79    utils.DISABLE_COLORS = options.color_disable
     80
     81    # set log level
     82    if options.quiet:
     83        set_log_level('WARNING')
     84    elif options.debug:
     85        set_log_level('DEBUG')
     86
     87    # find .tx
     88    path_to_tx = options.root_dir or utils.find_dot_tx()
     89
     90
     91    cmd = args[0]
     92    try:
     93        print "utils.exec_command(" + str(cmd) + ", " + str(args[1:]) + ", " + path_to_tx + ")"
     94        utils.exec_command(cmd, args[1:], path_to_tx)
     95    except ssl.SSLError as e:
     96        if 'certificate verify failed' in e.strerror:
     97            logger.error(
     98                'Error: Could not verify the SSL certificate of the remote host'
     99            )
     100        else:
     101            logger.error(errno.errorcode[e.errno])
     102        sys.exit(1)
     103    except utils.UnknownCommandError:
     104        logger.error("tx: Command %s not found" % cmd)
     105    except SystemExit:
     106        sys.exit()
     107    except:
     108        import traceback
     109        if options.trace:
     110            traceback.print_exc()
     111        else:
     112            formatted_lines = traceback.format_exc().splitlines()
     113            logger.error(formatted_lines[-1])
     114        sys.exit(1)
     115
     116# Run baby :) ... run
     117if __name__ == "__main__":
     118    # sys.argv[0] is the name of the script that we’re running.
     119    main(sys.argv[1:])
  • new file source/tools/i18n/txclib/LICENSE

    diff --git a/source/tools/i18n/txclib/LICENSE b/source/tools/i18n/txclib/LICENSE
    new file mode 100644
    index 0000000..add7251
    - +  
     1            GNU GENERAL PUBLIC LICENSE
     2               Version 2, June 1991
     3
     4 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
     5                       51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
     6 Everyone is permitted to copy and distribute verbatim copies
     7 of this license document, but changing it is not allowed.
     8
     9                Preamble
     10
     11  The licenses for most software are designed to take away your
     12freedom to share and change it.  By contrast, the GNU General Public
     13License is intended to guarantee your freedom to share and change free
     14software--to make sure the software is free for all its users.  This
     15General Public License applies to most of the Free Software
     16Foundation's software and to any other program whose authors commit to
     17using it.  (Some other Free Software Foundation software is covered by
     18the GNU Library General Public License instead.)  You can apply it to
     19your programs, too.
     20
     21  When we speak of free software, we are referring to freedom, not
     22price.  Our General Public Licenses are designed to make sure that you
     23have the freedom to distribute copies of free software (and charge for
     24this service if you wish), that you receive source code or can get it
     25if you want it, that you can change the software or use pieces of it
     26in new free programs; and that you know you can do these things.
     27
     28  To protect your rights, we need to make restrictions that forbid
     29anyone to deny you these rights or to ask you to surrender the rights.
     30These restrictions translate to certain responsibilities for you if you
     31distribute copies of the software, or if you modify it.
     32
     33  For example, if you distribute copies of such a program, whether
     34gratis or for a fee, you must give the recipients all the rights that
     35you have.  You must make sure that they, too, receive or can get the
     36source code.  And you must show them these terms so they know their
     37rights.
     38
     39  We protect your rights with two steps: (1) copyright the software, and
     40(2) offer you this license which gives you legal permission to copy,
     41distribute and/or modify the software.
     42
     43  Also, for each author's protection and ours, we want to make certain
     44that everyone understands that there is no warranty for this free
     45software.  If the software is modified by someone else and passed on, we
     46want its recipients to know that what they have is not the original, so
     47that any problems introduced by others will not reflect on the original
     48authors' reputations.
     49
     50  Finally, any free program is threatened constantly by software
     51patents.  We wish to avoid the danger that redistributors of a free
     52program will individually obtain patent licenses, in effect making the
     53program proprietary.  To prevent this, we have made it clear that any
     54patent must be licensed for everyone's free use or not licensed at all.
     55
     56  The precise terms and conditions for copying, distribution and
     57modification follow.
     58
     59            GNU GENERAL PUBLIC LICENSE
     60   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
     61
     62  0. This License applies to any program or other work which contains
     63a notice placed by the copyright holder saying it may be distributed
     64under the terms of this General Public License.  The "Program", below,
     65refers to any such program or work, and a "work based on the Program"
     66means either the Program or any derivative work under copyright law:
     67that is to say, a work containing the Program or a portion of it,
     68either verbatim or with modifications and/or translated into another
     69language.  (Hereinafter, translation is included without limitation in
     70the term "modification".)  Each licensee is addressed as "you".
     71
     72Activities other than copying, distribution and modification are not
     73covered by this License; they are outside its scope.  The act of
     74running the Program is not restricted, and the output from the Program
     75is covered only if its contents constitute a work based on the
     76Program (independent of having been made by running the Program).
     77Whether that is true depends on what the Program does.
     78
     79  1. You may copy and distribute verbatim copies of the Program's
     80source code as you receive it, in any medium, provided that you
     81conspicuously and appropriately publish on each copy an appropriate
     82copyright notice and disclaimer of warranty; keep intact all the
     83notices that refer to this License and to the absence of any warranty;
     84and give any other recipients of the Program a copy of this License
     85along with the Program.
     86
     87You may charge a fee for the physical act of transferring a copy, and
     88you may at your option offer warranty protection in exchange for a fee.
     89
     90  2. You may modify your copy or copies of the Program or any portion
     91of it, thus forming a work based on the Program, and copy and
     92distribute such modifications or work under the terms of Section 1
     93above, provided that you also meet all of these conditions:
     94
     95    a) You must cause the modified files to carry prominent notices
     96    stating that you changed the files and the date of any change.
     97
     98    b) You must cause any work that you distribute or publish, that in
     99    whole or in part contains or is derived from the Program or any
     100    part thereof, to be licensed as a whole at no charge to all third
     101    parties under the terms of this License.
     102
     103    c) If the modified program normally reads commands interactively
     104    when run, you must cause it, when started running for such
     105    interactive use in the most ordinary way, to print or display an
     106    announcement including an appropriate copyright notice and a
     107    notice that there is no warranty (or else, saying that you provide
     108    a warranty) and that users may redistribute the program under
     109    these conditions, and telling the user how to view a copy of this
     110    License.  (Exception: if the Program itself is interactive but
     111    does not normally print such an announcement, your work based on
     112    the Program is not required to print an announcement.)
     113
     114These requirements apply to the modified work as a whole.  If
     115identifiable sections of that work are not derived from the Program,
     116and can be reasonably considered independent and separate works in
     117themselves, then this License, and its terms, do not apply to those
     118sections when you distribute them as separate works.  But when you
     119distribute the same sections as part of a whole which is a work based
     120on the Program, the distribution of the whole must be on the terms of
     121this License, whose permissions for other licensees extend to the
     122entire whole, and thus to each and every part regardless of who wrote it.
     123
     124Thus, it is not the intent of this section to claim rights or contest
     125your rights to work written entirely by you; rather, the intent is to
     126exercise the right to control the distribution of derivative or
     127collective works based on the Program.
     128
     129In addition, mere aggregation of another work not based on the Program
     130with the Program (or with a work based on the Program) on a volume of
     131a storage or distribution medium does not bring the other work under
     132the scope of this License.
     133
     134  3. You may copy and distribute the Program (or a work based on it,
     135under Section 2) in object code or executable form under the terms of
     136Sections 1 and 2 above provided that you also do one of the following:
     137
     138    a) Accompany it with the complete corresponding machine-readable
     139    source code, which must be distributed under the terms of Sections
     140    1 and 2 above on a medium customarily used for software
     141    interchange; or,
     142
     143    b) Accompany it with a written offer, valid for at least three
     144    years, to give any third party, for a charge no more than your
     145    cost of physically performing source distribution, a complete
     146    machine-readable copy of the corresponding source code, to be
     147    distributed under the terms of Sections 1 and 2 above on a medium
     148    customarily used for software interchange; or,
     149
     150    c) Accompany it with the information you received as to the offer
     151    to distribute corresponding source code.  (This alternative is
     152    allowed only for noncommercial distribution and only if you
     153    received the program in object code or executable form with such
     154    an offer, in accord with Subsection b above.)
     155
     156The source code for a work means the preferred form of the work for
     157making modifications to it.  For an executable work, complete source
     158code means all the source code for all modules it contains, plus any
     159associated interface definition files, plus the scripts used to
     160control compilation and installation of the executable.  However, as a
     161special exception, the source code distributed need not include
     162anything that is normally distributed (in either source or binary
     163form) with the major components (compiler, kernel, and so on) of the
     164operating system on which the executable runs, unless that component
     165itself accompanies the executable.
     166
     167If distribution of executable or object code is made by offering
     168access to copy from a designated place, then offering equivalent
     169access to copy the source code from the same place counts as
     170distribution of the source code, even though third parties are not
     171compelled to copy the source along with the object code.
     172
     173  4. You may not copy, modify, sublicense, or distribute the Program
     174except as expressly provided under this License.  Any attempt
     175otherwise to copy, modify, sublicense or distribute the Program is
     176void, and will automatically terminate your rights under this License.
     177However, parties who have received copies, or rights, from you under
     178this License will not have their licenses terminated so long as such
     179parties remain in full compliance.
     180
     181  5. You are not required to accept this License, since you have not
     182signed it.  However, nothing else grants you permission to modify or
     183distribute the Program or its derivative works.  These actions are
     184prohibited by law if you do not accept this License.  Therefore, by
     185modifying or distributing the Program (or any work based on the
     186Program), you indicate your acceptance of this License to do so, and
     187all its terms and conditions for copying, distributing or modifying
     188the Program or works based on it.
     189
     190  6. Each time you redistribute the Program (or any work based on the
     191Program), the recipient automatically receives a license from the
     192original licensor to copy, distribute or modify the Program subject to
     193these terms and conditions.  You may not impose any further
     194restrictions on the recipients' exercise of the rights granted herein.
     195You are not responsible for enforcing compliance by third parties to
     196this License.
     197
     198  7. If, as a consequence of a court judgment or allegation of patent
     199infringement or for any other reason (not limited to patent issues),
     200conditions are imposed on you (whether by court order, agreement or
     201otherwise) that contradict the conditions of this License, they do not
     202excuse you from the conditions of this License.  If you cannot
     203distribute so as to satisfy simultaneously your obligations under this
     204License and any other pertinent obligations, then as a consequence you
     205may not distribute the Program at all.  For example, if a patent
     206license would not permit royalty-free redistribution of the Program by
     207all those who receive copies directly or indirectly through you, then
     208the only way you could satisfy both it and this License would be to
     209refrain entirely from distribution of the Program.
     210
     211If any portion of this section is held invalid or unenforceable under
     212any particular circumstance, the balance of the section is intended to
     213apply and the section as a whole is intended to apply in other
     214circumstances.
     215
     216It is not the purpose of this section to induce you to infringe any
     217patents or other property right claims or to contest validity of any
     218such claims; this section has the sole purpose of protecting the
     219integrity of the free software distribution system, which is
     220implemented by public license practices.  Many people have made
     221generous contributions to the wide range of software distributed
     222through that system in reliance on consistent application of that
     223system; it is up to the author/donor to decide if he or she is willing
     224to distribute software through any other system and a licensee cannot
     225impose that choice.
     226
     227This section is intended to make thoroughly clear what is believed to
     228be a consequence of the rest of this License.
     229
     230  8. If the distribution and/or use of the Program is restricted in
     231certain countries either by patents or by copyrighted interfaces, the
     232original copyright holder who places the Program under this License
     233may add an explicit geographical distribution limitation excluding
     234those countries, so that distribution is permitted only in or among
     235countries not thus excluded.  In such case, this License incorporates
     236the limitation as if written in the body of this License.
     237
     238  9. The Free Software Foundation may publish revised and/or new versions
     239of the General Public License from time to time.  Such new versions will
     240be similar in spirit to the present version, but may differ in detail to
     241address new problems or concerns.
     242
     243Each version is given a distinguishing version number.  If the Program
     244specifies a version number of this License which applies to it and
     245"any later version", you have the option of following the terms and
     246conditions either of that version or of any later version published by
     247the Free Software Foundation.  If the Program does not specify a
     248version number of this License, you may choose any version ever
     249published by the Free Software Foundation.
     250
     251  10. If you wish to incorporate parts of the Program into other free
     252programs whose distribution conditions are different, write to the author
     253to ask for permission.  For software which is copyrighted by the Free
     254Software Foundation, write to the Free Software Foundation; we sometimes
     255make exceptions for this.  Our decision will be guided by the two goals
     256of preserving the free status of all derivatives of our free software and
     257of promoting the sharing and reuse of software generally.
     258
     259                NO WARRANTY
     260
     261  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
     262WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
     263EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
     264OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY
     265KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
     266IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     267PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
     268PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
     269THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
     270
     271  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
     272WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
     273AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
     274FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
     275CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
     276PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
     277RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
     278FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
     279SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     280DAMAGES.
     281
     282             END OF TERMS AND CONDITIONS
     283
     284        How to Apply These Terms to Your New Programs
     285
     286  If you develop a new program, and you want it to be of the greatest
     287possible use to the public, the best way to achieve this is to make it
     288free software which everyone can redistribute and change under these
     289terms.
     290
     291  To do so, attach the following notices to the program.  It is safest
     292to attach them to the start of each source file to most effectively
     293convey the exclusion of warranty; and each file should have at least
     294the "copyright" line and a pointer to where the full notice is found.
     295
     296    <one line to give the program's name and a brief idea of what it does.>
     297    Copyright (C) <year>  <name of author>
     298
     299    This program is free software; you can redistribute it and/or modify
     300    it under the terms of the GNU General Public License as published by
     301    the Free Software Foundation; either version 2 of the License, or
     302    (at your option) any later version.
     303
     304    This program is distributed in the hope that it will be useful,
     305    but WITHOUT ANY WARRANTY; without even the implied warranty of
     306    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     307    GNU General Public License for more details.
     308
     309    You should have received a copy of the GNU General Public License
     310    along with this program; if not, write to the Free Software
     311    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
     312
     313
     314Also add information on how to contact you by electronic and paper mail.
     315
     316If the program is interactive, make it output a short notice like this
     317when it starts in an interactive mode:
     318
     319    Gnomovision version 69, Copyright (C) year name of author
     320    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
     321    This is free software, and you are welcome to redistribute it
     322    under certain conditions; type `show c' for details.
     323
     324The hypothetical commands `show w' and `show c' should show the appropriate
     325parts of the General Public License.  Of course, the commands you use may
     326be called something other than `show w' and `show c'; they could even be
     327mouse-clicks or menu items--whatever suits your program.
     328
     329You should also get your employer (if you work as a programmer) or your
     330school, if any, to sign a "copyright disclaimer" for the program, if
     331necessary.  Here is a sample; alter the names:
     332
     333  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
     334  `Gnomovision' (which makes passes at compilers) written by James Hacker.
     335
     336  <signature of Ty Coon>, 1 April 1989
     337  Ty Coon, President of Vice
     338
     339This General Public License does not permit incorporating your program into
     340proprietary programs.  If your program is a subroutine library, you may
     341consider it more useful to permit linking proprietary applications with the
     342library.  If this is what you want to do, use the GNU Library General
     343Public License instead of this License.
     344
  • new file source/tools/i18n/txclib/__init__.py

    diff --git a/source/tools/i18n/txclib/__init__.py b/source/tools/i18n/txclib/__init__.py
    new file mode 100644
    index 0000000..b87f835
    - +  
     1# -*- coding: utf-8 -*-
     2
     3VERSION = (0, 9, 0, 'final')
     4
     5
     6def get_version():
     7    version = '%s.%s' % (VERSION[0], VERSION[1])
     8    if VERSION[2]:
     9        version = '%s.%s' % (version, VERSION[2])
     10    if VERSION[3] != 'final':
     11        version = '%s %s' % (version, VERSION[3])
     12    return version
  • new file source/tools/i18n/txclib/cacert.pem

    diff --git a/source/tools/i18n/txclib/cacert.pem b/source/tools/i18n/txclib/cacert.pem
    new file mode 100644
    index 0000000..8eb1d8a
    - +  
     1##
     2## cacert.pem -- Bundle of CA Root Certificates
     3##
     4## Certificate data from Mozilla as of: Sat Dec 29 20:03:40 2012
     5##
     6## This is a bundle of X.509 certificates of public Certificate Authorities
     7## (CA). These were automatically extracted from Mozilla's root certificates
     8## file (certdata.txt).  This file can be found in the mozilla source tree:
     9## http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1
     10##
     11## It contains the certificates in PEM format and therefore
     12## can be directly used with curl / libcurl / php_curl, or with
     13## an Apache+mod_ssl webserver for SSL client authentication.
     14## Just configure this file as the SSLCACertificateFile.
     15##
     16
     17# @(#) $RCSfile: certdata.txt,v $ $Revision: 1.87 $ $Date: 2012/12/29 16:32:45 $
     18
     19GTE CyberTrust Global Root
     20==========================
     21-----BEGIN CERTIFICATE-----
     22MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg
     23Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG
     24A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz
     25MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL
     26Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0
     27IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u
     28sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql
     29HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID
     30AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW
     31M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF
     32NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
     33-----END CERTIFICATE-----
     34
     35Thawte Server CA
     36================
     37-----BEGIN CERTIFICATE-----
     38MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT
     39DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs
     40dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UE
     41AxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5j
     42b20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNV
     43BAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29u
     44c3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcG
     45A1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0
     46ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl
     47/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg7
     481CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzAR
     49MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9J
     50GubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZ
     51GCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc=
     52-----END CERTIFICATE-----
     53
     54Thawte Premium Server CA
     55========================
     56-----BEGIN CERTIFICATE-----
     57MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT
     58DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs
     59dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE
     60AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl
     61ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT
     62AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU
     63VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2
     64aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ
     65cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2
     66aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh
     67Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/
     68qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm
     69SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf
     708UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t
     71UCemDaYj+bvLpgcUQg==
     72-----END CERTIFICATE-----
     73
     74Equifax Secure CA
     75=================
     76-----BEGIN CERTIFICATE-----
     77MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE
     78ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
     79MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT
     80B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB
     81nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR
     82fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW
     838Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG
     84A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE
     85CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG
     86A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS
     87spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB
     88Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961
     89zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB
     90BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95
     9170+sB3c4
     92-----END CERTIFICATE-----
     93
     94Digital Signature Trust Co. Global CA 1
     95=======================================
     96-----BEGIN CERTIFICATE-----
     97MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE
     98ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMTAeFw05ODEy
     99MTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs
     100IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUA
     101A4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJE
     102NySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2i
     103o74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo
     104BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0
     105dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw
     106IoAPMTk5ODEyMTAxODEwMjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQY
     107MBaAFGp5fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i+DAM
     108BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB
     109ACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lNQseSJqBcNJo4cvj9axY+IO6CizEq
     110kzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4
     111RbyhkwS7hp86W0N6w4pl
     112-----END CERTIFICATE-----
     113
     114Digital Signature Trust Co. Global CA 3
     115=======================================
     116-----BEGIN CERTIFICATE-----
     117MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE
     118ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMjAeFw05ODEy
     119MDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs
     120IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUA
     121A4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGOD
     122VvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JS
     123xhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo
     124BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0
     125dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw
     126IoAPMTk5ODEyMDkxOTE3MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQY
     127MBaAFB6CTShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5WzAM
     128BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB
     129AEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHRxdf0CiUPPXiBng+xZ8SQTGPdXqfi
     130up/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVLB3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1
     131mPnHfxsb1gYgAlihw6ID
     132-----END CERTIFICATE-----
     133
     134Verisign Class 3 Public Primary Certification Authority
     135=======================================================
     136-----BEGIN CERTIFICATE-----
     137MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMx
     138FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5
     139IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVow
     140XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz
     141IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA
     142A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94
     143f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol
     144hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBAgUAA4GBALtMEivPLCYA
     145TxQT3ab7/AoRhIzzKBxnki98tsX63/Dolbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59Ah
     146WM1pF+NEHJwZRDmJXNycAA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2Omuf
     147Tqj/ZA1k
     148-----END CERTIFICATE-----
     149
     150Verisign Class 1 Public Primary Certification Authority - G2
     151============================================================
     152-----BEGIN CERTIFICATE-----
     153MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT
     154MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMgUHJpbWFy
     155eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln
     156biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
     157dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT
     158MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMgUHJpbWFy
     159eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln
     160biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
     161dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgd
     162k4xWArzZbxpvUjZudVYKVdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIq
     163WpDBucSmFc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQIDAQAB
     164MA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0Jh9ZrbWB85a7FkCMM
     165XErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2uluIncrKTdcu1OofdPvAbT6shkdHvC
     166lUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68DzFc6PLZ
     167-----END CERTIFICATE-----
     168
     169Verisign Class 2 Public Primary Certification Authority - G2
     170============================================================
     171-----BEGIN CERTIFICATE-----
     172MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQswCQYDVQQGEwJV
     173UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1h
     174cnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNp
     175Z24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1
     176c3QgTmV0d29yazAeFw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJV
     177UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1h
     178cnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNp
     179Z24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1
     180c3QgTmV0d29yazCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjx
     181nNuX6Zr8wgQGE75fUsjMHiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRC
     182wiNPStjwDqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cCAwEA
     183ATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9jinb3/7aHmZuovCfTK
     1841+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAXrXfMSTWqz9iP0b63GJZHc2pUIjRk
     185LbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnInjBJ7xUS0rg==
     186-----END CERTIFICATE-----
     187
     188Verisign Class 3 Public Primary Certification Authority - G2
     189============================================================
     190-----BEGIN CERTIFICATE-----
     191MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT
     192MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy
     193eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln
     194biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
     195dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT
     196MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy
     197eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln
     198biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
     199dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCO
     200FoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71
     201lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQAB
     202MA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01UbSuvDV1Ai2TT
     2031+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7iF6YM40AIOw7n60RzKprxaZLvcRTD
     204Oaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpYoJ2daZH9
     205-----END CERTIFICATE-----
     206
     207GlobalSign Root CA
     208==================
     209-----BEGIN CERTIFICATE-----
     210MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
     211GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
     212b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
     213BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
     214VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
     215DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
     216THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
     217Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
     218c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
     219gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
     220HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
     221AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
     222Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
     223j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
     224hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
     225X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
     226-----END CERTIFICATE-----
     227
     228GlobalSign Root CA - R2
     229=======================
     230-----BEGIN CERTIFICATE-----
     231MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
     232YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
     233bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
     234aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
     235bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
     236ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
     237s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
     238S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
     239TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
     240ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
     241FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
     242YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
     243BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
     2449Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
     24501yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
     2469G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
     247TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
     248-----END CERTIFICATE-----
     249
     250ValiCert Class 1 VA
     251===================
     252-----BEGIN CERTIFICATE-----
     253MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp
     254b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
     255YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh
     256bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIy
     257MjM0OFoXDTE5MDYyNTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0
     258d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEg
     259UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0
     260LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA
     261A4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIi
     262GQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCm
     263DuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0LBwG
     264lN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLWI8sogTLDAHkY7FkX
     265icnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPwnXS3qT6gpf+2SQMT2iLM7XGCK5nP
     266Orf1LXLI
     267-----END CERTIFICATE-----
     268
     269ValiCert Class 2 VA
     270===================
     271-----BEGIN CERTIFICATE-----
     272MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp
     273b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
     274YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh
     275bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw
     276MTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0
     277d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIg
     278UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0
     279LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA
     280A4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVC
     281CSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7Rf
     282ZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZ
     283SWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbV
     284UjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8
     285W9ViH0Pd
     286-----END CERTIFICATE-----
     287
     288RSA Root Certificate 1
     289======================
     290-----BEGIN CERTIFICATE-----
     291MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp
     292b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
     293YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh
     294bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw
     295MjIzM1oXDTE5MDYyNjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0
     296d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMg
     297UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0
     298LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA
     299A4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td
     3003zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89H
     301BFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliEZwgs
     3023x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJn0WuPIqpsHEzXcjF
     303V9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/APhmcGcwTTYJBtYze4D1gCCAPRX5r
     304on+jjBXu
     305-----END CERTIFICATE-----
     306
     307Verisign Class 1 Public Primary Certification Authority - G3
     308============================================================
     309-----BEGIN CERTIFICATE-----
     310MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
     311UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
     312cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
     313IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
     314dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
     315CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
     316dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
     317cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkg
     318Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
     319ggEBAN2E1Lm0+afY8wR4nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/E
     320bRrsC+MO8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjVojYJ
     321rKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjbPG7PoBMAGrgnoeS+
     322Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP26KbqxzcSXKMpHgLZ2x87tNcPVkeB
     323FQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vrn5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
     324q2aN17O6x5q25lXQBfGfMY1aqtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/N
     325y9Sn2WCVhDr4wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3
     326ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrspSCAaWihT37h
     327a88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4E1Z5T21Q6huwtVexN2ZYI/Pc
     328D98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g==
     329-----END CERTIFICATE-----
     330
     331Verisign Class 2 Public Primary Certification Authority - G3
     332============================================================
     333-----BEGIN CERTIFICATE-----
     334MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJBgNVBAYTAlVT
     335MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29y
     336azE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ug
     337b25seTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0
     338aW9uIEF1dGhvcml0eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJ
     339BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1
     340c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y
     341aXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBD
     342ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
     343AQEArwoNwtUs22e5LeWUJ92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6
     344tW8UvxDOJxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUYwZF7
     345C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9okoqQHgiBVrKtaaNS
     3460MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjNqWm6o+sdDZykIKbBoMXRRkwXbdKs
     347Zj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/ESrg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0
     348JhU8wI1NQ0kdvekhktdmnLfexbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf
     3490xwLRtxyID+u7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU
     350sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RIsH/7NiXaldDx
     351JBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTPcjnhsUPgKM+351psE2tJs//j
     352GHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q
     353-----END CERTIFICATE-----
     354
     355Verisign Class 3 Public Primary Certification Authority - G3
     356============================================================
     357-----BEGIN CERTIFICATE-----
     358MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
     359UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
     360cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
     361IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
     362dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
     363CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
     364dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
     365cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
     366Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
     367ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
     368EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
     369cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
     370EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
     371055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
     372ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
     373j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
     374/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
     375xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
     376t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
     377-----END CERTIFICATE-----
     378
     379Verisign Class 4 Public Primary Certification Authority - G3
     380============================================================
     381-----BEGIN CERTIFICATE-----
     382MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
     383UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
     384cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
     385IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
     386dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
     387CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
     388dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
     389cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg
     390Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
     391ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS
     392tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM
     3938BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW
     394Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX
     395Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
     396j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt
     397mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm
     398fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd
     399RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG
     400UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg==
     401-----END CERTIFICATE-----
     402
     403Entrust.net Secure Server CA
     404============================
     405-----BEGIN CERTIFICATE-----
     406MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMCVVMxFDASBgNV
     407BAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5uZXQvQ1BTIGluY29ycC4gYnkg
     408cmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRl
     409ZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhv
     410cml0eTAeFw05OTA1MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIG
     411A1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBi
     412eSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1p
     413dGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0
     414aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQ
     415aO2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5
     416gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OCAdcw
     417ggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHboIHYpIHVMIHSMQsw
     418CQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5l
     419dC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
     420bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENl
     421cnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
     422dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0MFqBDzIwMTkw
     423NTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0Bow
     424HQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAaMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA
     425BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyN
     426Ewr75Ji174z4xRAN95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9
     427n9cd2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
     428-----END CERTIFICATE-----
     429
     430Entrust.net Premium 2048 Secure Server CA
     431=========================================
     432-----BEGIN CERTIFICATE-----
     433MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
     434ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
     435bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
     436BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
     437NzUwNTFaFw0xOTEyMjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
     438d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
     439MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
     440ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
     441MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
     442Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
     443hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
     444nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
     445VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo3QwcjARBglghkgBhvhC
     446AQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGAvtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdER
     447gL7YibkIozH5oSQJFrlwMB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0B
     448AQUFAAOCAQEAWUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo
     449oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQh7A6tcOdBTcS
     450o8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18f3v/rxzP5tsHrV7bhZ3QKw0z
     4512wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfNB/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjX
     452OP/swNlQ8C5LWK5Gb9Auw2DaclVyvUxFnmG6v4SBkgPR0ml8xQ==
     453-----END CERTIFICATE-----
     454
     455Baltimore CyberTrust Root
     456=========================
     457-----BEGIN CERTIFICATE-----
     458MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
     459ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
     460ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
     461SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
     462dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
     463uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
     464UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
     465G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
     466XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
     467l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
     468VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
     469BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
     470cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
     471hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
     472Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
     473RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
     474-----END CERTIFICATE-----
     475
     476Equifax Secure Global eBusiness CA
     477==================================
     478-----BEGIN CERTIFICATE-----
     479MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
     480RXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNp
     481bmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMx
     482HDAaBgNVBAoTE0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEds
     483b2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRV
     484PEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzN
     485qfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxn
     486hcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j
     487BBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hs
     488MA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okEN
     489I7SS+RkAZ70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIY
     490NMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV
     491-----END CERTIFICATE-----
     492
     493Equifax Secure eBusiness CA 1
     494=============================
     495-----BEGIN CERTIFICATE-----
     496MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
     497RXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENB
     498LTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UE
     499ChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNz
     500IENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ
     5011MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBuWqDZQu4a
     502IZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKwEnv+j6YDAgMBAAGjZjBk
     503MBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEp4MlIR21kW
     504Nl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQF
     505AAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5
     506lSE/9dR+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+
     507KpYrtWKmpj29f5JZzVoqgrI3eQ==
     508-----END CERTIFICATE-----
     509
     510Equifax Secure eBusiness CA 2
     511=============================
     512-----BEGIN CERTIFICATE-----
     513MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEXMBUGA1UE
     514ChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0y
     515MB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoT
     516DkVxdWlmYXggU2VjdXJlMSYwJAYDVQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCB
     517nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn
     5182Z0GvxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/BPO3QSQ5
     519BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0CAwEAAaOCAQkwggEFMHAG
     520A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUx
     521JjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoG
     522A1UdEAQTMBGBDzIwMTkwNjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9e
     523uSBIplBqy/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQFMAMB
     524Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAAyGgq3oThr1
     525jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia
     52678O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUm
     527V+GRMOrN
     528-----END CERTIFICATE-----
     529
     530AddTrust Low-Value Services Root
     531================================
     532-----BEGIN CERTIFICATE-----
     533MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
     534QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU
     535cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw
     536CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO
     537ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB
     538AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6
     53954eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr
     540oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1
     541Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui
     542GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w
     543HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD
     544AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT
     545RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw
     546HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt
     547ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph
     548iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
     549eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr
     550mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj
     551ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
     552-----END CERTIFICATE-----
     553
     554AddTrust External Root
     555======================
     556-----BEGIN CERTIFICATE-----
     557MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
     558QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
     559VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
     560NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
     561cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
     562Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
     563+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
     564Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
     565aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
     5662xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
     5677+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
     568BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
     569VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
     570VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
     571IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
     572j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
     5736wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
     574e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
     575G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
     576-----END CERTIFICATE-----
     577
     578AddTrust Public Services Root
     579=============================
     580-----BEGIN CERTIFICATE-----
     581MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
     582QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU
     583cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ
     584BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l
     585dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF
     586AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu
     587nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i
     588d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG
     589Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw
     590HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G
     591A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
     592/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux
     593FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G
     594A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4
     595JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL
     596+YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao
     597GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9
     598Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H
     599EufOX1362KqxMy3ZdvJOOjMMK7MtkAY=
     600-----END CERTIFICATE-----
     601
     602AddTrust Qualified Certificates Root
     603====================================
     604-----BEGIN CERTIFICATE-----
     605MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
     606QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU
     607cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx
     608CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ
     609IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG
     6109w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx
     61164r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3
     612KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o
     613L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR
     614wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU
     615MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/
     616BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE
     617BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y
     618azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD
     619ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG
     620GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X
     621dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze
     622RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB
     623iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE=
     624-----END CERTIFICATE-----
     625
     626Entrust Root Certification Authority
     627====================================
     628-----BEGIN CERTIFICATE-----
     629MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
     630BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
     631b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
     632A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
     633MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
     634MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
     635Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
     636dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
     637ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
     638A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
     639Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
     640j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
     641rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
     642DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
     643MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
     644hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
     645A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
     646Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
     647v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
     648W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
     649tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
     650-----END CERTIFICATE-----
     651
     652RSA Security 2048 v3
     653====================
     654-----BEGIN CERTIFICATE-----
     655MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYDVQQK
     656ExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAy
     657MjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAb
     658BgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
     659AQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7
     660Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgb
     661WhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iH
     662KrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP
     663+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/
     664MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4E
     665FgQUB8NRMKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmY
     666v/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj
     6670aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwj
     668VAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395
     669nzIlQnQFgCi/vcEkllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA
     670pKnXwiJPZ9d37CAFYd4=
     671-----END CERTIFICATE-----
     672
     673GeoTrust Global CA
     674==================
     675-----BEGIN CERTIFICATE-----
     676MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
     677Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
     678MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
     679LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
     680CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
     681BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
     6828u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
     683T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
     684vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
     685AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
     686DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
     687zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
     688d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
     689mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
     690XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
     691Mw==
     692-----END CERTIFICATE-----
     693
     694GeoTrust Global CA 2
     695====================
     696-----BEGIN CERTIFICATE-----
     697MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
     698R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw
     699MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
     700LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
     701ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/
     702NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k
     703LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA
     704Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b
     705HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF
     706MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH
     707K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7
     708srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh
     709ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL
     710OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC
     711x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF
     712H4z1Ir+rzoPz4iIprn2DQKi6bA==
     713-----END CERTIFICATE-----
     714
     715GeoTrust Universal CA
     716=====================
     717-----BEGIN CERTIFICATE-----
     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
     742P/rmMuGNG2+k5o7Y+SlIis5z/iw=
     743-----END CERTIFICATE-----
     744
     745GeoTrust Universal CA 2
     746=======================
     747-----BEGIN CERTIFICATE-----
     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
     772X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
     773-----END CERTIFICATE-----
     774
     775UTN-USER First-Network Applications
     776===================================
     777-----BEGIN CERTIFICATE-----
     778MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCBozELMAkGA1UE
     779BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
     780IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzAp
     781BgNVBAMTIlVUTi1VU0VSRmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5
     782WhcNMTkwNzA5MTg1NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5T
     783YWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
     784dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3QtTmV0d29yayBB
     785cHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz+5Gh5DZVhawGNFug
     786mliy+LUPBXeDrjKxdpJo7CNKyXY/45y2N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4Cj
     787DUeJT1FxL+78P/m4FoCHiZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXu
     788Ozr0hAReYFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1axwi
     789P8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6gyN7igEL66S/ozjIE
     790j3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8w
     791HQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPhahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9j
     792cmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0G
     793CSqGSIb3DQEBBQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y
     794IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6LzsQCv4AdRWOOTK
     795RIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4ZSfP1FMa8Kxun08FDAOBp4Qp
     796xFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qMYEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAq
     797DbUMo2s/rn9X9R+WfN9v3YIwLGUbQErNaLly7HF27FSOH4UMAWr6pjisH8SE
     798-----END CERTIFICATE-----
     799
     800America Online Root Certification Authority 1
     801=============================================
     802-----BEGIN CERTIFICATE-----
     803MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
     804QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp
     805Y2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkG
     806A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg
     807T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQAD
     808ggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lkhsmj76CG
     809v2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym1BW32J/X3HGrfpq/m44z
     810DyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsWOqMFf6Dch9Wc/HKpoH145LcxVR5lu9Rh
     811sCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP
     8128c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0T
     813AQH/BAUwAwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Z
     814o/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQB8itEf
     815GDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkFZu90821fnZmv9ov761KyBZiibyrF
     816VL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft
     8173OJvx8Fi8eNy1gTIdGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43g
     818Kd8hdIaC2y+CMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds
     819sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7
     820-----END CERTIFICATE-----
     821
     822America Online Root Certification Authority 2
     823=============================================
     824-----BEGIN CERTIFICATE-----
     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
     850cX/9XhmgD0uRuMRUvAawRY8mkaKO/qk=
     851-----END CERTIFICATE-----
     852
     853Visa eCommerce Root
     854===================
     855-----BEGIN CERTIFICATE-----
     856MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG
     857EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug
     858QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2
     859WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm
     860VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
     861bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL
     862F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b
     863RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0
     864TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI
     865/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs
     866GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG
     867MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc
     868CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW
     869YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz
     870zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu
     871YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
     872398znM/jra6O1I7mT1GvFpLgXPYHDw==
     873-----END CERTIFICATE-----
     874
     875Certum Root CA
     876==============
     877-----BEGIN CERTIFICATE-----
     878MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK
     879ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla
     880Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u
     881by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x
     882wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL
     883kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ
     88489eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K
     885Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P
     886NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq
     887hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+
     888GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg
     889GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/
     8900YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS
     891qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw==
     892-----END CERTIFICATE-----
     893
     894Comodo AAA Services root
     895========================
     896-----BEGIN CERTIFICATE-----
     897MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
     898R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
     899TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
     900MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
     901c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
     902BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
     903ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
     904C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
     905i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
     906Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
     907Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
     908Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
     909BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
     910cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
     911LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
     9127l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
     913Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
     9148VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
     91512yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
     916-----END CERTIFICATE-----
     917
     918Comodo Secure Services root
     919===========================
     920-----BEGIN CERTIFICATE-----
     921MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
     922R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
     923TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw
     924MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu
     925Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi
     926BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
     927ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP
     9289nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc
     929rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC
     930oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V
     931p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E
     932FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
     933gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj
     934YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm
     935aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm
     9364J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj
     937Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL
     938DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw
     939pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H
     940RR3B7Hzs/Sk=
     941-----END CERTIFICATE-----
     942
     943Comodo Trusted Services root
     944============================
     945-----BEGIN CERTIFICATE-----
     946MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
     947R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
     948TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw
     949MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h
     950bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw
     951IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC
     952AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7
     9533TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y
     954/9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6
     955juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS
     956ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud
     957DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
     958/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp
     959ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl
     960cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw
     961uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
     962pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA
     963BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l
     964R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O
     9659y5Xt5hwXsjEeLBi
     966-----END CERTIFICATE-----
     967
     968QuoVadis Root CA
     969================
     970-----BEGIN CERTIFICATE-----
     971MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
     972ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
     973eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
     974MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
     975cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
     976EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
     977AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
     978J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
     979F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
     980YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
     981AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
     982PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
     983ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
     984MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
     985YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
     986ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
     987Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
     988Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
     989BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
     990FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
     991aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
     992tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
     993fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
     994LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
     995gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
     9965upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
     9975nrQNiOKSnQ2+Q==
     998-----END CERTIFICATE-----
     999
     1000QuoVadis Root CA 2
     1001==================
     1002-----BEGIN CERTIFICATE-----
     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
     1029-----END CERTIFICATE-----
     1030
     1031QuoVadis Root CA 3
     1032==================
     1033-----BEGIN CERTIFICATE-----
     1034MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
     1035EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
     1036OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
     1037aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
     1038DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
     1039DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
     1040KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
     1041DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
     1042BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
     1043p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
     1044nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
     1045MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
     1046Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
     1047uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
     1048BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
     1049YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
     1050aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
     1051BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
     1052VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
     1053ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
     1054AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
     1055qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
     1056hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
     1057POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
     1058Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
     10598kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
     1060bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
     1061g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
     1062vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
     1063qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
     1064-----END CERTIFICATE-----
     1065
     1066Security Communication Root CA
     1067==============================
     1068-----BEGIN CERTIFICATE-----
     1069MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
     1070U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
     1071HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
     1072U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
     1073ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
     10748yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
     1075DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
     10765HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
     1077DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
     1078JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
     1079DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
     10800dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
     1081mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
     1082s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
     10836rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
     1084FL39vmwLAw==
     1085-----END CERTIFICATE-----
     1086
     1087Sonera Class 1 Root CA
     1088======================
     1089-----BEGIN CERTIFICATE-----
     1090MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
     1091U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAxMDQwNjEwNDkxM1oXDTIxMDQw
     1092NjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
     1093IENsYXNzMSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H88
     10947dF+2rDNbS82rDTG29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9
     1095EJUkoVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk3w0LBUXl
     10960fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBLqdReLjVQCfOAl/QMF645
     10972F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIINnvmLVz5MxxftLItyM19yejhW1ebZrgUa
     1098HXVFsculJRwSVzb9IjcCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZT
     1099iFIwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE9
     110028Jj2VuXZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0HDjxV
     1101yhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VOTzF2nBBhjrZTOqMR
     1102vq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2UvkVrCqIexVmiUefkl98HVrhq4uz2P
     1103qYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4wzMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9Z
     1104IRlXvVWa
     1105-----END CERTIFICATE-----
     1106
     1107Sonera Class 2 Root CA
     1108======================
     1109-----BEGIN CERTIFICATE-----
     1110MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
     1111U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
     1112NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
     1113IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
     1114/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
     1115dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
     1116f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
     1117tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
     1118nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
     1119XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
     11200jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
     1121cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
     1122Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
     1123EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
     1124llpwrN9M
     1125-----END CERTIFICATE-----
     1126
     1127Staat der Nederlanden Root CA
     1128=============================
     1129-----BEGIN CERTIFICATE-----
     1130MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE
     1131ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g
     1132Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w
     1133HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh
     1134bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt
     1135vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P
     1136jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca
     1137C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth
     1138vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6
     113922r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV
     1140HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v
     1141dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN
     1142BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR
     1143EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw
     1144MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y
     1145nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR
     1146iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw==
     1147-----END CERTIFICATE-----
     1148
     1149TDC Internet Root CA
     1150====================
     1151-----BEGIN CERTIFICATE-----
     1152MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJESzEVMBMGA1UE
     1153ChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTAeFw0wMTA0MDUx
     1154NjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNVBAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJu
     1155ZXQxHTAbBgNVBAsTFFREQyBJbnRlcm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
     1156MIIBCgKCAQEAxLhAvJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20j
     1157xsNuZp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a0vnRrEvL
     1158znWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc14izbSysseLlJ28TQx5yc
     11595IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGNeGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6
     1160otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcDR0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZI
     1161AYb4QgEBBAQDAgAHMGUGA1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMM
     1162VERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxMEQ1JM
     1163MTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3WjALBgNVHQ8EBAMC
     1164AQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAwHQYDVR0OBBYEFGxkAcf9hW2syNqe
     1165UAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJKoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0G
     1166CSqGSIb3DQEBBQUAA4IBAQBOQ8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540m
     1167gwV5dOy0uaOXwTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+
     11682ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm899qNLPg7kbWzb
     1169O0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0jUNAE4z9mQNUecYu6oah9jrU
     1170Cbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38aQNiuJkFBT1reBK9sG9l
     1171-----END CERTIFICATE-----
     1172
     1173TDC OCES Root CA
     1174================
     1175-----BEGIN CERTIFICATE-----
     1176MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJESzEMMAoGA1UE
     1177ChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEwODM5MzBaFw0zNzAyMTEwOTA5
     1178MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNUREMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIB
     1179IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuH
     1180nEz9pPPEXyG9VhDr2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0
     1181zY0s2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItUGBxIYXvV
     1182iGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKjdGqPqcNiKXEx5TukYBde
     1183dObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+rTpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO
     11843QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB
     11855DCB4TCB3gYIKoFQgSkBAQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5k
     1186ay9yZXBvc2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRlciBm
     1187cmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEuMS4xLiBDZXJ0aWZp
     1188Y2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEuMS4x
     1189LjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1UdHwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEM
     1190MAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYm
     1191aHR0cDovL2NybC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy
     1192MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZJ2cdUBVLc647
     1193+RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqGSIb2fQdBAAQQMA4bCFY2LjA6
     1194NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACromJkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4
     1195A9G28kNBKWKnctj7fAXmMXAnVBhOinxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYsc
     1196A+UYyAFMP8uXBV2YcaaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9
     1197AOoBmbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQYqbsFbS1
     1198AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9BKNDLdr8C2LqL19iUw==
     1199-----END CERTIFICATE-----
     1200
     1201UTN DATACorp SGC Root CA
     1202========================
     1203-----BEGIN CERTIFICATE-----
     1204MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE
     1205BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
     1206IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ
     1207BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa
     1208MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w
     1209HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy
     1210dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC
     1211AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys
     1212raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo
     1213wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA
     12149P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv
     121533i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud
     1216DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9
     1217BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD
     1218LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3
     1219DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft
     1220Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0
     1221I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx
     1222EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP
     1223DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI
     1224-----END CERTIFICATE-----
     1225
     1226UTN USERFirst Email Root CA
     1227===========================
     1228-----BEGIN CERTIFICATE-----
     1229MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCBrjELMAkGA1UE
     1230BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
     1231IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0
     1232BgNVBAMTLVVUTi1VU0VSRmlyc3QtQ2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05
     1233OTA3MDkxNzI4NTBaFw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQx
     1234FzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsx
     1235ITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UEAxMtVVROLVVTRVJGaXJz
     1236dC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWlsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
     1237MIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3BYHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIx
     1238B8dOtINknS4p1aJkxIW9hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8
     1239om+rWV6lL8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLmSGHG
     1240TPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM1tZUOt4KpLoDd7Nl
     1241yP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws6wIDAQABo4G5MIG2MAsGA1UdDwQE
     1242AwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNV
     1243HR8EUTBPME2gS6BJhkdodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGll
     1244bnRBdXRoZW50aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH
     1245AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u7mFVbwQ+zzne
     1246xRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0xtcgBEXkzYABurorbs6q15L+
     12475K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQrfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarV
     1248NZ1yQAOJujEdxRBoUp7fooXFXAimeOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZ
     1249w7JHpsIyYdfHb0gkUSeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ=
     1250-----END CERTIFICATE-----
     1251
     1252UTN USERFirst Hardware Root CA
     1253==============================
     1254-----BEGIN CERTIFICATE-----
     1255MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE
     1256BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
     1257IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd
     1258BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx
     1259OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0
     1260eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz
     1261ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3
     1262DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI
     1263wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd
     1264tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8
     1265i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf
     1266Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw
     1267gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF
     1268lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF
     1269UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF
     1270BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
     1271//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW
     1272XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2
     1273lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn
     1274iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67
     1275nfhmqA==
     1276-----END CERTIFICATE-----
     1277
     1278UTN USERFirst Object Root CA
     1279============================
     1280-----BEGIN CERTIFICATE-----
     1281MIIEZjCCA06gAwIBAgIQRL4Mi1AAJLQR0zYt4LNfGzANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UE
     1282BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
     1283IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAb
     1284BgNVBAMTFFVUTi1VU0VSRmlyc3QtT2JqZWN0MB4XDTk5MDcwOTE4MzEyMFoXDTE5MDcwOTE4NDAz
     1285NlowgZUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkx
     1286HjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3dy51c2Vy
     1287dHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdDCCASIwDQYJKoZIhvcNAQEB
     1288BQADggEPADCCAQoCggEBAM6qgT+jo2F4qjEAVZURnicPHxzfOpuCaDDASmEd8S8O+r5596Uj71VR
     1289loTN2+O5bj4x2AogZ8f02b+U60cEPgLOKqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQ
     1290w5ujm9M89RKZd7G3CeBo5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbHd2pBnqcP1/vu
     1291lBe3/IW+pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh2JU022R5KP+6LhHC5ehbkkj7
     1292RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzTbafc8H9vg2XiaquHhnUCAwEAAaOBrzCBrDAL
     1293BgNVHQ8EBAMCAcYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU2u1kdBScFDyr3ZmpvVsoTYs8
     1294ydgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmly
     1295c3QtT2JqZWN0LmNybDApBgNVHSUEIjAgBggrBgEFBQcDAwYIKwYBBQUHAwgGCisGAQQBgjcKAwQw
     1296DQYJKoZIhvcNAQEFBQADggEBAAgfUrE3RHjb/c652pWWmKpVZIC1WkDdIaXFwfNfLEzIR1pp6ujw
     1297NTX00CXzyKakh0q9G7FzCL3Uw8q2NbtZhncxzaeAFK4T7/yxSPlrJSUtUbYsbUXBmMiKVl0+7kNO
     1298PmsnjtA6S4ULX9Ptaqd1y9Fahy85dRNacrACgZ++8A+EVCBibGnU4U3GDZlDAQ0Slox4nb9QorFE
     1299qmrPF3rPbw/U+CRVX/A0FklmPlBGyWNxODFiuGK581OtbLUrohKqGU8J2l7nk8aOFAj+8DCAGKCG
     1300hU3IfdeLA/5u1fedFqySLKAj5ZyRUh+U3xeUc8OzwcFxBSAAeL0TUh2oPs0AH8g=
     1301-----END CERTIFICATE-----
     1302
     1303Camerfirma Chambers of Commerce Root
     1304====================================
     1305-----BEGIN CERTIFICATE-----
     1306MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
     1307QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
     1308ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx
     1309NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp
     1310cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn
     1311MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC
     1312AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU
     1313xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH
     1314NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW
     1315DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV
     1316d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud
     1317EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v
     1318cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P
     1319AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh
     1320bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD
     1321VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz
     1322aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi
     1323fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD
     1324L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN
     1325UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n
     1326ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1
     1327erfutGWaIZDgqtCYvDi1czyL+Nw=
     1328-----END CERTIFICATE-----
     1329
     1330Camerfirma Global Chambersign Root
     1331==================================
     1332-----BEGIN CERTIFICATE-----
     1333MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
     1334QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
     1335ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx
     1336NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt
     1337YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg
     1338MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw
     1339ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J
     13401tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O
     1341by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl
     13426DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c
     13438lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/
     1344BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j
     1345aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B
     1346Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj
     1347aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y
     1348ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh
     1349bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA
     1350PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y
     1351gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ
     1352PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4
     1353IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes
     1354t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A==
     1355-----END CERTIFICATE-----
     1356
     1357NetLock Qualified (Class QA) Root
     1358=================================
     1359-----BEGIN CERTIFICATE-----
     1360MIIG0TCCBbmgAwIBAgIBezANBgkqhkiG9w0BAQUFADCByTELMAkGA1UEBhMCSFUxETAPBgNVBAcT
     1361CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV
     1362BAsTEVRhbnVzaXR2YW55a2lhZG9rMUIwQAYDVQQDEzlOZXRMb2NrIE1pbm9zaXRldHQgS296amVn
     1363eXpvaSAoQ2xhc3MgUUEpIFRhbnVzaXR2YW55a2lhZG8xHjAcBgkqhkiG9w0BCQEWD2luZm9AbmV0
     1364bG9jay5odTAeFw0wMzAzMzAwMTQ3MTFaFw0yMjEyMTUwMTQ3MTFaMIHJMQswCQYDVQQGEwJIVTER
     1365MA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNhZ2kgS2Z0
     1366LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxQjBABgNVBAMTOU5ldExvY2sgTWlub3NpdGV0
     1367dCBLb3pqZWd5em9pIChDbGFzcyBRQSkgVGFudXNpdHZhbnlraWFkbzEeMBwGCSqGSIb3DQEJARYP
     1368aW5mb0BuZXRsb2NrLmh1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx1Ilstg91IRV
     1369CacbvWy5FPSKAtt2/GoqeKvld/Bu4IwjZ9ulZJm53QE+b+8tmjwi8F3JV6BVQX/yQ15YglMxZc4e
     13708ia6AFQer7C8HORSjKAyr7c3sVNnaHRnUPYtLmTeriZ539+Zhqurf4XsoPuAzPS4DB6TRWO53Lhb
     1371m+1bOdRfYrCnjnxmOCyqsQhjF2d9zL2z8cM/z1A57dEZgxXbhxInlrfa6uWdvLrqOU+L73Sa58XQ
     13720uqGURzk/mQIKAR5BevKxXEOC++r6uwSEaEYBTJp0QwsGj0lmT+1fMptsK6ZmfoIYOcZwvK9UdPM
     13730wKswREMgM6r3JSda6M5UzrWhQIDAMV9o4ICwDCCArwwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV
     1374HQ8BAf8EBAMCAQYwggJ1BglghkgBhvhCAQ0EggJmFoICYkZJR1lFTEVNISBFemVuIHRhbnVzaXR2
     1375YW55IGEgTmV0TG9jayBLZnQuIE1pbm9zaXRldHQgU3pvbGdhbHRhdGFzaSBTemFiYWx5emF0YWJh
     1376biBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBBIG1pbm9zaXRldHQgZWxla3Ryb25p
     1377a3VzIGFsYWlyYXMgam9naGF0YXMgZXJ2ZW55ZXN1bGVzZW5laywgdmFsYW1pbnQgZWxmb2dhZGFz
     1378YW5hayBmZWx0ZXRlbGUgYSBNaW5vc2l0ZXR0IFN6b2xnYWx0YXRhc2kgU3phYmFseXphdGJhbiwg
     1379YXogQWx0YWxhbm9zIFN6ZXJ6b2Rlc2kgRmVsdGV0ZWxla2JlbiBlbG9pcnQgZWxsZW5vcnplc2kg
     1380ZWxqYXJhcyBtZWd0ZXRlbGUuIEEgZG9rdW1lbnR1bW9rIG1lZ3RhbGFsaGF0b2sgYSBodHRwczov
     1381L3d3dy5uZXRsb2NrLmh1L2RvY3MvIGNpbWVuIHZhZ3kga2VyaGV0b2sgYXogaW5mb0BuZXRsb2Nr
     1382Lm5ldCBlLW1haWwgY2ltZW4uIFdBUk5JTkchIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0
     1383aGlzIGNlcnRpZmljYXRlIGFyZSBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIFF1YWxpZmllZCBDUFMg
     1384YXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3Lm5ldGxvY2suaHUvZG9jcy8gb3IgYnkgZS1tYWlsIGF0
     1385IGluZm9AbmV0bG9jay5uZXQwHQYDVR0OBBYEFAlqYhaSsFq7VQ7LdTI6MuWyIckoMA0GCSqGSIb3
     1386DQEBBQUAA4IBAQCRalCc23iBmz+LQuM7/KbD7kPgz/PigDVJRXYC4uMvBcXxKufAQTPGtpvQMznN
     1387wNuhrWw3AkxYQTvyl5LGSKjN5Yo5iWH5Upfpvfb5lHTocQ68d4bDBsxafEp+NFAwLvt/MpqNPfMg
     1388W/hqyobzMUwsWYACff44yTB1HLdV47yfuqhthCgFdbOLDcCRVCHnpgu0mfVRQdzNo0ci2ccBgcTc
     1389R08m6h/t280NmPSjnLRzMkqWmf68f8glWPhY83ZmiVSkpj7EUFy6iRiCdUgh0k8T6GB+B3bbELVR
     13905qq5aKrN9p2QdRLqOBrKROi3macqaJVmlaut74nLYKkGEsaUR+ko
     1391-----END CERTIFICATE-----
     1392
     1393NetLock Notary (Class A) Root
     1394=============================
     1395-----BEGIN CERTIFICATE-----
     1396MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI
     1397EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6
     1398dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j
     1399ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX
     1400DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH
     1401EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD
     1402VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz
     1403cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM
     1404D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ
     1405z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC
     1406/tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7
     1407tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6
     14084sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG
     1409A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC
     1410Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv
     1411bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu
     1412IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn
     1413LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0
     1414ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz
     1415IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh
     1416IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu
     1417b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh
     1418bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg
     1419Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp
     1420bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5
     1421ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP
     1422ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB
     1423CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr
     1424KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM
     14258CgHrTwXZoi1/baI
     1426-----END CERTIFICATE-----
     1427
     1428NetLock Business (Class B) Root
     1429===============================
     1430-----BEGIN CERTIFICATE-----
     1431MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUxETAPBgNVBAcT
     1432CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV
     1433BAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQDEylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikg
     1434VGFudXNpdHZhbnlraWFkbzAeFw05OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYD
     1435VQQGEwJIVTERMA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRv
     1436bnNhZ2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5ldExvY2sg
     1437VXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
     1438iQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2S
     1439o/1bXHQawEfKOml2mrriRBf8TKPV/riXiK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr
     14401nGTLbO/CVRY7QbrqHvcQ7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV
     1441HQ8BAf8EBAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZ
     1442RUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRh
     1443dGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQuIEEgaGl0
     1444ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRv
     1445c2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUg
     1446YXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh
     1447c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBz
     1448Oi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6ZXNA
     1449bmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhl
     1450IHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2
     1451YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBj
     1452cHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06sPgzTEdM
     145343WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXan3BukxowOR0w2y7jfLKR
     1454stE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKSNitjrFgBazMpUIaD8QFI
     1455-----END CERTIFICATE-----
     1456
     1457NetLock Express (Class C) Root
     1458==============================
     1459-----BEGIN CERTIFICATE-----
     1460MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUxETAPBgNVBAcT
     1461CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV
     1462BAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQDEytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBD
     1463KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJ
     1464BgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6
     1465dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMrTmV0TG9j
     1466ayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzANBgkqhkiG9w0BAQEFAAOB
     1467jQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNAOoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3Z
     1468W3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63
     1469euyucYT2BDMIJTLrdKwWRMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQw
     1470DgYDVR0PAQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEWggJN
     1471RklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0YWxhbm9zIFN6b2xn
     1472YWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBB
     1473IGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBOZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1i
     1474aXp0b3NpdGFzYSB2ZWRpLiBBIGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0
     1475ZWxlIGF6IGVsb2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs
     1476ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25sYXBqYW4gYSBo
     1477dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kga2VyaGV0byBheiBlbGxlbm9y
     1478emVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4gSU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5k
     1479IHRoZSB1c2Ugb2YgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQ
     1480UyBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwg
     1481YXQgY3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmYta3UzbM2
     1482xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2gpO0u9f38vf5NNwgMvOOW
     1483gyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4Fp1hBWeAyNDYpQcCNJgEjTME1A==
     1484-----END CERTIFICATE-----
     1485
     1486XRamp Global CA Root
     1487====================
     1488-----BEGIN CERTIFICATE-----
     1489MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
     1490BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
     1491dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
     1492dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
     1493HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
     1494U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
     1495dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
     1496IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
     1497foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
     1498zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
     1499AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
     1500xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
     1501EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
     1502oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
     1503AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
     1504/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
     1505qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
     1506nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
     15078LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
     1508-----END CERTIFICATE-----
     1509
     1510Go Daddy Class 2 CA
     1511===================
     1512-----BEGIN CERTIFICATE-----
     1513MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
     1514VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
     1515ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
     1516A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
     1517RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
     1518ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
     15192vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
     1520qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
     1521YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
     1522vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
     1523BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
     1524atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
     1525MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
     1526A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
     1527PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
     1528I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
     1529HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
     1530Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
     1531vZ8=
     1532-----END CERTIFICATE-----
     1533
     1534Starfield Class 2 CA
     1535====================
     1536-----BEGIN CERTIFICATE-----
     1537MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
     1538U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
     1539Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
     1540MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
     1541A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
     1542SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
     1543bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
     1544JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
     1545epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
     1546F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
     1547MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
     1548hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
     1549bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
     1550QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
     1551afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
     1552PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
     1553xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
     1554KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
     1555QBFGmh95DmK/D5fs4C8fF5Q=
     1556-----END CERTIFICATE-----
     1557
     1558StartCom Certification Authority
     1559================================
     1560-----BEGIN CERTIFICATE-----
     1561MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
     1562U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
     1563ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
     1564NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
     1565LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
     1566U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
     1567ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
     1568o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
     1569Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
     1570eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
     15712PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
     15726+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
     1573osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
     1574untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
     1575UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
     157637uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
     1577FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0
     1578Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj
     1579YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH
     1580AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw
     1581Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg
     1582U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5
     1583LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl
     1584cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh
     1585cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT
     1586dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC
     1587AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh
     15883TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm
     1589vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk
     1590fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3
     1591fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ
     1592EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
     1593yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl
     15941njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/
     1595lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro
     1596g14=
     1597-----END CERTIFICATE-----
     1598
     1599Taiwan GRCA
     1600===========
     1601-----BEGIN CERTIFICATE-----
     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
     1627-----END CERTIFICATE-----
     1628
     1629Firmaprofesional Root CA
     1630========================
     1631-----BEGIN CERTIFICATE-----
     1632MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMxIjAgBgNVBAcT
     1633GUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1dG9yaWRhZCBkZSBDZXJ0aWZp
     1634Y2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FA
     1635ZmlybWFwcm9mZXNpb25hbC5jb20wHhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTEL
     1636MAkGA1UEBhMCRVMxIjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMT
     1637OUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2
     1638ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20wggEiMA0GCSqGSIb3DQEB
     1639AQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5uCp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5V
     1640j1H5WuretXDE7aTt/6MNbg9kUDGvASdYrv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJH
     1641lShbz++AbOCQl4oBPB3zhxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf
     16423H5idPayBQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcLiam8
     1643NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcbAgMBAAGjgZ8wgZww
     1644KgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lvbmFsLmNvbTASBgNVHRMBAf8ECDAG
     1645AQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1Ud
     1646DwEB/wQEAwIBBjAdBgNVHQ4EFgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQAD
     1647ggEBAEdz/o0nVPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq
     1648u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36mhoEyIwOdyPdf
     1649wUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzflZKG+TQyTmAyX9odtsz/ny4Cm
     16507YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBpQWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YG
     1651VM+h4k0460tQtcsm9MracEpqoeJ5quGnM/b9Sh/22WA=
     1652-----END CERTIFICATE-----
     1653
     1654Wells Fargo Root CA
     1655===================
     1656-----BEGIN CERTIFICATE-----
     1657MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCVVMxFDASBgNV
     1658BAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhv
     1659cml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN
     1660MDAxMDExMTY0MTI4WhcNMjEwMTE0MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dl
     1661bGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEv
     1662MC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG
     1663SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n135zHCLielTWi5MbqNQ1mX
     1664x3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHESxP9cMIlrCL1dQu3U+SlK93OvRw6esP3
     1665E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4OJgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5
     1666OEL8pahbSCOz6+MlsoCultQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4j
     1667sNtlAHCEAQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMBAAGj
     1668YTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcBCzAyMDAGCCsGAQUF
     1669BwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRwb2xpY3kwDQYJKoZIhvcNAQEFBQAD
     1670ggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrv
     1671m+0fazbuSCUlFLZWohDo7qd/0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0R
     1672OhPs7fpvcmR7nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx
     1673x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ33ZwmVxwQ023
     1674tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s=
     1675-----END CERTIFICATE-----
     1676
     1677Swisscom Root CA 1
     1678==================
     1679-----BEGIN CERTIFICATE-----
     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
     1706NY6E0F/6MBr1mmz0DlP5OlvRHA==
     1707-----END CERTIFICATE-----
     1708
     1709DigiCert Assured ID Root CA
     1710===========================
     1711-----BEGIN CERTIFICATE-----
     1712MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
     1713EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
     1714IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
     1715MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
     1716ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
     1717ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
     17189SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
     1719UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
     1720/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
     1721oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
     1722GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
     172366Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
     1724hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
     1725EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
     1726SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
     17278b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
     1728+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
     1729-----END CERTIFICATE-----
     1730
     1731DigiCert Global Root CA
     1732=======================
     1733-----BEGIN CERTIFICATE-----
     1734MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
     1735EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
     1736HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
     1737MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
     1738dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
     1739hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
     1740TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
     1741BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
     17424idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
     17437vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
     1744o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
     17458KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
     1746BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
     1747EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
     1748tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
     1749UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
     1750CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
     1751-----END CERTIFICATE-----
     1752
     1753DigiCert High Assurance EV Root CA
     1754==================================
     1755-----BEGIN CERTIFICATE-----
     1756MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
     1757EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
     1758KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
     1759MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
     1760MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
     1761Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
     1762Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
     1763OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
     1764MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
     1765NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
     1766h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
     1767Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
     1768JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
     1769V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
     1770myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
     1771mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
     1772vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
     1773-----END CERTIFICATE-----
     1774
     1775Certplus Class 2 Primary CA
     1776===========================
     1777-----BEGIN CERTIFICATE-----
     1778MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE
     1779BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN
     1780OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy
     1781dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
     1782ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR
     17835aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ
     1784Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO
     1785YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e
     1786e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME
     1787CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ
     1788YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t
     1789L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD
     1790P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R
     1791TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+
     17927UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW
     1793//1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
     1794l7+ijrRU
     1795-----END CERTIFICATE-----
     1796
     1797DST Root CA X3
     1798==============
     1799-----BEGIN CERTIFICATE-----
     1800MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
     1801ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
     1802DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
     1803cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
     1804ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
     1805rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
     1806UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
     1807xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
     1808utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
     1809AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
     1810MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
     1811dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
     1812GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
     1813RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
     1814fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
     1815-----END CERTIFICATE-----
     1816
     1817DST ACES CA X6
     1818==============
     1819-----BEGIN CERTIFICATE-----
     1820MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG
     1821EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT
     1822MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha
     1823MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE
     1824CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC
     1825AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI
     1826DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa
     1827pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow
     1828GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy
     1829MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud
     1830EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu
     1831Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy
     1832dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU
     1833CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2
     18345FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t
     1835Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq
     1836nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs
     1837vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3
     1838oKfN5XozNmr6mis=
     1839-----END CERTIFICATE-----
     1840
     1841TURKTRUST Certificate Services Provider Root 1
     1842==============================================
     1843-----BEGIN CERTIFICATE-----
     1844MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVTVCBF
     1845bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGDAJUUjEP
     1846MA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0
     1847acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMx
     1848MDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsg
     1849U2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYDVQQHDAZB
     1850TktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBC
     1851aWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOC
     1852AQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GX
     1853yGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8i
     1854Si9BB35JYbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ
     18558y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4
     1856W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRME
     1857BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46
     1858sWrv7/hg0Uw2ZkUd82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxE
     1859q8Sn5RTOPEFhfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy
     1860B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgY
     1861nNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H
     1862-----END CERTIFICATE-----
     1863
     1864TURKTRUST Certificate Services Provider Root 2
     1865==============================================
     1866-----BEGIN CERTIFICATE-----
     1867MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBF
     1868bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP
     1869MA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg
     1870QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcN
     1871MDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVr
     1872dHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEPMA0G
     1873A1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls
     1874acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwggEiMA0G
     1875CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqe
     1876LCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKI
     1877x+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2g
     1878QrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr
     18795A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMB
     1880AAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8G
     1881A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/ntt
     1882Rbj2hWyfIvwqECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4
     1883Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+
     1884hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P
     18859Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5
     1886UrbnBEI=
     1887-----END CERTIFICATE-----
     1888
     1889SwissSign Platinum CA - G2
     1890==========================
     1891-----BEGIN CERTIFICATE-----
     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
     1918-----END CERTIFICATE-----
     1919
     1920SwissSign Gold CA - G2
     1921======================
     1922-----BEGIN CERTIFICATE-----
     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
     1949-----END CERTIFICATE-----
     1950
     1951SwissSign Silver CA - G2
     1952========================
     1953-----BEGIN CERTIFICATE-----
     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
     1980-----END CERTIFICATE-----
     1981
     1982GeoTrust Primary Certification Authority
     1983========================================
     1984-----BEGIN CERTIFICATE-----
     1985MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
     1986EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
     1987ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
     1988CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
     1989cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
     1990CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
     1991b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
     1992nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
     1993RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
     1994tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
     1995AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
     1996hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
     1997Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
     1998NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
     1999Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
     20001riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
     2001-----END CERTIFICATE-----
     2002
     2003thawte Primary Root CA
     2004======================
     2005-----BEGIN CERTIFICATE-----
     2006MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
     2007BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
     2008aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
     2009cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
     2010MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
     2011SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
     2012KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
     2013FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
     2014oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
     20151CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
     2016q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
     2017aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
     2018afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
     2019VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
     2020AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
     2021uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
     2022xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
     2023jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
     2024z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
     2025-----END CERTIFICATE-----
     2026
     2027VeriSign Class 3 Public Primary Certification Authority - G5
     2028============================================================
     2029-----BEGIN CERTIFICATE-----
     2030MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
     2031BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
     2032ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
     2033IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
     2034ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
     2035yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
     2036biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
     2037dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
     2038YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
     2039ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
     2040j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
     2041Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
     2042Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
     2043fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
     2044BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
     2045Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
     2046aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
     2047SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
     2048X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
     2049KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
     2050Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
     2051ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
     2052-----END CERTIFICATE-----
     2053
     2054SecureTrust CA
     2055==============
     2056-----BEGIN CERTIFICATE-----
     2057MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
     2058EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
     2059dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
     2060BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
     2061ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
     2062OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
     2063DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
     2064GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
     206501k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
     2066ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
     2067BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
     2068aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
     2069KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
     2070SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
     2071mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
     2072nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
     20733ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
     2074-----END CERTIFICATE-----
     2075
     2076Secure Global CA
     2077================
     2078-----BEGIN CERTIFICATE-----
     2079MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
     2080EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
     2081bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
     2082MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
     2083Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
     2084YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
     2085bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
     20868NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
     2087HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
     20880XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
     2089EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
     2090oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
     2091MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
     2092OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
     2093CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
     20943CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
     2095f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
     2096-----END CERTIFICATE-----
     2097
     2098COMODO Certification Authority
     2099==============================
     2100-----BEGIN CERTIFICATE-----
     2101MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
     2102BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
     2103A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
     2104dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
     2105MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
     2106T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
     2107MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
     2108+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
     2109xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
     21104EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
     21111KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
     2112rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
     2113BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
     2114b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
     2115AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
     2116OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
     2117RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
     2118IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
     2119+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
     2120-----END CERTIFICATE-----
     2121
     2122Network Solutions Certificate Authority
     2123=======================================
     2124-----BEGIN CERTIFICATE-----
     2125MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
     2126EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
     2127IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
     2128MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
     2129MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
     2130CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
     2131jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
     2132aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
     2133crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
     2134/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
     2135AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
     2136BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
     2137bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
     2138A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
     21394LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
     2140GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
     2141wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
     2142ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
     2143-----END CERTIFICATE-----
     2144
     2145WellsSecure Public Root Certificate Authority
     2146=============================================
     2147-----BEGIN CERTIFICATE-----
     2148MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM
     2149F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw
     2150NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN
     2151MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl
     2152bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD
     2153VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
     2154CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1
     2155iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13
     2156i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8
     2157bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB
     2158K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB
     2159AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu
     2160cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm
     2161lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB
     2162i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww
     2163GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg
     2164Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI
     2165K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0
     2166bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj
     2167qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es
     2168E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ
     2169tylv2G0xffX8oRAHh84vWdw+WNs=
     2170-----END CERTIFICATE-----
     2171
     2172COMODO ECC Certification Authority
     2173==================================
     2174-----BEGIN CERTIFICATE-----
     2175MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
     2176R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
     2177ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
     2178dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
     2179GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
     2180Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
     2181b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
     21824QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
     2183wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
     2184BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
     2185FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
     2186U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
     2187-----END CERTIFICATE-----
     2188
     2189IGC/A
     2190=====
     2191-----BEGIN CERTIFICATE-----
     2192MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAkZSMQ8wDQYD
     2193VQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVE
     2194Q1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZy
     2195MB4XDTAyMTIxMzE0MjkyM1oXDTIwMTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQI
     2196EwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NT
     2197STEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMIIB
     2198IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaIs9z4iPf930Pfeo2aSVz2
     2199TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCW
     2200So7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYy
     2201HF2fYPepraX/z9E0+X1bF8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNd
     2202frGoRpAxVs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGdPDPQ
     2203tQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNVHSAEDjAMMAoGCCqB
     2204egF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAxNjAfBgNVHSMEGDAWgBSjBS8YYFDC
     2205iQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUFAAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RK
     2206q89toB9RlPhJy3Q2FLwV3duJL92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3Q
     2207MZsyK10XZZOYYLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg
     2208Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2aNjSaTFR+FwNI
     2209lQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R0982gaEbeC9xs/FZTEYYKKuF
     22100mBWWg==
     2211-----END CERTIFICATE-----
     2212
     2213Security Communication EV RootCA1
     2214=================================
     2215-----BEGIN CERTIFICATE-----
     2216MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
     2217U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh
     2218dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE
     2219BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl
     2220Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
     2221AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO
     2222/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX
     2223WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z
     2224ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4
     2225bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK
     22269U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
     2227SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm
     2228iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG
     2229Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW
     2230mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW
     2231T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490
     2232-----END CERTIFICATE-----
     2233
     2234OISTE WISeKey Global Root GA CA
     2235===============================
     2236-----BEGIN CERTIFICATE-----
     2237MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
     2238BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
     2239A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
     2240bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
     2241VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
     2242IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
     2243IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
     2244Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
     2245Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
     2246d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
     2247/yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
     2248LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
     2249AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
     2250KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
     2251MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
     2252+vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
     2253hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
     2254okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
     2255-----END CERTIFICATE-----
     2256
     2257S-TRUST Authentication and Encryption Root CA 2005 PN
     2258=====================================================
     2259-----BEGIN CERTIFICATE-----
     2260MIIEezCCA2OgAwIBAgIQNxkY5lNUfBq1uMtZWts1tzANBgkqhkiG9w0BAQUFADCBrjELMAkGA1UE
     2261BhMCREUxIDAeBgNVBAgTF0JhZGVuLVd1ZXJ0dGVtYmVyZyAoQlcpMRIwEAYDVQQHEwlTdHV0dGdh
     2262cnQxKTAnBgNVBAoTIERldXRzY2hlciBTcGFya2Fzc2VuIFZlcmxhZyBHbWJIMT4wPAYDVQQDEzVT
     2263LVRSVVNUIEF1dGhlbnRpY2F0aW9uIGFuZCBFbmNyeXB0aW9uIFJvb3QgQ0EgMjAwNTpQTjAeFw0w
     2264NTA2MjIwMDAwMDBaFw0zMDA2MjEyMzU5NTlaMIGuMQswCQYDVQQGEwJERTEgMB4GA1UECBMXQmFk
     2265ZW4tV3VlcnR0ZW1iZXJnIChCVykxEjAQBgNVBAcTCVN0dXR0Z2FydDEpMCcGA1UEChMgRGV1dHNj
     2266aGVyIFNwYXJrYXNzZW4gVmVybGFnIEdtYkgxPjA8BgNVBAMTNVMtVFJVU1QgQXV0aGVudGljYXRp
     2267b24gYW5kIEVuY3J5cHRpb24gUm9vdCBDQSAyMDA1OlBOMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
     2268MIIBCgKCAQEA2bVKwdMz6tNGs9HiTNL1toPQb9UY6ZOvJ44TzbUlNlA0EmQpoVXhOmCTnijJ4/Ob
     22694QSwI7+Vio5bG0F/WsPoTUzVJBY+h0jUJ67m91MduwwA7z5hca2/OnpYH5Q9XIHV1W/fuJvS9eXL
     2270g3KSwlOyggLrra1fFi2SU3bxibYs9cEv4KdKb6AwajLrmnQDaHgTncovmwsdvs91DSaXm8f1Xgqf
     2271eN+zvOyauu9VjxuapgdjKRdZYgkqeQd3peDRF2npW932kKvimAoA0SVtnteFhy+S8dF2g08LOlk3
     2272KC8zpxdQ1iALCvQm+Z845y2kuJuJja2tyWp9iRe79n+Ag3rm7QIDAQABo4GSMIGPMBIGA1UdEwEB
     2273/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMCkGA1UdEQQiMCCkHjAcMRowGAYDVQQDExFTVFJv
     2274bmxpbmUxLTIwNDgtNTAdBgNVHQ4EFgQUD8oeXHngovMpttKFswtKtWXsa1IwHwYDVR0jBBgwFoAU
     2275D8oeXHngovMpttKFswtKtWXsa1IwDQYJKoZIhvcNAQEFBQADggEBAK8B8O0ZPCjoTVy7pWMciDMD
     2276pwCHpB8gq9Yc4wYfl35UvbfRssnV2oDsF9eK9XvCAPbpEW+EoFolMeKJ+aQAPzFoLtU96G7m1R08
     2277P7K9n3frndOMusDXtk3sU5wPBG7qNWdX4wple5A64U8+wwCSersFiXOMy6ZNwPv2AtawB6MDwidA
     2278nwzkhYItr5pCHdDHjfhA7p0GVxzZotiAFP7hYy0yh9WUUpY6RsZxlj33mA6ykaqP2vROJAA5Veit
     2279F7nTNCtKqUDMFypVZUF0Qn71wK/Ik63yGFs9iQzbRzkk+OBM8h+wPQrKBU6JIRrjKpms/H+h8Q8b
     2280Hz2eBIPdltkdOpQ=
     2281-----END CERTIFICATE-----
     2282
     2283Microsec e-Szigno Root CA
     2284=========================
     2285-----BEGIN CERTIFICATE-----
     2286MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE
     2287BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL
     2288EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0
     2289MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz
     2290dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT
     2291GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
     2292AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG
     2293d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N
     2294oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc
     2295QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ
     2296PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb
     2297MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG
     2298IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD
     2299VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3
     2300LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A
     2301dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn
     2302AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA
     23034QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg
     2304AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA
     2305egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6
     2306Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO
     2307PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv
     2308c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h
     2309cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw
     2310IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT
     2311WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV
     2312MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER
     2313MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp
     2314Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal
     2315HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT
     2316nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE
     2317aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a
     231886g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK
     2319yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB
     2320S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU=
     2321-----END CERTIFICATE-----
     2322
     2323Certigna
     2324========
     2325-----BEGIN CERTIFICATE-----
     2326MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
     2327EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
     2328MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
     2329Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
     2330XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
     2331GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
     2332ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
     2333DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
     2334Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
     2335tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
     2336BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
     2337SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
     2338hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
     2339ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
     2340PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
     23411gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
     2342WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
     2343-----END CERTIFICATE-----
     2344
     2345AC Ra\xC3\xADz Certic\xC3\xA1mara S.A.
     2346======================================
     2347-----BEGIN CERTIFICATE-----
     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
     2377-----END CERTIFICATE-----
     2378
     2379TC TrustCenter Class 2 CA II
     2380============================
     2381-----BEGIN CERTIFICATE-----
     2382MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC
     2383REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy
     2384IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw
     2385MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1
     2386c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE
     2387AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
     2388AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw
     2389IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2
     2390xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ
     2391Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u
     2392SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB
     2393/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB
     23947QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90
     2395Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU
     2396cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i
     2397SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
     2398TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G
     2399dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ
     2400KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj
     2401TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP
     2402JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk
     2403vQ==
     2404-----END CERTIFICATE-----
     2405
     2406TC TrustCenter Class 3 CA II
     2407============================
     2408-----BEGIN CERTIFICATE-----
     2409MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC
     2410REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy
     2411IENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYw
     2412MTEyMTQ0MTU3WhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1
     2413c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UE
     2414AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
     2415AQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJWHt4bNwcwIi9v8Qbxq63W
     2416yKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+QVl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo
     24176SI7dYnWRBpl8huXJh0obazovVkdKyT21oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZ
     2418uV3bOx4a+9P/FRQI2AlqukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk
     24192ZyqBwi1Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1UdEwEB
     2420/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NXXAek0CSnwPIA1DCB
     24217QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90
     2422Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU
     2423cnVzdENlbnRlciUyMENsYXNzJTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i
     2424SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
     2425TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlNirTzwppVMXzE
     2426O2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8TtXqluJucsG7Kv5sbviRmEb8
     2427yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9
     2428IJqDnxrcOfHFcqMRA/07QlIp2+gB95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal
     2429092Y+tTmBvTwtiBjS+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc
     24305A==
     2431-----END CERTIFICATE-----
     2432
     2433TC TrustCenter Universal CA I
     2434=============================
     2435-----BEGIN CERTIFICATE-----
     2436MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC
     2437REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy
     2438IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN
     2439MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg
     2440VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw
     2441JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD
     2442ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC
     2443qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv
     2444xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw
     2445ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O
     2446gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j
     2447BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
     2448AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG
     24491eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy
     2450vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3
     2451ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT
     2452ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a
     24537CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY
     2454-----END CERTIFICATE-----
     2455
     2456Deutsche Telekom Root CA 2
     2457==========================
     2458-----BEGIN CERTIFICATE-----
     2459MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT
     2460RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG
     2461A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5
     2462MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G
     2463A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS
     2464b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5
     2465bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI
     2466KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY
     2467AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK
     2468Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV
     2469jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV
     2470HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr
     2471E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy
     2472zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8
     2473rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G
     2474dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
     2475Cm26OWMohpLzGITY+9HPBVZkVw==
     2476-----END CERTIFICATE-----
     2477
     2478ComSign CA
     2479==========
     2480-----BEGIN CERTIFICATE-----
     2481MIIDkzCCAnugAwIBAgIQFBOWgxRVjOp7Y+X8NId3RDANBgkqhkiG9w0BAQUFADA0MRMwEQYDVQQD
     2482EwpDb21TaWduIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0wNDAzMjQxMTMy
     2483MThaFw0yOTAzMTkxNTAyMThaMDQxEzARBgNVBAMTCkNvbVNpZ24gQ0ExEDAOBgNVBAoTB0NvbVNp
     2484Z24xCzAJBgNVBAYTAklMMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8ORUaSvTx49q
     2485ROR+WCf4C9DklBKK8Rs4OC8fMZwG1Cyn3gsqrhqg455qv588x26i+YtkbDqthVVRVKU4VbirgwTy
     2486P2Q298CNQ0NqZtH3FyrV7zb6MBBC11PN+fozc0yz6YQgitZBJzXkOPqUm7h65HkfM/sb2CEJKHxN
     2487GGleZIp6GZPKfuzzcuc3B1hZKKxC+cX/zT/npfo4sdAMx9lSGlPWgcxCejVb7Us6eva1jsz/D3zk
     2488YDaHL63woSV9/9JLEYhwVKZBqGdTUkJe5DSe5L6j7KpiXd3DTKaCQeQzC6zJMw9kglcq/QytNuEM
     2489rkvF7zuZ2SOzW120V+x0cAwqTwIDAQABo4GgMIGdMAwGA1UdEwQFMAMBAf8wPQYDVR0fBDYwNDAy
     2490oDCgLoYsaHR0cDovL2ZlZGlyLmNvbXNpZ24uY28uaWwvY3JsL0NvbVNpZ25DQS5jcmwwDgYDVR0P
     2491AQH/BAQDAgGGMB8GA1UdIwQYMBaAFEsBmz5WGmU2dst7l6qSBe4y5ygxMB0GA1UdDgQWBBRLAZs+
     2492VhplNnbLe5eqkgXuMucoMTANBgkqhkiG9w0BAQUFAAOCAQEA0Nmlfv4pYEWdfoPPbrxHbvUanlR2
     2493QnG0PFg/LUAlQvaBnPGJEMgOqnhPOAlXsDzACPw1jvFIUY0McXS6hMTXcpuEfDhOZAYnKuGntewI
     2494mbQKDdSFc8gS4TXt8QUxHXOZDOuWyt3T5oWq8Ir7dcHyCTxlZWTzTNity4hp8+SDtwy9F1qWF8pb
     2495/627HOkthIDYIb6FUtnUdLlphbpN7Sgy6/lhSuTENh4Z3G+EER+V9YMoGKgzkkMn3V0TBEVPh9VG
     2496zT2ouvDzuFYkRes3x+F2T3I5GN9+dHLHcy056mDmrRGiVod7w2ia/viMcKjfZTL0pECMocJEAw6U
     2497AGegcQCCSA==
     2498-----END CERTIFICATE-----
     2499
     2500ComSign Secured CA
     2501==================
     2502-----BEGIN CERTIFICATE-----
     2503MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE
     2504AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w
     2505NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD
     2506QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
     2507ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs
     250849ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH
     25097Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB
     2510kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1
     25119guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw
     2512AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t
     2513U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA
     2514j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC
     2515AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a
     2516BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp
     2517FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP
     251851qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz
     2519OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw==
     2520-----END CERTIFICATE-----
     2521
     2522Cybertrust Global Root
     2523======================
     2524-----BEGIN CERTIFICATE-----
     2525MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
     2526ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
     2527MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
     2528ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
     2529+Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
     25300ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
     2531AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
     253289cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
     25338M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
     2534BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
     2535MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
     2536A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
     2537lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
     25385MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
     2539hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
     2540X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
     2541WL1WMRJOEcgh4LMRkWXbtKaIOM5V
     2542-----END CERTIFICATE-----
     2543
     2544ePKI Root Certification Authority
     2545=================================
     2546-----BEGIN CERTIFICATE-----
     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
     2573-----END CERTIFICATE-----
     2574
     2575T\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
     2576=============================================================================================================================
     2577-----BEGIN CERTIFICATE-----
     2578MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH
     2579DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q
     2580aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry
     2581b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV
     2582BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg
     2583S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4
     2584MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl
     2585IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF
     2586n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl
     2587IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft
     2588dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl
     2589cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B
     2590AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO
     2591Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1
     2592xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR
     25936Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL
     2594hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd
     2595BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
     2596MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4
     2597N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT
     2598y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh
     2599LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M
     2600dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI=
     2601-----END CERTIFICATE-----
     2602
     2603Buypass Class 2 CA 1
     2604====================
     2605-----BEGIN CERTIFICATE-----
     2606MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
     2607QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAxMB4XDTA2
     2608MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh
     2609c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZI
     2610hvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7M
     2611cXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLXl18xoS83
     26120r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVBHfCuuCkslFJgNJQ72uA4
     26130Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/R
     2614uFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNC
     2615MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0P
     2616AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV
     26171Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt
     26187h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2
     2619fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w
     2620wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho
     2621-----END CERTIFICATE-----
     2622
     2623Buypass Class 3 CA 1
     2624====================
     2625-----BEGIN CERTIFICATE-----
     2626MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
     2627QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1
     2628MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh
     2629c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI
     2630hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx
     2631ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0
     2632n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia
     2633AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c
     26341jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC
     2635MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P
     2636AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7
     2637pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA
     2638EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5
     2639htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj
     2640el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915
     2641-----END CERTIFICATE-----
     2642
     2643EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1
     2644==========================================================================
     2645-----BEGIN CERTIFICATE-----
     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
     2673-----END CERTIFICATE-----
     2674
     2675certSIGN ROOT CA
     2676================
     2677-----BEGIN CERTIFICATE-----
     2678MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
     2679VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
     2680Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
     2681CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
     2682JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
     2683rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
     2684ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
     26850IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
     2686AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
     2687Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
     2688AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
     2689SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
     2690x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
     2691vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
     2692TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
     2693-----END CERTIFICATE-----
     2694
     2695CNNIC ROOT
     2696==========
     2697-----BEGIN CERTIFICATE-----
     2698MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE
     2699ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw
     2700OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw
     2701ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD
     2702o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz
     2703VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT
     2704VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or
     2705czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK
     2706y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC
     2707wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S
     2708lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5
     2709Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM
     2710O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8
     2711BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2
     2712G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m
     2713mxE=
     2714-----END CERTIFICATE-----
     2715
     2716ApplicationCA - Japanese Government
     2717===================================
     2718-----BEGIN CERTIFICATE-----
     2719MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT
     2720SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw
     2721MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl
     2722cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
     2723CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4
     2724fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN
     2725wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE
     2726jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu
     2727nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU
     2728WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV
     2729BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD
     2730vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs
     2731o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g
     2732/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD
     2733io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW
     2734dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL
     2735rosot4LKGAfmt1t06SAZf7IbiVQ=
     2736-----END CERTIFICATE-----
     2737
     2738GeoTrust Primary Certification Authority - G3
     2739=============================================
     2740-----BEGIN CERTIFICATE-----
     2741MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
     2742BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
     2743IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
     2744eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
     2745NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
     2746YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
     2747LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
     2748hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
     2749K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
     2750c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
     2751IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
     2752dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
     2753MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
     27542zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
     2755cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
     2756Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
     2757AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
     2758t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
     2759-----END CERTIFICATE-----
     2760
     2761thawte Primary Root CA - G2
     2762===========================
     2763-----BEGIN CERTIFICATE-----
     2764MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
     2765VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
     2766IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
     2767Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
     2768MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
     2769b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
     2770IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
     2771LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
     27728/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
     2773mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
     2774G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
     2775rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
     2776-----END CERTIFICATE-----
     2777
     2778thawte Primary Root CA - G3
     2779===========================
     2780-----BEGIN CERTIFICATE-----
     2781MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
     2782BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
     2783aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
     2784cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
     2785ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
     2786d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
     2787VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
     2788A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
     2789MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
     2790P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
     2791+BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
     27927CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
     2793vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
     2794BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
     2795KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
     2796A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
     2797t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
     27988rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
     2799er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
     2800-----END CERTIFICATE-----
     2801
     2802GeoTrust Primary Certification Authority - G2
     2803=============================================
     2804-----BEGIN CERTIFICATE-----
     2805MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
     2806VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
     2807Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
     2808ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
     2809OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
     2810MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
     2811b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
     2812BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
     2813KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
     2814VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
     2815EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
     2816ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
     2817npaqBA+K
     2818-----END CERTIFICATE-----
     2819
     2820VeriSign Universal Root Certification Authority
     2821===============================================
     2822-----BEGIN CERTIFICATE-----
     2823MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
     2824BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
     2825ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
     2826IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
     2827IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
     2828UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
     2829cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
     2830IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
     2831aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
     28321mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
     2833MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
     28349fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
     2835AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
     2836tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
     2837CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
     2838a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
     2839DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
     2840Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
     2841Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
     2842P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
     2843wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
     2844mJO37M2CYfE45k+XmCpajQ==
     2845-----END CERTIFICATE-----
     2846
     2847VeriSign Class 3 Public Primary Certification Authority - G4
     2848============================================================
     2849-----BEGIN CERTIFICATE-----
     2850MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
     2851VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
     2852b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
     2853ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
     2854YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
     2855MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
     2856cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
     2857b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
     2858IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
     2859Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
     2860rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
     2861/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
     2862HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
     2863Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
     2864A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
     2865AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
     2866-----END CERTIFICATE-----
     2867
     2868NetLock Arany (Class Gold) Főtanúsítvány
     2869============================================
     2870-----BEGIN CERTIFICATE-----
     2871MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
     2872A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
     2873dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
     2874cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
     2875MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
     2876ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
     2877biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
     2878c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
     28790jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
     2880/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
     2881H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
     2882fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
     2883neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
     2884BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
     2885qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
     2886YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
     2887bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
     2888NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
     2889dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
     2890-----END CERTIFICATE-----
     2891
     2892Staat der Nederlanden Root CA - G2
     2893==================================
     2894-----BEGIN CERTIFICATE-----
     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
     292166+KAQ==
     2922-----END CERTIFICATE-----
     2923
     2924CA Disig
     2925========
     2926-----BEGIN CERTIFICATE-----
     2927MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK
     2928QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw
     2929MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz
     2930bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3
     2931DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm
     2932GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD
     2933Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo
     2934hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt
     2935ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w
     2936gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P
     2937AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz
     2938aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff
     2939ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa
     2940BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t
     2941WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3
     2942mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/
     2943CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K
     2944ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA
     29454Z7CRneC9VkGjCFMhwnN5ag=
     2946-----END CERTIFICATE-----
     2947
     2948Juur-SK
     2949=======
     2950-----BEGIN CERTIFICATE-----
     2951MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcNAQkBFglwa2lA
     2952c2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMRAw
     2953DgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMwMVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqG
     2954SIb3DQEJARYJcGtpQHNrLmVlMQswCQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVy
     2955aW1pc2tlc2t1czEQMA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
     2956ggEBAIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOBSvZiF3tf
     2957TQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkzABpTpyHhOEvWgxutr2TC
     2958+Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvHLCu3GFH+4Hv2qEivbDtPL+/40UceJlfw
     2959UR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMPPbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDa
     2960Tpxt4brNj3pssAki14sL2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQF
     2961MAMBAf8wggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwICMIHD
     2962HoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDkAGwAagBhAHMAdABh
     2963AHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0AHMAZQBlAHIAaQBtAGkAcwBrAGUA
     2964cwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABzAGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABr
     2965AGkAbgBuAGkAdABhAG0AaQBzAGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nw
     2966cy8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE
     2967FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcYP2/v6X2+MA4G
     2968A1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOiCfP+JmeaUOTDBS8rNXiRTHyo
     2969ERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+gkcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyL
     2970abVAyJRld/JXIWY7zoVAtjNjGr95HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678
     2971IIbsSt4beDI3poHSna9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkh
     2972Mp6qqIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0ZTbvGRNs2
     2973yyqcjg==
     2974-----END CERTIFICATE-----
     2975
     2976Hongkong Post Root CA 1
     2977=======================
     2978-----BEGIN CERTIFICATE-----
     2979MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
     2980DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
     2981NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
     2982IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
     2983AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
     2984ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
     2985auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
     2986qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
     2987V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
     2988HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
     2989h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
     2990l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
     2991IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
     2992T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
     2993c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
     2994-----END CERTIFICATE-----
     2995
     2996SecureSign RootCA11
     2997===================
     2998-----BEGIN CERTIFICATE-----
     2999MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
     3000SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
     3001b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
     3002KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
     3003cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
     3004TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
     3005wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
     3006g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
     3007O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
     3008bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
     3009t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
     3010OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
     3011bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
     3012Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
     3013y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
     3014lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
     3015-----END CERTIFICATE-----
     3016
     3017ACEDICOM Root
     3018=============
     3019-----BEGIN CERTIFICATE-----
     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
     3046-----END CERTIFICATE-----
     3047
     3048Verisign Class 1 Public Primary Certification Authority
     3049=======================================================
     3050-----BEGIN CERTIFICATE-----
     3051MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx
     3052FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmltYXJ5
     3053IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow
     3054XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAx
     3055IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA
     3056A4GNADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0fzGVuDLDQ
     3057VoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHiTkVWaR94AoDa3EeRKbs2
     3058yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFgVKTk8d6Pa
     3059XCUDfGD67gmZPCcQcMgMCeazh88K4hiWNWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n
     30600a3hUKw8fGJLj7qE1xIVGx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZ
     3061RjXZ+Hxb
     3062-----END CERTIFICATE-----
     3063
     3064Verisign Class 3 Public Primary Certification Authority
     3065=======================================================
     3066-----BEGIN CERTIFICATE-----
     3067MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx
     3068FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5
     3069IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow
     3070XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz
     3071IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA
     3072A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94
     3073f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol
     3074hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBABByUqkFFBky
     3075CEHwxWsKzH4PIRnN5GfcX6kb5sroc50i2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWX
     3076bj9T/UWZYB2oK0z5XqcJ2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/
     3077D/xwzoiQ
     3078-----END CERTIFICATE-----
     3079
     3080Microsec e-Szigno Root CA 2009
     3081==============================
     3082-----BEGIN CERTIFICATE-----
     3083MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
     3084MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
     3085c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
     3086dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
     3087BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
     3088U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
     3089DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
     3090fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
     30910IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
     3092pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
     30931HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
     3094AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
     3095QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
     3096FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
     3097lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
     3098I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
     3099tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
     3100yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
     3101LXpUq3DDfSJlgnCW
     3102-----END CERTIFICATE-----
     3103
     3104E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi
     3105===================================================
     3106-----BEGIN CERTIFICATE-----
     3107MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
     3108EwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE8MDoGA1UEAxMz
     3109ZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3
     3110MDEwNDExMzI0OFoXDTE3MDEwNDExMzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0
     3111cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9u
     3112aWsgU2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
     3113AQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdUMZTe1RK6UxYC6lhj71vY
     31148+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlTL/jDj/6z/P2douNffb7tC+Bg62nsM+3Y
     3115jfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAI
     3116JjjcJRFHLfO6IxClv7wC90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk
     31179Ok0oSy1c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/BAQD
     3118AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoEVtstxNulMA0GCSqG
     3119SIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLPqk/CaOv/gKlR6D1id4k9CnU58W5d
     3120F4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwq
     3121D2fK/A+JYZ1lpTzlvBNbCNvj/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4
     3122Vwpm+Vganf2XKWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq
     3123fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX
     3124-----END CERTIFICATE-----
     3125
     3126GlobalSign Root CA - R3
     3127=======================
     3128-----BEGIN CERTIFICATE-----
     3129MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
     3130YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
     3131bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
     3132aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
     3133bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
     3134iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
     31350mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
     3136rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
     3137OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
     3138xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
     3139FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
     3140lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
     3141EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
     3142bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
     3143YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
     3144kpeDMdmztcpHWD9f
     3145-----END CERTIFICATE-----
     3146
     3147TC TrustCenter Universal CA III
     3148===============================
     3149-----BEGIN CERTIFICATE-----
     3150MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezELMAkGA1UEBhMC
     3151REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy
     3152IFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAe
     3153Fw0wOTA5MDkwODE1MjdaFw0yOTEyMzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNU
     3154QyBUcnVzdENlbnRlciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0Ex
     3155KDAmBgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqGSIb3DQEB
     3156AQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF5+cvAqBNLaT6hdqbJYUt
     3157QCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYvDIRlzg9uwliT6CwLOunBjvvya8o84pxO
     3158juT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8vzArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+Eut
     3159CHnNaYlAJ/Uqwa1D7KRTyGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1
     3160M4BDj5yjdipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBhMB8G
     3161A1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
     3162BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI4jANBgkqhkiG9w0BAQUFAAOCAQEA
     3163g8ev6n9NCjw5sWi+e22JLumzCecYV42FmhfzdkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+
     3164KGwWaODIl0YgoGhnYIg5IFHYaAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhK
     3165BgePxLcHsU0GDeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV
     3166CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPHLQNjO9Po5KIq
     3167woIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg==
     3168-----END CERTIFICATE-----
     3169
     3170Autoridad de Certificacion Firmaprofesional CIF A62634068
     3171=========================================================
     3172-----BEGIN CERTIFICATE-----
     3173MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
     3174BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
     3175MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
     3176QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
     3177NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
     3178Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
     3179B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
     31807Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
     3181ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
     3182plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
     3183MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
     3184LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
     3185bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
     3186vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
     3187EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
     3188DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
     3189cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
     3190bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
     3191ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
     319251tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
     3193R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
     3194T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
     3195Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
     3196osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
     3197crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
     3198saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
     3199KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
     32006Et8Vcad+qMUu2WFbm5PEn4KPJ2V
     3201-----END CERTIFICATE-----
     3202
     3203Izenpe.com
     3204==========
     3205-----BEGIN CERTIFICATE-----
     3206MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
     3207EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
     3208MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
     3209QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
     321003rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
     3211ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
     3212+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
     3213PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
     3214OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
     3215F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
     32160GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
     32170rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
     3218leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
     3219AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
     3220SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
     3221NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
     3222MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
     3223BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
     3224Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
     3225kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
     3226hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
     3227g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
     3228aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
     3229nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
     3230ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
     3231Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
     3232WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
     3233-----END CERTIFICATE-----
     3234
     3235Chambers of Commerce Root - 2008
     3236================================
     3237-----BEGIN CERTIFICATE-----
     3238MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
     3239MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
     3240bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
     3241QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
     3242Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
     3243ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
     3244EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
     3245cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
     3246AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
     3247XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
     3248h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
     3249ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
     3250NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
     3251D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
     3252lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
     32530wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
     3254ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
     3255EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
     3256G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
     3257BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
     3258bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
     3259bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
     3260CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
     3261AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
     3262wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
     32633qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
     3264RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
     3265M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
     3266YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
     32679dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
     3268zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
     3269nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
     3270OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
     3271-----END CERTIFICATE-----
     3272
     3273Global Chambersign Root - 2008
     3274==============================
     3275-----BEGIN CERTIFICATE-----
     3276MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
     3277MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
     3278bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
     3279QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
     3280NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
     3281Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
     3282QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
     3283aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
     3284VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
     3285XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
     3286ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
     3287/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
     3288TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
     3289H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
     3290Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
     3291HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
     3292wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
     3293AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
     3294BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
     3295BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
     3296aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
     3297aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
     32981X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
     3299dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
     3300/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
     3301ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
     3302dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
     33039jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
     3304foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
     3305qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
     3306P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
     3307c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
     330809gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
     3309-----END CERTIFICATE-----
     3310
     3311Go Daddy Root Certificate Authority - G2
     3312========================================
     3313-----BEGIN CERTIFICATE-----
     3314MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
     3315B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
     3316MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
     3317MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
     3318b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
     3319A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
     3320hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
     33219oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
     3322+qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
     3323fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
     3324NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
     3325MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
     3326BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
     3327vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
     33285N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
     3329N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
     3330LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
     3331-----END CERTIFICATE-----
     3332
     3333Starfield Root Certificate Authority - G2
     3334=========================================
     3335-----BEGIN CERTIFICATE-----
     3336MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
     3337B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
     3338b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
     3339eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
     3340DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
     3341VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
     3342dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
     3343W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
     3344bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
     3345N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
     3346ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
     3347JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
     3348AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
     3349TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
     33504mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
     3351F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
     3352pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
     3353c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
     3354-----END CERTIFICATE-----
     3355
     3356Starfield Services Root Certificate Authority - G2
     3357==================================================
     3358-----BEGIN CERTIFICATE-----
     3359MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
     3360B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
     3361b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
     3362IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
     3363BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
     3364dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
     3365Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
     3366AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
     3367h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
     3368hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
     3369LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
     3370rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
     3371AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
     3372SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
     3373E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
     3374xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
     3375iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
     3376YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
     3377-----END CERTIFICATE-----
     3378
     3379AffirmTrust Commercial
     3380======================
     3381-----BEGIN CERTIFICATE-----
     3382MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
     3383BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
     3384MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
     3385bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
     3386AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
     3387DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
     3388C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
     3389BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
     3390MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
     3391HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
     3392AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
     3393hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
     3394qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
     33950wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
     3396sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
     3397-----END CERTIFICATE-----
     3398
     3399AffirmTrust Networking
     3400======================
     3401-----BEGIN CERTIFICATE-----
     3402MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
     3403BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
     3404MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
     3405bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
     3406AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
     3407Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
     3408dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
     3409/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
     3410h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
     3411HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
     3412AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
     3413UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
     341412S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
     3415WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
     3416/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
     3417-----END CERTIFICATE-----
     3418
     3419AffirmTrust Premium
     3420===================
     3421-----BEGIN CERTIFICATE-----
     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
     3446-----END CERTIFICATE-----
     3447
     3448AffirmTrust Premium ECC
     3449=======================
     3450-----BEGIN CERTIFICATE-----
     3451MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
     3452BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
     3453MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
     3454cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
     3455IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
     3456N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
     3457BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
     3458BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
     345957hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
     3460eQ==
     3461-----END CERTIFICATE-----
     3462
     3463Certum Trusted Network CA
     3464=========================
     3465-----BEGIN CERTIFICATE-----
     3466MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
     3467ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
     3468biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
     3469MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
     3470ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
     3471MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
     3472AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
     3473l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
     3474J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
     3475fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
     3476cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
     3477Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
     3478DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
     3479jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
     3480mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
     3481Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
     348203YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
     3483-----END CERTIFICATE-----
     3484
     3485Certinomis - Autorité Racine
     3486=============================
     3487-----BEGIN CERTIFICATE-----
     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
     3513vgt2Fl43N+bYdJeimUV5
     3514-----END CERTIFICATE-----
     3515
     3516Root CA Generalitat Valenciana
     3517==============================
     3518-----BEGIN CERTIFICATE-----
     3519MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJFUzEfMB0GA1UE
     3520ChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290
     3521IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcNMDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3
     3522WjBoMQswCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UE
     3523CxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0G
     3524CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+WmmmO3I2
     3525F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKjSgbwJ/BXufjpTjJ3Cj9B
     3526ZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGlu6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQ
     3527D0EbtFpKd71ng+CT516nDOeB0/RSrFOyA8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXte
     3528JajCq+TA81yc477OMUxkHl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMB
     3529AAGjggM7MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBraS5n
     3530dmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIICIwYKKwYBBAG/VQIB
     3531ADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBl
     3532AHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIAYQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIA
     3533YQBsAGkAdABhAHQAIABWAGEAbABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQBy
     3534AGEAYwBpAPMAbgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA
     3535aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMAaQBvAG4AYQBt
     3536AGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQAZQAgAEEAdQB0AG8AcgBpAGQA
     3537YQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBu
     3538AHQAcgBhACAAZQBuACAAbABhACAAZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAA
     3539OgAvAC8AdwB3AHcALgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0
     3540dHA6Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+yeAT8MIGV
     3541BgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQswCQYDVQQGEwJFUzEfMB0G
     3542A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5S
     3543b290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRh
     3544TvW1yEICKrNcda3FbcrnlD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdz
     3545Ckj+IHLtb8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg9J63
     3546NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XFducTZnV+ZfsBn5OH
     3547iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt
     3548+GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM=
     3549-----END CERTIFICATE-----
     3550
     3551A-Trust-nQual-03
     3552================
     3553-----BEGIN CERTIFICATE-----
     3554MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYGA1UE
     3555Cgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy
     3556a2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5R
     3557dWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgw
     3558RgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0
     3559ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMMEEEtVHJ1
     3560c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtPWFuA/OQO8BBC4SA
     3561zewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUjlUC5B3ilJfYKvUWG6Nm9wASOhURh73+n
     3562yfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPE
     3563SU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4
     3564iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3V
     3565cuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdV
     3566eRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40
     3567ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmr
     3568sQd7TZjTXLDR8KdCoLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZd
     3569JXDRZslo+S4RFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS
     3570mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6
     3571ahq97BvIxYSazQ==
     3572-----END CERTIFICATE-----
     3573
     3574TWCA Root Certification Authority
     3575=================================
     3576-----BEGIN CERTIFICATE-----
     3577MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
     3578VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
     3579dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
     3580EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
     3581IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
     3582AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
     3583QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
     3584oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
     35854HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
     3586y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
     3587BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
     35889w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
     3589mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
     3590QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
     3591T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
     3592Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
     3593-----END CERTIFICATE-----
     3594
     3595Security Communication RootCA2
     3596==============================
     3597-----BEGIN CERTIFICATE-----
     3598MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
     3599U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
     3600dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
     3601SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
     3602aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
     3603ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
     3604+T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
     36053n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
     3606spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
     3607EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
     3608QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
     3609CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
     3610u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
     36113fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
     3612tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
     3613mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
     3614-----END CERTIFICATE-----
     3615
     3616EC-ACC
     3617======
     3618-----BEGIN CERTIFICATE-----
     3619MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
     3620BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
     3621ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
     3622VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
     3623CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
     3624BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
     3625MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
     3626SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
     3627Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
     3628cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
     3629MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
     3630w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
     3631ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
     3632HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
     3633E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
     36340JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
     3635BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
     3636VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
     3637Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
     3638dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
     3639lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
     3640Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
     3641l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
     3642E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
     36435EI=
     3644-----END CERTIFICATE-----
     3645
     3646Hellenic Academic and Research Institutions RootCA 2011
     3647=======================================================
     3648-----BEGIN CERTIFICATE-----
     3649MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
     3650O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
     3651aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
     3652IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
     3653AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
     3654IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
     3655IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
     3656AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
     36571Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
     365871HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
     36598yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
     36603N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
     3661MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
     3662MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
     3663b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
     3664XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
     3665TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
     3666/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
     36677yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
     3668-----END CERTIFICATE-----
     3669
     3670Actalis Authentication Root CA
     3671==============================
     3672-----BEGIN CERTIFICATE-----
     3673MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
     3674BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
     3675AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
     3676MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
     3677IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
     3678IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
     3679wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
     3680by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
     3681zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
     3682YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
     3683oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
     3684EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
     3685hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
     3686EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
     3687jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
     3688iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
     3689ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
     3690WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
     3691JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
     3692K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
     3693Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
     36944yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
     36952qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
     3696lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
     3697OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
     3698vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
     3699-----END CERTIFICATE-----
     3700
     3701Trustis FPS Root CA
     3702===================
     3703-----BEGIN CERTIFICATE-----
     3704MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
     3705EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
     3706IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
     3707BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
     3708KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
     3709RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
     3710H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
     3711cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
     3712o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
     3713AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
     3714BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
     3715GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
     3716yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
     37178Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
     3718l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
     3719iB6XzCGcKQENZetX2fNXlrtIzYE=
     3720-----END CERTIFICATE-----
     3721
     3722StartCom Certification Authority
     3723================================
     3724-----BEGIN CERTIFICATE-----
     3725MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
     3726U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
     3727ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
     3728NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
     3729LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
     3730U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
     3731ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
     3732o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
     3733Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
     3734eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
     37352PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
     37366+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
     3737osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
     3738untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
     3739UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
     374037uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
     3741VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ
     3742Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0
     3743dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu
     3744c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv
     3745bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0
     3746aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0
     3747aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t
     3748L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG
     3749cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5
     3750fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm
     3751N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN
     3752Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T
     3753tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX
     3754e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA
     37552MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs
     3756HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
     3757JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib
     3758D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8=
     3759-----END CERTIFICATE-----
     3760
     3761StartCom Certification Authority G2
     3762===================================
     3763-----BEGIN CERTIFICATE-----
     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
     3788obp573PYtlNXLfbQ4ddI
     3789-----END CERTIFICATE-----
     3790
     3791Buypass Class 2 Root CA
     3792=======================
     3793-----BEGIN CERTIFICATE-----
     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
     3818rJgWVqA=
     3819-----END CERTIFICATE-----
     3820
     3821Buypass Class 3 Root CA
     3822=======================
     3823-----BEGIN CERTIFICATE-----
     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
     3848Cp/HuZc=
     3849-----END CERTIFICATE-----
     3850
     3851T-TeleSec GlobalRoot Class 3
     3852============================
     3853-----BEGIN CERTIFICATE-----
     3854MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
     3855IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
     3856cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
     3857MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
     3858dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
     3859ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
     3860DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
     38619tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
     3862NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
     3863iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
     38640eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
     3865MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
     3866AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
     3867fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
     3868ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
     3869P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
     3870e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
     3871-----END CERTIFICATE-----
     3872
     3873EE Certification Centre Root CA
     3874===============================
     3875-----BEGIN CERTIFICATE-----
     3876MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
     3877EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
     3878dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
     3879MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
     3880UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
     3881ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
     3882DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
     3883TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
     3884rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
     388593X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
     3886P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
     3887AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
     3888MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
     3889BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
     3890xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
     3891lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
     3892uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
     38933j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
     3894dcGWxZ0=
     3895-----END CERTIFICATE-----
  • new file source/tools/i18n/txclib/commands.py

    diff --git a/source/tools/i18n/txclib/commands.py b/source/tools/i18n/txclib/commands.py
    new file mode 100644
    index 0000000..d811c3a
    - +  
     1# -*- coding: utf-8 -*-
     2"""
     3In this file we have all the top level commands for the transifex client.
     4Since we're using a way to automatically list them and execute them, when
     5adding code to this file you must take care of the following:
     6 * Added functions must begin with 'cmd_' followed by the actual name of the
     7   command being used in the command line (eg cmd_init)
     8 * The description for each function that we display to the user is read from
     9   the func_doc attribute which reads the doc string. So, when adding
     10   docstring to a new function make sure you add an oneliner which is
     11   descriptive and is meant to be seen by the user.
     12 * When including libraries, it's best if you include modules instead of
     13   functions because that way our function resolution will work faster and the
     14   chances of overlapping are minimal
     15 * All functions should use the OptionParser and should have a usage and
     16   descripition field.
     17"""
     18import os
     19import re, shutil
     20import sys
     21from optparse import OptionParser, OptionGroup
     22import ConfigParser
     23
     24
     25from txclib import utils, project
     26from txclib.utils import parse_json, compile_json, files_in_project
     27from txclib.config import OrderedRawConfigParser
     28from txclib.exceptions import UnInitializedError
     29from txclib.parsers import delete_parser, help_parser, parse_csv_option, \
     30        status_parser, pull_parser, set_parser, push_parser, init_parser
     31from txclib.paths import posix_path
     32from txclib.log import logger
     33
     34
     35def cmd_init(argv, path_to_tx):
     36    "Initialize a new transifex project."
     37    parser = init_parser()
     38    (options, args) = parser.parse_args(argv)
     39    if len(args) > 1:
     40        parser.error("Too many arguments were provided. Aborting...")
     41    if args:
     42        path_to_tx = args[0]
     43    else:
     44        path_to_tx = os.getcwd()
     45
     46    if os.path.isdir(os.path.join(path_to_tx,".tx")):
     47        logger.info("tx: There is already a tx folder!")
     48        reinit = raw_input("Do you want to delete it and reinit the project? [y/N]: ")
     49        while (reinit != 'y' and reinit != 'Y' and reinit != 'N' and reinit != 'n' and reinit != ''):
     50            reinit = raw_input("Do you want to delete it and reinit the project? [y/N]: ")
     51        if not reinit or reinit in ['N', 'n', 'NO', 'no', 'No']:
     52            return
     53        # Clean the old settings
     54        # FIXME: take a backup
     55        else:
     56            rm_dir = os.path.join(path_to_tx, ".tx")
     57            shutil.rmtree(rm_dir)
     58
     59    logger.info("Creating .tx folder...")
     60    os.mkdir(os.path.join(path_to_tx,".tx"))
     61
     62    # Handle the credentials through transifexrc
     63    home = os.path.expanduser("~")
     64    txrc = os.path.join(home, ".transifexrc")
     65    config = OrderedRawConfigParser()
     66
     67    default_transifex = "https://www.transifex.com"
     68    transifex_host = options.host or raw_input("Transifex instance [%s]: " % default_transifex)
     69
     70    if not transifex_host:
     71        transifex_host = default_transifex
     72    if not transifex_host.startswith(('http://', 'https://')):
     73        transifex_host = 'https://' + transifex_host
     74
     75    config_file = os.path.join(path_to_tx, ".tx", "config")
     76    if not os.path.exists(config_file):
     77        # The path to the config file (.tx/config)
     78        logger.info("Creating skeleton...")
     79        config = OrderedRawConfigParser()
     80        config.add_section('main')
     81        config.set('main', 'host', transifex_host)
     82        # Touch the file if it doesn't exist
     83        logger.info("Creating config file...")
     84        fh = open(config_file, 'w')
     85        config.write(fh)
     86        fh.close()
     87
     88    prj = project.Project(path_to_tx)
     89    prj.getset_host_credentials(transifex_host, user=options.user,
     90        password=options.password)
     91    prj.save()
     92    logger.info("Done.")
     93
     94
     95def cmd_set(argv, path_to_tx):
     96    "Add local or remote files under transifex"
     97    parser = set_parser()
     98    (options, args) = parser.parse_args(argv)
     99
     100    # Implement options/args checks
     101    # TODO !!!!!!!
     102    if options.local:
     103        try:
     104            expression = args[0]
     105        except IndexError:
     106            parser.error("Please specify an expression.")
     107        if not options.resource:
     108            parser.error("Please specify a resource")
     109        if not options.source_language:
     110            parser.error("Please specify a source language.")
     111        if not '<lang>' in expression:
     112            parser.error("The expression you have provided is not valid.")
     113        if not utils.valid_slug(options.resource):
     114            parser.error("Invalid resource slug. The format is <project_slug>"\
     115                ".<resource_slug> and the valid characters include [_-\w].")
     116        _auto_local(path_to_tx, options.resource,
     117            source_language=options.source_language,
     118            expression = expression, source_file=options.source_file,
     119            execute=options.execute, regex=False)
     120        if options.execute:
     121            _set_minimum_perc(options.resource, options.minimum_perc, path_to_tx)
     122            _set_mode(options.resource, options.mode, path_to_tx)
     123            _set_type(options.resource, options.i18n_type, path_to_tx)
     124        return
     125
     126    if options.remote:
     127        try:
     128            url = args[0]
     129        except IndexError:
     130            parser.error("Please specify an remote url")
     131        _auto_remote(path_to_tx, url)
     132        _set_minimum_perc(options.resource, options.minimum_perc, path_to_tx)
     133        _set_mode(options.resource, options.mode, path_to_tx)
     134        return
     135
     136    if options.is_source:
     137        resource = options.resource
     138        if not resource:
     139            parser.error("You must specify a resource name with the"
     140                " -r|--resource flag.")
     141
     142        lang = options.language
     143        if not lang:
     144            parser.error("Please specify a source language.")
     145
     146        if len(args) != 1:
     147            parser.error("Please specify a file.")
     148
     149        if not utils.valid_slug(resource):
     150            parser.error("Invalid resource slug. The format is <project_slug>"\
     151                ".<resource_slug> and the valid characters include [_-\w].")
     152
     153        file = args[0]
     154        # Calculate relative path
     155        path_to_file = os.path.relpath(file, path_to_tx)
     156        _set_source_file(path_to_tx, resource, options.language, path_to_file)
     157    elif options.resource or options.language:
     158        resource = options.resource
     159        lang = options.language
     160
     161        if len(args) != 1:
     162            parser.error("Please specify a file")
     163
     164        # Calculate relative path
     165        path_to_file = os.path.relpath(args[0], path_to_tx)
     166
     167        try:
     168            _go_to_dir(path_to_tx)
     169        except UnInitializedError, e:
     170            utils.logger.error(e)
     171            return
     172
     173        if not utils.valid_slug(resource):
     174            parser.error("Invalid resource slug. The format is <project_slug>"\
     175                ".<resource_slug> and the valid characters include [_-\w].")
     176        _set_translation(path_to_tx, resource, lang, path_to_file)
     177
     178    _set_mode(options.resource, options.mode, path_to_tx)
     179    _set_type(options.resource, options.i18n_type, path_to_tx)
     180    _set_minimum_perc(options.resource, options.minimum_perc, path_to_tx)
     181
     182    logger.info("Done.")
     183    return
     184
     185
     186def _auto_local(path_to_tx, resource, source_language, expression, execute=False,
     187                source_file=None, regex=False):
     188    """Auto configure local project."""
     189    # The path everything will be relative to
     190    curpath = os.path.abspath(os.curdir)
     191
     192    # Force expr to be a valid regex expr (escaped) but keep <lang> intact
     193    expr_re = utils.regex_from_filefilter(expression, curpath)
     194    expr_rec = re.compile(expr_re)
     195
     196    if not execute:
     197        logger.info("Only printing the commands which will be run if the "
     198                  "--execute switch is specified.")
     199
     200    # First, let's construct a dictionary of all matching files.
     201    # Note: Only the last matching file of a language will be stored.
     202    translation_files = {}
     203    for f_path in files_in_project(curpath):
     204        match = expr_rec.match(posix_path(f_path))
     205        if match:
     206            lang = match.group(1)
     207            if lang == source_language and not source_file:
     208                source_file = f_path
     209            else:
     210                translation_files[lang] = f_path
     211
     212    if not source_file:
     213        raise Exception("Could not find a source language file. Please run"
     214            " set --source manually and then re-run this command or provide"
     215            " the source file with the -s flag.")
     216    if execute:
     217        logger.info("Updating source for resource %s ( %s -> %s )." % (resource,
     218            source_language, os.path.relpath(source_file, path_to_tx)))
     219        _set_source_file(path_to_tx, resource, source_language,
     220            os.path.relpath(source_file, path_to_tx))
     221    else:
     222        logger.info('\ntx set --source -r %(res)s -l %(lang)s %(file)s\n' % {
     223            'res': resource,
     224            'lang': source_language,
     225            'file': os.path.relpath(source_file, curpath)})
     226
     227    prj = project.Project(path_to_tx)
     228    root_dir = os.path.abspath(path_to_tx)
     229
     230    if execute:
     231        try:
     232            prj.config.get("%s" % resource, "source_file")
     233        except ConfigParser.NoSectionError:
     234            raise Exception("No resource with slug \"%s\" was found.\nRun 'tx set --auto"
     235                "-local -r %s \"expression\"' to do the initial configuration." % resource)
     236
     237    # Now let's handle the translation files.
     238    if execute:
     239        logger.info("Updating file expression for resource %s ( %s )." % (resource,
     240            expression))
     241        # Eval file_filter relative to root dir
     242        file_filter = posix_path(
     243            os.path.relpath(os.path.join(curpath, expression), path_to_tx)
     244        )
     245        prj.config.set("%s" % resource, "file_filter", file_filter)
     246    else:
     247        for (lang, f_path) in sorted(translation_files.items()):
     248            logger.info('tx set -r %(res)s -l %(lang)s %(file)s' % {
     249                'res': resource,
     250                'lang': lang,
     251                'file': os.path.relpath(f_path, curpath)})
     252
     253    if execute:
     254        prj.save()
     255
     256
     257def _auto_remote(path_to_tx, url):
     258    """
     259    Initialize a remote release/project/resource to the current directory.
     260    """
     261    logger.info("Auto configuring local project from remote URL...")
     262
     263    type, vars = utils.parse_tx_url(url)
     264    prj = project.Project(path_to_tx)
     265    username, password = prj.getset_host_credentials(vars['hostname'])
     266
     267    if type == 'project':
     268        logger.info("Getting details for project %s" % vars['project'])
     269        proj_info = utils.get_details('project_details',
     270            username, password,
     271            hostname = vars['hostname'], project = vars['project'])
     272        resources = [ '.'.join([vars['project'], r['slug']]) for r in proj_info['resources'] ]
     273        logger.info("%s resources found. Configuring..." % len(resources))
     274    elif type == 'release':
     275        logger.info("Getting details for release %s" % vars['release'])
     276        rel_info = utils.get_details('release_details',
     277            username, password, hostname = vars['hostname'],
     278            project = vars['project'], release = vars['release'])
     279        resources = []
     280        for r in rel_info['resources']:
     281            if r.has_key('project'):
     282                resources.append('.'.join([r['project']['slug'], r['slug']]))
     283            else:
     284                resources.append('.'.join([vars['project'], r['slug']]))
     285        logger.info("%s resources found. Configuring..." % len(resources))
     286    elif type == 'resource':
     287        logger.info("Getting details for resource %s" % vars['resource'])
     288        resources = [ '.'.join([vars['project'], vars['resource']]) ]
     289    else:
     290        raise("Url '%s' is not recognized." % url)
     291
     292    for resource in resources:
     293        logger.info("Configuring resource %s." % resource)
     294        proj, res = resource.split('.')
     295        res_info = utils.get_details('resource_details',
     296             username, password, hostname = vars['hostname'],
     297             project = proj, resource=res)
     298        try:
     299            source_lang = res_info['source_language_code']
     300            i18n_type = res_info['i18n_type']
     301        except KeyError:
     302            raise Exception("Remote server seems to be running an unsupported version"
     303                " of Transifex. Either update your server software of fallback"
     304                " to a previous version of transifex-client.")
     305        prj.set_remote_resource(
     306            resource=resource,
     307            host = vars['hostname'],
     308            source_lang = source_lang,
     309            i18n_type = i18n_type)
     310
     311    prj.save()
     312
     313
     314def cmd_push(argv, path_to_tx):
     315    "Push local files to remote server"
     316    parser = push_parser()
     317    (options, args) = parser.parse_args(argv)
     318    force_creation = options.force_creation
     319    languages = parse_csv_option(options.languages)
     320    resources = parse_csv_option(options.resources)
     321    skip = options.skip_errors
     322    prj = project.Project(path_to_tx)
     323    if not (options.push_source or options.push_translations):
     324        parser.error("You need to specify at least one of the -s|--source,"
     325            " -t|--translations flags with the push command.")
     326
     327    prj.push(
     328        force=force_creation, resources=resources, languages=languages,
     329        skip=skip, source=options.push_source,
     330        translations=options.push_translations,
     331        no_interactive=options.no_interactive
     332    )
     333    logger.info("Done.")
     334
     335
     336def cmd_pull(argv, path_to_tx):
     337    "Pull files from remote server to local repository"
     338    parser = pull_parser()
     339    (options, args) = parser.parse_args(argv)
     340    if options.fetchall and options.languages:
     341        parser.error("You can't user a language filter along with the"\
     342            " -a|--all option")
     343    languages = parse_csv_option(options.languages)
     344    resources = parse_csv_option(options.resources)
     345    skip = options.skip_errors
     346    minimum_perc = options.minimum_perc or None
     347
     348    try:
     349        _go_to_dir(path_to_tx)
     350    except UnInitializedError, e:
     351        utils.logger.error(e)
     352        return
     353
     354    # instantiate the project.Project
     355    prj = project.Project(path_to_tx)
     356    prj.pull(
     357        languages=languages, resources=resources, overwrite=options.overwrite,
     358        fetchall=options.fetchall, fetchsource=options.fetchsource,
     359        force=options.force, skip=skip, minimum_perc=minimum_perc,
     360        mode=options.mode
     361    )
     362    logger.info("Done.")
     363
     364
     365def _set_source_file(path_to_tx, resource, lang, path_to_file):
     366    """Reusable method to set source file."""
     367    proj, res = resource.split('.')
     368    if not proj or not res:
     369        raise Exception("\"%s.%s\" is not a valid resource identifier. It should"
     370            " be in the following format project_slug.resource_slug." %
     371            (proj, res))
     372    if not lang:
     373        raise Exception("You haven't specified a source language.")
     374
     375    try:
     376        _go_to_dir(path_to_tx)
     377    except UnInitializedError, e:
     378        utils.logger.error(e)
     379        return
     380
     381    if not os.path.exists(path_to_file):
     382        raise Exception("tx: File ( %s ) does not exist." %
     383            os.path.join(path_to_tx, path_to_file))
     384
     385    # instantiate the project.Project
     386    prj = project.Project(path_to_tx)
     387    root_dir = os.path.abspath(path_to_tx)
     388
     389    if root_dir not in os.path.normpath(os.path.abspath(path_to_file)):
     390        raise Exception("File must be under the project root directory.")
     391
     392    logger.info("Setting source file for resource %s.%s ( %s -> %s )." % (
     393        proj, res, lang, path_to_file))
     394
     395    path_to_file = os.path.relpath(path_to_file, root_dir)
     396
     397    prj = project.Project(path_to_tx)
     398
     399    # FIXME: Check also if the path to source file already exists.
     400    try:
     401        try:
     402            prj.config.get("%s.%s" % (proj, res), "source_file")
     403        except ConfigParser.NoSectionError:
     404            prj.config.add_section("%s.%s" % (proj, res))
     405        except ConfigParser.NoOptionError:
     406            pass
     407    finally:
     408        prj.config.set(
     409            "%s.%s" % (proj, res), "source_file", posix_path(path_to_file)
     410        )
     411        prj.config.set("%s.%s" % (proj, res), "source_lang", lang)
     412
     413    prj.save()
     414
     415
     416def _set_translation(path_to_tx, resource, lang, path_to_file):
     417    """Reusable method to set translation file."""
     418
     419    proj, res = resource.split('.')
     420    if not project or not resource:
     421        raise Exception("\"%s\" is not a valid resource identifier. It should"
     422            " be in the following format project_slug.resource_slug." %
     423            resource)
     424
     425    try:
     426        _go_to_dir(path_to_tx)
     427    except UnInitializedError, e:
     428        utils.logger.error(e)
     429        return
     430
     431    # Warn the user if the file doesn't exist
     432    if not os.path.exists(path_to_file):
     433        logger.info("Warning: File '%s' doesn't exist." % path_to_file)
     434
     435    # instantiate the project.Project
     436    prj = project.Project(path_to_tx)
     437    root_dir = os.path.abspath(path_to_tx)
     438
     439    if root_dir not in os.path.normpath(os.path.abspath(path_to_file)):
     440        raise Exception("File must be under the project root directory.")
     441
     442    if lang ==  prj.config.get("%s.%s" % (proj, res), "source_lang"):
     443        raise Exception("tx: You cannot set translation file for the source language."
     444            " Source languages contain the strings which will be translated!")
     445
     446    logger.info("Updating translations for resource %s ( %s -> %s )." % (resource,
     447        lang, path_to_file))
     448    path_to_file = os.path.relpath(path_to_file, root_dir)
     449    prj.config.set(
     450        "%s.%s" % (proj, res), "trans.%s" % lang, posix_path(path_to_file)
     451    )
     452
     453    prj.save()
     454
     455
     456def cmd_status(argv, path_to_tx):
     457    "Print status of current project"
     458    parser = status_parser()
     459    (options, args) = parser.parse_args(argv)
     460    resources = parse_csv_option(options.resources)
     461    prj = project.Project(path_to_tx)
     462    resources = prj.get_chosen_resources(resources)
     463    resources_num = len(resources)
     464    for idx, res in enumerate(resources):
     465        p, r = res.split('.')
     466        logger.info("%s -> %s (%s of %s)" % (p, r, idx + 1, resources_num))
     467        logger.info("Translation Files:")
     468        slang = prj.get_resource_option(res, 'source_lang')
     469        sfile = prj.get_resource_option(res, 'source_file') or "N/A"
     470        lang_map = prj.get_resource_lang_mapping(res)
     471        logger.info(" - %s: %s (%s)" % (utils.color_text(slang, "RED"),
     472            sfile, utils.color_text("source", "YELLOW")))
     473        files = prj.get_resource_files(res)
     474        fkeys = files.keys()
     475        fkeys.sort()
     476        for lang in fkeys:
     477            local_lang = lang
     478            if lang in lang_map.values():
     479                local_lang = lang_map.flip[lang]
     480            logger.info(" - %s: %s" % (utils.color_text(local_lang, "RED"),
     481                files[lang]))
     482        logger.info("")
     483
     484
     485def cmd_help(argv, path_to_tx):
     486    """List all available commands"""
     487    parser = help_parser()
     488    (options, args) = parser.parse_args(argv)
     489    if len(args) > 1:
     490        parser.error("Multiple arguments received. Exiting...")
     491
     492    # Get all commands
     493    fns = utils.discover_commands()
     494
     495    # Print help for specific command
     496    if len(args) == 1:
     497        try:
     498            fns[argv[0]](['--help'], path_to_tx)
     499        except KeyError:
     500            utils.logger.error("Command %s not found" % argv[0])
     501    # or print summary of all commands
     502
     503    # the code below will only be executed if the KeyError exception is thrown
     504    # becuase in all other cases the function called with --help will exit
     505    # instead of return here
     506    keys = fns.keys()
     507    keys.sort()
     508
     509    logger.info("Transifex command line client.\n")
     510    logger.info("Available commands are:")
     511    for key in keys:
     512        logger.info("  %-15s\t%s" % (key, fns[key].func_doc))
     513    logger.info("\nFor more information run %s command --help" % sys.argv[0])
     514
     515
     516def cmd_delete(argv, path_to_tx):
     517    "Delete an accessible resource or translation in a remote server."
     518    parser = delete_parser()
     519    (options, args) = parser.parse_args(argv)
     520    languages = parse_csv_option(options.languages)
     521    resources = parse_csv_option(options.resources)
     522    skip = options.skip_errors
     523    force = options.force_delete
     524    prj = project.Project(path_to_tx)
     525    prj.delete(resources, languages, skip, force)
     526    logger.info("Done.")
     527
     528
     529def _go_to_dir(path):
     530    """Change the current working directory to the directory specified as
     531    argument.
     532
     533    Args:
     534        path: The path to chdor to.
     535    Raises:
     536        UnInitializedError, in case the directory has not been initialized.
     537    """
     538    if path is None:
     539        raise UnInitializedError(
     540            "Directory has not been initialzied. "
     541            "Did you forget to run 'tx init' first?"
     542        )
     543    os.chdir(path)
     544
     545
     546def _set_minimum_perc(resource, value, path_to_tx):
     547    """Set the minimum percentage in the .tx/config file."""
     548    args = (resource, 'minimum_perc', value, path_to_tx, 'set_min_perc')
     549    _set_project_option(*args)
     550
     551
     552def _set_mode(resource, value, path_to_tx):
     553    """Set the mode in the .tx/config file."""
     554    args = (resource, 'mode', value, path_to_tx, 'set_default_mode')
     555    _set_project_option(*args)
     556
     557
     558def _set_type(resource, value, path_to_tx):
     559    """Set the i18n type in the .tx/config file."""
     560    args = (resource, 'type', value, path_to_tx, 'set_i18n_type')
     561    _set_project_option(*args)
     562
     563
     564def _set_project_option(resource, name, value, path_to_tx, func_name):
     565    """Save the option to the project config file."""
     566    if value is None:
     567        return
     568    if not resource:
     569        logger.debug("Setting the %s for all resources." % name)
     570        resources = []
     571    else:
     572        logger.debug("Setting the %s for resource %s." % (name, resource))
     573        resources = [resource, ]
     574    prj = project.Project(path_to_tx)
     575    getattr(prj, func_name)(resources, value)
     576    prj.save()
  • new file source/tools/i18n/txclib/config.py

    diff --git a/source/tools/i18n/txclib/config.py b/source/tools/i18n/txclib/config.py
    new file mode 100644
    index 0000000..a9d055f
    - +  
     1import ConfigParser
     2
     3
     4class OrderedRawConfigParser( ConfigParser.RawConfigParser ):
     5    """
     6    Overload standard Class ConfigParser.RawConfigParser
     7    """
     8    def write(self, fp):
     9        """Write an .ini-format representation of the configuration state."""
     10        if self._defaults:
     11            fp.write("[%s]\n" % DEFAULTSECT)
     12            for key in sorted( self._defaults ):
     13                fp.write( "%s = %s\n" % (key, str( self._defaults[ key ]
     14                    ).replace('\n', '\n\t')) )
     15            fp.write("\n")
     16        for section in self._sections:
     17            fp.write("[%s]\n" % section)
     18            for key in sorted( self._sections[section] ):
     19                if key != "__name__":
     20                    fp.write("%s = %s\n" %
     21                        (key, str( self._sections[section][ key ]
     22                        ).replace('\n', '\n\t')))
     23            fp.write("\n")
     24
     25    optionxform = str
     26
     27
     28_NOTFOUND = object()
     29
     30
     31class Flipdict(dict):
     32    """An injective (one-to-one) python dict.  Ensures that each key maps
     33    to a unique value, and each value maps back to that same key.
     34
     35    Code mostly taken from here:
     36    http://code.activestate.com/recipes/576968-flipdict-python-dict-that-also-maintains-a-one-to-/
     37    """
     38
     39    def __init__(self, *args, **kw):
     40        self._flip = dict.__new__(self.__class__)
     41        setattr(self._flip, "_flip", self)
     42        for key, val in dict(*args, **kw).iteritems():
     43            self[key] = val
     44
     45    @property
     46    def flip(self):
     47        """The inverse mapping."""
     48        return self._flip
     49
     50    def __repr__(self):
     51        return "%s(%r)" % (self.__class__.__name__, dict(self))
     52
     53    __str__ = __repr__
     54
     55    def copy(self):
     56        return self.__class__(self)
     57
     58    @classmethod
     59    def fromkeys(cls, keys, value=None):
     60        return cls(dict.fromkeys(keys, value))
     61
     62    def __setitem__(self, key, val):
     63        k = self._flip.get(val, _NOTFOUND)
     64        if not (k is _NOTFOUND or k==key):
     65            raise KeyError('(key,val) would erase mapping for value %r' % val)
     66
     67        v = self.get(key, _NOTFOUND)
     68        if v is not _NOTFOUND:
     69            dict.__delitem__(self._flip, v)
     70
     71        dict.__setitem__(self,       key, val)
     72        dict.__setitem__(self._flip, val, key)
     73
     74    def setdefault(self, key, default = None):
     75        # Copied from python's UserDict.DictMixin code.
     76        try:
     77            return self[key]
     78        except KeyError:
     79            self[key] = default
     80            return default
     81
     82    def update(self, other = None, **kwargs):
     83        # Copied from python's UserDict.DictMixin code.
     84        # Make progressively weaker assumptions about "other"
     85        if other is None:
     86            pass
     87        elif hasattr(other, 'iteritems'):  # iteritems saves memory and lookups
     88            for k, v in other.iteritems():
     89                self[k] = v
     90        elif hasattr(other, 'keys'):
     91            for k in other.keys():
     92                self[k] = other[k]
     93        else:
     94            for k, v in other:
     95                self[k] = v
     96        if kwargs:
     97            self.update(kwargs)
     98
     99    def __delitem__(self, key):
     100        val = dict.pop(self, key)
     101        dict.__delitem__(self._flip, val)
     102
     103    def pop(self, key, *args):
     104        val = dict.pop(self, key, *args)
     105        dict.__delitem__(self._flip, val)
     106        return val
     107
     108    def popitem(self):
     109        key, val = dict.popitem(self)
     110        dict.__delitem__(self._flip, val)
     111        return key, val
     112
     113    def clear(self):
     114        dict.clear(self)
     115        dict.clear(self._flip)
  • new file source/tools/i18n/txclib/exceptions.py

    diff --git a/source/tools/i18n/txclib/exceptions.py b/source/tools/i18n/txclib/exceptions.py
    new file mode 100644
    index 0000000..8766a01
    - +  
     1# -*- coding: utf-8 -*-
     2
     3"""
     4Exception classes for the tx client.
     5"""
     6
     7
     8class UnInitializedError(Exception):
     9    """The project directory has not been initialized."""
     10
     11
     12class UnknownCommandError(Exception):
     13    """The provided command is not supported."""
  • new file source/tools/i18n/txclib/http_utils.py

    diff --git a/source/tools/i18n/txclib/http_utils.py b/source/tools/i18n/txclib/http_utils.py
    new file mode 100644
    index 0000000..9e1f201
    - +  
     1# -*- coding: utf-8 -*-
     2
     3"""
     4HTTP-related utility functions.
     5"""
     6
     7import gzip
     8try:
     9    import cStringIO as StringIO
     10except ImportError:
     11    import StringIO
     12
     13
     14def _gzip_decode(gzip_data):
     15    """
     16    Unzip gzipped data and return them.
     17
     18    :param gzip_data: Gzipped data.
     19    :returns: The actual data.
     20    """
     21    try:
     22        gzip_data = StringIO.StringIO(gzip_data)
     23        gzip_file = gzip.GzipFile(fileobj=gzip_data)
     24        data = gzip_file.read()
     25        return data
     26    finally:
     27        gzip_data.close()
     28
     29
     30def http_response(response):
     31    """
     32    Return the response of a HTTP request.
     33
     34    If the response has been gzipped, gunzip it first.
     35
     36    :param response: The raw response of a HTTP request.
     37    :returns: A response suitable to be used by clients.
     38    """
     39    metadata = response.info()
     40    data = response.read()
     41    response.close()
     42    if metadata.get('content-encoding') == 'gzip':
     43        return _gzip_decode(data)
     44    else:
     45        return data
  • new file source/tools/i18n/txclib/log.py

    diff --git a/source/tools/i18n/txclib/log.py b/source/tools/i18n/txclib/log.py
    new file mode 100644
    index 0000000..9baf322
    - +  
     1# -*- coding: utf-8 -*-
     2
     3"""
     4Add logging capabilities to tx-client.
     5"""
     6
     7import sys
     8import logging
     9
     10_logger = logging.getLogger('txclib')
     11_logger.setLevel(logging.INFO)
     12
     13_formatter = logging.Formatter('%(message)s')
     14
     15_error_handler = logging.StreamHandler(sys.stderr)
     16_error_handler.setLevel(logging.ERROR)
     17_error_handler.setFormatter(_formatter)
     18_logger.addHandler(_error_handler)
     19
     20_msg_handler = logging.StreamHandler(sys.stdout)
     21_msg_handler.setLevel(logging.DEBUG)
     22_msg_handler.setFormatter(_formatter)
     23_msg_filter = logging.Filter()
     24_msg_filter.filter = lambda r: r.levelno < logging.ERROR
     25_msg_handler.addFilter(_msg_filter)
     26_logger.addHandler(_msg_handler)
     27
     28logger = _logger
     29
     30
     31def set_log_level(level):
     32    """Set the level for the logger.
     33
     34    Args:
     35        level: A string among DEBUG, INFO, WARNING, ERROR, CRITICAL.
     36    """
     37    logger.setLevel(getattr(logging, level))
  • new file source/tools/i18n/txclib/packages/ssl_match_hostname/__init__.py

    diff --git a/source/tools/i18n/txclib/packages/__init__.py b/source/tools/i18n/txclib/packages/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/source/tools/i18n/txclib/packages/ssl_match_hostname/__init__.py b/source/tools/i18n/txclib/packages/ssl_match_hostname/__init__.py
    new file mode 100644
    index 0000000..a3accef
    - +  
     1"""The match_hostname() function from Python 3.2, essential when using SSL."""
     2
     3# See https://bitbucket.org/brandon/backports.ssl_match_hostname
     4
     5import re
     6
     7__version__ = '3.2.3'                             # Transifex-fixed
     8
     9
     10class CertificateError(ValueError):
     11    pass
     12
     13
     14def _dnsname_to_pat(dn, max_wildcards=2):
     15    # See also http://bugs.python.org/issue17980
     16    pats = []
     17    for frag in dn.split(r'.'):
     18        if frag.count('*') > max_wildcards:
     19            raise CertificateError(
     20                "too many wildcards in certificate name: " + repr(dn)
     21            )
     22        if frag == '*':
     23            # When '*' is a fragment by itself, it matches a non-empty dotless
     24            # fragment.
     25            pats.append('[^.]+')
     26        else:
     27            if frag.count('*') > 2:
     28                raise CertificateError('Invalid hostname in the certificate')
     29            # Otherwise, '*' matches any dotless fragment.
     30            frag = re.escape(frag)
     31            pats.append(frag.replace(r'\*', '[^.]*'))
     32    return re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
     33
     34
     35def match_hostname(cert, hostname):
     36    """Verify that *cert* (in decoded format as returned by
     37    SSLSocket.getpeercert()) matches the *hostname*.  RFC 2818 rules
     38    are mostly followed, but IP addresses are not accepted for *hostname*.
     39
     40    CertificateError is raised on failure. On success, the function
     41    returns nothing.
     42    """
     43    if not cert:
     44        raise ValueError("empty or no certificate")
     45    dnsnames = []
     46    san = cert.get('subjectAltName', ())
     47    for key, value in san:
     48        if key == 'DNS':
     49            if _dnsname_to_pat(value).match(hostname):
     50                return
     51            dnsnames.append(value)
     52    if not dnsnames:
     53        # The subject is only checked when there is no dNSName entry
     54        # in subjectAltName
     55        for sub in cert.get('subject', ()):
     56            for key, value in sub:
     57                # XXX according to RFC 2818, the most specific Common Name
     58                # must be used.
     59                if key == 'commonName':
     60                    if _dnsname_to_pat(value).match(hostname):
     61                        return
     62                    dnsnames.append(value)
     63    if len(dnsnames) > 1:
     64        raise CertificateError("hostname %r "
     65            "doesn't match either of %s"
     66            % (hostname, ', '.join(map(repr, dnsnames))))
     67    elif len(dnsnames) == 1:
     68        raise CertificateError("hostname %r "
     69            "doesn't match %r"
     70            % (hostname, dnsnames[0]))
     71    else:
     72        raise CertificateError("no appropriate commonName or "
     73            "subjectAltName fields were found")
  • new file source/tools/i18n/txclib/parsers.py

    diff --git a/source/tools/i18n/txclib/parsers.py b/source/tools/i18n/txclib/parsers.py
    new file mode 100644
    index 0000000..fd3237d
    - +  
     1# -*- coding: utf-8 -*-
     2
     3from optparse import OptionParser, OptionGroup
     4
     5
     6class EpilogParser(OptionParser):
     7    def format_epilog(self, formatter):
     8        return self.epilog
     9
     10
     11def delete_parser():
     12    """Return the command-line parser for the delete command."""
     13    usage = "usage: %prog [tx_options] delete OPTION [OPTIONS]"
     14    description = (
     15        "This command deletes translations for a resource in the remote server."
     16    )
     17    epilog = (
     18        "\nExamples:\n"
     19        " To delete a translation:\n  "
     20        "$ tx delete -r project.resource -l <lang_code>\n\n"
     21        " To delete a resource:\n  $ tx delete -r project.resource\n"
     22    )
     23    parser = EpilogParser(usage=usage, description=description, epilog=epilog)
     24    parser.add_option(
     25        "-r", "--resource", action="store", dest="resources", default=None,
     26        help="Specify the resource you want to delete (defaults to all)"
     27    )
     28    parser.add_option(
     29        "-l","--language", action="store", dest="languages",
     30        default=None, help="Specify the translation you want to delete"
     31    )
     32    parser.add_option(
     33        "--skip", action="store_true", dest="skip_errors", default=False,
     34        help="Don't stop on errors."
     35    )
     36    parser.add_option(
     37        "-f","--force", action="store_true", dest="force_delete",
     38        default=False, help="Delete an entity forcefully."
     39    )
     40    return parser
     41
     42
     43def help_parser():
     44    """Return the command-line parser for the help command."""
     45    usage="usage: %prog help command"
     46    description="Lists all available commands in the transifex command"\
     47        " client. If a command is specified, the help page of the specific"\
     48        " command is displayed instead."
     49
     50    parser = OptionParser(usage=usage, description=description)
     51    return parser
     52
     53
     54def init_parser():
     55    """Return the command-line parser for the init command."""
     56    usage="usage: %prog [tx_options] init <path>"
     57    description="This command initializes a new project for use with"\
     58        " transifex. It is recommended to execute this command in the"\
     59        " top level directory of your project so that you can include"\
     60        " all files under it in transifex. If no path is provided, the"\
     61        " current working dir will be used."
     62    parser = OptionParser(usage=usage, description=description)
     63    parser.add_option("--host", action="store", dest="host",
     64        default=None, help="Specify a default Transifex host.")
     65    parser.add_option("--user", action="store", dest="user",
     66        default=None, help="Specify username for Transifex server.")
     67    parser.add_option("--pass", action="store", dest="password",
     68        default=None, help="Specify password for Transifex server.")
     69    return parser
     70
     71
     72def pull_parser():
     73    """Return the command-line parser for the pull command."""
     74    usage="usage: %prog [tx_options] pull [options]"
     75    description="This command pulls all outstanding changes from the remote"\
     76        " Transifex server to the local repository. By default, only the"\
     77        " files that are watched by Transifex will be updated but if you"\
     78        " want to fetch the translations for new languages as well, use the"\
     79        " -a|--all option. (Note: new translations are saved in the .tx folder"\
     80        " and require the user to manually rename them and add then in "\
     81        " transifex using the set_translation command)."
     82    parser = OptionParser(usage=usage,description=description)
     83    parser.add_option("-l","--language", action="store", dest="languages",
     84        default=[], help="Specify which translations you want to pull"
     85        " (defaults to all)")
     86    parser.add_option("-r","--resource", action="store", dest="resources",
     87        default=[], help="Specify the resource for which you want to pull"
     88        " the translations (defaults to all)")
     89    parser.add_option("-a","--all", action="store_true", dest="fetchall",
     90        default=False, help="Fetch all translation files from server (even new"
     91        " ones)")
     92    parser.add_option("-s","--source", action="store_true", dest="fetchsource",
     93        default=False, help="Force the fetching of the source file (default:"
     94        " False)")
     95    parser.add_option("-f","--force", action="store_true", dest="force",
     96        default=False, help="Force download of translations files.")
     97    parser.add_option("--skip", action="store_true", dest="skip_errors",
     98        default=False, help="Don't stop on errors. Useful when pushing many"
     99        " files concurrently.")
     100    parser.add_option("--disable-overwrite", action="store_false",
     101        dest="overwrite", default=True,
     102        help="By default transifex will fetch new translations files and"\
     103            " replace existing ones. Use this flag if you want to disable"\
     104            " this feature")
     105    parser.add_option("--minimum-perc", action="store", type="int",
     106        dest="minimum_perc", default=0,
     107        help="Specify the minimum acceptable percentage of a translation "
     108             "in order to download it.")
     109    parser.add_option(
     110        "--mode", action="store", dest="mode", help=(
     111            "Specify the mode of the translation file to pull (e.g. "
     112            "'reviewed'). See http://bit.ly/txcmod1 for available values."
     113        )
     114    )
     115    return parser
     116
     117
     118def push_parser():
     119    """Return the command-line parser for the push command."""
     120    usage="usage: %prog [tx_options] push [options]"
     121    description="This command pushes all local files that have been added to"\
     122        " Transifex to the remote server. All new translations are merged"\
     123        " with existing ones and if a language doesn't exists then it gets"\
     124        " created. If you want to push the source file as well (either"\
     125        " because this is your first time running the client or because"\
     126        " you just have updated with new entries), use the -f|--force option."\
     127        " By default, this command will push all files which are watched by"\
     128        " Transifex but you can filter this per resource or/and language."
     129    parser = OptionParser(usage=usage, description=description)
     130    parser.add_option("-l","--language", action="store", dest="languages",
     131        default=None, help="Specify which translations you want to push"
     132        " (defaults to all)")
     133    parser.add_option("-r","--resource", action="store", dest="resources",
     134        default=None, help="Specify the resource for which you want to push"
     135        " the translations (defaults to all)")
     136    parser.add_option("-f","--force", action="store_true", dest="force_creation",
     137        default=False, help="Push source files without checking modification"
     138        " times.")
     139    parser.add_option("--skip", action="store_true", dest="skip_errors",
     140        default=False, help="Don't stop on errors. Useful when pushing many"
     141        " files concurrently.")
     142    parser.add_option("-s", "--source", action="store_true", dest="push_source",
     143        default=False, help="Push the source file to the server.")
     144
     145    parser.add_option("-t", "--translations", action="store_true", dest="push_translations",
     146        default=False, help="Push the translation files to the server")
     147    parser.add_option("--no-interactive", action="store_true", dest="no_interactive",
     148        default=False, help="Don't require user input when forcing a push.")
     149    return parser
     150
     151
     152def set_parser():
     153    """Return the command-line parser for the set command."""
     154    usage="usage: %prog [tx_options] set [options] [args]"
     155    description="This command can be used to create a mapping between files"\
     156        " and projects either using local files or using files from a remote"\
     157        " Transifex server."
     158    epilog="\nExamples:\n"\
     159        " To set the source file:\n  $ tx set -r project.resource --source -l en <file>\n\n"\
     160        " To set a single translation file:\n  $ tx set -r project.resource -l de <file>\n\n"\
     161        " To automatically detect and assign the source files and translations:\n"\
     162        "  $ tx set --auto-local -r project.resource 'expr' --source-lang en\n\n"\
     163        " To set a specific file as a source and auto detect translations:\n"\
     164        "  $ tx set --auto-local -r project.resource 'expr' --source-lang en"\
     165        " --source-file <file>\n\n"\
     166        " To set a remote release/resource/project:\n"\
     167        "  $ tx set --auto-remote <transifex-url>\n"
     168    parser = EpilogParser(usage=usage, description=description, epilog=epilog)
     169    parser.add_option("--auto-local", action="store_true", dest="local",
     170        default=False, help="Used when auto configuring local project.")
     171    parser.add_option("--auto-remote", action="store_true", dest="remote",
     172        default=False, help="Used when adding remote files from Transifex"
     173        " server.")
     174    parser.add_option("-r","--resource", action="store", dest="resource",
     175        default=None, help="Specify the slug of the resource that you're"
     176            " setting up (This must be in the following format:"
     177            " `project_slug.resource_slug`).")
     178    parser.add_option(
     179        "--source", action="store_true", dest="is_source", default=False,
     180        help=(
     181            "Specify that the given file is a source file "
     182            "[doesn't work with the --auto-* commands]."
     183        )
     184    )
     185    parser.add_option("-l","--language", action="store", dest="language",
     186        default=None, help="Specify which translations you want to pull"
     187        " [doesn't work with the --auto-* commands].")
     188    parser.add_option("-t", "--type", action="store", dest="i18n_type",
     189        help=(
     190            "Specify the i18n type of the resource(s). This is only needed, if "
     191            "the resource(s) does not exist yet in Transifex. For a list of "
     192            "available i18n types, see "
     193            "http://help.transifex.com/features/formats.html"
     194        )
     195    )
     196    parser.add_option("--minimum-perc", action="store", dest="minimum_perc",
     197        help=(
     198            "Specify the minimum acceptable percentage of a translation "
     199            "in order to download it."
     200        )
     201    )
     202    parser.add_option(
     203        "--mode", action="store", dest="mode", help=(
     204            "Specify the mode of the translation file to pull (e.g. "
     205            "'reviewed'). See http://help.transifex.com/features/client/"
     206            "index.html#defining-the-mode-of-the-translated-file for the"
     207            "available values."
     208        )
     209    )
     210    group = OptionGroup(parser, "Extended options", "These options can only be"
     211        " used with the --auto-local command.")
     212    group.add_option("-s","--source-language", action="store",
     213        dest="source_language",
     214        default=None, help="Specify the source language of a resource"
     215        " [requires --auto-local].")
     216    group.add_option("-f","--source-file", action="store", dest="source_file",
     217        default=None, help="Specify the source file of a resource [requires"
     218        " --auto-local].")
     219    group.add_option("--execute", action="store_true", dest="execute",
     220        default=False, help="Execute commands [requires --auto-local].")
     221    parser.add_option_group(group)
     222    return parser
     223
     224
     225def status_parser():
     226    """Return the command-line parser for the status command."""
     227    usage="usage: %prog [tx_options] status [options]"
     228    description="Prints the status of the current project by reading the"\
     229        " data in the configuration file."
     230    parser = OptionParser(usage=usage,description=description)
     231    parser.add_option("-r","--resource", action="store", dest="resources",
     232        default=[], help="Specify resources")
     233    return parser
     234
     235
     236def parse_csv_option(option):
     237    """Return a list out of the comma-separated option or an empty list."""
     238    if option:
     239        return option.split(',')
     240    else:
     241        return []
  • new file source/tools/i18n/txclib/paths.py

    diff --git a/source/tools/i18n/txclib/paths.py b/source/tools/i18n/txclib/paths.py
    new file mode 100644
    index 0000000..6cea2de
    - +  
     1# -*- coding: utf-8 -*-
     2
     3"""
     4Path handling.
     5
     6We need to take into account the differences between UNIX systems and
     7Windows.
     8"""
     9
     10import os
     11
     12
     13posix_sep = os.sep if os.altsep is None else os.altsep
     14
     15
     16def posix_path(fpath):
     17    """Convert a filesystem path to a posix path.
     18
     19    Always use the forward slash as a separator. For instance,
     20    in windows the separator is the backslash.
     21
     22    Args:
     23        fpath: The path to convert.
     24    """
     25    return fpath if os.altsep is None else fpath.replace(os.sep, os.altsep)
     26
     27
     28def native_path(fpath):
     29    """Convert a filesystem path to a native path.
     30
     31    Use whatever separator is defined by the platform.
     32
     33    Args:
     34        fpath: The path to convert.
     35    """
     36    return fpath if os.altsep is None else fpath.replace(os.altsep, os.sep)
  • new file source/tools/i18n/txclib/processors.py

    diff --git a/source/tools/i18n/txclib/processors.py b/source/tools/i18n/txclib/processors.py
    new file mode 100644
    index 0000000..dc3a73f
    - +  
     1# -*- coding: utf-8 -*-
     2
     3"""
     4Module for API-related calls.
     5"""
     6
     7import urlparse
     8
     9
     10def hostname_tld_migration(hostname):
     11    """
     12    Migrate transifex.net to transifex.com.
     13
     14    :param hostname: The hostname to migrate (if needed).
     15    :returns: A hostname with the transifex.com domain (if needed).
     16    """
     17    parts = urlparse.urlparse(hostname)
     18    if parts.hostname.endswith('transifex.net'):
     19        hostname = hostname.replace('transifex.net', 'transifex.com', 1)
     20    return hostname
     21
     22
     23def hostname_ssl_migration(hostname):
     24    """
     25    Migrate Transifex hostnames to use HTTPS.
     26
     27    :param hostname: The hostname to migrate (if needed).
     28    :returns: A https hostname (if needed).
     29    """
     30    parts = urlparse.urlparse(hostname)
     31    is_transifex = (
     32        parts.hostname[-14:-3] == '.transifex.' or
     33        parts.hostname == 'transifex.net' or
     34        parts.hostname == 'transifex.com'
     35    )
     36    is_https = parts.scheme == 'https'
     37    if is_transifex and not is_https:
     38        if not parts.scheme:
     39            hostname = 'https:' + hostname
     40        else:
     41            hostname = hostname.replace(parts.scheme, 'https', 1)
     42    return hostname
     43
     44
     45def visit_hostname(hostname):
     46    """
     47    Have a chance to visit a hostname before actually using it.
     48
     49    :param hostname: The original hostname.
     50    :returns: The hostname with the necessary changes.
     51    """
     52    for processor in [hostname_ssl_migration, hostname_tld_migration, ]:
     53        hostname = processor(hostname)
     54    return hostname
  • new file source/tools/i18n/txclib/project.py

    diff --git a/source/tools/i18n/txclib/project.py b/source/tools/i18n/txclib/project.py
    new file mode 100644
    index 0000000..33dbae3
    - +  
     1
     2# -*- coding: utf-8 -*-
     3
     4import base64
     5import getpass
     6import os
     7import re
     8import fnmatch
     9import urllib2
     10import datetime
     11import time
     12import ConfigParser
     13from txclib.web import *
     14from txclib.utils import *
     15from txclib.urls import API_URLS
     16from txclib.config import OrderedRawConfigParser, Flipdict
     17from txclib.log import logger
     18from txclib.http_utils import http_response
     19from txclib.processors import visit_hostname
     20from txclib.paths import posix_path, native_path, posix_sep
     21
     22
     23class ProjectNotInit(Exception):
     24    pass
     25
     26
     27class Project(object):
     28    """
     29    Represents an association between the local and remote project instances.
     30    """
     31
     32    def __init__(self, path_to_tx=None, init=True):
     33        """
     34        Initialize the Project attributes.
     35        """
     36        if init:
     37            self._init(path_to_tx)
     38
     39    def _init(self, path_to_tx=None):
     40        instructions = "Run 'tx init' to initialize your project first!"
     41        try:
     42            self.root = self._get_tx_dir_path(path_to_tx)
     43            self.config_file = self._get_config_file_path(self.root)
     44            self.config = self._read_config_file(self.config_file)
     45            self.txrc_file = self._get_transifex_file()
     46            local_txrc_file = self._get_transifex_file(os.getcwd())
     47            self.txrc = self._get_transifex_config([self.txrc_file, local_txrc_file])
     48            if os.path.exists(local_txrc_file):
     49                self.txrc_file = local_txrc_file
     50        except ProjectNotInit, e:
     51            logger.error('\n'.join([unicode(e), instructions]))
     52            raise
     53
     54    def _get_config_file_path(self, root_path):
     55        """Check the .tx/config file exists."""
     56        config_file = os.path.join(root_path, ".tx", "config")
     57        logger.debug("Config file is %s" % config_file)
     58        if not os.path.exists(config_file):
     59            msg = "Cannot find the config file (.tx/config)!"
     60            raise ProjectNotInit(msg)
     61        return config_file
     62
     63    def _get_tx_dir_path(self, path_to_tx):
     64        """Check the .tx directory exists."""
     65        root_path = path_to_tx or find_dot_tx()
     66        logger.debug("Path to tx is %s." % root_path)
     67        if not root_path:
     68            msg = "Cannot find any .tx directory!"
     69            raise ProjectNotInit(msg)
     70        return root_path
     71
     72    def _read_config_file(self, config_file):
     73        """Parse the config file and return its contents."""
     74        config = OrderedRawConfigParser()
     75        try:
     76            config.read(config_file)
     77        except Exception, err:
     78            msg = "Cannot open/parse .tx/config file: %s" % err
     79            raise ProjectNotInit(msg)
     80        return config
     81
     82    def _get_transifex_config(self, txrc_files):
     83        """Read the configuration from the .transifexrc files."""
     84        txrc = OrderedRawConfigParser()
     85        try:
     86            txrc.read(txrc_files)
     87        except Exception, e:
     88            msg = "Cannot read configuration file: %s" % e
     89            raise ProjectNotInit(msg)
     90        self._migrate_txrc_file(txrc)
     91        return txrc
     92
     93    def _migrate_txrc_file(self, txrc):
     94        """Migrate the txrc file, if needed."""
     95        if not os.path.exists(self.txrc_file):
     96            return txrc
     97        for section in txrc.sections():
     98            orig_hostname = txrc.get(section, 'hostname')
     99            hostname = visit_hostname(orig_hostname)
     100            if hostname != orig_hostname:
     101                msg = "Hostname %s should be changed to %s."
     102                logger.info(msg % (orig_hostname, hostname))
     103                if (sys.stdin.isatty() and sys.stdout.isatty() and
     104                    confirm('Change it now? ', default=True)):
     105                    txrc.set(section, 'hostname', hostname)
     106                    msg = 'Hostname changed'
     107                    logger.info(msg)
     108                else:
     109                    hostname = orig_hostname
     110            self._save_txrc_file(txrc)
     111        return txrc
     112
     113    def _get_transifex_file(self, directory=None):
     114        """Fetch the path of the .transifexrc file.
     115
     116        It is in the home directory of the user by default.
     117        """
     118        if directory is not None:
     119            logger.debug(".transifexrc file is at %s" % directory)
     120            return os.path.join(directory, ".transifexrc")
     121
     122        directory = os.path.expanduser('~')
     123        txrc_file = os.path.join(directory, ".transifexrc")
     124        logger.debug(".transifexrc file is at %s" % directory)
     125        if not os.path.exists(txrc_file):
     126            msg = "%s not found." % (txrc_file)
     127            logger.info(msg)
     128            mask = os.umask(077)
     129            open(txrc_file, 'w').close()
     130            os.umask(mask)
     131        return txrc_file
     132
     133    def validate_config(self):
     134        """
     135        To ensure the json structure is correctly formed.
     136        """
     137        pass
     138
     139    def getset_host_credentials(self, host, user=None, password=None):
     140        """
     141        Read .transifexrc and report user,pass for a specific host else ask the
     142        user for input.
     143        """
     144        try:
     145            username = self.txrc.get(host, 'username')
     146            passwd = self.txrc.get(host, 'password')
     147        except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
     148            logger.info("No entry found for host %s. Creating..." % host)
     149            username = user or raw_input("Please enter your transifex username: ")
     150            while (not username):
     151                username = raw_input("Please enter your transifex username: ")
     152            passwd = password
     153            while (not passwd):
     154                passwd = getpass.getpass()
     155
     156            logger.info("Updating %s file..." % self.txrc_file)
     157            self.txrc.add_section(host)
     158            self.txrc.set(host, 'username', username)
     159            self.txrc.set(host, 'password', passwd)
     160            self.txrc.set(host, 'token', '')
     161            self.txrc.set(host, 'hostname', host)
     162
     163        return username, passwd
     164
     165    def set_remote_resource(self, resource, source_lang, i18n_type, host,
     166            file_filter="translations<sep>%(proj)s.%(res)s<sep><lang>.%(extension)s"):
     167        """Method to handle the add/conf of a remote resource."""
     168        if not self.config.has_section(resource):
     169            self.config.add_section(resource)
     170
     171        p_slug, r_slug = resource.split('.')
     172        file_filter = file_filter.replace("<sep>", r"%s" % posix_sep)
     173        self.url_info = {
     174            'host': host,
     175            'project': p_slug,
     176            'resource': r_slug
     177        }
     178        extension = self._extension_for(i18n_type)[1:]
     179
     180        self.config.set(resource, 'source_lang', source_lang)
     181        self.config.set(
     182            resource, 'file_filter',
     183            file_filter % {'proj': p_slug, 'res': r_slug, 'extension': extension}
     184        )
     185        self.config.set(resource, 'type', i18n_type)
     186        if host != self.config.get('main', 'host'):
     187            self.config.set(resource, 'host', host)
     188
     189    def get_resource_host(self, resource):
     190        """
     191        Returns the host that the resource is configured to use. If there is no
     192        such option we return the default one
     193        """
     194        if self.config.has_option(resource, 'host'):
     195            return self.config.get(resource, 'host')
     196        return self.config.get('main', 'host')
     197
     198    def get_resource_lang_mapping(self, resource):
     199        """Get language mappings for a specific resource."""
     200        lang_map = Flipdict()
     201        try:
     202            args = self.config.get("main", "lang_map")
     203            for arg in args.replace(' ', '').split(','):
     204                k,v = arg.split(":")
     205                lang_map.update({k:v})
     206        except ConfigParser.NoOptionError:
     207            pass
     208        except (ValueError, KeyError):
     209            raise Exception("Your lang map configuration is not correct.")
     210
     211        if self.config.has_section(resource):
     212            res_lang_map = Flipdict()
     213            try:
     214                args = self.config.get(resource, "lang_map")
     215                for arg in args.replace(' ', '').split(','):
     216                    k,v = arg.split(":")
     217                    res_lang_map.update({k:v})
     218            except ConfigParser.NoOptionError:
     219                pass
     220            except (ValueError, KeyError):
     221                raise Exception("Your lang map configuration is not correct.")
     222
     223        # merge the lang maps and return result
     224        lang_map.update(res_lang_map)
     225
     226        return lang_map
     227
     228    def get_source_file(self, resource):
     229        """
     230        Get source file for a resource.
     231        """
     232        if self.config.has_section(resource):
     233            source_lang = self.config.get(resource, "source_lang")
     234            source_file = self.get_resource_option(resource, 'source_file') or None
     235
     236            if source_file is None:
     237                try:
     238                    file_filter = self.config.get(resource, "file_filter")
     239                    filename = file_filter.replace('<lang>', source_lang)
     240                    if os.path.exists(filename):
     241                        return native_path(filename)
     242                except ConfigParser.NoOptionError:
     243                    pass
     244            else:
     245                return native_path(source_file)
     246
     247    def get_resource_files(self, resource):
     248        """
     249        Get a dict for all files assigned to a resource. First we calculate the
     250        files matching the file expression and then we apply all translation
     251        excpetions. The resulting dict will be in this format:
     252
     253        { 'en': 'path/foo/en/bar.po', 'de': 'path/foo/de/bar.po', 'es': 'path/exceptions/es.po'}
     254
     255        NOTE: All paths are relative to the root of the project
     256        """
     257        tr_files = {}
     258        if self.config.has_section(resource):
     259            try:
     260                file_filter = self.config.get(resource, "file_filter")
     261            except ConfigParser.NoOptionError:
     262                file_filter = "$^"
     263            source_lang = self.config.get(resource, "source_lang")
     264            source_file = self.get_source_file(resource)
     265            expr_re = regex_from_filefilter(file_filter, self.root)
     266            expr_rec = re.compile(expr_re)
     267            for f_path in files_in_project(self.root):
     268                match = expr_rec.match(posix_path(f_path))
     269                if match:
     270                    lang = match.group(1)
     271                    if lang != source_lang:
     272                        f_path = os.path.relpath(f_path, self.root)
     273                        if f_path != source_file:
     274                            tr_files.update({lang: f_path})
     275
     276            for (name, value) in self.config.items(resource):
     277                if name.startswith("trans."):
     278                    value = native_path(value)
     279                    lang = name.split('.')[1]
     280                    # delete language which has same file
     281                    if value in tr_files.values():
     282                        keys = []
     283                        for k, v in tr_files.iteritems():
     284                            if v == value:
     285                                keys.append(k)
     286                        if len(keys) == 1:
     287                            del tr_files[keys[0]]
     288                        else:
     289                            raise Exception("Your configuration seems wrong."\
     290                                " You have multiple languages pointing to"\
     291                                " the same file.")
     292                    # Add language with correct file
     293                    tr_files.update({lang:value})
     294
     295            return tr_files
     296
     297        return None
     298
     299    def get_resource_option(self, resource, option):
     300        """
     301        Return the requested option for a specific resource
     302
     303        If there is no such option, we return None
     304        """
     305
     306        if self.config.has_section(resource):
     307            if self.config.has_option(resource, option):
     308                return self.config.get(resource, option)
     309        return None
     310
     311    def get_resource_list(self, project=None):
     312        """
     313        Parse config file and return tuples with the following format
     314
     315        [ (project_slug, resource_slug), (..., ...)]
     316        """
     317
     318        resource_list= []
     319        for r in self.config.sections():
     320            if r == 'main':
     321                continue
     322            p_slug, r_slug = r.split('.', 1)
     323            if project and p_slug != project:
     324                continue
     325            resource_list.append(r)
     326
     327        return resource_list
     328
     329    def save(self):
     330        """
     331        Store the config dictionary in the .tx/config file of the project.
     332        """
     333        self._save_tx_config()
     334        self._save_txrc_file()
     335
     336    def _save_tx_config(self, config=None):
     337        """Save the local config file."""
     338        if config is None:
     339            config = self.config
     340        fh = open(self.config_file,"w")
     341        config.write(fh)
     342        fh.close()
     343
     344    def _save_txrc_file(self, txrc=None):
     345        """Save the .transifexrc file."""
     346        if txrc is None:
     347            txrc = self.txrc
     348        mask = os.umask(077)
     349        fh = open(self.txrc_file, 'w')
     350        txrc.write(fh)
     351        fh.close()
     352        os.umask(mask)
     353
     354    def get_full_path(self, relpath):
     355        if relpath[0] == os.path.sep:
     356            return relpath
     357        else:
     358            return os.path.join(self.root, relpath)
     359
     360    def pull(self, languages=[], resources=[], overwrite=True, fetchall=False,
     361        fetchsource=False, force=False, skip=False, minimum_perc=0, mode=None):
     362        """Pull all translations file from transifex server."""
     363        self.minimum_perc = minimum_perc
     364        resource_list = self.get_chosen_resources(resources)
     365
     366        if mode == 'reviewed':
     367            url = 'pull_reviewed_file'
     368        elif mode == 'translator':
     369            url = 'pull_translator_file'
     370        elif mode == 'developer':
     371            url = 'pull_developer_file'
     372        else:
     373            url = 'pull_file'
     374
     375        for resource in resource_list:
     376            logger.debug("Handling resource %s" % resource)
     377            self.resource = resource
     378            project_slug, resource_slug = resource.split('.')
     379            files = self.get_resource_files(resource)
     380            slang = self.get_resource_option(resource, 'source_lang')
     381            sfile = self.get_source_file(resource)
     382            lang_map = self.get_resource_lang_mapping(resource)
     383            host = self.get_resource_host(resource)
     384            verify_ssl(host)
     385            logger.debug("Language mapping is: %s" % lang_map)
     386            if mode is None:
     387                mode = self._get_option(resource, 'mode')
     388            self.url_info = {
     389                'host': host,
     390                'project': project_slug,
     391                'resource': resource_slug
     392            }
     393            logger.debug("URL data are: %s" % self.url_info)
     394
     395            stats = self._get_stats_for_resource()
     396
     397            try:
     398                file_filter = self.config.get(resource, 'file_filter')
     399            except ConfigParser.NoOptionError:
     400                file_filter = None
     401
     402            # Pull source file
     403            pull_languages = set([])
     404            new_translations = set([])
     405
     406            if fetchall:
     407                new_translations = self._new_translations_to_add(
     408                    files, slang, lang_map, stats, force
     409                )
     410                if new_translations:
     411                    msg = "New translations found for the following languages: %s"
     412                    logger.info(msg % ', '.join(new_translations))
     413
     414            existing, new = self._languages_to_pull(
     415                languages, files, lang_map, stats, force
     416            )
     417            pull_languages |= existing
     418            new_translations |= new
     419            logger.debug("Adding to new translations: %s" % new)
     420
     421            if fetchsource:
     422                if sfile and slang not in pull_languages:
     423                    pull_languages.add(slang)
     424                elif slang not in new_translations:
     425                    new_translations.add(slang)
     426
     427            if pull_languages:
     428                logger.debug("Pulling languages for: %s" % pull_languages)
     429                msg = "Pulling translations for resource %s (source: %s)"
     430                logger.info(msg % (resource, sfile))
     431
     432            for lang in pull_languages:
     433                local_lang = lang
     434                if lang in lang_map.values():
     435                    remote_lang = lang_map.flip[lang]
     436                else:
     437                    remote_lang = lang
     438                if languages and lang not in pull_languages:
     439                    logger.debug("Skipping language %s" % lang)
     440                    continue
     441                if lang != slang:
     442                    local_file = files.get(lang, None) or files[lang_map[lang]]
     443                else:
     444                    local_file = sfile
     445                logger.debug("Using file %s" % local_file)
     446
     447                kwargs = {
     448                    'lang': remote_lang,
     449                    'stats': stats,
     450                    'local_file': local_file,
     451                    'force': force,
     452                    'mode': mode,
     453                }
     454                if not self._should_update_translation(**kwargs):
     455                    msg = "Skipping '%s' translation (file: %s)."
     456                    logger.info(
     457                        msg % (color_text(remote_lang, "RED"), local_file)
     458                    )
     459                    continue
     460
     461                if not overwrite:
     462                    local_file = ("%s.new" % local_file)
     463                logger.warning(
     464                    " -> %s: %s" % (color_text(remote_lang, "RED"), local_file)
     465                )
     466                try:
     467                    r = self.do_url_request(url, language=remote_lang)
     468                except Exception,e:
     469                    if not skip:
     470                        raise e
     471                    else:
     472                        logger.error(e)
     473                        continue
     474                base_dir = os.path.split(local_file)[0]
     475                mkdir_p(base_dir)
     476                fd = open(local_file, 'wb')
     477                fd.write(r)
     478                fd.close()
     479
     480            if new_translations:
     481                msg = "Pulling new translations for resource %s (source: %s)"
     482                logger.info(msg % (resource, sfile))
     483                for lang in new_translations:
     484                    if lang in lang_map.keys():
     485                        local_lang = lang_map[lang]
     486                    else:
     487                        local_lang = lang
     488                    remote_lang = lang
     489                    if file_filter:
     490                        local_file = os.path.relpath(
     491                            os.path.join(
     492                                self.root, native_path(
     493                                    file_filter.replace('<lang>', local_lang)
     494                                )
     495                            ), os.curdir
     496                        )
     497                    else:
     498                        trans_dir = os.path.join(self.root, ".tx", resource)
     499                        if not os.path.exists(trans_dir):
     500                            os.mkdir(trans_dir)
     501                        local_file = os.path.relpath(os.path.join(trans_dir, '%s_translation' %
     502                            local_lang, os.curdir))
     503
     504                    if lang != slang:
     505                        satisfies_min = self._satisfies_min_translated(
     506                            stats[remote_lang], mode
     507                        )
     508                        if not satisfies_min:
     509                            msg = "Skipping language %s due to used options."
     510                            logger.info(msg % lang)
     511                            continue
     512                    logger.warning(
     513                        " -> %s: %s" % (color_text(remote_lang, "RED"), local_file)
     514                    )
     515                    r = self.do_url_request(url, language=remote_lang)
     516
     517                    base_dir = os.path.split(local_file)[0]
     518                    mkdir_p(base_dir)
     519                    fd = open(local_file, 'wb')
     520                    fd.write(r)
     521                    fd.close()
     522
     523    def push(self, source=False, translations=False, force=False, resources=[], languages=[],
     524        skip=False, no_interactive=False):
     525        """
     526        Push all the resources
     527        """
     528        resource_list = self.get_chosen_resources(resources)
     529        self.skip = skip
     530        self.force = force
     531        for resource in resource_list:
     532            push_languages = []
     533            project_slug, resource_slug = resource.split('.')
     534            files = self.get_resource_files(resource)
     535            slang = self.get_resource_option(resource, 'source_lang')
     536            sfile = self.get_source_file(resource)
     537            lang_map = self.get_resource_lang_mapping(resource)
     538            host = self.get_resource_host(resource)
     539            verify_ssl(host)
     540            logger.debug("Language mapping is: %s" % lang_map)
     541            logger.debug("Using host %s" % host)
     542            self.url_info = {
     543                'host': host,
     544                'project': project_slug,
     545                'resource': resource_slug
     546            }
     547
     548            logger.info("Pushing translations for resource %s:" % resource)
     549
     550            stats = self._get_stats_for_resource()
     551
     552            if force and not no_interactive:
     553                answer = raw_input("Warning: By using --force, the uploaded"
     554                    " files will overwrite remote translations, even if they"
     555                    " are newer than your uploaded files.\nAre you sure you"
     556                    " want to continue? [y/N] ")
     557
     558                if not answer in ["", 'Y', 'y', "yes", 'YES']:
     559                    return
     560
     561            if source:
     562                if sfile is None:
     563                    logger.error("You don't seem to have a proper source file"
     564                        " mapping for resource %s. Try without the --source"
     565                        " option or set a source file first and then try again." %
     566                        resource)
     567                    continue
     568                # Push source file
     569                try:
     570                    logger.warning("Pushing source file (%s)" % sfile)
     571                    if not self._resource_exists(stats):
     572                        logger.info("Resource does not exist.  Creating...")
     573                        fileinfo = "%s;%s" % (resource_slug, slang)
     574                        filename = self.get_full_path(sfile)
     575                        self._create_resource(resource, project_slug, fileinfo, filename)
     576                    self.do_url_request(
     577                        'push_source', multipart=True, method="PUT",
     578                        files=[(
     579                                "%s;%s" % (resource_slug, slang)
     580                                , self.get_full_path(sfile)
     581                        )],
     582                    )
     583                except Exception, e:
     584                    if not skip:
     585                        raise
     586                    else:
     587                        logger.error(e)
     588            else:
     589                try:
     590                    self.do_url_request('resource_details')
     591                except Exception, e:
     592                    code = getattr(e, 'code', None)
     593                    if code == 404:
     594                        msg = "Resource %s doesn't exist on the server."
     595                        logger.error(msg % resource)
     596                        continue
     597
     598            if translations:
     599                # Check if given language codes exist
     600                if not languages:
     601                    push_languages = files.keys()
     602                else:
     603                    push_languages = []
     604                    f_langs = files.keys()
     605                    for l in languages:
     606                        if l in lang_map.keys():
     607                            l = lang_map[l]
     608                        push_languages.append(l)
     609                        if l not in f_langs:
     610                            msg = "Warning: No mapping found for language code '%s'."
     611                            logger.error(msg % color_text(l,"RED"))
     612                logger.debug("Languages to push are %s" % push_languages)
     613
     614                # Push translation files one by one
     615                for lang in push_languages:
     616                    local_lang = lang
     617                    if lang in lang_map.values():
     618                        remote_lang = lang_map.flip[lang]
     619                    else:
     620                        remote_lang = lang
     621
     622                    local_file = files[local_lang]
     623
     624                    kwargs = {
     625                        'lang': remote_lang,
     626                        'stats': stats,
     627                        'local_file': local_file,
     628                        'force': force,
     629                    }
     630                    if not self._should_push_translation(**kwargs):
     631                        msg = "Skipping '%s' translation (file: %s)."
     632                        logger.info(msg % (color_text(lang, "RED"), local_file))
     633                        continue
     634
     635                    msg = "Pushing '%s' translations (file: %s)"
     636                    logger.warning(
     637                         msg % (color_text(remote_lang, "RED"), local_file)
     638                    )
     639                    try:
     640                        self.do_url_request(
     641                            'push_translation', multipart=True, method='PUT',
     642                            files=[(
     643                                    "%s;%s" % (resource_slug, remote_lang),
     644                                    self.get_full_path(local_file)
     645                            )], language=remote_lang
     646                        )
     647                        logger.debug("Translation %s pushed." % remote_lang)
     648                    except Exception, e:
     649                        if not skip:
     650                            raise e
     651                        else:
     652                            logger.error(e)
     653
     654    def delete(self, resources=[], languages=[], skip=False, force=False):
     655        """Delete translations."""
     656        resource_list = self.get_chosen_resources(resources)
     657        self.skip = skip
     658        self.force = force
     659
     660        if not languages:
     661            delete_func = self._delete_resource
     662        else:
     663            delete_func = self._delete_translations
     664
     665        for resource in resource_list:
     666            project_slug, resource_slug = resource.split('.')
     667            host = self.get_resource_host(resource)
     668            verify_ssl(host)
     669            self.url_info = {
     670                'host': host,
     671                'project': project_slug,
     672                'resource': resource_slug
     673            }
     674            logger.debug("URL data are: %s" % self.url_info)
     675            project_details = parse_json(
     676                self.do_url_request('project_details', project=self)
     677            )
     678            teams = project_details['teams']
     679            stats = self._get_stats_for_resource()
     680            delete_func(project_details, resource, stats, languages)
     681
     682    def _delete_resource(self, project_details, resource, stats, *args):
     683        """Delete a resource from Transifex."""
     684        project_slug, resource_slug = resource.split('.')
     685        project_resource_slugs = [
     686            r['slug'] for r in project_details['resources']
     687        ]
     688        logger.info("Deleting resource %s:" % resource)
     689        if resource_slug not in project_resource_slugs:
     690            if not self.skip:
     691                msg = "Skipping: %s : Resource does not exist."
     692                logger.info(msg % resource)
     693            return
     694        if not self.force:
     695            slang = self.get_resource_option(resource, 'source_lang')
     696            for language in stats:
     697                if language == slang:
     698                    continue
     699                if int(stats[language]['translated_entities']) > 0:
     700                    msg = (
     701                        "Skipping: %s : Unable to delete resource because it "
     702                        "has a not empty %s translation.\nPlease use -f or "
     703                        "--force option to delete this resource."
     704                    )
     705                    logger.info(msg % (resource, language))
     706                    return
     707        try:
     708            self.do_url_request('delete_resource', method="DELETE")
     709            self.config.remove_section(resource)
     710            self.save()
     711            msg = "Deleted resource %s of project %s."
     712            logger.info(msg % (resource_slug, project_slug))
     713        except Exception, e:
     714            msg = "Unable to delete resource %s of project %s."
     715            logger.error(msg % (resource_slug, project_slug))
     716            if not self.skip:
     717                raise
     718
     719    def _delete_translations(self, project_details, resource, stats, languages):
     720        """Delete the specified translations for the specified resource."""
     721        logger.info("Deleting translations from resource %s:" % resource)
     722        for language in languages:
     723            self._delete_translation(project_details, resource, stats, language)
     724
     725    def _delete_translation(self, project_details, resource, stats, language):
     726        """Delete a specific translation from the specified resource."""
     727        project_slug, resource_slug = resource.split('.')
     728        if language not in stats:
     729            if not self.skip:
     730                msg = "Skipping %s: Translation does not exist."
     731                logger.warning(msg % (language))
     732            return
     733        if not self.force:
     734            teams = project_details['teams']
     735            if language in teams:
     736                msg = (
     737                    "Skipping %s: Unable to delete translation because it is "
     738                    "associated with a team.\nPlease use -f or --force option "
     739                    "to delete this translation."
     740                )
     741                logger.warning(msg % language)
     742                return
     743            if int(stats[language]['translated_entities']) > 0:
     744                msg = (
     745                    "Skipping %s: Unable to delete translation because it "
     746                    "is not empty.\nPlease use -f or --force option to delete "
     747                    "this translation."
     748                )
     749                logger.warning(msg % language)
     750                return
     751        try:
     752            self.do_url_request(
     753                'delete_translation', language=language, method="DELETE"
     754            )
     755            msg = "Deleted language %s from resource %s of project %s."
     756            logger.info(msg % (language, resource_slug, project_slug))
     757        except Exception, e:
     758            msg = "Unable to delete translation %s"
     759            logger.error(msg % language)
     760            if not self.skip:
     761                raise
     762
     763    def do_url_request(self, api_call, multipart=False, data=None,
     764                       files=[], encoding=None, method="GET", **kwargs):
     765        """
     766        Issues a url request.
     767        """
     768        # Read the credentials from the config file (.transifexrc)
     769        host = self.url_info['host']
     770        try:
     771            username = self.txrc.get(host, 'username')
     772            passwd = self.txrc.get(host, 'password')
     773            token = self.txrc.get(host, 'token')
     774            hostname = self.txrc.get(host, 'hostname')
     775        except ConfigParser.NoSectionError:
     776            raise Exception("No user credentials found for host %s. Edit"
     777                " ~/.transifexrc and add the appropriate info in there." %
     778                host)
     779
     780        # Create the Url
     781        kwargs['hostname'] = hostname
     782        kwargs.update(self.url_info)
     783        url = (API_URLS[api_call] % kwargs).encode('UTF-8')
     784        logger.debug(url)
     785
     786        opener = None
     787        headers = None
     788        req = None
     789
     790        if multipart:
     791            opener = urllib2.build_opener(MultipartPostHandler)
     792            for info,filename in files:
     793                data = { "resource" : info.split(';')[0],
     794                         "language" : info.split(';')[1],
     795                         "uploaded_file" :  open(filename,'rb') }
     796
     797            urllib2.install_opener(opener)
     798            req = RequestWithMethod(url=url, data=data, method=method)
     799        else:
     800            req = RequestWithMethod(url=url, data=data, method=method)
     801            if encoding:
     802                req.add_header("Content-Type",encoding)
     803
     804        base64string = base64.encodestring('%s:%s' % (username, passwd))[:-1]
     805        authheader = "Basic %s" % base64string
     806        req.add_header("Authorization", authheader)
     807        req.add_header("Accept-Encoding", "gzip,deflate")
     808        req.add_header("User-Agent", user_agent_identifier())
     809
     810        try:
     811            response = urllib2.urlopen(req, timeout=300)
     812            return http_response(response)
     813        except urllib2.HTTPError, e:
     814            if e.code in [401, 403, 404]:
     815                raise e
     816            elif 200 <= e.code < 300:
     817                return None
     818            else:
     819                # For other requests, we should print the message as well
     820                raise Exception("Remote server replied: %s" % e.read())
     821        except urllib2.URLError, e:
     822            error = e.args[0]
     823            raise Exception("Remote server replied: %s" % error[1])
     824
     825
     826    def _should_update_translation(self, lang, stats, local_file, force=False,
     827                                   mode=None):
     828        """Whether a translation should be udpated from Transifex.
     829
     830        We use the following criteria for that:
     831        - If user requested to force the download.
     832        - If language exists in Transifex.
     833        - If the local file is older than the Transifex's file.
     834        - If the user requested a x% completion.
     835
     836        Args:
     837            lang: The language code to check.
     838            stats: The (global) statistics object.
     839            local_file: The local translation file.
     840            force: A boolean flag.
     841            mode: The mode for the translation.
     842        Returns:
     843            True or False.
     844        """
     845        return self._should_download(lang, stats, local_file, force)
     846
     847    def _should_add_translation(self, lang, stats, force=False, mode=None):
     848        """Whether a translation should be added from Transifex.
     849
     850        We use the following criteria for that:
     851        - If user requested to force the download.
     852        - If language exists in Transifex.
     853        - If the user requested a x% completion.
     854
     855        Args:
     856            lang: The language code to check.
     857            stats: The (global) statistics object.
     858            force: A boolean flag.
     859            mode: The mode for the translation.
     860        Returns:
     861            True or False.
     862        """
     863        return self._should_download(lang, stats, None, force)
     864
     865    def _should_download(self, lang, stats, local_file=None, force=False,
     866                         mode=None):
     867        """Return whether a translation should be downloaded.
     868
     869        If local_file is None, skip the timestamps check (the file does
     870        not exist locally).
     871        """
     872        try:
     873            lang_stats = stats[lang]
     874        except KeyError, e:
     875            logger.debug("No lang %s in statistics" % lang)
     876            return False
     877
     878        satisfies_min = self._satisfies_min_translated(lang_stats, mode)
     879        if not satisfies_min:
     880            return False
     881
     882        if force:
     883            logger.debug("Downloading translation due to -f")
     884            return True
     885
     886        if local_file is not None:
     887            remote_update = self._extract_updated(lang_stats)
     888            if not self._remote_is_newer(remote_update, local_file):
     889                logger.debug("Local is newer than remote for lang %s" % lang)
     890                return False
     891        return True
     892
     893    def _should_push_translation(self, lang, stats, local_file, force=False):
     894        """Return whether a local translation file should be
     895        pushed to Trasnifex.
     896
     897        We use the following criteria for that:
     898        - If user requested to force the upload.
     899        - If language exists in Transifex.
     900        - If local file is younger than the remote file.
     901
     902        Args:
     903            lang: The language code to check.
     904            stats: The (global) statistics object.
     905            local_file: The local translation file.
     906            force: A boolean flag.
     907        Returns:
     908            True or False.
     909        """
     910        if force:
     911            logger.debug("Push translation due to -f.")
     912            return True
     913        try:
     914            lang_stats = stats[lang]
     915        except KeyError, e:
     916            logger.debug("Language %s does not exist in Transifex." % lang)
     917            return True
     918        if local_file is not None:
     919            remote_update = self._extract_updated(lang_stats)
     920            if self._remote_is_newer(remote_update, local_file):
     921                msg  = "Remote translation is newer than local file for lang %s"
     922                logger.debug(msg % lang)
     923                return False
     924        return True
     925
     926    def _generate_timestamp(self, update_datetime):
     927        """Generate a UNIX timestamp from the argument.
     928
     929        Args:
     930            update_datetime: The datetime in the format used by Transifex.
     931        Returns:
     932            A float, representing the timestamp that corresponds to the
     933            argument.
     934        """
     935        time_format = "%Y-%m-%d %H:%M:%S"
     936        return time.mktime(
     937            datetime.datetime(
     938                *time.strptime(update_datetime, time_format)[0:5]
     939            ).utctimetuple()
     940        )
     941
     942    def _get_time_of_local_file(self, path):
     943        """Get the modified time of the path_.
     944
     945        Args:
     946            path: The path we want the mtime for.
     947        Returns:
     948            The time as a timestamp or None, if the file does not exist
     949        """
     950        if not os.path.exists(path):
     951            return None
     952        return time.mktime(time.gmtime(os.path.getmtime(path)))
     953
     954    def _satisfies_min_translated(self, stats, mode=None):
     955        """Check whether a translation fulfills the filter used for
     956        minimum translated percentage.
     957
     958        Args:
     959            perc: The current translation percentage.
     960        Returns:
     961            True or False
     962        """
     963        cur = self._extract_completed(stats, mode)
     964        option_name = 'minimum_perc'
     965        if self.minimum_perc is not None:
     966            minimum_percent = self.minimum_perc
     967        else:
     968            global_minimum = int(
     969                self.get_resource_option('main', option_name) or 0
     970            )
     971            resource_minimum = int(
     972                self.get_resource_option(
     973                    self.resource, option_name
     974                ) or global_minimum
     975            )
     976            minimum_percent = resource_minimum
     977        return cur >= minimum_percent
     978
     979    def _remote_is_newer(self, remote_updated, local_file):
     980        """Check whether the remote translation is newer that the local file.
     981
     982        Args:
     983            remote_updated: The date and time the translation was last
     984                updated remotely.
     985            local_file: The local file.
     986        Returns:
     987            True or False.
     988        """
     989        if remote_updated is None:
     990            logger.debug("No remote time")
     991            return False
     992        remote_time = self._generate_timestamp(remote_updated)
     993        local_time = self._get_time_of_local_file(
     994            self.get_full_path(local_file)
     995        )
     996        logger.debug(
     997            "Remote time is %s and local %s" % (remote_time, local_time)
     998        )
     999        if local_time is not None and remote_time < local_time:
     1000            return False
     1001        return True
     1002
     1003    @classmethod
     1004    def _extract_completed(cls, stats, mode=None):
     1005        """Extract the information for the translated percentage from the stats.
     1006
     1007        Args:
     1008            stats: The stats object for a language as returned by Transifex.
     1009            mode: The mode of translations requested.
     1010        Returns:
     1011            The percentage of translation as integer.
     1012        """
     1013        if mode == 'reviewed':
     1014            key = 'reviewed_percentage'
     1015        else:
     1016            key = 'completed'
     1017        try:
     1018            return int(stats[key][:-1])
     1019        except KeyError, e:
     1020            return 0
     1021
     1022    @classmethod
     1023    def _extract_updated(cls, stats):
     1024        """Extract the  information for the last update of a translation.
     1025
     1026        Args:
     1027            stats: The stats object for a language as returned by Transifex.
     1028        Returns:
     1029            The last update field.
     1030        """
     1031        try:
     1032            return stats['last_update']
     1033        except KeyError, e:
     1034            return None
     1035
     1036    def _new_translations_to_add(self, files, slang, lang_map,
     1037                                 stats, force=False):
     1038        """Return a list of translations which are new to the
     1039        local installation.
     1040        """
     1041        new_translations = []
     1042        timestamp = time.time()
     1043        langs = stats.keys()
     1044        logger.debug("Available languages are: %s" % langs)
     1045
     1046        for lang in langs:
     1047            lang_exists = lang in files.keys()
     1048            lang_is_source = lang == slang
     1049            mapped_lang_exists = (
     1050                lang in lang_map and lang_map[lang] in files.keys()
     1051            )
     1052            if lang_exists or lang_is_source or mapped_lang_exists:
     1053                continue
     1054            if self._should_add_translation(lang, stats, force):
     1055                new_translations.append(lang)
     1056        return set(new_translations)
     1057
     1058    def _get_stats_for_resource(self):
     1059        """Get the statistics information for a resource."""
     1060        try:
     1061            r = self.do_url_request('resource_stats')
     1062            logger.debug("Statistics response is %s" % r)
     1063            stats = parse_json(r)
     1064        except urllib2.HTTPError, e:
     1065            logger.debug("Resource not found: %s" % e)
     1066            stats = {}
     1067        except Exception,e:
     1068            logger.debug("Network error: %s" % e)
     1069            raise
     1070        return stats
     1071
     1072    def get_chosen_resources(self, resources):
     1073        """Get the resources the user selected.
     1074
     1075        Support wildcards in the resources specified by the user.
     1076
     1077        Args:
     1078            resources: A list of resources as specified in command-line or
     1079                an empty list.
     1080        Returns:
     1081            A list of resources.
     1082        """
     1083        configured_resources = self.get_resource_list()
     1084        if not resources:
     1085            return configured_resources
     1086
     1087        selected_resources = []
     1088        for resource in resources:
     1089            found = False
     1090            for full_name in configured_resources:
     1091                if fnmatch.fnmatch(full_name, resource):
     1092                    selected_resources.append(full_name)
     1093                    found = True
     1094            if not found:
     1095                msg = "Specified resource '%s' does not exist."
     1096                raise Exception(msg % resource)
     1097        logger.debug("Operating on resources: %s" % selected_resources)
     1098        return selected_resources
     1099
     1100    def _languages_to_pull(self, languages, files, lang_map, stats, force):
     1101        """Get a set of langauges to pull.
     1102
     1103        Args:
     1104            languages: A list of languages the user selected in cmd.
     1105            files: A dictionary of current local translation files.
     1106        Returns:
     1107            A tuple of a set of existing languages and new translations.
     1108        """
     1109        if not languages:
     1110            pull_languages = set([])
     1111            pull_languages |= set(files.keys())
     1112            mapped_files = []
     1113            for lang in pull_languages:
     1114                if lang in lang_map.flip:
     1115                    mapped_files.append(lang_map.flip[lang])
     1116            pull_languages -= set(lang_map.flip.keys())
     1117            pull_languages |= set(mapped_files)
     1118            return (pull_languages, set([]))
     1119        else:
     1120            pull_languages = []
     1121            new_translations = []
     1122            f_langs = files.keys()
     1123            for l in languages:
     1124                if l not in f_langs and not (l in lang_map and lang_map[l] in f_langs):
     1125                    if self._should_add_translation(l, stats, force):
     1126                        new_translations.append(l)
     1127                else:
     1128                    if l in lang_map.keys():
     1129                        l = lang_map[l]
     1130                    pull_languages.append(l)
     1131            return (set(pull_languages), set(new_translations))
     1132
     1133    def _extension_for(self, i18n_type):
     1134        """Return the extension used for the specified type."""
     1135        try:
     1136            res = parse_json(self.do_url_request('formats'))
     1137            return res[i18n_type]['file-extensions'].split(',')[0]
     1138        except Exception,e:
     1139            logger.error(e)
     1140            return ''
     1141
     1142    def _resource_exists(self, stats):
     1143        """Check if resource exists.
     1144
     1145        Args:
     1146            stats: The statistics dict as returned by Tx.
     1147        Returns:
     1148            True, if the resource exists in the server.
     1149        """
     1150        return bool(stats)
     1151
     1152    def _create_resource(self, resource, pslug, fileinfo, filename, **kwargs):
     1153        """Create a resource.
     1154
     1155        Args:
     1156            resource: The full resource name.
     1157            pslug: The slug of the project.
     1158            fileinfo: The information of the resource.
     1159            filename: The name of the file.
     1160        Raises:
     1161            URLError, in case of a problem.
     1162        """
     1163        multipart = True
     1164        method = "POST"
     1165        api_call = 'create_resource'
     1166
     1167        host = self.url_info['host']
     1168        try:
     1169            username = self.txrc.get(host, 'username')
     1170            passwd = self.txrc.get(host, 'password')
     1171            token = self.txrc.get(host, 'token')
     1172            hostname = self.txrc.get(host, 'hostname')
     1173        except ConfigParser.NoSectionError:
     1174            raise Exception("No user credentials found for host %s. Edit"
     1175                " ~/.transifexrc and add the appropriate info in there." %
     1176                host)
     1177
     1178        # Create the Url
     1179        kwargs['hostname'] = hostname
     1180        kwargs.update(self.url_info)
     1181        kwargs['project'] = pslug
     1182        url = (API_URLS[api_call] % kwargs).encode('UTF-8')
     1183
     1184        opener = None
     1185        headers = None
     1186        req = None
     1187
     1188        i18n_type = self._get_option(resource, 'type')
     1189        if i18n_type is None:
     1190            logger.error(
     1191                "Please define the resource type in .tx/config (eg. type = PO)."
     1192                " More info: http://bit.ly/txcl-rt"
     1193            )
     1194
     1195        opener = urllib2.build_opener(MultipartPostHandler)
     1196        data = {
     1197            "slug": fileinfo.split(';')[0],
     1198            "name": fileinfo.split(';')[0],
     1199            "uploaded_file":  open(filename,'rb'),
     1200            "i18n_type": i18n_type
     1201        }
     1202        urllib2.install_opener(opener)
     1203        req = RequestWithMethod(url=url, data=data, method=method)
     1204
     1205        base64string = base64.encodestring('%s:%s' % (username, passwd))[:-1]
     1206        authheader = "Basic %s" % base64string
     1207        req.add_header("Authorization", authheader)
     1208
     1209        try:
     1210            fh = urllib2.urlopen(req)
     1211        except urllib2.HTTPError, e:
     1212            if e.code in [401, 403, 404]:
     1213                raise e
     1214            else:
     1215                # For other requests, we should print the message as well
     1216                raise Exception("Remote server replied: %s" % e.read())
     1217        except urllib2.URLError, e:
     1218            error = e.args[0]
     1219            raise Exception("Remote server replied: %s" % error[1])
     1220
     1221        raw = fh.read()
     1222        fh.close()
     1223        return raw
     1224
     1225    def _get_option(self, resource, option):
     1226        """Get the value for the option in the config file.
     1227
     1228        If the option is not in the resource section, look for it in
     1229        the project.
     1230
     1231        Args:
     1232            resource: The resource name.
     1233            option: The option the value of which we are interested in.
     1234        Returns:
     1235            The option value or None, if it does not exist.
     1236        """
     1237        value = self.get_resource_option(resource, option)
     1238        if value is None:
     1239            if self.config.has_option('main', option):
     1240                return self.config.get('main', option)
     1241        return value
     1242
     1243    def set_i18n_type(self, resources, i18n_type):
     1244        """Set the type for the specified resources."""
     1245        self._set_resource_option(resources, key='type', value=i18n_type)
     1246
     1247    def set_min_perc(self, resources, perc):
     1248        """Set the minimum percentage for the resources."""
     1249        self._set_resource_option(resources, key='minimum_perc', value=perc)
     1250
     1251    def set_default_mode(self, resources, mode):
     1252        """Set the default mode for the specified resources."""
     1253        self._set_resource_option(resources, key='mode', value=mode)
     1254
     1255    def _set_resource_option(self, resources, key, value):
     1256        """Set options in the config file.
     1257
     1258        If resources is empty. set the option globally.
     1259        """
     1260        if not resources:
     1261            self.config.set('main', key, value)
     1262            return
     1263        for r in resources:
     1264            self.config.set(r, key, value)
  • new file source/tools/i18n/txclib/urls.py

    diff --git a/source/tools/i18n/txclib/urls.py b/source/tools/i18n/txclib/urls.py
    new file mode 100644
    index 0000000..d5b7ef8
    - +  
     1# These are the Transifex API urls
     2
     3API_URLS = {
     4    'get_resources': '%(hostname)s/api/2/project/%(project)s/resources/',
     5    'project_details': '%(hostname)s/api/2/project/%(project)s/?details',
     6    'resource_details': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/',
     7    'release_details': '%(hostname)s/api/2/project/%(project)s/release/%(release)s/',
     8    'pull_file': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/translation/%(language)s/?file',
     9    'pull_reviewed_file': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/translation/%(language)s/?file&mode=reviewed',
     10    'pull_translator_file': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/translation/%(language)s/?file&mode=translator',
     11    'pull_developer_file': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/translation/%(language)s/?file&mode=default',
     12    'resource_stats': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/stats/',
     13    'create_resource': '%(hostname)s/api/2/project/%(project)s/resources/',
     14    'push_source': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/content/',
     15    'push_translation': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/translation/%(language)s/',
     16    'delete_translation': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/translation/%(language)s/',
     17    'formats': '%(hostname)s/api/2/formats/',
     18    'delete_resource': '%(hostname)s/api/2/project/%(project)s/resource/%(resource)s/',
     19}
  • new file source/tools/i18n/txclib/utils.py

    diff --git a/source/tools/i18n/txclib/utils.py b/source/tools/i18n/txclib/utils.py
    new file mode 100644
    index 0000000..7115ca7
    - +  
     1import os, sys, re, errno
     2try:
     3    from json import loads as parse_json, dumps as compile_json
     4except ImportError:
     5    from simplejson import loads as parse_json, dumps as compile_json
     6import urllib2 # This should go and instead use do_url_request everywhere
     7
     8from txclib.urls import API_URLS
     9from txclib.log import logger
     10from txclib.exceptions import UnknownCommandError
     11from txclib.paths import posix_path, native_path, posix_sep
     12from txclib.web import verify_ssl
     13
     14
     15def find_dot_tx(path = os.path.curdir, previous = None):
     16    """Return the path where .tx folder is found.
     17
     18    The 'path' should be a DIRECTORY.
     19    This process is functioning recursively from the current directory to each
     20    one of the ancestors dirs.
     21    """
     22    path = os.path.abspath(path)
     23    if path == previous:
     24        return None
     25    joined = os.path.join(path, ".tx")
     26    if os.path.isdir(joined):
     27        return path
     28    else:
     29        return find_dot_tx(os.path.dirname(path), path)
     30
     31
     32#################################################
     33# Parse file filter expressions and create regex
     34
     35def regex_from_filefilter(file_filter, root_path = os.path.curdir):
     36    """Create proper regex from <lang> expression."""
     37    # Force expr to be a valid regex expr (escaped) but keep <lang> intact
     38    expr_re = re.escape(
     39        posix_path(os.path.join(root_path, native_path(file_filter)))
     40    )
     41    expr_re = expr_re.replace("\\<lang\\>", '<lang>').replace(
     42        '<lang>', '([^%(sep)s]+)' % { 'sep': re.escape(posix_sep)})
     43
     44    return "^%s$" % expr_re
     45
     46
     47TX_URLS = {
     48    'resource': '(?P<hostname>https?://(\w|\.|:|-)+)/projects/p/(?P<project>(\w|-)+)/resource/(?P<resource>(\w|-)+)/?$',
     49    'release': '(?P<hostname>https?://(\w|\.|:|-)+)/projects/p/(?P<project>(\w|-)+)/r/(?P<release>(\w|-)+)/?$',
     50    'project': '(?P<hostname>https?://(\w|\.|:|-)+)/projects/p/(?P<project>(\w|-)+)/?$',
     51}
     52
     53
     54def parse_tx_url(url):
     55    """
     56    Try to match given url to any of the valid url patterns specified in
     57    TX_URLS. If not match is found, we raise exception
     58    """
     59    for type_ in TX_URLS.keys():
     60        pattern = TX_URLS[type_]
     61        m = re.match(pattern, url)
     62        if m:
     63            return type_, m.groupdict()
     64    raise Exception(
     65        "tx: Malformed url given. Please refer to our docs: http://bit.ly/txautor"
     66    )
     67
     68
     69def get_details(api_call, username, password, *args, **kwargs):
     70    """
     71    Get the tx project info through the API.
     72
     73    This function can also be used to check the existence of a project.
     74    """
     75    import base64
     76    url = (API_URLS[api_call] % (kwargs)).encode('UTF-8')
     77    verify_ssl(url)
     78
     79    req = urllib2.Request(url=url)
     80    base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
     81    authheader = "Basic %s" % base64string
     82    req.add_header("Authorization", authheader)
     83
     84    try:
     85        fh = urllib2.urlopen(req)
     86        raw = fh.read()
     87        fh.close()
     88        remote_project = parse_json(raw)
     89    except urllib2.HTTPError, e:
     90        if e.code in [401, 403, 404]:
     91            raise e
     92        else:
     93            # For other requests, we should print the message as well
     94            raise Exception("Remote server replied: %s" % e.read())
     95    except urllib2.URLError, e:
     96        error = e.args[0]
     97        raise Exception("Remote server replied: %s" % error[1])
     98
     99    return remote_project
     100
     101
     102def valid_slug(slug):
     103    """
     104    Check if a slug contains only valid characters.
     105
     106    Valid chars include [-_\w]
     107    """
     108    try:
     109        a, b = slug.split('.')
     110    except ValueError:
     111        return False
     112    else:
     113        if re.match("^[A-Za-z0-9_-]*$", a) and re.match("^[A-Za-z0-9_-]*$", b):
     114            return True
     115        return False
     116
     117
     118def discover_commands():
     119    """
     120    Inspect commands.py and find all available commands
     121    """
     122    import inspect
     123    from txclib import commands
     124
     125    command_table = {}
     126    fns = inspect.getmembers(commands, inspect.isfunction)
     127
     128    for name, fn in fns:
     129        if name.startswith("cmd_"):
     130            command_table.update({
     131                name.split("cmd_")[1]:fn
     132            })
     133
     134    return command_table
     135
     136
     137def exec_command(command, *args, **kwargs):
     138    """
     139    Execute given command
     140    """
     141    commands = discover_commands()
     142    try:
     143        cmd_fn = commands[command]
     144    except KeyError:
     145        raise UnknownCommandError
     146    cmd_fn(*args,**kwargs)
     147
     148
     149def mkdir_p(path):
     150    try:
     151        if path:
     152            os.makedirs(path)
     153    except OSError, exc: # Python >2.5
     154        if exc.errno == errno.EEXIST:
     155            pass
     156        else:
     157            raise
     158
     159
     160def confirm(prompt='Continue?', default=True):
     161    """
     162    Prompt the user for a Yes/No answer.
     163
     164    Args:
     165        prompt: The text displayed to the user ([Y/n] will be appended)
     166        default: If the default value will be yes or no
     167    """
     168    valid_yes = ['Y', 'y', 'Yes', 'yes', ]
     169    valid_no = ['N', 'n', 'No', 'no', ]
     170    if default:
     171        prompt = prompt + '[Y/n]'
     172        valid_yes.append('')
     173    else:
     174        prompt = prompt + '[y/N]'
     175        valid_no.append('')
     176
     177    ans = raw_input(prompt)
     178    while (ans not in valid_yes and ans not in valid_no):
     179        ans = raw_input(prompt)
     180
     181    return ans in valid_yes
     182
     183
     184# Stuff for command line colored output
     185
     186COLORS = [
     187    'BLACK', 'RED', 'GREEN', 'YELLOW',
     188    'BLUE', 'MAGENTA', 'CYAN', 'WHITE'
     189]
     190
     191DISABLE_COLORS = False
     192
     193
     194def color_text(text, color_name, bold=False):
     195    """
     196    This command can be used to colorify command line output. If the shell
     197    doesn't support this or the --disable-colors options has been set, it just
     198    returns the plain text.
     199
     200    Usage:
     201        print "%s" % color_text("This text is red", "RED")
     202    """
     203    if color_name in COLORS and not DISABLE_COLORS:
     204        return '\033[%s;%sm%s\033[0m' % (
     205            int(bold), COLORS.index(color_name) + 30, text)
     206    else:
     207        return text
     208
     209
     210def files_in_project(curpath):
     211    """
     212    Iterate over the files in the project.
     213
     214    Return each file under ``curpath`` with its absolute name.
     215    """
     216    for root, dirs, files in os.walk(curpath, followlinks=True):
     217        for f in files:
     218            yield os.path.abspath(os.path.join(root, f))
  • new file source/tools/i18n/txclib/web.py

    diff --git a/source/tools/i18n/txclib/web.py b/source/tools/i18n/txclib/web.py
    new file mode 100644
    index 0000000..cbef36d
    - +  
     1# -*- coding: utf-8 -*-
     2
     3import os
     4import urllib2
     5import socket
     6import ssl
     7import urlparse
     8import mimetools
     9import mimetypes
     10import platform
     11#from pkg_resources import resource_filename, resource_string
     12from txclib import get_version
     13from txclib.packages.ssl_match_hostname import match_hostname
     14
     15
     16# Helper class to enable urllib2 to handle PUT/DELETE requests as well
     17class RequestWithMethod(urllib2.Request):
     18    """Workaround for using DELETE with urllib2"""
     19
     20    def __init__(self, url, method, data=None, headers={},
     21        origin_req_host=None, unverifiable=False):
     22        self._method = method
     23        urllib2.Request.__init__(self, url, data=data, headers=headers,
     24                 origin_req_host=None, unverifiable=False)
     25
     26    def get_method(self):
     27        return self._method
     28
     29
     30import urllib
     31import stat
     32from cStringIO import StringIO
     33
     34
     35class Callable:
     36    def __init__(self, anycallable):
     37        self.__call__ = anycallable
     38
     39# Controls how sequences are uncoded. If true, elements may be given multiple
     40# values by assigning a sequence.
     41doseq = 1
     42
     43
     44class MultipartPostHandler(urllib2.BaseHandler):
     45    handler_order = urllib2.HTTPHandler.handler_order - 10 # needs to run first
     46
     47    def http_request(self, request):
     48        data = request.get_data()
     49        if data is not None and type(data) != str:
     50            v_files = []
     51            v_vars = []
     52            try:
     53                 for (key, value) in data.items():
     54                     if type(value) == file:
     55                         v_files.append((key, value))
     56                     else:
     57                         v_vars.append((key, value))
     58            except TypeError:
     59                systype, value, traceback = sys.exc_info()
     60                raise TypeError, "not a valid non-string sequence or mapping object", traceback
     61
     62            if len(v_files) == 0:
     63                data = urllib.urlencode(v_vars, doseq)
     64            else:
     65                boundary, data = self.multipart_encode(v_vars, v_files)
     66
     67                contenttype = 'multipart/form-data; boundary=%s' % boundary
     68                if(request.has_header('Content-Type')
     69                   and request.get_header('Content-Type').find('multipart/form-data') != 0):
     70                    print "Replacing %s with %s" % (request.get_header('content-type'), 'multipart/form-data')
     71                request.add_unredirected_header('Content-Type', contenttype)
     72
     73            request.add_data(data)
     74
     75        return request
     76
     77    def multipart_encode(vars, files, boundary = None, buf = None):
     78        if boundary is None:
     79            boundary = mimetools.choose_boundary()
     80        if buf is None:
     81            buf = StringIO()
     82        for(key, value) in vars:
     83            buf.write('--%s\r\n' % boundary)
     84            buf.write('Content-Disposition: form-data; name="%s"' % key)
     85            buf.write('\r\n\r\n' + value + '\r\n')
     86        for(key, fd) in files:
     87            file_size = os.fstat(fd.fileno())[stat.ST_SIZE]
     88            filename = fd.name.split(os.path.sep)[-1]
     89            contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
     90            buf.write('--%s\r\n' % boundary)
     91            buf.write('Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (key, filename))
     92            buf.write('Content-Type: %s\r\n' % contenttype)
     93            # buffer += 'Content-Length: %s\r\n' % file_size
     94            fd.seek(0)
     95            buf.write('\r\n' + fd.read() + '\r\n')
     96        buf.write('--' + boundary + '--\r\n\r\n')
     97        buf = buf.getvalue()
     98        return boundary, buf
     99    multipart_encode = Callable(multipart_encode)
     100
     101    https_request = http_request
     102
     103
     104def user_agent_identifier():
     105    """Return the user agent for the client."""
     106    client_info = (get_version(), platform.system(), platform.machine())
     107    return "txclient/%s (%s %s)" % client_info
     108
     109
     110def _verify_ssl(hostname, port=443):
     111    """Verify the SSL certificate of the given host."""
     112    sock = socket.create_connection((hostname, port))
     113    try:
     114        ssl_sock = ssl.wrap_socket(
     115            sock, cert_reqs=ssl.CERT_REQUIRED, ca_certs=certs_file()
     116        )
     117        match_hostname(ssl_sock.getpeercert(), hostname)
     118    finally:
     119        sock.close()
     120
     121
     122def certs_file():
     123    if platform.system() == 'Windows':
     124        # Workaround py2exe and resource_filename incompatibility.
     125        # Store the content in the filesystem permanently.
     126        app_dir = os.path.join(
     127            os.getenv('appdata', os.path.expanduser('~')), 'transifex-client'
     128        )
     129        if not os.path.exists(app_dir):
     130            os.mkdir(app_dir)
     131        ca_file = os.path.join(app_dir, 'cacert.pem')
     132        if not os.path.exists(ca_file):
     133            content = resource_string(__name__, 'cacert.pem')
     134            with open(ca_file, 'w') as f:
     135                f.write(content)
     136        return ca_file
     137    else:
     138        POSSIBLE_CA_BUNDLE_PATHS = [
     139            # Red Hat, CentOS, Fedora and friends
     140            # (provided by the ca-certificates package):
     141            '/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem',
     142            '/etc/ssl/certs/ca-bundle.crt',
     143            '/etc/pki/tls/certs/ca-bundle.crt',
     144            # Ubuntu, Debian, and friends
     145            # (provided by the ca-certificates package):
     146            '/etc/ssl/certs/ca-certificates.crt',
     147            # FreeBSD (provided by the ca_root_nss package):
     148            '/usr/local/share/certs/ca-root-nss.crt',
     149            # openSUSE (provided by the ca-certificates package),
     150            # the 'certs' directory is the
     151            # preferred way but may not be supported by the SSL module,
     152            # thus it has 'ca-bundle.pem'
     153            # as a fallback (which is generated from pem files in the
     154            # 'certs' directory):
     155            '/etc/ssl/ca-bundle.pem',
     156        ]
     157        for path in POSSIBLE_CA_BUNDLE_PATHS:
     158            if os.path.exists(path):
     159                return path
     160        return resource_filename(__name__, 'cacert.pem')
     161
     162
     163def verify_ssl(host):
     164    parts = urlparse.urlparse(host)
     165    if parts.scheme != 'https':
     166        return
     167
     168    if ':' in parts.netloc:
     169        hostname, port = parts.netloc.split(':')
     170    else:
     171        hostname = parts.netloc
     172        if parts.port is not None:
     173            port = parts.port
     174        else:
     175            port = 443
     176    _verify_ssl(hostname, port)
  • new file source/tools/i18n/updateTemplates.py

    diff --git a/source/tools/i18n/updateTemplates.py b/source/tools/i18n/updateTemplates.py
    new file mode 100644
    index 0000000..471dd69
    - +  
     1#!/usr/bin/env python
     2# -*- coding:utf-8 -*-
     3#
     4# Copyright (C) 2013 Wildfire Games.
     5# This file is part of 0 A.D.
     6#
     7# 0 A.D. is free software: you can redistribute it and/or modify
     8# it under the terms of the GNU General Public License as published by
     9# the Free Software Foundation, either version 2 of the License, or
     10# (at your option) any later version.
     11#
     12# 0 A.D. is distributed in the hope that it will be useful,
     13# but WITHOUT ANY WARRANTY; without even the implied warranty of
     14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15# GNU General Public License for more details.
     16#
     17# You should have received a copy of the GNU General Public License
     18# along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     19
     20from __future__ import absolute_import, division, print_function, unicode_literals
     21
     22import codecs, json, os, textwrap
     23
     24from potter.catalog import Catalog, Message
     25from potter.extract import getExtractorInstance
     26from potter.pofile import write_po
     27
     28
     29l10nToolsDirectory = os.path.dirname(os.path.realpath(__file__))
     30projectRootDirectory = os.path.abspath(os.path.join(l10nToolsDirectory, os.pardir, os.pardir, os.pardir))
     31l10nFolderName = "l10n"
     32messagesFilename = "messages.json"
     33
     34
     35def warnAboutUntouchedMods():
     36    """
     37        Warn about mods that are not properly configured to get their messages extracted.
     38    """
     39    modsRootFolder = os.path.join(projectRootDirectory, "binaries", "data", "mods")
     40    untouchedMods = {}
     41    for modFolder in os.listdir(modsRootFolder):
     42        if modFolder[0] != "_":
     43            if not os.path.exists(os.path.join(modsRootFolder, modFolder, l10nFolderName)):
     44                untouchedMods[modFolder] = "There is no '{folderName}' folder in the root folder of this mod.".format(folderName=l10nFolderName)
     45            elif not os.path.exists(os.path.join(modsRootFolder, modFolder, l10nFolderName, messagesFilename)):
     46                untouchedMods[modFolder] = "There is no '{filename}' file within the '{folderName}' folder in the root folder of this mod.".format(folderName=l10nFolderName, filename=messagesFilename)
     47    if untouchedMods:
     48        print(textwrap.dedent("""
     49                Warning: No messages were extracted from the following mods:
     50            """))
     51        for mod in untouchedMods:
     52            print("• {modName}: {warningMessage}".format(modName=mod, warningMessage=untouchedMods[mod]))
     53        print(textwrap.dedent("""
     54                For this script to extract messages from a mod folder, this mod folder must contain a '{folderName}'
     55                folder, and this folder must contain a '{filename}' file that describes how to extract messages for the
     56                mod. See the folder of the main mod ('public') for an example, and see the documentation for more
     57                information.
     58                """.format(folderName=l10nFolderName, filename=messagesFilename)
     59             ))
     60
     61
     62def generateTemplatesForMessagesFile(messagesFilePath):
     63
     64    with open(messagesFilePath, 'r') as fileObject:
     65        settings = json.load(fileObject)
     66
     67    rootPath = os.path.dirname(messagesFilePath)
     68
     69    for templateSettings in settings:
     70
     71        if "skip" in templateSettings and templateSettings["skip"] == "yes":
     72            continue
     73
     74        inputRootPath = rootPath
     75        if "inputRoot" in templateSettings:
     76            inputRootPath = os.path.join(rootPath, templateSettings["inputRoot"])
     77
     78        template = Catalog()
     79        template.project = templateSettings["project"]
     80        template.copyright_holder = templateSettings["copyrightHolder"]
     81
     82        for rule in templateSettings["rules"]:
     83
     84            if "skip" in rule and rule["skip"] == "yes":
     85                continue
     86
     87            extractor = getExtractorInstance(rule["extractor"], inputRootPath, rule["filemasks"], rule.get("options", {}))
     88            for message, context, location, comments in extractor.run():
     89                template.add(message, context=context, locations=[location], auto_comments=comments)
     90
     91        with codecs.open(os.path.join(rootPath, templateSettings["output"]), 'w', 'utf-8') as fileObject:
     92            write_po(fileObject, template)
     93
     94
     95def main():
     96
     97    for root, folders, filenames in os.walk(projectRootDirectory):
     98        for folder in folders:
     99            if folder == l10nFolderName:
     100                messagesFilePath = os.path.join(root, folder, messagesFilename)
     101                if os.path.exists(messagesFilePath):
     102                    generateTemplatesForMessagesFile(messagesFilePath)
     103
     104    warnAboutUntouchedMods()
     105
     106
     107if __name__ == "__main__":
     108    main()