ÿØÿà JFIF ÿþ >CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality
ÿÛ C
Server IP : 93.127.196.66 / Your IP : 216.73.216.37 Web Server : LiteSpeed System : Linux sg-nme-web1517.main-hosting.eu 5.14.0-611.16.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Dec 22 03:40:39 EST 2025 x86_64 User : u323805470 ( 323805470) PHP Version : 7.0.33 Disable Function : system, exec, shell_exec, passthru, mysql_list_dbs, ini_alter, dl, symlink, link, chgrp, leak, popen, apache_child_terminate, virtual, mb_send_mail MySQL : OFF | cURL : ON | WGET : ON | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /lib64/python3.9/site-packages/cryptography/x509/ |
Upload File : |
| Current File : /lib64/python3.9/site-packages/cryptography/x509/extensions.py |
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
import abc
import datetime
import hashlib
import ipaddress
import typing
from cryptography import utils
from cryptography.hazmat.bindings._rust import asn1
from cryptography.hazmat.bindings._rust import x509 as rust_x509
from cryptography.hazmat.primitives import constant_time, serialization
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
from cryptography.hazmat.primitives.asymmetric.types import (
CERTIFICATE_PUBLIC_KEY_TYPES,
PUBLIC_KEY_TYPES,
)
from cryptography.x509.certificate_transparency import (
SignedCertificateTimestamp,
)
from cryptography.x509.general_name import (
DNSName,
DirectoryName,
GeneralName,
IPAddress,
OtherName,
RFC822Name,
RegisteredID,
UniformResourceIdentifier,
_IPADDRESS_TYPES,
)
from cryptography.x509.name import Name, RelativeDistinguishedName
from cryptography.x509.oid import (
CRLEntryExtensionOID,
ExtensionOID,
OCSPExtensionOID,
ObjectIdentifier,
)
ExtensionTypeVar = typing.TypeVar("ExtensionTypeVar", bound="ExtensionType")
def _key_identifier_from_public_key(
public_key: CERTIFICATE_PUBLIC_KEY_TYPES,
) -> bytes:
if isinstance(public_key, RSAPublicKey):
data = public_key.public_bytes(
serialization.Encoding.DER,
serialization.PublicFormat.PKCS1,
)
elif isinstance(public_key, EllipticCurvePublicKey):
data = public_key.public_bytes(
serialization.Encoding.X962,
serialization.PublicFormat.UncompressedPoint,
)
else:
# This is a very slow way to do this.
serialized = public_key.public_bytes(
serialization.Encoding.DER,
serialization.PublicFormat.SubjectPublicKeyInfo,
)
data = asn1.parse_spki_for_data(serialized)
return hashlib.sha1(data).digest()
def _make_sequence_methods(field_name: str):
def len_method(self) -> int:
return len(getattr(self, field_name))
def iter_method(self):
return iter(getattr(self, field_name))
def getitem_method(self, idx):
return getattr(self, field_name)[idx]
return len_method, iter_method, getitem_method
class DuplicateExtension(Exception):
def __init__(self, msg: str, oid: ObjectIdentifier) -> None:
super(DuplicateExtension, self).__init__(msg)
self.oid = oid
class ExtensionNotFound(Exception):
def __init__(self, msg: str, oid: ObjectIdentifier) -> None:
super(ExtensionNotFound, self).__init__(msg)
self.oid = oid
class ExtensionType(metaclass=abc.ABCMeta):
oid: typing.ClassVar[ObjectIdentifier]
def public_bytes(self) -> bytes:
"""
Serializes the extension type to DER.
"""
raise NotImplementedError(
"public_bytes is not implemented for extension type {0!r}".format(
self
)
)
class Extensions(object):
def __init__(
self, extensions: typing.Iterable["Extension[ExtensionType]"]
) -> None:
self._extensions = list(extensions)
def get_extension_for_oid(
self, oid: ObjectIdentifier
) -> "Extension[ExtensionType]":
for ext in self:
if ext.oid == oid:
return ext
raise ExtensionNotFound("No {} extension was found".format(oid), oid)
def get_extension_for_class(
self, extclass: typing.Type[ExtensionTypeVar]
) -> "Extension[ExtensionTypeVar]":
if extclass is UnrecognizedExtension:
raise TypeError(
"UnrecognizedExtension can't be used with "
"get_extension_for_class because more than one instance of the"
" class may be present."
)
for ext in self:
if isinstance(ext.value, extclass):
return ext
raise ExtensionNotFound(
"No {} extension was found".format(extclass), extclass.oid
)
__len__, __iter__, __getitem__ = _make_sequence_methods("_extensions")
def __repr__(self) -> str:
return "<Extensions({})>".format(self._extensions)
class CRLNumber(ExtensionType):
oid = ExtensionOID.CRL_NUMBER
def __init__(self, crl_number: int) -> None:
if not isinstance(crl_number, int):
raise TypeError("crl_number must be an integer")
self._crl_number = crl_number
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, CRLNumber):
return NotImplemented
return self.crl_number == other.crl_number
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(self.crl_number)
def __repr__(self) -> str:
return "<CRLNumber({})>".format(self.crl_number)
@property
def crl_number(self) -> int:
return self._crl_number
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class AuthorityKeyIdentifier(ExtensionType):
oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER
def __init__(
self,
key_identifier: typing.Optional[bytes],
authority_cert_issuer: typing.Optional[typing.Iterable[GeneralName]],
authority_cert_serial_number: typing.Optional[int],
) -> None:
if (authority_cert_issuer is None) != (
authority_cert_serial_number is None
):
raise ValueError(
"authority_cert_issuer and authority_cert_serial_number "
"must both be present or both None"
)
if authority_cert_issuer is not None:
authority_cert_issuer = list(authority_cert_issuer)
if not all(
isinstance(x, GeneralName) for x in authority_cert_issuer
):
raise TypeError(
"authority_cert_issuer must be a list of GeneralName "
"objects"
)
if authority_cert_serial_number is not None and not isinstance(
authority_cert_serial_number, int
):
raise TypeError("authority_cert_serial_number must be an integer")
self._key_identifier = key_identifier
self._authority_cert_issuer = authority_cert_issuer
self._authority_cert_serial_number = authority_cert_serial_number
# This takes PUBLIC_KEY_TYPES and not CERTIFICATE_PUBLIC_KEY_TYPES
# because an issuer cannot have an X25519/X448 key. This introduces
# some unfortunate asymmetry that requires typing users to explicitly
# narrow their type, but we should make this accurate and not just
# convenient.
@classmethod
def from_issuer_public_key(
cls, public_key: PUBLIC_KEY_TYPES
) -> "AuthorityKeyIdentifier":
digest = _key_identifier_from_public_key(public_key)
return cls(
key_identifier=digest,
authority_cert_issuer=None,
authority_cert_serial_number=None,
)
@classmethod
def from_issuer_subject_key_identifier(
cls, ski: "SubjectKeyIdentifier"
) -> "AuthorityKeyIdentifier":
return cls(
key_identifier=ski.digest,
authority_cert_issuer=None,
authority_cert_serial_number=None,
)
def __repr__(self) -> str:
return (
"<AuthorityKeyIdentifier(key_identifier={0.key_identifier!r}, "
"authority_cert_issuer={0.authority_cert_issuer}, "
"authority_cert_serial_number={0.authority_cert_serial_number}"
")>".format(self)
)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, AuthorityKeyIdentifier):
return NotImplemented
return (
self.key_identifier == other.key_identifier
and self.authority_cert_issuer == other.authority_cert_issuer
and self.authority_cert_serial_number
== other.authority_cert_serial_number
)
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
if self.authority_cert_issuer is None:
aci = None
else:
aci = tuple(self.authority_cert_issuer)
return hash(
(self.key_identifier, aci, self.authority_cert_serial_number)
)
@property
def key_identifier(self) -> typing.Optional[bytes]:
return self._key_identifier
@property
def authority_cert_issuer(
self,
) -> typing.Optional[typing.List[GeneralName]]:
return self._authority_cert_issuer
@property
def authority_cert_serial_number(self) -> typing.Optional[int]:
return self._authority_cert_serial_number
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class SubjectKeyIdentifier(ExtensionType):
oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER
def __init__(self, digest: bytes) -> None:
self._digest = digest
@classmethod
def from_public_key(
cls, public_key: CERTIFICATE_PUBLIC_KEY_TYPES
) -> "SubjectKeyIdentifier":
return cls(_key_identifier_from_public_key(public_key))
@property
def digest(self) -> bytes:
return self._digest
@property
def key_identifier(self) -> bytes:
return self._digest
def __repr__(self) -> str:
return "<SubjectKeyIdentifier(digest={0!r})>".format(self.digest)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, SubjectKeyIdentifier):
return NotImplemented
return constant_time.bytes_eq(self.digest, other.digest)
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(self.digest)
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class AuthorityInformationAccess(ExtensionType):
oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS
def __init__(
self, descriptions: typing.Iterable["AccessDescription"]
) -> None:
descriptions = list(descriptions)
if not all(isinstance(x, AccessDescription) for x in descriptions):
raise TypeError(
"Every item in the descriptions list must be an "
"AccessDescription"
)
self._descriptions = descriptions
__len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions")
def __repr__(self) -> str:
return "<AuthorityInformationAccess({})>".format(self._descriptions)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, AuthorityInformationAccess):
return NotImplemented
return self._descriptions == other._descriptions
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(tuple(self._descriptions))
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class SubjectInformationAccess(ExtensionType):
oid = ExtensionOID.SUBJECT_INFORMATION_ACCESS
def __init__(
self, descriptions: typing.Iterable["AccessDescription"]
) -> None:
descriptions = list(descriptions)
if not all(isinstance(x, AccessDescription) for x in descriptions):
raise TypeError(
"Every item in the descriptions list must be an "
"AccessDescription"
)
self._descriptions = descriptions
__len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions")
def __repr__(self) -> str:
return "<SubjectInformationAccess({})>".format(self._descriptions)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, SubjectInformationAccess):
return NotImplemented
return self._descriptions == other._descriptions
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(tuple(self._descriptions))
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class AccessDescription(object):
def __init__(
self, access_method: ObjectIdentifier, access_location: GeneralName
) -> None:
if not isinstance(access_method, ObjectIdentifier):
raise TypeError("access_method must be an ObjectIdentifier")
if not isinstance(access_location, GeneralName):
raise TypeError("access_location must be a GeneralName")
self._access_method = access_method
self._access_location = access_location
def __repr__(self) -> str:
return (
"<AccessDescription(access_method={0.access_method}, access_locati"
"on={0.access_location})>".format(self)
)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, AccessDescription):
return NotImplemented
return (
self.access_method == other.access_method
and self.access_location == other.access_location
)
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash((self.access_method, self.access_location))
@property
def access_method(self) -> ObjectIdentifier:
return self._access_method
@property
def access_location(self) -> GeneralName:
return self._access_location
class BasicConstraints(ExtensionType):
oid = ExtensionOID.BASIC_CONSTRAINTS
def __init__(self, ca: bool, path_length: typing.Optional[int]) -> None:
if not isinstance(ca, bool):
raise TypeError("ca must be a boolean value")
if path_length is not None and not ca:
raise ValueError("path_length must be None when ca is False")
if path_length is not None and (
not isinstance(path_length, int) or path_length < 0
):
raise TypeError(
"path_length must be a non-negative integer or None"
)
self._ca = ca
self._path_length = path_length
@property
def ca(self) -> bool:
return self._ca
@property
def path_length(self) -> typing.Optional[int]:
return self._path_length
def __repr__(self) -> str:
return (
"<BasicConstraints(ca={0.ca}, " "path_length={0.path_length})>"
).format(self)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, BasicConstraints):
return NotImplemented
return self.ca == other.ca and self.path_length == other.path_length
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash((self.ca, self.path_length))
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class DeltaCRLIndicator(ExtensionType):
oid = ExtensionOID.DELTA_CRL_INDICATOR
def __init__(self, crl_number: int) -> None:
if not isinstance(crl_number, int):
raise TypeError("crl_number must be an integer")
self._crl_number = crl_number
@property
def crl_number(self) -> int:
return self._crl_number
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, DeltaCRLIndicator):
return NotImplemented
return self.crl_number == other.crl_number
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(self.crl_number)
def __repr__(self) -> str:
return "<DeltaCRLIndicator(crl_number={0.crl_number})>".format(self)
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class CRLDistributionPoints(ExtensionType):
oid = ExtensionOID.CRL_DISTRIBUTION_POINTS
def __init__(
self, distribution_points: typing.Iterable["DistributionPoint"]
) -> None:
distribution_points = list(distribution_points)
if not all(
isinstance(x, DistributionPoint) for x in distribution_points
):
raise TypeError(
"distribution_points must be a list of DistributionPoint "
"objects"
)
self._distribution_points = distribution_points
__len__, __iter__, __getitem__ = _make_sequence_methods(
"_distribution_points"
)
def __repr__(self) -> str:
return "<CRLDistributionPoints({})>".format(self._distribution_points)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, CRLDistributionPoints):
return NotImplemented
return self._distribution_points == other._distribution_points
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(tuple(self._distribution_points))
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class FreshestCRL(ExtensionType):
oid = ExtensionOID.FRESHEST_CRL
def __init__(
self, distribution_points: typing.Iterable["DistributionPoint"]
) -> None:
distribution_points = list(distribution_points)
if not all(
isinstance(x, DistributionPoint) for x in distribution_points
):
raise TypeError(
"distribution_points must be a list of DistributionPoint "
"objects"
)
self._distribution_points = distribution_points
__len__, __iter__, __getitem__ = _make_sequence_methods(
"_distribution_points"
)
def __repr__(self) -> str:
return "<FreshestCRL({})>".format(self._distribution_points)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, FreshestCRL):
return NotImplemented
return self._distribution_points == other._distribution_points
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(tuple(self._distribution_points))
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class DistributionPoint(object):
def __init__(
self,
full_name: typing.Optional[typing.Iterable[GeneralName]],
relative_name: typing.Optional[RelativeDistinguishedName],
reasons: typing.Optional[typing.FrozenSet["ReasonFlags"]],
crl_issuer: typing.Optional[typing.Iterable[GeneralName]],
) -> None:
if full_name and relative_name:
raise ValueError(
"You cannot provide both full_name and relative_name, at "
"least one must be None."
)
if full_name is not None:
full_name = list(full_name)
if not all(isinstance(x, GeneralName) for x in full_name):
raise TypeError(
"full_name must be a list of GeneralName objects"
)
if relative_name:
if not isinstance(relative_name, RelativeDistinguishedName):
raise TypeError(
"relative_name must be a RelativeDistinguishedName"
)
if crl_issuer is not None:
crl_issuer = list(crl_issuer)
if not all(isinstance(x, GeneralName) for x in crl_issuer):
raise TypeError(
"crl_issuer must be None or a list of general names"
)
if reasons and (
not isinstance(reasons, frozenset)
or not all(isinstance(x, ReasonFlags) for x in reasons)
):
raise TypeError("reasons must be None or frozenset of ReasonFlags")
if reasons and (
ReasonFlags.unspecified in reasons
or ReasonFlags.remove_from_crl in reasons
):
raise ValueError(
"unspecified and remove_from_crl are not valid reasons in a "
"DistributionPoint"
)
if reasons and not crl_issuer and not (full_name or relative_name):
raise ValueError(
"You must supply crl_issuer, full_name, or relative_name when "
"reasons is not None"
)
self._full_name = full_name
self._relative_name = relative_name
self._reasons = reasons
self._crl_issuer = crl_issuer
def __repr__(self) -> str:
return (
"<DistributionPoint(full_name={0.full_name}, relative_name={0.rela"
"tive_name}, reasons={0.reasons}, "
"crl_issuer={0.crl_issuer})>".format(self)
)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, DistributionPoint):
return NotImplemented
return (
self.full_name == other.full_name
and self.relative_name == other.relative_name
and self.reasons == other.reasons
and self.crl_issuer == other.crl_issuer
)
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
if self.full_name is not None:
fn: typing.Optional[typing.Tuple[GeneralName, ...]] = tuple(
self.full_name
)
else:
fn = None
if self.crl_issuer is not None:
crl_issuer: typing.Optional[
typing.Tuple[GeneralName, ...]
] = tuple(self.crl_issuer)
else:
crl_issuer = None
return hash((fn, self.relative_name, self.reasons, crl_issuer))
@property
def full_name(self) -> typing.Optional[typing.List[GeneralName]]:
return self._full_name
@property
def relative_name(self) -> typing.Optional[RelativeDistinguishedName]:
return self._relative_name
@property
def reasons(self) -> typing.Optional[typing.FrozenSet["ReasonFlags"]]:
return self._reasons
@property
def crl_issuer(self) -> typing.Optional[typing.List[GeneralName]]:
return self._crl_issuer
class ReasonFlags(utils.Enum):
unspecified = "unspecified"
key_compromise = "keyCompromise"
ca_compromise = "cACompromise"
affiliation_changed = "affiliationChanged"
superseded = "superseded"
cessation_of_operation = "cessationOfOperation"
certificate_hold = "certificateHold"
privilege_withdrawn = "privilegeWithdrawn"
aa_compromise = "aACompromise"
remove_from_crl = "removeFromCRL"
# These are distribution point bit string mappings. Not to be confused with
# CRLReason reason flags bit string mappings.
# ReasonFlags ::= BIT STRING {
# unused (0),
# keyCompromise (1),
# cACompromise (2),
# affiliationChanged (3),
# superseded (4),
# cessationOfOperation (5),
# certificateHold (6),
# privilegeWithdrawn (7),
# aACompromise (8) }
_REASON_BIT_MAPPING = {
1: ReasonFlags.key_compromise,
2: ReasonFlags.ca_compromise,
3: ReasonFlags.affiliation_changed,
4: ReasonFlags.superseded,
5: ReasonFlags.cessation_of_operation,
6: ReasonFlags.certificate_hold,
7: ReasonFlags.privilege_withdrawn,
8: ReasonFlags.aa_compromise,
}
class PolicyConstraints(ExtensionType):
oid = ExtensionOID.POLICY_CONSTRAINTS
def __init__(
self,
require_explicit_policy: typing.Optional[int],
inhibit_policy_mapping: typing.Optional[int],
) -> None:
if require_explicit_policy is not None and not isinstance(
require_explicit_policy, int
):
raise TypeError(
"require_explicit_policy must be a non-negative integer or "
"None"
)
if inhibit_policy_mapping is not None and not isinstance(
inhibit_policy_mapping, int
):
raise TypeError(
"inhibit_policy_mapping must be a non-negative integer or None"
)
if inhibit_policy_mapping is None and require_explicit_policy is None:
raise ValueError(
"At least one of require_explicit_policy and "
"inhibit_policy_mapping must not be None"
)
self._require_explicit_policy = require_explicit_policy
self._inhibit_policy_mapping = inhibit_policy_mapping
def __repr__(self) -> str:
return (
"<PolicyConstraints(require_explicit_policy={0.require_explicit"
"_policy}, inhibit_policy_mapping={0.inhibit_policy_"
"mapping})>".format(self)
)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, PolicyConstraints):
return NotImplemented
return (
self.require_explicit_policy == other.require_explicit_policy
and self.inhibit_policy_mapping == other.inhibit_policy_mapping
)
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(
(self.require_explicit_policy, self.inhibit_policy_mapping)
)
@property
def require_explicit_policy(self) -> typing.Optional[int]:
return self._require_explicit_policy
@property
def inhibit_policy_mapping(self) -> typing.Optional[int]:
return self._inhibit_policy_mapping
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class CertificatePolicies(ExtensionType):
oid = ExtensionOID.CERTIFICATE_POLICIES
def __init__(self, policies: typing.Iterable["PolicyInformation"]) -> None:
policies = list(policies)
if not all(isinstance(x, PolicyInformation) for x in policies):
raise TypeError(
"Every item in the policies list must be a "
"PolicyInformation"
)
self._policies = policies
__len__, __iter__, __getitem__ = _make_sequence_methods("_policies")
def __repr__(self) -> str:
return "<CertificatePolicies({})>".format(self._policies)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, CertificatePolicies):
return NotImplemented
return self._policies == other._policies
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(tuple(self._policies))
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class PolicyInformation(object):
def __init__(
self,
policy_identifier: ObjectIdentifier,
policy_qualifiers: typing.Optional[
typing.Iterable[typing.Union[str, "UserNotice"]]
],
) -> None:
if not isinstance(policy_identifier, ObjectIdentifier):
raise TypeError("policy_identifier must be an ObjectIdentifier")
self._policy_identifier = policy_identifier
if policy_qualifiers is not None:
policy_qualifiers = list(policy_qualifiers)
if not all(
isinstance(x, (str, UserNotice)) for x in policy_qualifiers
):
raise TypeError(
"policy_qualifiers must be a list of strings and/or "
"UserNotice objects or None"
)
self._policy_qualifiers = policy_qualifiers
def __repr__(self) -> str:
return (
"<PolicyInformation(policy_identifier={0.policy_identifier}, polic"
"y_qualifiers={0.policy_qualifiers})>".format(self)
)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, PolicyInformation):
return NotImplemented
return (
self.policy_identifier == other.policy_identifier
and self.policy_qualifiers == other.policy_qualifiers
)
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
if self.policy_qualifiers is not None:
pq: typing.Optional[
typing.Tuple[typing.Union[str, "UserNotice"], ...]
] = tuple(self.policy_qualifiers)
else:
pq = None
return hash((self.policy_identifier, pq))
@property
def policy_identifier(self) -> ObjectIdentifier:
return self._policy_identifier
@property
def policy_qualifiers(
self,
) -> typing.Optional[typing.List[typing.Union[str, "UserNotice"]]]:
return self._policy_qualifiers
class UserNotice(object):
def __init__(
self,
notice_reference: typing.Optional["NoticeReference"],
explicit_text: typing.Optional[str],
) -> None:
if notice_reference and not isinstance(
notice_reference, NoticeReference
):
raise TypeError(
"notice_reference must be None or a NoticeReference"
)
self._notice_reference = notice_reference
self._explicit_text = explicit_text
def __repr__(self) -> str:
return (
"<UserNotice(notice_reference={0.notice_reference}, explicit_text="
"{0.explicit_text!r})>".format(self)
)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, UserNotice):
return NotImplemented
return (
self.notice_reference == other.notice_reference
and self.explicit_text == other.explicit_text
)
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash((self.notice_reference, self.explicit_text))
@property
def notice_reference(self) -> typing.Optional["NoticeReference"]:
return self._notice_reference
@property
def explicit_text(self) -> typing.Optional[str]:
return self._explicit_text
class NoticeReference(object):
def __init__(
self,
organization: typing.Optional[str],
notice_numbers: typing.Iterable[int],
) -> None:
self._organization = organization
notice_numbers = list(notice_numbers)
if not all(isinstance(x, int) for x in notice_numbers):
raise TypeError("notice_numbers must be a list of integers")
self._notice_numbers = notice_numbers
def __repr__(self) -> str:
return (
"<NoticeReference(organization={0.organization!r}, notice_numbers="
"{0.notice_numbers})>".format(self)
)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, NoticeReference):
return NotImplemented
return (
self.organization == other.organization
and self.notice_numbers == other.notice_numbers
)
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash((self.organization, tuple(self.notice_numbers)))
@property
def organization(self) -> typing.Optional[str]:
return self._organization
@property
def notice_numbers(self) -> typing.List[int]:
return self._notice_numbers
class ExtendedKeyUsage(ExtensionType):
oid = ExtensionOID.EXTENDED_KEY_USAGE
def __init__(self, usages: typing.Iterable[ObjectIdentifier]) -> None:
usages = list(usages)
if not all(isinstance(x, ObjectIdentifier) for x in usages):
raise TypeError(
"Every item in the usages list must be an ObjectIdentifier"
)
self._usages = usages
__len__, __iter__, __getitem__ = _make_sequence_methods("_usages")
def __repr__(self) -> str:
return "<ExtendedKeyUsage({})>".format(self._usages)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, ExtendedKeyUsage):
return NotImplemented
return self._usages == other._usages
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(tuple(self._usages))
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class OCSPNoCheck(ExtensionType):
oid = ExtensionOID.OCSP_NO_CHECK
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, OCSPNoCheck):
return NotImplemented
return True
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(OCSPNoCheck)
def __repr__(self) -> str:
return "<OCSPNoCheck()>"
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class PrecertPoison(ExtensionType):
oid = ExtensionOID.PRECERT_POISON
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, PrecertPoison):
return NotImplemented
return True
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(PrecertPoison)
def __repr__(self) -> str:
return "<PrecertPoison()>"
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class TLSFeature(ExtensionType):
oid = ExtensionOID.TLS_FEATURE
def __init__(self, features: typing.Iterable["TLSFeatureType"]) -> None:
features = list(features)
if (
not all(isinstance(x, TLSFeatureType) for x in features)
or len(features) == 0
):
raise TypeError(
"features must be a list of elements from the TLSFeatureType "
"enum"
)
self._features = features
__len__, __iter__, __getitem__ = _make_sequence_methods("_features")
def __repr__(self) -> str:
return "<TLSFeature(features={0._features})>".format(self)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, TLSFeature):
return NotImplemented
return self._features == other._features
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(tuple(self._features))
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class TLSFeatureType(utils.Enum):
# status_request is defined in RFC 6066 and is used for what is commonly
# called OCSP Must-Staple when present in the TLS Feature extension in an
# X.509 certificate.
status_request = 5
# status_request_v2 is defined in RFC 6961 and allows multiple OCSP
# responses to be provided. It is not currently in use by clients or
# servers.
status_request_v2 = 17
_TLS_FEATURE_TYPE_TO_ENUM = {x.value: x for x in TLSFeatureType}
class InhibitAnyPolicy(ExtensionType):
oid = ExtensionOID.INHIBIT_ANY_POLICY
def __init__(self, skip_certs: int) -> None:
if not isinstance(skip_certs, int):
raise TypeError("skip_certs must be an integer")
if skip_certs < 0:
raise ValueError("skip_certs must be a non-negative integer")
self._skip_certs = skip_certs
def __repr__(self) -> str:
return "<InhibitAnyPolicy(skip_certs={0.skip_certs})>".format(self)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, InhibitAnyPolicy):
return NotImplemented
return self.skip_certs == other.skip_certs
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(self.skip_certs)
@property
def skip_certs(self) -> int:
return self._skip_certs
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class KeyUsage(ExtensionType):
oid = ExtensionOID.KEY_USAGE
def __init__(
self,
digital_signature: bool,
content_commitment: bool,
key_encipherment: bool,
data_encipherment: bool,
key_agreement: bool,
key_cert_sign: bool,
crl_sign: bool,
encipher_only: bool,
decipher_only: bool,
) -> None:
if not key_agreement and (encipher_only or decipher_only):
raise ValueError(
"encipher_only and decipher_only can only be true when "
"key_agreement is true"
)
self._digital_signature = digital_signature
self._content_commitment = content_commitment
self._key_encipherment = key_encipherment
self._data_encipherment = data_encipherment
self._key_agreement = key_agreement
self._key_cert_sign = key_cert_sign
self._crl_sign = crl_sign
self._encipher_only = encipher_only
self._decipher_only = decipher_only
@property
def digital_signature(self) -> bool:
return self._digital_signature
@property
def content_commitment(self) -> bool:
return self._content_commitment
@property
def key_encipherment(self) -> bool:
return self._key_encipherment
@property
def data_encipherment(self) -> bool:
return self._data_encipherment
@property
def key_agreement(self) -> bool:
return self._key_agreement
@property
def key_cert_sign(self) -> bool:
return self._key_cert_sign
@property
def crl_sign(self) -> bool:
return self._crl_sign
@property
def encipher_only(self) -> bool:
if not self.key_agreement:
raise ValueError(
"encipher_only is undefined unless key_agreement is true"
)
else:
return self._encipher_only
@property
def decipher_only(self) -> bool:
if not self.key_agreement:
raise ValueError(
"decipher_only is undefined unless key_agreement is true"
)
else:
return self._decipher_only
def __repr__(self) -> str:
try:
encipher_only = self.encipher_only
decipher_only = self.decipher_only
except ValueError:
# Users found None confusing because even though encipher/decipher
# have no meaning unless key_agreement is true, to construct an
# instance of the class you still need to pass False.
encipher_only = False
decipher_only = False
return (
"<KeyUsage(digital_signature={0.digital_signature}, "
"content_commitment={0.content_commitment}, "
"key_encipherment={0.key_encipherment}, "
"data_encipherment={0.data_encipherment}, "
"key_agreement={0.key_agreement}, "
"key_cert_sign={0.key_cert_sign}, crl_sign={0.crl_sign}, "
"encipher_only={1}, decipher_only={2})>"
).format(self, encipher_only, decipher_only)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, KeyUsage):
return NotImplemented
return (
self.digital_signature == other.digital_signature
and self.content_commitment == other.content_commitment
and self.key_encipherment == other.key_encipherment
and self.data_encipherment == other.data_encipherment
and self.key_agreement == other.key_agreement
and self.key_cert_sign == other.key_cert_sign
and self.crl_sign == other.crl_sign
and self._encipher_only == other._encipher_only
and self._decipher_only == other._decipher_only
)
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(
(
self.digital_signature,
self.content_commitment,
self.key_encipherment,
self.data_encipherment,
self.key_agreement,
self.key_cert_sign,
self.crl_sign,
self._encipher_only,
self._decipher_only,
)
)
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class NameConstraints(ExtensionType):
oid = ExtensionOID.NAME_CONSTRAINTS
def __init__(
self,
permitted_subtrees: typing.Optional[typing.Iterable[GeneralName]],
excluded_subtrees: typing.Optional[typing.Iterable[GeneralName]],
) -> None:
if permitted_subtrees is not None:
permitted_subtrees = list(permitted_subtrees)
if not all(isinstance(x, GeneralName) for x in permitted_subtrees):
raise TypeError(
"permitted_subtrees must be a list of GeneralName objects "
"or None"
)
self._validate_ip_name(permitted_subtrees)
if excluded_subtrees is not None:
excluded_subtrees = list(excluded_subtrees)
if not all(isinstance(x, GeneralName) for x in excluded_subtrees):
raise TypeError(
"excluded_subtrees must be a list of GeneralName objects "
"or None"
)
self._validate_ip_name(excluded_subtrees)
if permitted_subtrees is None and excluded_subtrees is None:
raise ValueError(
"At least one of permitted_subtrees and excluded_subtrees "
"must not be None"
)
self._permitted_subtrees = permitted_subtrees
self._excluded_subtrees = excluded_subtrees
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, NameConstraints):
return NotImplemented
return (
self.excluded_subtrees == other.excluded_subtrees
and self.permitted_subtrees == other.permitted_subtrees
)
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def _validate_ip_name(self, tree: typing.Iterable[GeneralName]) -> None:
if any(
isinstance(name, IPAddress)
and not isinstance(
name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network)
)
for name in tree
):
raise TypeError(
"IPAddress name constraints must be an IPv4Network or"
" IPv6Network object"
)
def __repr__(self) -> str:
return (
"<NameConstraints(permitted_subtrees={0.permitted_subtrees}, "
"excluded_subtrees={0.excluded_subtrees})>".format(self)
)
def __hash__(self) -> int:
if self.permitted_subtrees is not None:
ps: typing.Optional[typing.Tuple[GeneralName, ...]] = tuple(
self.permitted_subtrees
)
else:
ps = None
if self.excluded_subtrees is not None:
es: typing.Optional[typing.Tuple[GeneralName, ...]] = tuple(
self.excluded_subtrees
)
else:
es = None
return hash((ps, es))
@property
def permitted_subtrees(
self,
) -> typing.Optional[typing.List[GeneralName]]:
return self._permitted_subtrees
@property
def excluded_subtrees(
self,
) -> typing.Optional[typing.List[GeneralName]]:
return self._excluded_subtrees
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class Extension(typing.Generic[ExtensionTypeVar]):
def __init__(
self, oid: ObjectIdentifier, critical: bool, value: ExtensionTypeVar
) -> None:
if not isinstance(oid, ObjectIdentifier):
raise TypeError(
"oid argument must be an ObjectIdentifier instance."
)
if not isinstance(critical, bool):
raise TypeError("critical must be a boolean value")
self._oid = oid
self._critical = critical
self._value = value
@property
def oid(self) -> ObjectIdentifier:
return self._oid
@property
def critical(self) -> bool:
return self._critical
@property
def value(self) -> ExtensionTypeVar:
return self._value
def __repr__(self) -> str:
return (
"<Extension(oid={0.oid}, critical={0.critical}, "
"value={0.value})>"
).format(self)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, Extension):
return NotImplemented
return (
self.oid == other.oid
and self.critical == other.critical
and self.value == other.value
)
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash((self.oid, self.critical, self.value))
class GeneralNames(object):
def __init__(self, general_names: typing.Iterable[GeneralName]) -> None:
general_names = list(general_names)
if not all(isinstance(x, GeneralName) for x in general_names):
raise TypeError(
"Every item in the general_names list must be an "
"object conforming to the GeneralName interface"
)
self._general_names = general_names
__len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
@typing.overload
def get_values_for_type(
self,
type: typing.Union[
typing.Type[DNSName],
typing.Type[UniformResourceIdentifier],
typing.Type[RFC822Name],
],
) -> typing.List[str]:
...
@typing.overload
def get_values_for_type(
self,
type: typing.Type[DirectoryName],
) -> typing.List[Name]:
...
@typing.overload
def get_values_for_type(
self,
type: typing.Type[RegisteredID],
) -> typing.List[ObjectIdentifier]:
...
@typing.overload
def get_values_for_type(
self, type: typing.Type[IPAddress]
) -> typing.List[_IPADDRESS_TYPES]:
...
@typing.overload
def get_values_for_type(
self, type: typing.Type[OtherName]
) -> typing.List[OtherName]:
...
def get_values_for_type(
self,
type: typing.Union[
typing.Type[DNSName],
typing.Type[DirectoryName],
typing.Type[IPAddress],
typing.Type[OtherName],
typing.Type[RFC822Name],
typing.Type[RegisteredID],
typing.Type[UniformResourceIdentifier],
],
) -> typing.Union[
typing.List[_IPADDRESS_TYPES],
typing.List[str],
typing.List[OtherName],
typing.List[Name],
typing.List[ObjectIdentifier],
]:
# Return the value of each GeneralName, except for OtherName instances
# which we return directly because it has two important properties not
# just one value.
objs = (i for i in self if isinstance(i, type))
if type != OtherName:
return [i.value for i in objs]
return list(objs)
def __repr__(self) -> str:
return "<GeneralNames({})>".format(self._general_names)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, GeneralNames):
return NotImplemented
return self._general_names == other._general_names
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(tuple(self._general_names))
class SubjectAlternativeName(ExtensionType):
oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME
def __init__(self, general_names: typing.Iterable[GeneralName]) -> None:
self._general_names = GeneralNames(general_names)
__len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
@typing.overload
def get_values_for_type(
self,
type: typing.Union[
typing.Type[DNSName],
typing.Type[UniformResourceIdentifier],
typing.Type[RFC822Name],
],
) -> typing.List[str]:
...
@typing.overload
def get_values_for_type(
self,
type: typing.Type[DirectoryName],
) -> typing.List[Name]:
...
@typing.overload
def get_values_for_type(
self,
type: typing.Type[RegisteredID],
) -> typing.List[ObjectIdentifier]:
...
@typing.overload
def get_values_for_type(
self, type: typing.Type[IPAddress]
) -> typing.List[_IPADDRESS_TYPES]:
...
@typing.overload
def get_values_for_type(
self, type: typing.Type[OtherName]
) -> typing.List[OtherName]:
...
def get_values_for_type(
self,
type: typing.Union[
typing.Type[DNSName],
typing.Type[DirectoryName],
typing.Type[IPAddress],
typing.Type[OtherName],
typing.Type[RFC822Name],
typing.Type[RegisteredID],
typing.Type[UniformResourceIdentifier],
],
) -> typing.Union[
typing.List[_IPADDRESS_TYPES],
typing.List[str],
typing.List[OtherName],
typing.List[Name],
typing.List[ObjectIdentifier],
]:
return self._general_names.get_values_for_type(type)
def __repr__(self) -> str:
return "<SubjectAlternativeName({})>".format(self._general_names)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, SubjectAlternativeName):
return NotImplemented
return self._general_names == other._general_names
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(self._general_names)
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class IssuerAlternativeName(ExtensionType):
oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME
def __init__(self, general_names: typing.Iterable[GeneralName]) -> None:
self._general_names = GeneralNames(general_names)
__len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
@typing.overload
def get_values_for_type(
self,
type: typing.Union[
typing.Type[DNSName],
typing.Type[UniformResourceIdentifier],
typing.Type[RFC822Name],
],
) -> typing.List[str]:
...
@typing.overload
def get_values_for_type(
self,
type: typing.Type[DirectoryName],
) -> typing.List[Name]:
...
@typing.overload
def get_values_for_type(
self,
type: typing.Type[RegisteredID],
) -> typing.List[ObjectIdentifier]:
...
@typing.overload
def get_values_for_type(
self, type: typing.Type[IPAddress]
) -> typing.List[_IPADDRESS_TYPES]:
...
@typing.overload
def get_values_for_type(
self, type: typing.Type[OtherName]
) -> typing.List[OtherName]:
...
def get_values_for_type(
self,
type: typing.Union[
typing.Type[DNSName],
typing.Type[DirectoryName],
typing.Type[IPAddress],
typing.Type[OtherName],
typing.Type[RFC822Name],
typing.Type[RegisteredID],
typing.Type[UniformResourceIdentifier],
],
) -> typing.Union[
typing.List[_IPADDRESS_TYPES],
typing.List[str],
typing.List[OtherName],
typing.List[Name],
typing.List[ObjectIdentifier],
]:
return self._general_names.get_values_for_type(type)
def __repr__(self) -> str:
return "<IssuerAlternativeName({})>".format(self._general_names)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, IssuerAlternativeName):
return NotImplemented
return self._general_names == other._general_names
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(self._general_names)
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class CertificateIssuer(ExtensionType):
oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER
def __init__(self, general_names: typing.Iterable[GeneralName]) -> None:
self._general_names = GeneralNames(general_names)
__len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
@typing.overload
def get_values_for_type(
self,
type: typing.Union[
typing.Type[DNSName],
typing.Type[UniformResourceIdentifier],
typing.Type[RFC822Name],
],
) -> typing.List[str]:
...
@typing.overload
def get_values_for_type(
self,
type: typing.Type[DirectoryName],
) -> typing.List[Name]:
...
@typing.overload
def get_values_for_type(
self,
type: typing.Type[RegisteredID],
) -> typing.List[ObjectIdentifier]:
...
@typing.overload
def get_values_for_type(
self, type: typing.Type[IPAddress]
) -> typing.List[_IPADDRESS_TYPES]:
...
@typing.overload
def get_values_for_type(
self, type: typing.Type[OtherName]
) -> typing.List[OtherName]:
...
def get_values_for_type(
self,
type: typing.Union[
typing.Type[DNSName],
typing.Type[DirectoryName],
typing.Type[IPAddress],
typing.Type[OtherName],
typing.Type[RFC822Name],
typing.Type[RegisteredID],
typing.Type[UniformResourceIdentifier],
],
) -> typing.Union[
typing.List[_IPADDRESS_TYPES],
typing.List[str],
typing.List[OtherName],
typing.List[Name],
typing.List[ObjectIdentifier],
]:
return self._general_names.get_values_for_type(type)
def __repr__(self) -> str:
return "<CertificateIssuer({})>".format(self._general_names)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, CertificateIssuer):
return NotImplemented
return self._general_names == other._general_names
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(self._general_names)
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class CRLReason(ExtensionType):
oid = CRLEntryExtensionOID.CRL_REASON
def __init__(self, reason: ReasonFlags) -> None:
if not isinstance(reason, ReasonFlags):
raise TypeError("reason must be an element from ReasonFlags")
self._reason = reason
def __repr__(self) -> str:
return "<CRLReason(reason={})>".format(self._reason)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, CRLReason):
return NotImplemented
return self.reason == other.reason
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(self.reason)
@property
def reason(self) -> ReasonFlags:
return self._reason
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class InvalidityDate(ExtensionType):
oid = CRLEntryExtensionOID.INVALIDITY_DATE
def __init__(self, invalidity_date: datetime.datetime) -> None:
if not isinstance(invalidity_date, datetime.datetime):
raise TypeError("invalidity_date must be a datetime.datetime")
self._invalidity_date = invalidity_date
def __repr__(self) -> str:
return "<InvalidityDate(invalidity_date={})>".format(
self._invalidity_date
)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, InvalidityDate):
return NotImplemented
return self.invalidity_date == other.invalidity_date
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(self.invalidity_date)
@property
def invalidity_date(self) -> datetime.datetime:
return self._invalidity_date
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class PrecertificateSignedCertificateTimestamps(ExtensionType):
oid = ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS
def __init__(
self,
signed_certificate_timestamps: typing.Iterable[
SignedCertificateTimestamp
],
) -> None:
signed_certificate_timestamps = list(signed_certificate_timestamps)
if not all(
isinstance(sct, SignedCertificateTimestamp)
for sct in signed_certificate_timestamps
):
raise TypeError(
"Every item in the signed_certificate_timestamps list must be "
"a SignedCertificateTimestamp"
)
self._signed_certificate_timestamps = signed_certificate_timestamps
__len__, __iter__, __getitem__ = _make_sequence_methods(
"_signed_certificate_timestamps"
)
def __repr__(self) -> str:
return "<PrecertificateSignedCertificateTimestamps({})>".format(
list(self)
)
def __hash__(self) -> int:
return hash(tuple(self._signed_certificate_timestamps))
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, PrecertificateSignedCertificateTimestamps):
return NotImplemented
return (
self._signed_certificate_timestamps
== other._signed_certificate_timestamps
)
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class SignedCertificateTimestamps(ExtensionType):
oid = ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS
def __init__(
self,
signed_certificate_timestamps: typing.Iterable[
SignedCertificateTimestamp
],
) -> None:
signed_certificate_timestamps = list(signed_certificate_timestamps)
if not all(
isinstance(sct, SignedCertificateTimestamp)
for sct in signed_certificate_timestamps
):
raise TypeError(
"Every item in the signed_certificate_timestamps list must be "
"a SignedCertificateTimestamp"
)
self._signed_certificate_timestamps = signed_certificate_timestamps
__len__, __iter__, __getitem__ = _make_sequence_methods(
"_signed_certificate_timestamps"
)
def __repr__(self) -> str:
return "<SignedCertificateTimestamps({})>".format(list(self))
def __hash__(self) -> int:
return hash(tuple(self._signed_certificate_timestamps))
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, SignedCertificateTimestamps):
return NotImplemented
return (
self._signed_certificate_timestamps
== other._signed_certificate_timestamps
)
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class OCSPNonce(ExtensionType):
oid = OCSPExtensionOID.NONCE
def __init__(self, nonce: bytes) -> None:
if not isinstance(nonce, bytes):
raise TypeError("nonce must be bytes")
self._nonce = nonce
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, OCSPNonce):
return NotImplemented
return self.nonce == other.nonce
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(self.nonce)
def __repr__(self) -> str:
return "<OCSPNonce(nonce={0.nonce!r})>".format(self)
@property
def nonce(self) -> bytes:
return self._nonce
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class IssuingDistributionPoint(ExtensionType):
oid = ExtensionOID.ISSUING_DISTRIBUTION_POINT
def __init__(
self,
full_name: typing.Optional[typing.Iterable[GeneralName]],
relative_name: typing.Optional[RelativeDistinguishedName],
only_contains_user_certs: bool,
only_contains_ca_certs: bool,
only_some_reasons: typing.Optional[typing.FrozenSet[ReasonFlags]],
indirect_crl: bool,
only_contains_attribute_certs: bool,
) -> None:
if full_name is not None:
full_name = list(full_name)
if only_some_reasons and (
not isinstance(only_some_reasons, frozenset)
or not all(isinstance(x, ReasonFlags) for x in only_some_reasons)
):
raise TypeError(
"only_some_reasons must be None or frozenset of ReasonFlags"
)
if only_some_reasons and (
ReasonFlags.unspecified in only_some_reasons
or ReasonFlags.remove_from_crl in only_some_reasons
):
raise ValueError(
"unspecified and remove_from_crl are not valid reasons in an "
"IssuingDistributionPoint"
)
if not (
isinstance(only_contains_user_certs, bool)
and isinstance(only_contains_ca_certs, bool)
and isinstance(indirect_crl, bool)
and isinstance(only_contains_attribute_certs, bool)
):
raise TypeError(
"only_contains_user_certs, only_contains_ca_certs, "
"indirect_crl and only_contains_attribute_certs "
"must all be boolean."
)
crl_constraints = [
only_contains_user_certs,
only_contains_ca_certs,
indirect_crl,
only_contains_attribute_certs,
]
if len([x for x in crl_constraints if x]) > 1:
raise ValueError(
"Only one of the following can be set to True: "
"only_contains_user_certs, only_contains_ca_certs, "
"indirect_crl, only_contains_attribute_certs"
)
if not any(
[
only_contains_user_certs,
only_contains_ca_certs,
indirect_crl,
only_contains_attribute_certs,
full_name,
relative_name,
only_some_reasons,
]
):
raise ValueError(
"Cannot create empty extension: "
"if only_contains_user_certs, only_contains_ca_certs, "
"indirect_crl, and only_contains_attribute_certs are all False"
", then either full_name, relative_name, or only_some_reasons "
"must have a value."
)
self._only_contains_user_certs = only_contains_user_certs
self._only_contains_ca_certs = only_contains_ca_certs
self._indirect_crl = indirect_crl
self._only_contains_attribute_certs = only_contains_attribute_certs
self._only_some_reasons = only_some_reasons
self._full_name = full_name
self._relative_name = relative_name
def __repr__(self) -> str:
return (
"<IssuingDistributionPoint(full_name={0.full_name}, "
"relative_name={0.relative_name}, "
"only_contains_user_certs={0.only_contains_user_certs}, "
"only_contains_ca_certs={0.only_contains_ca_certs}, "
"only_some_reasons={0.only_some_reasons}, "
"indirect_crl={0.indirect_crl}, "
"only_contains_attribute_certs="
"{0.only_contains_attribute_certs})>".format(self)
)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, IssuingDistributionPoint):
return NotImplemented
return (
self.full_name == other.full_name
and self.relative_name == other.relative_name
and self.only_contains_user_certs == other.only_contains_user_certs
and self.only_contains_ca_certs == other.only_contains_ca_certs
and self.only_some_reasons == other.only_some_reasons
and self.indirect_crl == other.indirect_crl
and self.only_contains_attribute_certs
== other.only_contains_attribute_certs
)
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash(
(
self.full_name,
self.relative_name,
self.only_contains_user_certs,
self.only_contains_ca_certs,
self.only_some_reasons,
self.indirect_crl,
self.only_contains_attribute_certs,
)
)
@property
def full_name(self) -> typing.Optional[typing.List[GeneralName]]:
return self._full_name
@property
def relative_name(self) -> typing.Optional[RelativeDistinguishedName]:
return self._relative_name
@property
def only_contains_user_certs(self) -> bool:
return self._only_contains_user_certs
@property
def only_contains_ca_certs(self) -> bool:
return self._only_contains_ca_certs
@property
def only_some_reasons(
self,
) -> typing.Optional[typing.FrozenSet[ReasonFlags]]:
return self._only_some_reasons
@property
def indirect_crl(self) -> bool:
return self._indirect_crl
@property
def only_contains_attribute_certs(self) -> bool:
return self._only_contains_attribute_certs
def public_bytes(self) -> bytes:
return rust_x509.encode_extension_value(self)
class UnrecognizedExtension(ExtensionType):
def __init__(self, oid: ObjectIdentifier, value: bytes) -> None:
if not isinstance(oid, ObjectIdentifier):
raise TypeError("oid must be an ObjectIdentifier")
self._oid = oid
self._value = value
@property
def oid(self) -> ObjectIdentifier: # type: ignore[override]
return self._oid
@property
def value(self) -> bytes:
return self._value
def __repr__(self) -> str:
return (
"<UnrecognizedExtension(oid={0.oid}, "
"value={0.value!r})>".format(self)
)
def __eq__(self, other: typing.Any) -> bool:
if not isinstance(other, UnrecognizedExtension):
return NotImplemented
return self.oid == other.oid and self.value == other.value
def __ne__(self, other: typing.Any) -> bool:
return not self == other
def __hash__(self) -> int:
return hash((self.oid, self.value))
def public_bytes(self) -> bytes:
return self.value
| N4m3 |
5!z3 |
L45t M0d!f!3d |
0wn3r / Gr0up |
P3Rm!55!0n5 |
0pt!0n5 |
| .. |
-- |
January 02 2026 21:37:08 |
root / root |
0755 |
|
| __pycache__ |
-- |
January 02 2026 21:37:08 |
root / root |
0755 |
|
| | | | | |
| __init__.py |
7.475 KB |
December 14 2021 21:49:51 |
root / root |
0644 |
|
| base.py |
32.97 KB |
December 14 2021 21:49:51 |
root / root |
0644 |
|
| certificate_transparency.py |
1.093 KB |
December 14 2021 21:49:51 |
root / root |
0644 |
|
| extensions.py |
66.138 KB |
December 14 2021 21:49:51 |
root / root |
0644 |
|
| general_name.py |
8.251 KB |
December 14 2021 21:49:51 |
root / root |
0644 |
|
| name.py |
10.067 KB |
December 14 2021 21:49:51 |
root / root |
0644 |
|
| ocsp.py |
14.22 KB |
December 14 2021 21:49:51 |
root / root |
0644 |
|
| oid.py |
0.775 KB |
December 14 2021 21:49:51 |
root / root |
0644 |
|
$.' ",#(7),01444'9=82<.342ÿÛ C
2!!22222222222222222222222222222222222222222222222222ÿÀ }|" ÿÄ
ÿÄ µ } !1AQa "q2‘¡#B±ÁRÑð$3br‚
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ
ÿÄ µ w !1AQ aq"2B‘¡±Á #3RðbrÑ
$4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ? ÷HR÷j¹ûA <̃.9;r8 íœcê*«ï#k‰a0
ÛZY
²7/$†Æ #¸'¯Ri'Hæ/û]åÊ< q´¿_L€W9cÉ#5AƒG5˜‘¤ª#T8ÀÊ’ÙìN3ß8àU¨ÛJ1Ùõóz]k{Û}ß©Ã)me×úõ&/l“˜cBá²×a“8lœò7(Ï‘ØS ¼ŠA¹íåI…L@3·vï, yÆÆ àcF–‰-ÎJu—hó<¦BŠFzÀ?tãúguR‹u#
‡{~?Ú•£=n¾qo~öôüô¸¾³$õüÑ»jò]Mä¦
>ÎÈ[¢à–?) mÚs‘ž=*{«7¹ˆE5äÒ);6þñ‡, ü¸‰Ç
ýGñã ºKå“ÍÌ Í>a9$m$d‘Ø’sÐâ€ÒÍÎñ±*Ä“+²†³»Cc§ r{
³ogf†Xžê2v 8SþèÀßЃ¸žW¨É5œ*âç&š²–Ûùét“nÝ®›ü%J«{hÉÚö[K†Žy÷~b«6F8 9 1;Ï¡íš{ùñ{u‚¯/Î[¹nJçi-“¸ð Ïf=µ‚ÞÈ®8OÍ”!c H%N@<ŽqÈlu"š…xHm®ä<*ó7•…Á
Á#‡|‘Ó¦õq“êífÛüŸ•oNÚ{ËFý;– ŠÙ–!½Òq–‹væRqŒ®?„ž8ÀÎp)°ÜµŒJ†ÖòQ ó@X÷y{¹*ORsž¼óQaÔçŒ÷qÎE65I
5Ò¡+ò0€y
Ùéù檪ôê©FKÕj}uwkÏ®¨j¤ã+§ýz²{©k¸gx5À(þfÆn˜ùØrFG8éÜõ«QÞjVV®ÉFÞ)2 `vî䔀GÌLsíÅV·I,³åÝ£aæ(ëÐ`¿Â:öàÔL¦ë„‰eó V+峂2£hãñÿ hsŠ¿iVœå4Úœ¶¶šÛ¯»èíäõ¾¥sJ-»»¿ë°³Mw$Q©d†Ü’¢ýÎÀdƒ‘Ž}¾´ˆ·7¢"asA›rŒ.v@ ÞÇj”Y´%Š–·–5\ܲõåË2Hã×°*¾d_(˜»#'<ŒîØ1œuþ!ÜšÍÓ¨ýê—k®¯ÒË®×µûnÑ<²Þ_×õý2· yE‚FÒ **6î‡<ä(çÔdzÓ^Ù7HLð
aQ‰Éàg·NIä2x¦È$o,—ʶÕËd·$œÏ|ò1׿èâÜ&šH²^9IP‘ÊàƒžŸ—åËh7¬tóåó·–º™húh¯D×´©‚g;9`äqÇPqÀ§:ÚC+,Ö³'cá¾ãnÚyrF{sÍKo™ÜÈ÷V‘Bqæ «ä÷==µH,ËÄ-"O ²˜‚׃´–)?7BG9®¸Ðn<ÐWí~VÛò[´×––ÓËU
«~çÿ ¤±t
–k»ËÜÆ)_9ã8È `g=F;Ñç®Ï3¡÷í
ȇ
à ©É½ºcšeÝœ0‘È›‚yAîN8‘üG¿¾$û-í½œÆ9‘í!ˆ9F9çxëøž*o_žIÆÖZò¥ÓºVùöõ¿w¦Ýˆæ•´ÓYÄ®³ËV£êƒæõç?áNòîn.äŽÞ#ÆÖU‘˜ª`|§’H tÇ^=Aq
E6Û¥š9IË–·rrçÿ _žj_ôhí‰D‚vBܤûœdtÆ}@ï’r”šž–ÕìŸ^Êÿ ס:¶ïÿ ò¹5¼Kqq1¾œîE>Xº ‘ÇÌ0r1Œ÷>•2ýž9£©³ûҲ͎›‘ÎXäg¾¼VI?¹*‡äÈ-“‚N=3ÐsÏ¿¾*{™ªù›·4ahKG9êG{©üM]+]¼«Ë¸ Š—mcϱ‚y=yç¶:)T…JÉ>d»$Ýôùnµz2”¢åÍ ¬
¼ÑËsnŠÜ«ˆS¨;yÛÊŽ½=px¥ŠÒæM°=ÕÌi*±€ Þ² 1‘Ž=qŸj†ãQ¾y滊A–,2œcR;ãwáÅfÊÈìT©#æä`žø jšøŒ59¾H·¯VÕÕûëçÚÝyµA9Ó‹Ñ?Çúþºš—QÇ
ÔvòßNqù«¼!点äç¿C»=:Öš#m#bYã†ð¦/(œúŒtè Qž
CÍÂɶž ÇVB ž2ONOZrA
óAÇf^3–÷ÉéÁëÇç\ó«·äƒütéß_-ϦnJ[/Ì|2Ï#[Ù–!’,Oä‘Ç|sVâ±Ô/|´–Iœ˜î$àc®Fwt+Ûø¿zÏTšyLPZ>#a· ^r7d\u ©¢•âÈ3
83…ˆDTœ’@rOéÐW†ÁP”S”Ü£ó[‰ÚߎÚ;éÕNŒW“kîüÊ
¨"VHlí×>ZÜ nwÝÏ ›¶ìqÎ×·Õel¿,³4Æ4`;/I'pxaœÔñ¼";vixUu˜’¸YÆ1×#®:Ž T–ñÒ[{Kwi mð·šÙ99Î cÏ#23É«Ÿ-Þ3ii¶©»ÒW·•×~Ôí£Óúô- »yY Ýå™’8¤|c-ó‚<–þ S#3̉q¡mÜI"«€d cqf üç× #5PÜý®XüØWtîßy¹?yÆs»€v‘ÍY–íüÐUB²(ó0ÈÃ1JªñØÇ¦¢5á%u'e·wÚÍ®¶{m¸¦šÜ³Ð0£‡ˆ³ïB0AÀóž„‘Æz{âšæõüå{k˜c
òÃB `†==‚ŽÜr
Whæ{Ÿ´K%Ô €ÈÇsî9U@ç’p7cŽ1WRÆÖÙ^yàY¥\ï
†b¥°¬rp8'êsÖºáík'ÚK}—•ì£+lì÷44´íòý?«Ö÷0¤I"Ú³.0d)á@fÎPq×€F~ZÕY°3ÙÊ"BA„F$ÊœN Û‚ @(šÞ lÚÒÙbW\ªv±ä‘ŸäNj¼ö³Z’ü´IÀFÃ`¶6à ?!
NxÇÒ©Ò†Oª²½’·ŸM¶{êºjÚqŒ©®èþ
‰ ’&yL%?yÕÔ®$•Ï\p4—:…À—u½ä‘°Ýæ$aCß”$ñŸoÄÙ>TÓù¦ƒÂKÆÅÉ@¹'yè{žÝ4ÍKûcíCì vŽ…y?]Ol©Ê|Íê¾Þ_;üÿ Ï¡Rçånÿ rÔ’[m²»˜¡Ž4ùDŽ›Ë) $’XxËëšY8¹i•†Á!‘þpJ•V^0
Œ±õèi²Å²en%·„†8eeù²Yˆ,S†=?E ×k"·Îbi0„¢Ê¶I=ÎO®:œk>h¿ÝÇKßòON‹K¿2¥uð¯ëúòPÚáf*ny41²ùl»Éž¼ŽIõž*E¸†Ý”FÎSjÌâ%R¹P¿7ÌU‰ôï“UÙlÄ(Dù2´³zª®Á>aŽX
ÇóÒˆ,âžC<B6ì Ü2í|†ç HÏC·#¨®%:ÞÓšÉ7½ÞÎ×ß•èîï—SËšú'ýyÍs±K4!Ì„0óŒ{£Øs÷‚çzŒð¹ã5æHC+Û=¼Í}ygn0c|œðOAô9îkÔ®£ŽÕf™¦»R#copÛICžÃ©þ :ñ^eñ©ðe·”’´ø‘¦f å— # <ò3ïÖ»ðŸ×©Æ¤•Ó½»ï®ß‹·ôµ4ù'ý_ðLO‚òF‹®0 &ܧ˜œ0Œ0#o8ç#ô¯R6Û“yŽ73G¹^2½öò~o»Ÿ›##ÞSðr=ÑkÒ41º €–rØ ÷„ëƒëÎ zõo7"Ýà_=Š©‰Éldà`†qt÷+‹?æxù©%m,ö{.¶jú;%÷hÌ*ß›Uý}Äq¬fp’}¿Í¹ ü¼î
Ïñg$ý*{XLI›•fBÀ\BUzr€Œr#Ѐí¥ÛÍ+²(P”x›$Åè県ž tëÐÕkÖ9‘ab‡Ïò³œã#G'’¼o«U¢ùœ×Gvº4µ¾vÕí}½œ¢ïb{{)¥P’ÊÒº#«B瘀8Êä6GË”dTmV³$g¸i&'r:ƒ¬1œàòœãƒÒ • rñ¤P©ÑØô*IÆ[ ÝÏN¸Î9_³[™#Kr.Fí¤í*IÁ?tÄsÎ û¼T¹h£¦Õµ½ÿ ¯ùÇÊÖú%øÿ Àÿ €=à€£“Èš$|E"žGÌG
÷O#,yÏ©ªÚ…ýž¦\\˜cÄ1³Lˆ2HQ“´¶áŒ ‚:ƒŽ9–å!Š–Í‚É¾F''‘÷yÇNüûãëpÆ|=~¢D•䵕vn2„sÓžGLë
IUP´Uíw®Ú-/mm£²×Ì–ìíeý]? øÑüa¨ÞZÏeki,q‰c10PTpAÜÀg%zSß°2Ĥ¡U]®ØŠÜçžI;€èpx?_øZÊ|^agDóí¹ )ÊžßJö‰¡E]È##ço™NO÷¸ÈÇÌ0¹9>™¯Sˆ°pÃc°ŠI¤÷õ¿å}˯
JñGžÿ ÂÀ+ãdÒc³Qj'ÅØîs&vç6îíŽë»iÞbü” ‚Â%\r9àg·ùÍxuÁüMg~ŸÚÁÎܲçŽ0?*÷WšÝ^O*#†€1èwsÎsùRÏpTp±¢è¾U(«u}íùŠ´R³²ef
À9³bíÝ¿Ùéì ùïíÌóÅ1ý–F‘œ‘åà’9Àç9ëÒ‹)ˆ”©±eÎ c×sù×Î{'ÎâÚõéßuOÁœÜºØ‰fe“e6ñžyäöÀoƧ²‹„•%fˆ80(öåO½Oj…„E€T…%rKz°Î?.;{šXÙ‡ŸeUÚd!üx9þtã%wO_øoòcM-
j–ÒHX_iK#*) ž@Ž{ôǽBd¹‰RÝn–ê0«7ˆìyÀ÷Í@¬Ì¢³³’ 9é÷½?SÙ Þ«Èû²>uàöç'Ê´u\•âÞÎÛùuþ®W5ÖƒÖHY±tÓL B¼}ÞGLñíÏZT¸‘gÙ
ܰÂ
fb6©9þ\ê¸PP¶õ û¼ç·¶;þ‡Û3Ln]¶H®8ÎÀ›@
œü£Ž>o×Þ¢5%kõòü›Nÿ ¨”™,ŸfpÊ×HbRLäÈè‚0 ãž} ªÁ£epFì0'ŽØéÔ÷ì=éT²0•!…Îzt9ç¾?”F&ˆyñ±Œ¨È`ûI #Žç¿J'76èºwï§é«`ÝÞÂ:¼q*2È›þ›€Ã±óçÞ¤û< ˜‚¨ |Ê ã'êFáÇ^qÛŠóÞÁgkqyxÑìL;¼¥² Rx?‡¯Y7PŽwnù¶†û¾Ü·.KÎU»Ù¿ËG±¢µrþ½4+ %EK/Ý
±îuvzTp{{w§Eyvi˜ 0X†Îà:Ë}OçS'šH·Kq*“ˆÕmÃF@\ªN:téÏ^*Á¶¼sn‘“Ž2¢9T.½„\ýò@>˜7NFïNRÓ·wèôßEÕua'¬[þ¾cö¡ÌOæ¦âÅŠ². Ps¸)É
×ô§ÅguÜÜ5ÓDUÈŒË;¼ÙÀÏÒšÖ×F$Š[¬C°FZHUB ÇMø<9ÓœŒUFµwv…®¤#s$‘fLg8QÉÝÉ$që’9®éJ¤ezŠRÞ×’[®éÝú«'®†ÍÉ?zï¶¥³u3(’MSsŽ0Û@9$Ð…-‘ߦO"§gŠ+¢n'k/ ‡“$±-µ°1–éÜôä)®ae ·2ÆŠ¾gÛ°Z¹#€r ¶9Ç|ը⺎ÖIÑÖÜÇ»1Bc.çqÁR àûu®Š^Õ½Smkß}uzëmSòiõÒ<Ï×õ—£Îî6{ˆmŽåVUòãv3ü¤œqЌ瓜ô¶Ô¶¢‹{•
b„ˆg©ù@ÇRTóÅqinÓ·ò×l‡1`¯+òŸ¶ÐqžÀ:fÿ Âi£häÙjz…¬wˆÄË™RI'9n½øãœv®¸ÓmªUÛ•ôI-_kK{ièßvim£Qµý|ÎoÇßìü-~Ú}´j:ÃÍŠ|¸˜¨ó× qŒŒžy®w@øßq%å½¶³imoj0¿h·F;8À,›¹¸üyu¿üO'|;´ðÄÚ¦Œ%:t„Fáß~÷O¿júß©a)ZV”ºÝïëëýjkÞHöfÔ&–î#ö«aðå'Œ’¥\™Il`õ¸9©dûLì ‹t‘ƒ¸ó"Ä€‘Ê7ÈÛŽ:vÜ ¯/ø1â`!»Ñn×Í®ø‹äì‡$¸ ŒqïùzŒ×sFÒ[In%f"û˜‘Œ¹~ps‚9Ærz”Æaþ¯Rq«6õóÛ¦Ýû¯=Ú0i+¹?ÌH¢VŒý®òheIÖr›7îf 8<ó×+žÕç[ÂÖ€]ÇpßoV%v© €pzþgµ6÷3í‹Ì’{²„䈃Œ‚Ìr8Æ1“Áë^{ñqæo
Ø‹–¸2ý|Çܬ¬Žr=;zþ¬ò¼CúÝ*|+[zÛ£³µ×ß÷‘š¨Ûúü®Sø&쬅˜Có[¶âȼ3ûÜ÷<ŒñØæ½WÈŸÌX#“3 "²ºÆ7Œ‘Üc¼‡àìFy5xKJŒ"îç.r@ï×Þ½Ä-ÿ þ“}ª}’*Þ!,Fm¸Î@†9b?1W{Yæ3„`Ú¼VõŠÚÛ_kùöG.mhÎñ ôíhí§Ô$.ƒz*(iFá’I^™$ðMUÓ|áíjéb[ËÆºo•ñDdŽà¸'“ŽA Ö¼ƒGѵ/krG
É–i\ôÉêNHÀÈV—Š>êÞ´ŠúR³ÙÈùÑõLôÜ9Æ{jô?°°Kýš¥WíZ¿V—m6·E}{X~Æ?
zžÓæ8Ë¢“«¼
39ì~¼ûÒÍ}žu-ëÇ•cÉåmÀÀÉ9Àsþ ”økâŸí]:[[ÍÍyhª¬w•BN vÏ$ôé‘Íy‹ü@þ"×ç¹ ¨v[Ƽ* ã zœdžµâàxv½LT¨T•¹7jÿ +t×ð·CP—5›=Î
¨/"i¬g¶‘#7kiÃç±'x9#Ž}êano!òKD‘ílï”('¿SÔð?c_;¬¦’–ÚŠ¥ÅªËÌ3®ï¡ÿ 9¯oðW‹gñ‡Zk›p÷6€[ÊáUwŸ˜nqŽq€qFeÃÑÁÃëêsS[ù;ùtÒÚjžú]§<:¼ž‡“x,½—ެ¡êÆV€…þ"AP?ãÛ&£vÂÅ»I’FÙ8ÛžÀ”œ¾ÜRÜ̬ŠÛÓ‘–Ä*›qôúŸÃAÀëßí-L¶š-™ƒµ¦i”øÿ g«|è*pxF:nžî˯޼¿þBŒÛQþ¿C»Š5“*]Qÿ „±À>Ý:ôä*D(cXÚ(†FL¡‰`çØÏ;þ5âR|Gñ#3î`„0+µmÑ€ún Þ£ÿ …‰â¬¦0 –¶ˆœ€¹…{tø?ʯ(_çþ_Š5XY[¡Ù|Q¿ú
µŠ2︛sO* Бÿ ×â°<+à›MkÂ÷š…ij
·Ü–ˆ«ò‚?ˆœúäc½øåunû]¹Iïåè› ç ¯[ð&©¥Ýxn;6>}²’'`IË0ÁèN}zö5éâ©âr\¢0¥ñs^Ml¿«%®ýM$¥F•–ç‘Øj÷Ze¦£k
2¥ô"FqÀ`„~5Ùü+Ò¤—QºÕ†GÙ—Ë‹ çqä°=¶ÏûÔÍcá¶¡/ˆ¤[ý†iK ™°"ó•Æp;`t¯MÑt}+@²¶Óí·Ídy’3mÕË‘’zc€0 íyÎq„ž ¬4×5[_]Rë{]ì¬UZ±p÷^åØÞÈ[©&OúÝÛ‚‚s÷zžIïßó btÎΪ\ya¾U;C¤t*IÎFF3Џ™c
1žYD…U° êÄàõë\oŒ¼a ‡c[[GŽãP‘7 â znÈ>Ãü3ñ˜,=lUENŒäô¾ÚÀÓ[_ð9 œ´JçMy©E¢Àí}x,bpAó¦üdcûŒW9?Å[Há$¿¹pÄ™#^9O88©zO=«Ë!µÖüY¨³ªÍy9ûÒ1 úôÚ»M?àô÷«ÞëÖ–ÙMÌ#C&ßnJ“Üp#Ђ~²†G–àíekϵío»_žŸuΨQ„t“ÔÛ²øáû›´W6»Øoy FQÎr $Óõìk¬„‹ïÞÚ¼sÆíòÉ67\míÎyF¯ð¯TÓã’K;ë[ð·ld«7üyíšÉ𯊵 êáeYžÏq[«&vMÀðßFà}p3ÅgW‡°8ØßVín›þšõ³¹/ ü,÷ií|’‘´R,®ŠÉ‡W“Ž1ØöëÓ¾xžÖÞ¹xÞݬXZGù\’vŒž˜ÆsØúÓïí&ÒÒ{]Qž9£Ê¡ù·ÄÀ»¶áHäž™5—ìö« -&ù¤U<±ÉÆA>½ý+æg
jžö륢þNÛ=÷JÖÛfdÔ õýËúû‹ÓØB²¬fInZ8wÌÉЮ~aƒÎ=3ìx‚+/¶äÁlŠ‚?™Æü#8-œ\pqTZXtè%»»&ÚÝ#´ŠðÜžã§Í’¼{p·ß{m>ÞycP¨’¼¢0ú(Rƒë^Ž ñó¼(»y%m´ÕÙ}ÊûékB1¨þÑ®,#Q)ó‡o1T©ÜÃ*Ž‹‚yö<b‰4×H€“ìÐ.
¤²9ÌŠ>„Žãøgšñ
¯Š~)¸ßå\ÛÛoBŒa·L²œg$‚Iã¯ZÈ—Æ~%”äë—È8â)Œcƒ‘Âàu9¯b%)ÞS²¿Ïïÿ 4Öºù}Z/[H%¤vÉ#Ì’x§†b
© ³´tÜ{gn=iï%õªÇç]ܧ—!åw„SÓp ·VÈÏ¡?5Âcâb¥_ĤŠz¬—nàþÖΟñKÄöJé=ÌWèêT‹¸÷qÎჟ•q’zWUN«N/ØO^Ÿe|í¾©k{üõ4öV^ïù~G¹êzÂèº|·÷×[’Þ31†rpjg·n
Æ0Ý}kåË‹‰nîe¹ËÍ+™ÏVbrOç]'‰¼o®xÎh`¹Ç*±ÙÚ!T$d/$žN>¼WqᯅZ9ÑÒO\ÜÛê1o&,-z ~^NCgNÕéá)ÒÊ©7‰¨¯'Õþ¯þ_¿Ehîþóâ €ï¬uÛûý*ÎK9ä.â-öv<²‘×h$àãúW%ö¯~«g-ÕõÀàG~>Zú¾Iš+(šM³ Û#9äl%ðc¬ ûÝ xÖKG´x®|¸¤Ï™O:Ê8Ã’qÉcÔä‚yÇNJyËŒTj¥&µOmztjÿ ?KëaµÔù¯áýóXøãLeb¾tžAÇû`¨êGBAõ¾•:g˜’ù·,þhÀ`¬qÜ` e·~+å[±ý“âYÄjWì—µHé±ø?Nõô>½âX<5 Ç©ÏѼM¶8cܪXŽÉ^r?¼IróÈS•ZmÇ›™5»òÚÚ7ïu«&|·÷•Ά
>[©ÞXHeS$Œyà€ ÷ù²:ò2|óãDf? Z¼PD¶ÓßC(xÆ0|©ßR;ôMsÿ µ´ÔVi¬,͹›Ìxâi˜`¹,GAéÇlV§ÄýF×Yø§ê–‘:Ã=ò2³9n±ÉžØÏ@yÎWžæ±Ãàe„ÄÒN ]ïòêìú_Go'¦ŽÑ’_×õЯðR66þ!›ÑÄ gFMÙ— äžäqôÈ;ÿ eX<#%»Aö‰ãR¤ Í”Ž¹È G&¹Ÿƒ&á?¶Zˆ±keRè Kãnz·ãŠÕøÄÒÂ9j%@®×q±ÜŒý[õ-É$uíè&¤¶9zÇï·Oøï®ÄJKšÖìdü"µˆ[jײÎc;ã…B(g<9nàȯG½µŸPÓ.´Éfâ¼FŽP
31 ‘ÏR}<3šä~
Ã2xVöî Dr
Ç\›}Ý#S÷ÈÀëŽHÆI®à\OçKuäI¹†ó(”—GWî ñ³¹¸æ2¨›‹ºÚû%¾ýÖ_3ºNú¯ëúì|ÕÅÖ‰}ylM’ZËîTÿ á[ðÐñ/ˆ9Àû
¸ón3 Mòd‘÷ döª^.Êñް›BâîNp>cëÏçÍzïÃôÏ
YÍ%ª¬·ãÏ-*9ÜÂãhéŒc¾dÈêú¼Ë,. VŠ÷çeÿ n/¡¼äãõâ=‹xGQKx”|¹bÌŠD@2Œ 8'Ž àúƒŽ+áDÒ&¡¨"Œ§–Žr22 Ç·s]ŸÄ‹«ð%ÚÄ<¹ä’(×{e›HÀqÁç©Ç½`üŽÚõK饚9ƒÄ±€<–úƒú~ çðñO#Í%iKKlµ¦¾F)'Iê¬Î+Ç(`ñ¾£œdÈ’`™ºcßéé^ÿ i¸”Û\ý¡æhÔB«aq¸}ãÀÆ:ÜWƒ|FÛÿ BŒÇÀeaŸ-sÊ€:úW½ÜÝÜ<%$µ†%CóDªÀí%IÈÏʤ…ôäñÞŒ÷‘a0“ôŽÚë¤nŸoW÷0«e¶y'Å»aΗ2r’# Û°A^ý9ÉQÔõ=ù5¬£Öü.(Þ’M$~V«=éSÄFN½®©ÔWô»ÿ þHžkR‹ìÏ+µµžöê;khÚI¤m¨‹Ôš–âÖçJ¾_Z•’6a”Èô> ÕÉaÕ<%®£2n bQŠå\tÈõUÿ ø»þ‹k15‚ÃuCL$ݹp P1=Oøýs¯^u éEJ”–éêŸê½5ýzy›jÛ³á›Ûkÿ ÚOcn±ÛÏîW;boºz{ãžüVÆ¡a£a5½äÎÂks¸J@?1è¿{$ä‘=k”øsÖ^nŒ¦)ÝåXÃíùN1ØõÚOJë–xF÷h¸ Œ"Ž?x䜚ü³ì¨c*Fœ¯i;7~ñí׫Ðó¥Ë»3Ãü púw ‰°<Á%»ñž ÿ P+Û^ ¾Ye£ŽCÄŒ„/>˜>•á¶Ìm~&&À>M[hÈÈÿ [Ž•íd…RO@3^Ç(ʽ*¶ÖQZyßþ
1Vº}Ñç?¼O4Rh6R€ª£í¡ûÙ
a‚3ß·Õ
ü=mRÍ/µ9¤‚0ÑC¼Iè:cŽsÛ¾™x£ÆÐ¬ªÍöˢ샒W$•€Å{¨ÀPG
ÀÀàŸZìÍ1RÉ0´ðxEË9+Éÿ ^rEÕ—±Š„70l¼áË@û.' ¼¹Žz€N3úUÉ<3á×*?²¬‚ä†"Ùc=p íÛ'¡ª1ñ"økJ†HÒ'»Ÿ+
oÏN¬Ã9 dÙãÜדÏâÍ~æc+j·Jzâ7(£ðW]•æ™?nê´º6åwéåç÷N•ZŠíž›¬|?Ðõ?Ñ-E…®³ÇV$~X¯/…õ x‘LˆÑÜÚÈ7¦pzãÜüë½ðÄ^õtÝYËÍ7ÉÖÕ8ÏUe# #€r=sU¾/é’E§jRC4mxNÝ´9†íuá»›V‘
ZI€×cr1Ÿpzsøf»¨åV‹ìû`qËLÊIã?\~¼³áËC©êhªOîO»‘ÃmçÛçút×¢x“Z}?Üê#b-¤X7õÄò gž zzbº3œm*qvs·M=íúéw}¿&Úª°^Ö×µÏ(ø‡â†Öµƒenñý†×åQáYûœ÷ÇLœôÎNk¡ð‡¼/µ¸n0æÉ0¬ƒ‚üîÉÆvŒw®Sáö”š¯‹-üÕVŠØÙ[$`(9cqƒÔ_@BëqûÙ`Ýæ0;79È?w<ó |ÙÜkßÌ1±Ëã¿ìÒ»ðlìï«ÓnªèèrP´NÏš&ŽéöÙ¸÷æ°~-_O'‰`°!RÚÚÝ%]Ø%þbß1'¿ÿ XÕáOöÎŒ·‹¬+Åæ*ÛÛ™0¤ƒOÍÔ`u¯¦ÂaèÐÃÓ«‹¨Ô¥µœ¿¯ÉyÅÙ.oÔôŸ Úx&(STðݽ¦õ] ’ÒNóÁäÈùr3í·žÚ[™ƒ¼veÈ÷ÞIõÎGlqÎ=M|«gsªxÅI6
]Z·Îªä,¨zŒŽÄ~#ØŠúFñiÉqc©éÐD>S딑 GñŽ1éÐ^+
Ëi;Ô„µVÕú»i¯ÈÒ-ZÍ]òܘ®ì`bÛÙ¥_/y(@÷qÐúg Ô÷W0.Ø›
6Ò© r>QƒŒ0+Èîzb¨É+I0TbNñ"$~)ÕÒ6Þ‹{0VÆ27œWWñcÄcX×íôûyKZéðªc'iQ¿¯LaWŠŸS\·Š“źʸ…ôÙÂí|öÀÇåV|!¤ÂGâÛ[[’ï
3OrÙËPY¹=Î1õ5öåTžÑè Ú64/üö?Zëžk}¬¶éàoá¾á}3“ü]8Éæ¿´n²Žš_6¾pœ)2?úWÓÚ¥¾¨iWúdŽq{*ª1rXŒd…m»‰äcô¯–dâ•ã‘Jº¬§¨#¨®§,df«8ÉÅßN¾hˆ;îÓ=7áùpën®É 6ûJžO2^œÐò JÖø¥²ã›Ò6Ü·‰!wbÍ‚¬O©»õ¬ÿ ƒP=Ä:â¤-&ÙŽ
`È9 r9íϧzë> XÅ7ƒ5X–krÑ¢L7€ìw}ÑŸNHëŒüþ:2†á¼+u·á÷N/Û'Ðç~ߘô«ëh!ónRéeQ´6QÛÿ èEwëÅÒ|¸Yqó1uêyùzð8 ƒŠù¦Ò;¹ä6öi<'ü³„[ÃZhu½ ùÍ¡g‚>r¯×ŠîÌx}bñ2“k꣧oø~›hTèóËWò4|ki"xßQ˜Ï6øÀLnß‚0 ¹Æ{±–¶Öe#¨27È@^Ìß.1N¾œyç€õ†ñeé·Õã†çQ°€=Ì©ºB€Ø8<‚ÃSõ®ùcc>×Ú .Fr:žÝGæ=kÁâ,^!Fž
¬,àµ}%¶«îõ¹†"r²ƒGœüYÕd?aÑÃY®49PyU ÷þ!žxÅm|/‚ãNð˜¼PcûTÒ,¹/Ý=FkÏ|u¨¶«âë…{¤m¢]Û¾ïP>®XãÞ½iÓÁ¾
‰'¬–6ß¼(„ï— í!úÙäzôë^–:œ¨å|,_¿&š×]uÓѵÛô4’j”bž§x‘Æ©ã›á,‚[Ô
ÎÞ= ŒËæ ÀùYÁ?ŽïÚ¼?ÁªxºÕÛ,°1¸‘¿ÝäãØ¯v…@¤åq½ºã œàûââ·z8Xýˆþz~—û»™âµj=Ž
â~ãáh@'h¼F#·Üp?ŸëQü-løvépx»cŸø…lxâÃûG·‰¶ø”L£©%y?¦úõÆü-Õ¶¥y`Òl7>q’2üA?•F}c‡jB:¸Jÿ +§¹¿¸Q÷°ív=VÑìu[Qml%R7a×IèTõéŽx¬
?†š7
1†îã-ˆã’L¡lŽ0OÓ=ÅuˆpÇ•¼3ÛùÒ¶W/!|’wŽw^qÔ×ÏaóM8Q¨ãÑ?ëï0IEhÄa¸X•`a
?!ÐñùQ!Rä žqŽžÝO`I0ÿ J“y|ñ!Îã@99>þ8–+éáu…!ù—ä
ʰ<÷6’I®z
ÅS„¾)Zþ_Öýµ×ËPåOwø÷þ*üïænÖùmØÝûþ¹=>¦½öî×Jh]¼ç&@§nTŒ6ITÀõ^Fxð7Å3!Ö·aÛ$þÿ ¹ã5îIo:ȪmËY[’8ÇӾlj*òû¢¥xõ¾¼ú•åk+\ð¯ HÚoŽl•Ûk,¯ ç²²cõÅ{²Z\
´ìQ åpzŽ3Ôð}ÿ Jð¯XO¡øÎé€hÙ¥ûLdŒ`““ù6Gá^ÃáÝ^Ë[Ñb¾YåŒÊ»dŽ4†2§,;ÿ CQÄ´¾°¨c–±”mºV{«ßÕýÄW\ÖŸ‘çŸ,çMRÆí“l-ƒn~ë©ÉÈê Ü?#Ž•¹ðãSÒ¥ÐWNíà½;ãž)™ÎSÈ9cóLj뵿ūiÍk¨ió¶X‚7÷ƒ€yãnyÏŽëÞ Öt`×À×V's$È9Ú:ä{wÆEk€«†Çàc—â$éÎ.éí~Ýëk}ÅAÆpörÑ¢‡Šl¡ÑüSs‹¨‰IÄóÀ×wñ&eºðf™pŒÆ9gŽTø£lñëÀçŽ NkÊUK0U’p ï^¡ãÈ¥´ø{£ÙHp`’ØåbqÏ©äó^Æ:
Ž' ÊóM«õz+ß×ó5Ÿ»('¹ð¦C„$˜Å¢_ºÈI?»^äã'ñêzž+ë€ñ-½»´}¡Ë*õ?.xÇ^1ŽMyǸ&“—L–îëöâ7…' bqéÎGé]˪â1$o²¸R8Ã`.q€}sÖ¾C98cêÆÞíïóòvÓòùœÕfÔÚéýuèÖ·Ú
Å‚_¤³ÜۺƑß”àרý:׃xPþÅÕî-/üØmnQìïGΊÙRqê=>¢½õnæ·r!—h`+’;ò3È<“Û©éšóŸx*÷V¹¸×tÈiˆßwiÔÿ |cŒñÏ®3ֽ̰‰Ë Qr©ö½®¼ÛoÑÙZÅÑ«O൯ýw8;k›ÿ x†;ˆJa;‘º9÷÷R+¡ñgŽí|Iáë{ôáo2ʲ9 029ÉÏLí\‰¿¸Ÿb˜ "Bv$£ßiê>=ªª©f
’N ëí>¡NXW~5×úíø\‰»½Ï^ø(—wÖú¥¤2íŽÞXæÁ$°eÈ888^nÝë²ñÝÔ^ ÖÚ9Q~Ëå7ï
DC¶ÑµƒsËÇè9®Wáþƒ6‡£´·°2\Ý:ÈÑ?(#¨'$õèGJ¥ñW\ÿ ‰E¶—¸™g˜ÌÀ¹;Pv ú±ÎNs·ëŸ’–"Ž/:té+ûË]öJöÓM»ëø˜*‘•^Uý—êd|‰åñMæÔÝ‹23å™6æHùÛ‚ëüñ^…ñ1¢oêûÑEØ.õ7*ÅHtÎp{g<·Á«+¸c¿¿pÓ¾Æby=8É_ÄsÆk¬ñB\jÞÔì••Ë[9Píb‹Bヅ =93§ð§LšÛáÖšÆæXÌÞdÛP.0\ãïÛ0?™úJ¸™Ë
”•œº+=<µI£¦í¯õêt¬d‹T¬P=ËFêT>ÍØØ@Ï9<÷AQÌ×»Õ¡xùk",JÎæù±Éç$œŽŸZWH®¯"·UÌQ ’ÙÈ]ÅXg<ã
ߨg3-Üqe€0¢¨*Œ$܃
’Sû 8㎼_/e'+Ï–-èÓ¶¶Õíß[·ÙÙ½îì—¼sk%§µxä‰â-pÒeÆCrú
ôσžû=”šÅô(QW‚Õd\ƒæ. \àö¹¯F½°³½0M>‘gr÷q+œ¶NïºHO— ¤ ܥݔn·J|ÆP6Kµc=Isó}Ò çGš)a=—#vK›åoK§ßóÙ¤¶¿õú…ÄRÚ[ËsöÙ¼Ë•Ë ópw®qœŒ·Ø
ùÇâ‹ý‡ãKèS&ÞvûDAù‘É9ŒîqÅ}
$SnIV[]Ñ´Ó}ØÜ¾A Ü|½kÅþÓ|EMuR¼.I¼¶däò‚ÃkÆ}ðy¹vciUœZ…Õõ»z¾÷¿n¦*j-É/àœHã\y5 Û ß™ó0—äŸnzôã#Ô¯,†¥ÚeÔ÷ÜÅ´„“'c…<íÝ€<·SŠ¥k§Ã¢éÆÆÙna‚8–=«Êª[Ÿ™°pNî02z“ÔÙ–K8.È’Þî(vƒ2®@ äÈûãçžxäÇf¯ˆu¹yUÕîýWšÙ|›ëÒ%Q^í[æ|éo5ZY•^{96ˆY‚§v*x>âº_|U¹Ö´©tûMÒÂ9PÇ#«£#€ éÉñ‘ƒÍz/‰´-į¹°dd,Б›p03ƒœ{ç9=+
Ûᧇ¬¦[‡‚ê婺¸#±ß=³ý¿•Õµjñ½HÙh›Û[§ÚýÊöô÷{˜?ô÷·Ô.u©–_%còcAÀ˜’
}0x9Î>žñÇáÍ9,ahï¦Ì2òÓ ñÛAäry$V²Nð
]=$Ž
‚#Ù‚1ƒƒødõMax‡ÂÖ^!±KkÛ‘
«“Çó²FN8+ëÎ{Ò¼oí§[«ÕMRoËeç×[_m/¦¦k.kôgŽxsSÓ´ý`êzªÜÜKo‰cPC9ÎY‰#§^üý9¹âïÞx£Ë·Ú`±‰‹¤;³–=ÏaôÕAð‚÷kêÁNBéÎælcõö®£Fð†ô2Ò¬]ßÂK$ÓÜ®•”/ÊHàã$ä¸÷ëf¹Oµúâ“”’²øè´µþöjçNü÷üÌ¿ xNïFÒd»¼·h®îT9ŽAµÖ>qÁçÔœtïÒ»\ȶÎîcÞäîó3¶@#ÉIÎ ÔñW.<´’¥–ÑÑ€ÕšA‚ ;†qÓë‚2q
ÒÂó$# Çí‡
!Ë}Õ9ÈÎÑÉã=;ŒÇÎuñ+ÉûÏ¥öíeÙ+$úíÜ娯'+êZH4ƒq¶FV‹gïŒ208ÆÌ)íб>M|÷âÍã¾"iì‹¥£Jd´™OÝç;sÈúr+ÜäˆË)DŒ¥šF°*3Õ”d{zÔwºQ¿·UžÉf†~>I+ŒqÔ`ð3œ“Ü×f]œTÁÔn4“ƒø’Ýßõ_«*5šzGCÊ,þ+ê1ò÷O¶¸cœºb2yÇ;cùÕ£ñh¬›áÑŠr¤ÝäNBk¥—á—†gxšX/쑘hŸ*Tçn =ûã¦2|(ð¿e·ºÖ$
ýìŸ!'åΰyîî+×öœ=Y:²¦ÓÞ×iü’—ü
-BK™£˜›âÆ¡&véðõ-ûÉY¹=Onj¹ø¯¯yf4·±T Pó`çœ7={×mÃ/¢˜ZÚòK…G½¥b„’G AãÜœ*í¯Ã¿ IoæI¦NU8‘RwÈã;·€ Û×ëÒ”1Y
•£E»ÿ Oyto¢<£Áö·šï,䉧ûA¼sû»Nò}¹üE{ÜÖªò1’õÞr0â}ÎØ#>à/8ïéÎ~—áÍ#ñÎlí§³2f'h”?C÷YËdð:qëõÓ·‚ïeÄ©
ÔÈØÜRL+žAÎ3¼g=åšó³Œt3
ÑQ¦ùRÙßE®¼±w_;þhš’Sirÿ ^ˆã¼iੇ|RòO„m°J/“$·l“ ÇÓ¿ÿ [ÑŠÆ“„†Õø>cFÆ6Ø1ƒ– àz7Ldòxäüwá‹ÝAXùO•Úý’é®ähm •NÀ±ÌTÈç
ƒ‘I$pGž:‚ÄbêW¢®œ´|¦nÍ>¶ÖÏ¢§ÎÜ¢ºö¹•%ÄqL^öÛKpNA<ã¡ …î==ª¸óffËF‡yÌcÉ ©ç$ð=ñÏYþÊ’Ú]—¥‚¬‚eDïÎH>Ÿ_ÌTP™a‰ch['çÆÜò7a‡?w°Ïn§âÎ5”’¨¹uÚÛ|´ÓÓc§{O—ü1•ªxsÃZ…ÊÏy¡Ã3¸Ë2Èé» ‘ƒÎ äžÜðA§cáOéúÛ4ý5-fŒï„ù¬ûô.Ç Üsž•Ò¾•wo<¶Ÿ"¬¡º|£
î2sÇ¡éE²ÉFѱrU°dÜ6œ¨ mc†Îxë׺Þ'0²¡Rr„{j¾í·è›µ÷)º·å–‹î2|I®Y¼ºÍË·–ÃÆàã£'óÆxƒOÆÞ&>\lóÌxP Xc¸ì Sþ5§qà/ê>#žÞW¸if$\3 ® ûÄ“ùŽÕê¾ð<Ó‹H¶óÏ" å·( á‘€:ã†8Ï=+ꨬUA×ÃËÚT’ÑÞöù¥¢]{»ms¥F0\ÑÕ—ô}&ÛB´ƒOŽÚ+›xíÄÀ1
,v± žIëíZ0ǧ™3í2®0ทp9öÝÔž)ÓZËoq/Ú“‘L ²ŒmùŽï‘Ó9§[Û#Ä‘\ÞB¬Çs [;à à«g‚2ôòªœÝV§»·¯/[uó½õÛï¾
/šÍ}öüÿ «=x»HŸÂÞ.™ ÌQùŸh´‘#a$‚'¡u<Š›Æ>2>+ƒLSiöwµFó1!eg`£åœ ÷ëÛö}Á¿ÛVÙêv $¬ƒ|,s÷z€ð΃¨x÷ÅD\ÜŒÞmåÔ„ ˆ o| :{ÇÓ¶–òÁn!´0Ål€, ƒ ( ÛŒŒc¶rsšæ,4‹MÛOH!@¢ ÇŽ„`å²9ÝÃw;AÍt0®¤¡…¯ØÄ.Àìí´ƒ‘ßñ5Í,Óëu-ÈÔc¢KÃÓ£òÖ̺U.õL¯0…%2È—"~x
‚[`có±nHàŽyàö™¥keˆìŒÛFç{(Ø©†`Jã#Žwg<“:ÚÉ;M
^\yhûX‡vB·÷zrF?§BÊÔ/s<ÐÈB)Û± ·ÍÔwç5Âã:så§e{mѤï«Òíh—]Wm4âí¿ùþW4bC3¶ª¾Ùr$pw`àädzt!yŠI„hÂîàM)!edŒm'æ>Ç?wzºKìcŒ´¯Ìq6fp$)ãw¡éUl`µ»ARAˆÝÕgr:äŒgƒéé[Ôö±”iYs5Ýï«ÙG—K=þF’æMG«óÿ `ŠKɦuOQ!ÕåŒ/ÎGÞ`@ËqÕzdõâ«Ê/Ö(ƒK´%ŽbMüåÜŸö—>¤óŒŒV‘°„I¢Yž#™¥ùÏÊ@8
œgqöö5ª4vד[¬(q cò¨À!FGaÁõõ¯?§†¥ÏU½í¿WªZ$úyú½Žz×§Éþ?>Ã×È•6°{™™ŽÙ.$`ÎUœ…çè ' ¤r$1Ø(y7 ðV<ž:È ÁÎMw¾Â'Øb§øxb7gãО½óÉÊë²,i„Fȹ£§8ãä½k¹¥¦ê/ç{ïê驪2œ/«ü?¯Ô›ìñÜ$þeýœRIåŒg9Ác’zrrNO bÚi¢
ѺË/$,“ª¯Ýä;Œ× ´<ÛÑn³IvŸb™¥ nm–ÄŸ—nÝÀãŽ3ëÍG,.öó³˜Ù£¹uÊÌrŠ[<±!@Æ:c9ÅZh
ì’M5ÄìÌ-‚¼ëÉùqŽGì9¬á ;¨A-ž—évþÖ–^ON·Ô”ŸEý}ú×PO&e[]ÒG¸˜Ûp ƒÃà/Ë·8ûÀ€1ž@¿ÚB*²¼ñì8@p™8Q“žÆH'8«I-%¸‚
F»“åó6°Uù|¶Ú¸ã ò^Äw¥ŠÖK–1ÜÝK,Žddlí²0PÀü“×ükG…¯U«·¶–´w¶ŽÍ¾©yÞú[Zös•¯Á[™6°
¨¼ÉVæq·,#
ìãï‘×8îry®A››¨,ãc66»Ë´ã'æÉù?t}¢æH--Òá"›|ˆ¬[í 7¶ö#¸9«––‹$,+Ëqœ\Êøc€yê^ݸÄa°«™B-9%«×®‹V´w~vÜTéꢷþ¼ˆ%·¹• ’[xç•÷2gØS?6åÀÚ õ9É#š@÷bT¸º²C*3Bá¤òÎA9 =úU§Ó"2Ãlá0iÝIc‚2Î@%öç94ùô»'»HÄ¥Ô¾@à Tp£šíx:úÊ:5eºßMý×wµ›Ó_+šº3Ýyvÿ "ºÇ<ÂI>Õ1G·Ë«È«É# àÈÇ øp Jv·šæDûE¿›†Ë’NFr2qŸ½ÇAÜšu•´éí#Ħ8£2”Ú2Ã/€[ÎTr;qŠz*ý’Îþ(≠;¡TÆâ›;ºÿ àçœk‘Þ8¾Uª¾íé{^×IZéwÓkXÉûÑZo¯_øo×È¡¬ â–ÞR§2„‚Àœü½ùç® SVa†Âüª¼±D‘ŒísŸàä|ä2 æ[‹z”¯s{wn„ÆmáóCO+†GO8Ïeçåº`¯^¼ðG5f{Xžä,k‰<á y™¥voÆ éÛõëI=œ1‹éíÔÀÑ)R#;AÂncäŽ:tÏ#¶TkB.0Œ-ÖÞZÛgumß}fÎJÉ+#2êÔP£žùÈÅi¢%œ3P*Yƒò‚A쓎2r:ƒÐúñiRUQq‰H9!”={~¼“JŽV¥»×²m.ÛߺiYl¾òk˜gL³·rT•
’…wHÁ6ä`–Î3ùÌ4Øe³†&òL‘•%clyîAÂäà0 žüç$[3uŘpNOÀÉ=† cï{rYK
ååä~FÁ
•a»"Lär1Ó¯2Äõæ<™C•.fÕ»è¥~½-¿g½Â4¡{[ør¨¶·Žõäx¥’l®qpwÇ»8ärF \cޏܯÓ-g‚yciÏÀ¾rÎwèØÈ#o°Á9ã5¢šfÔxÞæfGusÏÌJÿ µ×œ/LtãÅT7²¶w,l
ɳ;”eúà·¨çîŒsÜgTÃS¦^ '~‹®›¯+k÷ZÖd©Æ*Ó[Ü«%Œk0ŽXƒ”$k#Ȩ P2bv‘ƒŸáÇ™ÆÕb)m$É*8óLE‘8'–ÜN Úyàúô+{uº±I'wvš4fÜr íì½=úuú
sFlìV$‘ö†HÑù€$§ õ=½¸«Ž]
:Ž+•¦ïmRþ½l´îÊT#nkiøÿ _ðÆT¶7Ò½ºÒ£Î¸d\ã8=yãŽÜäR{x]ZâÚé#¸r²#»ÎHÆ6õ ç® ÎFkr;sºÄ.&;só±Ç9êH÷ýSšÕtÐU¢-n Ì| vqœ„{gŒt§S.P‹’މ_[;m¥ÞZýRûÂX{+¥úü¼ú•-àÓ7!„G"“´‹žƒnrYXã¸îp éœ!ÓoPÌtÑ (‰Þ¹é€sÓ#GLçÕšÑnJý¡!‘Tä#“ß?îýp}xÇ‚I¥Õn#·¸–y'qó@r[ Êô÷<ÔWÃÓ¢áN¥4Ô’I&ݼ¬¬¼ÞºvéÆ
FQV~_ÒüJÖÚt¥¦Xá3BÄP^%ÈÎW-×c¡ú©¤·Iþèk¥š?–UQåIR[’O 5x\ÉhÆI¶K4«2ùªŠŒ<¼óœçØ`u«‚Í.VHä€ Ëgfx''9ÆI#±®Z8
sISºku¢ßÞ]úk»Jößl¡B.Ü»ÿ MWe
°·Ž%šêɆ¼»Âù³´œ O¿cÐÓÄh©"ÛÜÏ.ÖV’3nüÄmnq[ŒòznšÖ>J¬òˆæ…qýØP Ž:ä7^0yëWšÍ_79äoaÈ °#q0{ää×mœy”R{vÒÞ¶ÚÏe¥“ÚÆÐ¥Ì®—õýjR •íç›Ìb„+JyÜØÙ•Ç]¿Ôd þËOL²”9-Œ—õÃc'æÝלçÚ²ìejP“½
âù°¨†ðqòädЃÉäÖÜj÷PÇp“ÍšŠå«‘î
<iWNsmª»¶vÓz5»ûì:Rs\Ðßôû×uÔÿÙ