From d8423a33427af4edbb3f783f9206898c6cb430d9 Mon Sep 17 00:00:00 2001 From: Chris Church Date: Thu, 2 Jan 2014 15:09:48 -0500 Subject: [PATCH] Update third party packages. --- awx/lib/site-packages/README | 31 +- awx/lib/site-packages/billiard/__init__.py | 4 +- .../site-packages/billiard/_connection3.py | 17 +- awx/lib/site-packages/billiard/_reduction.py | 6 +- awx/lib/site-packages/billiard/common.py | 15 +- awx/lib/site-packages/billiard/compat.py | 6 +- awx/lib/site-packages/billiard/five.py | 7 +- awx/lib/site-packages/billiard/managers.py | 6 +- awx/lib/site-packages/billiard/pool.py | 63 +- awx/lib/site-packages/billiard/process.py | 16 +- .../billiard/tests/test_common.py | 23 +- awx/lib/site-packages/boto/__init__.py | 50 +- awx/lib/site-packages/boto/auth.py | 234 +- .../site-packages/boto/beanstalk/layer1.py | 76 +- .../boto/cloudformation/__init__.py | 1 + .../boto/cloudformation/connection.py | 2 +- .../boto/cloudformation/template.py | 4 +- .../site-packages/boto/cloudfront/__init__.py | 2 +- .../boto/cloudfront/distribution.py | 9 +- .../site-packages/boto/cloudfront/identity.py | 17 +- .../site-packages/boto/cloudfront/object.py | 8 +- .../site-packages/boto/cloudfront/signers.py | 13 +- .../site-packages/boto/cloudtrail/layer1.py | 293 +- awx/lib/site-packages/boto/connection.py | 15 +- .../site-packages/boto/contrib/ymlmessage.py | 4 +- .../site-packages/boto/datapipeline/layer1.py | 2 +- .../boto/directconnect/__init__.py | 66 + .../boto/directconnect/exceptions.py | 28 + .../boto/directconnect/layer1.py | 633 +++ .../site-packages/boto/dynamodb/__init__.py | 3 + awx/lib/site-packages/boto/dynamodb/layer1.py | 2 +- .../site-packages/boto/dynamodb2/__init__.py | 3 + .../site-packages/boto/dynamodb2/fields.py | 130 +- awx/lib/site-packages/boto/dynamodb2/items.py | 6 + .../site-packages/boto/dynamodb2/layer1.py | 180 +- awx/lib/site-packages/boto/dynamodb2/table.py | 130 +- awx/lib/site-packages/boto/ec2/__init__.py | 1 + awx/lib/site-packages/boto/ec2/address.py | 2 +- .../boto/ec2/autoscale/__init__.py | 7 +- .../site-packages/boto/ec2/autoscale/group.py | 4 +- .../site-packages/boto/ec2/bundleinstance.py | 10 +- .../boto/ec2/cloudwatch/__init__.py | 5 +- .../boto/ec2/cloudwatch/metric.py | 7 - awx/lib/site-packages/boto/ec2/connection.py | 106 +- awx/lib/site-packages/boto/ec2/ec2object.py | 2 +- .../site-packages/boto/ec2/elb/__init__.py | 77 +- .../site-packages/boto/ec2/elb/attributes.py | 61 + .../boto/ec2/elb/loadbalancer.py | 53 + awx/lib/site-packages/boto/ec2/group.py | 7 +- awx/lib/site-packages/boto/ec2/image.py | 23 +- awx/lib/site-packages/boto/ec2/instance.py | 11 +- awx/lib/site-packages/boto/ec2/keypair.py | 2 +- .../boto/ec2/launchspecification.py | 2 +- .../boto/ec2/networkinterface.py | 5 +- .../site-packages/boto/ec2/placementgroup.py | 2 +- awx/lib/site-packages/boto/ec2/regioninfo.py | 6 +- .../boto/ec2/reservedinstance.py | 11 +- .../site-packages/boto/ec2/securitygroup.py | 5 +- awx/lib/site-packages/boto/ec2/snapshot.py | 7 +- .../boto/ec2/spotdatafeedsubscription.py | 2 +- .../boto/ec2/spotinstancerequest.py | 5 +- .../boto/ec2/spotpricehistory.py | 6 +- awx/lib/site-packages/boto/ec2/vmtype.py | 2 +- awx/lib/site-packages/boto/ec2/volume.py | 8 +- awx/lib/site-packages/boto/ec2/zone.py | 10 +- awx/lib/site-packages/boto/ecs/__init__.py | 10 +- awx/lib/site-packages/boto/ecs/item.py | 12 +- .../boto/elasticache/__init__.py | 3 + .../site-packages/boto/elasticache/layer1.py | 17 +- .../boto/elastictranscoder/layer1.py | 54 +- awx/lib/site-packages/boto/emr/__init__.py | 3 + awx/lib/site-packages/boto/emr/connection.py | 59 +- awx/lib/site-packages/boto/emr/emrobject.py | 4 + awx/lib/site-packages/boto/emr/step.py | 10 +- awx/lib/site-packages/boto/exception.py | 72 +- awx/lib/site-packages/boto/fps/connection.py | 2 +- awx/lib/site-packages/boto/fps/response.py | 42 +- .../site-packages/boto/glacier/__init__.py | 3 + awx/lib/site-packages/boto/glacier/layer1.py | 4 +- awx/lib/site-packages/boto/gs/bucket.py | 8 + awx/lib/site-packages/boto/gs/connection.py | 12 +- awx/lib/site-packages/boto/iam/__init__.py | 3 + awx/lib/site-packages/boto/iam/connection.py | 128 +- .../site-packages/boto/kinesis/__init__.py | 45 + .../site-packages/boto/kinesis/exceptions.py | 51 + awx/lib/site-packages/boto/kinesis/layer1.py | 707 +++ awx/lib/site-packages/boto/manage/server.py | 48 +- awx/lib/site-packages/boto/manage/task.py | 22 +- awx/lib/site-packages/boto/manage/volume.py | 14 +- awx/lib/site-packages/boto/mashups/server.py | 10 +- .../site-packages/boto/mturk/connection.py | 14 +- .../site-packages/boto/mturk/layoutparam.py | 6 +- .../site-packages/boto/mturk/notification.py | 4 +- awx/lib/site-packages/boto/mturk/price.py | 4 +- .../site-packages/boto/mturk/qualification.py | 26 +- awx/lib/site-packages/boto/mturk/question.py | 8 +- awx/lib/site-packages/boto/mws/connection.py | 2 +- awx/lib/site-packages/boto/mws/response.py | 26 +- awx/lib/site-packages/boto/opsworks/layer1.py | 545 +- awx/lib/site-packages/boto/provider.py | 2 +- awx/lib/site-packages/boto/pyami/bootstrap.py | 4 +- awx/lib/site-packages/boto/pyami/config.py | 2 + awx/lib/site-packages/boto/pyami/copybot.py | 8 +- .../boto/pyami/installers/ubuntu/ebs.py | 14 +- .../site-packages/boto/pyami/scriptbase.py | 4 +- awx/lib/site-packages/boto/rds/__init__.py | 95 +- awx/lib/site-packages/boto/rds/dbinstance.py | 39 +- awx/lib/site-packages/boto/rds/dbsnapshot.py | 34 +- awx/lib/site-packages/boto/rds/regioninfo.py | 4 +- awx/lib/site-packages/boto/redshift/layer1.py | 2 +- .../boto/roboto/awsqueryrequest.py | 26 +- .../boto/roboto/awsqueryservice.py | 8 +- awx/lib/site-packages/boto/roboto/param.py | 14 +- .../site-packages/boto/route53/connection.py | 4 +- awx/lib/site-packages/boto/route53/record.py | 6 +- awx/lib/site-packages/boto/s3/__init__.py | 3 + awx/lib/site-packages/boto/s3/acl.py | 14 +- awx/lib/site-packages/boto/s3/bucket.py | 154 +- .../boto/s3/bucketlistresultset.py | 49 +- .../site-packages/boto/s3/bucketlogging.py | 6 +- awx/lib/site-packages/boto/s3/connection.py | 11 +- awx/lib/site-packages/boto/s3/deletemarker.py | 4 +- awx/lib/site-packages/boto/s3/key.py | 30 +- awx/lib/site-packages/boto/s3/multipart.py | 13 +- awx/lib/site-packages/boto/s3/user.py | 6 +- awx/lib/site-packages/boto/sdb/connection.py | 4 +- .../boto/sdb/db/manager/xmlmanager.py | 18 +- awx/lib/site-packages/boto/sdb/db/property.py | 62 +- awx/lib/site-packages/boto/sdb/domain.py | 38 +- .../site-packages/boto/sdb/queryresultset.py | 8 +- awx/lib/site-packages/boto/sdb/regioninfo.py | 4 +- awx/lib/site-packages/boto/services/result.py | 8 +- .../site-packages/boto/services/service.py | 6 +- .../site-packages/boto/services/servicedef.py | 18 +- .../site-packages/boto/services/sonofmmm.py | 6 +- awx/lib/site-packages/boto/services/submit.py | 4 +- awx/lib/site-packages/boto/ses/connection.py | 2 +- awx/lib/site-packages/boto/sns/__init__.py | 3 + awx/lib/site-packages/boto/sns/connection.py | 4 +- awx/lib/site-packages/boto/sqs/__init__.py | 4 +- awx/lib/site-packages/boto/sqs/bigmessage.py | 119 + awx/lib/site-packages/boto/sqs/connection.py | 2 +- awx/lib/site-packages/boto/sqs/message.py | 24 +- awx/lib/site-packages/boto/sqs/queue.py | 6 +- awx/lib/site-packages/boto/sqs/regioninfo.py | 4 +- awx/lib/site-packages/boto/sts/__init__.py | 6 +- awx/lib/site-packages/boto/sts/connection.py | 117 +- awx/lib/site-packages/boto/support/layer1.py | 204 +- awx/lib/site-packages/boto/swf/__init__.py | 1 + awx/lib/site-packages/boto/swf/layer1.py | 2 +- .../boto/swf/layer1_decisions.py | 2 +- awx/lib/site-packages/boto/utils.py | 136 +- awx/lib/site-packages/boto/vpc/__init__.py | 2 +- .../site-packages/boto/vpc/customergateway.py | 2 +- awx/lib/site-packages/boto/vpc/dhcpoptions.py | 12 +- .../site-packages/boto/vpc/internetgateway.py | 2 +- awx/lib/site-packages/boto/vpc/networkacl.py | 2 +- awx/lib/site-packages/boto/vpc/routetable.py | 2 +- awx/lib/site-packages/boto/vpc/subnet.py | 2 +- awx/lib/site-packages/boto/vpc/vpc.py | 2 +- .../site-packages/boto/vpc/vpnconnection.py | 2 +- awx/lib/site-packages/boto/vpc/vpngateway.py | 4 +- awx/lib/site-packages/celery/__init__.py | 10 +- awx/lib/site-packages/celery/__main__.py | 4 +- awx/lib/site-packages/celery/_state.py | 44 +- awx/lib/site-packages/celery/app/__init__.py | 4 +- awx/lib/site-packages/celery/app/amqp.py | 5 +- awx/lib/site-packages/celery/app/base.py | 88 +- awx/lib/site-packages/celery/app/builtins.py | 41 +- awx/lib/site-packages/celery/app/defaults.py | 1 - awx/lib/site-packages/celery/app/task.py | 17 +- awx/lib/site-packages/celery/app/trace.py | 90 +- awx/lib/site-packages/celery/app/utils.py | 48 +- awx/lib/site-packages/celery/apps/beat.py | 2 +- awx/lib/site-packages/celery/apps/worker.py | 46 +- awx/lib/site-packages/celery/backends/amqp.py | 1 + awx/lib/site-packages/celery/backends/base.py | 48 +- .../site-packages/celery/backends/cache.py | 43 +- .../celery/backends/database/models.py | 2 +- .../site-packages/celery/backends/redis.py | 108 +- awx/lib/site-packages/celery/beat.py | 5 +- awx/lib/site-packages/celery/bin/amqp.py | 17 +- awx/lib/site-packages/celery/bin/base.py | 59 +- awx/lib/site-packages/celery/bin/beat.py | 4 +- awx/lib/site-packages/celery/bin/celery.py | 28 +- awx/lib/site-packages/celery/bin/events.py | 2 +- awx/lib/site-packages/celery/bin/multi.py | 6 +- awx/lib/site-packages/celery/bin/worker.py | 17 +- awx/lib/site-packages/celery/bootsteps.py | 43 +- awx/lib/site-packages/celery/canvas.py | 64 +- .../celery/concurrency/asynpool.py | 46 +- .../celery/concurrency/prefork.py | 20 +- .../site-packages/celery/datastructures.py | 5 +- .../site-packages/celery/events/__init__.py | 44 +- awx/lib/site-packages/celery/events/state.py | 536 +- awx/lib/site-packages/celery/five.py | 36 +- awx/lib/site-packages/celery/fixups/django.py | 81 +- .../site-packages/celery/loaders/__init__.py | 4 +- awx/lib/site-packages/celery/loaders/base.py | 2 + awx/lib/site-packages/celery/local.py | 11 +- awx/lib/site-packages/celery/platforms.py | 70 +- awx/lib/site-packages/celery/result.py | 19 +- awx/lib/site-packages/celery/schedules.py | 26 +- awx/lib/site-packages/celery/signals.py | 1 + awx/lib/site-packages/celery/states.py | 8 +- awx/lib/site-packages/celery/task/http.py | 2 +- .../celery/tests/app/test_amqp.py | 30 + .../celery/tests/app/test_app.py | 123 +- .../celery/tests/app/test_log.py | 8 +- .../celery/tests/backends/test_base.py | 19 +- .../celery/tests/backends/test_cache.py | 35 +- .../celery/tests/backends/test_redis.py | 58 +- .../celery/tests/bin/test_base.py | 2 +- .../celery/tests/bin/test_celery.py | 40 +- .../celery/tests/bin/test_worker.py | 14 +- awx/lib/site-packages/celery/tests/case.py | 25 +- .../celery/tests/compat_modules/test_http.py | 4 +- .../celery/tests/events/test_state.py | 149 +- .../celery/tests/fixups/test_django.py | 85 +- .../celery/tests/tasks/test_canvas.py | 4 + .../celery/tests/tasks/test_chord.py | 20 +- .../celery/tests/tasks/test_context.py | 4 +- .../celery/tests/tasks/test_tasks.py | 6 +- .../celery/tests/utils/test_local.py | 5 +- .../celery/tests/worker/test_autoreload.py | 25 +- .../celery/tests/worker/test_consumer.py | 44 +- .../celery/tests/worker/test_control.py | 16 + .../celery/tests/worker/test_request.py | 1 + .../celery/tests/worker/test_worker.py | 40 +- .../site-packages/celery/utils/__init__.py | 79 +- .../celery/utils/dispatch/saferef.py | 22 +- .../celery/utils/dispatch/signal.py | 3 +- .../site-packages/celery/utils/functional.py | 3 + awx/lib/site-packages/celery/utils/log.py | 32 +- awx/lib/site-packages/celery/utils/term.py | 8 +- .../site-packages/celery/utils/timeutils.py | 2 +- .../site-packages/celery/worker/__init__.py | 26 +- .../site-packages/celery/worker/autoreload.py | 64 +- .../site-packages/celery/worker/components.py | 4 +- .../site-packages/celery/worker/consumer.py | 170 +- .../site-packages/celery/worker/control.py | 14 +- .../site-packages/celery/worker/heartbeat.py | 5 +- awx/lib/site-packages/celery/worker/job.py | 30 +- awx/lib/site-packages/celery/worker/state.py | 6 +- .../django_auth_ldap/__init__.py | 4 +- .../site-packages/django_auth_ldap/backend.py | 2 +- awx/lib/site-packages/jsonfield/VERSION | 2 +- awx/lib/site-packages/jsonfield/fields.py | 35 +- awx/lib/site-packages/jsonfield/forms.py | 23 +- .../jsonfield/templatetags/jsonify.py | 1 + .../jsonfield/tests/test_fields.py | 14 +- .../jsonfield/tests/test_forms.py | 40 +- awx/lib/site-packages/jsonfield/widgets.py | 1 - .../keyring/backends/SecretService.py | 7 +- .../site-packages/keyring/backends/kwallet.py | 8 +- .../keyring/tests/test_backend.py | 2 +- awx/lib/site-packages/kombu/__init__.py | 10 +- .../site-packages/kombu/async/semaphore.py | 11 +- awx/lib/site-packages/kombu/async/timer.py | 2 +- awx/lib/site-packages/kombu/clocks.py | 4 +- awx/lib/site-packages/kombu/common.py | 33 +- awx/lib/site-packages/kombu/connection.py | 23 +- awx/lib/site-packages/kombu/entity.py | 4 +- awx/lib/site-packages/kombu/exceptions.py | 14 + awx/lib/site-packages/kombu/five.py | 7 +- awx/lib/site-packages/kombu/pools.py | 3 +- awx/lib/site-packages/kombu/serialization.py | 33 +- .../site-packages/kombu/tests/test_clocks.py | 7 +- .../kombu/tests/test_serialization.py | 11 +- .../kombu/tests/transport/test_SQS.py | 293 + .../kombu/tests/transport/test_filesystem.py | 3 + .../kombu/tests/transport/test_redis.py | 20 +- awx/lib/site-packages/kombu/transport/SLMQ.py | 4 +- awx/lib/site-packages/kombu/transport/SQS.py | 188 +- .../site-packages/kombu/transport/__init__.py | 6 +- .../kombu/transport/beanstalk.py | 3 +- .../site-packages/kombu/transport/couchdb.py | 3 +- .../kombu/transport/django/__init__.py | 3 +- .../site-packages/kombu/transport/mongodb.py | 14 +- .../site-packages/kombu/transport/pyamqp.py | 2 +- .../site-packages/kombu/transport/redis.py | 100 +- .../kombu/transport/sqlalchemy/__init__.py | 3 +- .../kombu/transport/virtual/__init__.py | 38 +- .../kombu/transport/zookeeper.py | 3 +- awx/lib/site-packages/kombu/utils/__init__.py | 1 + awx/lib/site-packages/kombu/utils/debug.py | 3 +- awx/lib/site-packages/kombu/utils/eventio.py | 64 +- ...tual_interfacesv2_python_novaclient_ext.py | 96 + awx/lib/site-packages/pip/__init__.py | 85 +- awx/lib/site-packages/pip/_vendor/__init__.py | 8 + .../pip/_vendor/colorama/__init__.py | 7 + .../pip/_vendor/colorama/ansi.py | 50 + .../pip/_vendor/colorama/ansitowin32.py | 189 + .../pip/_vendor/colorama/initialise.py | 56 + .../pip/_vendor/colorama/win32.py | 134 + .../pip/_vendor/colorama/winterm.py | 120 + .../{vendor => _vendor}/distlib/__init__.py | 2 +- .../distlib/_backport/__init__.py | 0 .../distlib/_backport/misc.py | 0 .../distlib/_backport/shutil.py | 0 .../_vendor/distlib/_backport/sysconfig.cfg | 84 + .../distlib/_backport/sysconfig.py | 3 +- .../distlib/_backport/tarfile.py | 0 .../pip/{vendor => _vendor}/distlib/compat.py | 364 +- .../{vendor => _vendor}/distlib/database.py | 406 +- .../pip/{vendor => _vendor}/distlib/index.py | 77 +- .../{vendor => _vendor}/distlib/locators.py | 216 +- .../{vendor => _vendor}/distlib/manifest.py | 17 +- .../{vendor => _vendor}/distlib/markers.py | 25 +- .../{vendor => _vendor}/distlib/metadata.py | 605 +- .../{vendor => _vendor}/distlib/resources.py | 67 +- .../{vendor => _vendor}/distlib/scripts.py | 187 +- .../site-packages/pip/_vendor/distlib/t32.exe | Bin 0 -> 91136 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 0 -> 94720 bytes .../pip/{vendor => _vendor}/distlib/util.py | 359 +- .../{vendor => _vendor}/distlib/version.py | 421 +- .../site-packages/pip/_vendor/distlib/w32.exe | Bin 0 -> 87040 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 0 -> 91648 bytes .../pip/{vendor => _vendor}/distlib/wheel.py | 162 +- .../{vendor => _vendor}/html5lib/__init__.py | 0 .../{vendor => _vendor}/html5lib/constants.py | 0 .../html5lib/filters/__init__.py | 0 .../html5lib/filters/_base.py | 0 .../filters/alphabeticalattributes.py | 0 .../html5lib/filters/inject_meta_charset.py | 0 .../html5lib/filters/lint.py | 0 .../html5lib/filters/optionaltags.py | 0 .../html5lib/filters/sanitizer.py | 0 .../html5lib/filters/whitespace.py | 0 .../html5lib/html5parser.py | 2 +- .../{vendor => _vendor}/html5lib/ihatexml.py | 0 .../html5lib/inputstream.py | 2 +- .../{vendor => _vendor}/html5lib/sanitizer.py | 0 .../html5lib/serializer/__init__.py | 0 .../html5lib/serializer/htmlserializer.py | 2 +- .../{vendor => _vendor}/html5lib/tokenizer.py | 0 .../html5lib/treebuilders/__init__.py | 0 .../html5lib/treebuilders/_base.py | 2 +- .../html5lib/treebuilders/dom.py | 0 .../html5lib/treebuilders/etree.py | 2 +- .../html5lib/treebuilders/etree_lxml.py | 0 .../html5lib/treewalkers/__init__.py | 0 .../html5lib/treewalkers/_base.py | 2 +- .../html5lib/treewalkers/dom.py | 0 .../html5lib/treewalkers/etree.py | 2 +- .../html5lib/treewalkers/genshistream.py | 0 .../html5lib/treewalkers/lxmletree.py | 2 +- .../html5lib/treewalkers/pulldom.py | 0 .../html5lib/trie/__init__.py | 0 .../html5lib/trie/_base.py | 0 .../html5lib/trie/datrie.py | 2 +- .../{vendor => _vendor}/html5lib/trie/py.py | 2 +- .../pip/{vendor => _vendor}/html5lib/utils.py | 0 .../site-packages/pip/_vendor/re-vendor.py | 34 + .../pip/_vendor/requests/__init__.py | 77 + .../pip/_vendor/requests/adapters.py | 390 ++ .../site-packages/pip/_vendor/requests/api.py | 120 + .../pip/_vendor/requests/auth.py | 196 + .../pip/_vendor/requests/cacert.pem | 5026 +++++++++++++++++ .../pip/_vendor/requests/certs.py | 24 + .../pip/_vendor/requests/compat.py | 115 + .../pip/_vendor/requests/cookies.py | 445 ++ .../pip/_vendor/requests/exceptions.py | 63 + .../pip/_vendor/requests/hooks.py | 45 + .../pip/_vendor/requests/models.py | 773 +++ .../pip/_vendor/requests/packages/__init__.py | 3 + .../requests/packages/charade/__init__.py | 66 + .../requests/packages/charade/__main__.py | 7 + .../requests/packages/charade/big5freq.py | 925 +++ .../requests/packages/charade/big5prober.py | 42 + .../packages/charade/chardistribution.py | 231 + .../packages/charade/charsetgroupprober.py | 106 + .../packages/charade/charsetprober.py | 62 + .../packages/charade/codingstatemachine.py | 61 + .../requests/packages/charade/compat.py | 34 + .../requests/packages/charade/constants.py | 39 + .../requests/packages/charade/cp949prober.py | 44 + .../requests/packages/charade/escprober.py | 86 + .../requests/packages/charade/escsm.py | 242 + .../requests/packages/charade/eucjpprober.py | 90 + .../requests/packages/charade/euckrfreq.py | 596 ++ .../requests/packages/charade/euckrprober.py | 42 + .../requests/packages/charade/euctwfreq.py | 428 ++ .../requests/packages/charade/euctwprober.py | 41 + .../requests/packages/charade/gb2312freq.py | 472 ++ .../requests/packages/charade/gb2312prober.py | 41 + .../requests/packages/charade/hebrewprober.py | 283 + .../requests/packages/charade/jisfreq.py | 569 ++ .../requests/packages/charade/jpcntx.py | 219 + .../packages/charade/langbulgarianmodel.py | 229 + .../packages/charade/langcyrillicmodel.py | 329 ++ .../packages/charade/langgreekmodel.py | 225 + .../packages/charade/langhebrewmodel.py | 201 + .../packages/charade/langhungarianmodel.py | 225 + .../packages/charade/langthaimodel.py | 200 + .../requests/packages/charade/latin1prober.py | 139 + .../packages/charade/mbcharsetprober.py | 86 + .../packages/charade/mbcsgroupprober.py | 54 + .../requests/packages/charade/mbcssm.py | 575 ++ .../packages/charade/sbcharsetprober.py | 120 + .../packages/charade/sbcsgroupprober.py | 69 + .../requests/packages/charade/sjisprober.py | 91 + .../packages/charade/universaldetector.py | 168 + .../requests/packages/charade/utf8prober.py | 76 + .../requests/packages/urllib3/__init__.py | 58 + .../requests/packages/urllib3/_collections.py | 103 + .../requests/packages/urllib3/connection.py | 107 + .../packages/urllib3/connectionpool.py | 681 +++ .../packages/urllib3/contrib}/__init__.py | 0 .../packages/urllib3/contrib/ntlmpool.py | 120 + .../packages/urllib3/contrib/pyopenssl.py | 346 ++ .../requests/packages/urllib3/exceptions.py | 121 + .../requests/packages/urllib3/fields.py | 177 + .../requests/packages/urllib3/filepost.py | 101 + .../packages/urllib3/packages/__init__.py | 4 + .../packages/urllib3/packages/ordered_dict.py | 260 + .../requests/packages/urllib3/packages/six.py | 385 ++ .../packages/ssl_match_hostname/__init__.py | 13 + .../ssl_match_hostname/_implementation.py | 105 + .../requests/packages/urllib3/poolmanager.py | 258 + .../requests/packages/urllib3/request.py | 142 + .../requests/packages/urllib3/response.py | 312 + .../_vendor/requests/packages/urllib3/util.py | 643 +++ .../pip/_vendor/requests/sessions.py | 552 ++ .../pip/_vendor/requests/status_codes.py | 88 + .../pip/_vendor/requests/structures.py | 128 + .../pip/_vendor/requests/utils.py | 643 +++ .../pip/{vendor => _vendor}/six.py | 0 .../pip/backwardcompat/__init__.py | 43 +- .../pip/backwardcompat/ssl_match_hostname.py | 68 - awx/lib/site-packages/pip/basecommand.py | 118 +- awx/lib/site-packages/pip/baseparser.py | 180 +- awx/lib/site-packages/pip/cacert.pem | 3895 ------------- awx/lib/site-packages/pip/cmdoptions.py | 247 +- awx/lib/site-packages/pip/commands/bundle.py | 7 +- awx/lib/site-packages/pip/commands/help.py | 2 +- awx/lib/site-packages/pip/commands/install.py | 75 +- awx/lib/site-packages/pip/commands/list.py | 27 +- .../site-packages/pip/commands/uninstall.py | 9 +- awx/lib/site-packages/pip/commands/wheel.py | 52 +- awx/lib/site-packages/pip/download.py | 511 +- awx/lib/site-packages/pip/exceptions.py | 8 + awx/lib/site-packages/pip/index.py | 434 +- awx/lib/site-packages/pip/locations.py | 48 +- awx/lib/site-packages/pip/log.py | 117 +- awx/lib/site-packages/pip/req.py | 247 +- awx/lib/site-packages/pip/status_codes.py | 1 + awx/lib/site-packages/pip/util.py | 54 +- awx/lib/site-packages/pip/vcs/bazaar.py | 4 +- awx/lib/site-packages/pip/vcs/mercurial.py | 4 +- awx/lib/site-packages/pip/vendor/__init__.py | 8 - awx/lib/site-packages/pip/wheel.py | 212 +- awx/lib/site-packages/pkg_resources.py | 382 +- .../rackspace_auth_openstack/plugin.py | 2 +- awx/lib/site-packages/requests/__init__.py | 4 +- awx/lib/site-packages/requests/adapters.py | 56 +- awx/lib/site-packages/requests/auth.py | 54 +- awx/lib/site-packages/requests/cacert.pem | 122 +- awx/lib/site-packages/requests/cookies.py | 39 +- awx/lib/site-packages/requests/models.py | 64 +- .../requests/packages/urllib3/_collections.py | 11 +- .../packages/urllib3/connectionpool.py | 7 + .../packages/urllib3/contrib/pyopenssl.py | 8 +- .../packages/ssl_match_hostname/__init__.py | 109 +- .../ssl_match_hostname/_implementation.py | 105 + .../requests/packages/urllib3/poolmanager.py | 7 +- .../requests/packages/urllib3/response.py | 11 + .../requests/packages/urllib3/util.py | 10 +- awx/lib/site-packages/requests/sessions.py | 51 +- awx/lib/site-packages/requests/utils.py | 81 +- .../site-packages/rest_framework/__init__.py | 18 +- .../site-packages/rest_framework/compat.py | 8 + .../site-packages/rest_framework/fields.py | 40 +- .../site-packages/rest_framework/filters.py | 6 +- .../site-packages/rest_framework/generics.py | 37 +- .../site-packages/rest_framework/mixins.py | 13 +- .../site-packages/rest_framework/parsers.py | 4 +- .../rest_framework/permissions.py | 7 +- .../site-packages/rest_framework/renderers.py | 175 +- .../site-packages/rest_framework/request.py | 2 +- .../site-packages/rest_framework/response.py | 4 + .../rest_framework/serializers.py | 60 +- .../site-packages/rest_framework/status.py | 17 + .../templates/rest_framework/base.html | 11 +- .../templates/rest_framework/form.html | 12 +- .../rest_framework/raw_data_form.html | 12 + .../rest_framework/tests/test_fields.py | 92 +- .../rest_framework/tests/test_files.py | 13 + .../rest_framework/tests/test_filters.py | 53 +- .../rest_framework/tests/test_generics.py | 60 +- .../rest_framework/tests/test_pagination.py | 87 +- .../rest_framework/tests/test_permissions.py | 4 +- .../rest_framework/tests/test_renderers.py | 31 +- .../rest_framework/tests/test_request.py | 32 +- .../rest_framework/tests/test_serializer.py | 104 +- .../tests/test_serializer_empty.py | 15 + .../tests/test_serializer_nested.py | 67 + .../rest_framework/tests/test_status.py | 33 + .../rest_framework/urlpatterns.py | 2 +- .../rest_framework/utils/encoders.py | 5 + awx/lib/site-packages/rest_framework/views.py | 4 +- .../site-packages/rest_framework/viewsets.py | 2 +- .../setuptools/_backport/hashlib/__init__.py | 146 - .../setuptools/_backport/hashlib/_sha.py | 359 -- .../setuptools/_backport/hashlib/_sha256.py | 260 - .../setuptools/_backport/hashlib/_sha512.py | 288 - .../setuptools/command/__init__.py | 6 +- .../setuptools/command/build_py.py | 101 +- .../setuptools/command/easy_install.py | 50 +- .../setuptools/command/egg_info.py | 116 +- .../site-packages/setuptools/command/sdist.py | 4 +- .../setuptools/command/upload.py | 183 - .../setuptools/command/upload_docs.py | 24 +- awx/lib/site-packages/setuptools/compat.py | 24 +- .../site-packages/setuptools/lib2to3_ex.py | 58 + .../site-packages/setuptools/package_index.py | 85 +- .../site-packages/setuptools/py24compat.py | 17 - .../site-packages/setuptools/py31compat.py | 11 + awx/lib/site-packages/setuptools/sandbox.py | 82 +- .../site-packages/setuptools/ssl_support.py | 83 +- awx/lib/site-packages/setuptools/svn_utils.py | 75 +- .../site-packages/setuptools/tests/doctest.py | 4 +- .../setuptools/tests/environment.py | 63 +- .../setuptools/tests/test_easy_install.py | 150 +- .../setuptools/tests/test_egg_info.py | 115 +- .../setuptools/tests/test_packageindex.py | 18 +- .../setuptools/tests/test_sdist.py | 146 +- .../setuptools/tests/test_svn.py | 31 +- awx/lib/site-packages/setuptools/version.py | 2 +- awx/lib/site-packages/south/__init__.py | 2 +- .../site-packages/south/hacks/django_1_0.py | 9 +- .../south/migration/migrators.py | 32 +- awx/lib/site-packages/taggit/__init__.py | 2 +- awx/lib/site-packages/taggit/managers.py | 126 +- awx/lib/site-packages/taggit/models.py | 1 - awx/templates/rest_framework/base.html | 11 +- requirements/South-0.8.3.tar.gz | Bin 97650 -> 0 bytes requirements/South-0.8.4.tar.gz | Bin 0 -> 97800 bytes requirements/argparse-1.2.1.tar.gz | Bin 0 -> 69297 bytes requirements/billiard-3.3.0.13.tar.gz | Bin 0 -> 148777 bytes requirements/billiard-3.3.0.6.tar.gz | Bin 146649 -> 0 bytes requirements/boto-2.17.0.tar.gz | Bin 5993878 -> 0 bytes requirements/boto-2.21.2.tar.gz | Bin 0 -> 6103547 bytes requirements/celery-3.1.3.tar.gz | Bin 1269548 -> 0 bytes requirements/celery-3.1.7.tar.gz | Bin 0 -> 1271174 bytes requirements/dev.txt | 1 + requirements/dev_local.txt | 32 +- requirements/django-auth-ldap-1.1.6.tar.gz | Bin 39321 -> 0 bytes requirements/django-auth-ldap-1.1.7.tar.gz | Bin 0 -> 127186 bytes requirements/django-jsonfield-0.9.11.tar.gz | Bin 10882 -> 0 bytes requirements/django-jsonfield-0.9.12.tar.gz | Bin 0 -> 11378 bytes .../django-split-settings-0.1.1.tar.gz | Bin 0 -> 7883 bytes requirements/django-taggit-0.10.tar.gz | Bin 29610 -> 0 bytes requirements/django-taggit-0.11.2.tar.gz | Bin 0 -> 30961 bytes .../djangorestframework-2.3.10.tar.gz | Bin 0 -> 239154 bytes requirements/djangorestframework-2.3.8.tar.gz | Bin 234632 -> 0 bytes requirements/keyring-3.2.zip | Bin 85773 -> 0 bytes requirements/keyring-3.3.zip | Bin 0 -> 86419 bytes requirements/kombu-3.0.4.tar.gz | Bin 329216 -> 0 bytes requirements/kombu-3.0.8.tar.gz | Bin 0 -> 335226 bytes ...rfacesv2_python_novaclient_ext-0.14.tar.gz | Bin 0 -> 2553 bytes requirements/pip-1.4.1.tar.gz | Bin 445199 -> 0 bytes requirements/pip-1.5.tar.gz | Bin 0 -> 898803 bytes requirements/prod.txt | 1 + requirements/prod_local.txt | 32 +- .../rackspace-auth-openstack-1.1.tar.gz | Bin 6567 -> 0 bytes .../rackspace-auth-openstack-1.2.tar.gz | Bin 0 -> 6510 bytes requirements/rackspace-novaclient-1.3.tar.gz | Bin 1488 -> 0 bytes requirements/rackspace-novaclient-1.4.tar.gz | Bin 0 -> 1706 bytes requirements/requests-2.0.1.tar.gz | Bin 412648 -> 0 bytes requirements/requests-2.1.0.tar.gz | Bin 0 -> 420289 bytes requirements/setuptools-1.3.2.tar.gz | Bin 789412 -> 0 bytes requirements/setuptools-2.0.2.tar.gz | Bin 0 -> 784218 bytes 573 files changed, 34282 insertions(+), 10890 deletions(-) create mode 100644 awx/lib/site-packages/boto/directconnect/__init__.py create mode 100644 awx/lib/site-packages/boto/directconnect/exceptions.py create mode 100644 awx/lib/site-packages/boto/directconnect/layer1.py create mode 100644 awx/lib/site-packages/boto/ec2/elb/attributes.py create mode 100644 awx/lib/site-packages/boto/kinesis/__init__.py create mode 100644 awx/lib/site-packages/boto/kinesis/exceptions.py create mode 100644 awx/lib/site-packages/boto/kinesis/layer1.py create mode 100644 awx/lib/site-packages/boto/sqs/bigmessage.py create mode 100644 awx/lib/site-packages/kombu/tests/transport/test_SQS.py create mode 100644 awx/lib/site-packages/os_virtual_interfacesv2_python_novaclient_ext.py create mode 100644 awx/lib/site-packages/pip/_vendor/__init__.py create mode 100644 awx/lib/site-packages/pip/_vendor/colorama/__init__.py create mode 100644 awx/lib/site-packages/pip/_vendor/colorama/ansi.py create mode 100644 awx/lib/site-packages/pip/_vendor/colorama/ansitowin32.py create mode 100644 awx/lib/site-packages/pip/_vendor/colorama/initialise.py create mode 100644 awx/lib/site-packages/pip/_vendor/colorama/win32.py create mode 100644 awx/lib/site-packages/pip/_vendor/colorama/winterm.py rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/__init__.py (95%) rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/_backport/__init__.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/_backport/misc.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/_backport/shutil.py (100%) create mode 100644 awx/lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/_backport/sysconfig.py (99%) rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/_backport/tarfile.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/compat.py (69%) rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/database.py (81%) rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/index.py (87%) rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/locators.py (86%) rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/manifest.py (95%) rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/markers.py (90%) rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/metadata.py (54%) rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/resources.py (88%) rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/scripts.py (54%) create mode 100644 awx/lib/site-packages/pip/_vendor/distlib/t32.exe create mode 100644 awx/lib/site-packages/pip/_vendor/distlib/t64.exe rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/util.py (80%) rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/version.py (64%) create mode 100644 awx/lib/site-packages/pip/_vendor/distlib/w32.exe create mode 100644 awx/lib/site-packages/pip/_vendor/distlib/w64.exe rename awx/lib/site-packages/pip/{vendor => _vendor}/distlib/wheel.py (77%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/__init__.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/constants.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/filters/__init__.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/filters/_base.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/filters/alphabeticalattributes.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/filters/inject_meta_charset.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/filters/lint.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/filters/optionaltags.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/filters/sanitizer.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/filters/whitespace.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/html5parser.py (99%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/ihatexml.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/inputstream.py (99%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/sanitizer.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/serializer/__init__.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/serializer/htmlserializer.py (99%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/tokenizer.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/treebuilders/__init__.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/treebuilders/_base.py (99%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/treebuilders/dom.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/treebuilders/etree.py (99%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/treebuilders/etree_lxml.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/treewalkers/__init__.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/treewalkers/_base.py (99%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/treewalkers/dom.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/treewalkers/etree.py (99%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/treewalkers/genshistream.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/treewalkers/lxmletree.py (99%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/treewalkers/pulldom.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/trie/__init__.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/trie/_base.py (100%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/trie/datrie.py (96%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/trie/py.py (97%) rename awx/lib/site-packages/pip/{vendor => _vendor}/html5lib/utils.py (100%) create mode 100644 awx/lib/site-packages/pip/_vendor/re-vendor.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/__init__.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/adapters.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/api.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/auth.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/cacert.pem create mode 100644 awx/lib/site-packages/pip/_vendor/requests/certs.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/compat.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/cookies.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/exceptions.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/hooks.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/models.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/__init__.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/__init__.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/__main__.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/big5freq.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/big5prober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/chardistribution.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/charsetgroupprober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/charsetprober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/codingstatemachine.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/compat.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/constants.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/cp949prober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/escprober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/escsm.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/eucjpprober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/euckrfreq.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/euckrprober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/euctwfreq.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/euctwprober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/gb2312freq.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/gb2312prober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/hebrewprober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/jisfreq.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/jpcntx.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/langbulgarianmodel.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/langcyrillicmodel.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/langgreekmodel.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/langhebrewmodel.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/langhungarianmodel.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/langthaimodel.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/latin1prober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/mbcharsetprober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/mbcsgroupprober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/mbcssm.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/sbcharsetprober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/sbcsgroupprober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/sjisprober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/universaldetector.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/charade/utf8prober.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/__init__.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/_collections.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/connection.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/connectionpool.py rename awx/lib/site-packages/{setuptools/_backport => pip/_vendor/requests/packages/urllib3/contrib}/__init__.py (100%) create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/contrib/ntlmpool.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/contrib/pyopenssl.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/exceptions.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/fields.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/filepost.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/__init__.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/ordered_dict.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/six.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/poolmanager.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/request.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/response.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/util.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/sessions.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/status_codes.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/structures.py create mode 100644 awx/lib/site-packages/pip/_vendor/requests/utils.py rename awx/lib/site-packages/pip/{vendor => _vendor}/six.py (100%) delete mode 100644 awx/lib/site-packages/pip/backwardcompat/ssl_match_hostname.py delete mode 100644 awx/lib/site-packages/pip/cacert.pem delete mode 100644 awx/lib/site-packages/pip/vendor/__init__.py create mode 100644 awx/lib/site-packages/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py create mode 100644 awx/lib/site-packages/rest_framework/templates/rest_framework/raw_data_form.html create mode 100644 awx/lib/site-packages/rest_framework/tests/test_serializer_empty.py create mode 100644 awx/lib/site-packages/rest_framework/tests/test_status.py delete mode 100644 awx/lib/site-packages/setuptools/_backport/hashlib/__init__.py delete mode 100644 awx/lib/site-packages/setuptools/_backport/hashlib/_sha.py delete mode 100644 awx/lib/site-packages/setuptools/_backport/hashlib/_sha256.py delete mode 100644 awx/lib/site-packages/setuptools/_backport/hashlib/_sha512.py delete mode 100644 awx/lib/site-packages/setuptools/command/upload.py create mode 100644 awx/lib/site-packages/setuptools/lib2to3_ex.py delete mode 100644 awx/lib/site-packages/setuptools/py24compat.py create mode 100644 awx/lib/site-packages/setuptools/py31compat.py delete mode 100644 requirements/South-0.8.3.tar.gz create mode 100644 requirements/South-0.8.4.tar.gz create mode 100644 requirements/argparse-1.2.1.tar.gz create mode 100644 requirements/billiard-3.3.0.13.tar.gz delete mode 100644 requirements/billiard-3.3.0.6.tar.gz delete mode 100644 requirements/boto-2.17.0.tar.gz create mode 100644 requirements/boto-2.21.2.tar.gz delete mode 100644 requirements/celery-3.1.3.tar.gz create mode 100644 requirements/celery-3.1.7.tar.gz delete mode 100644 requirements/django-auth-ldap-1.1.6.tar.gz create mode 100644 requirements/django-auth-ldap-1.1.7.tar.gz delete mode 100644 requirements/django-jsonfield-0.9.11.tar.gz create mode 100644 requirements/django-jsonfield-0.9.12.tar.gz create mode 100644 requirements/django-split-settings-0.1.1.tar.gz delete mode 100644 requirements/django-taggit-0.10.tar.gz create mode 100644 requirements/django-taggit-0.11.2.tar.gz create mode 100644 requirements/djangorestframework-2.3.10.tar.gz delete mode 100644 requirements/djangorestframework-2.3.8.tar.gz delete mode 100644 requirements/keyring-3.2.zip create mode 100644 requirements/keyring-3.3.zip delete mode 100644 requirements/kombu-3.0.4.tar.gz create mode 100644 requirements/kombu-3.0.8.tar.gz create mode 100644 requirements/os_virtual_interfacesv2_python_novaclient_ext-0.14.tar.gz delete mode 100644 requirements/pip-1.4.1.tar.gz create mode 100644 requirements/pip-1.5.tar.gz delete mode 100644 requirements/rackspace-auth-openstack-1.1.tar.gz create mode 100644 requirements/rackspace-auth-openstack-1.2.tar.gz delete mode 100644 requirements/rackspace-novaclient-1.3.tar.gz create mode 100644 requirements/rackspace-novaclient-1.4.tar.gz delete mode 100644 requirements/requests-2.0.1.tar.gz create mode 100644 requirements/requests-2.1.0.tar.gz delete mode 100644 requirements/setuptools-1.3.2.tar.gz create mode 100644 requirements/setuptools-2.0.2.tar.gz diff --git a/awx/lib/site-packages/README b/awx/lib/site-packages/README index 58bf49acbc..a4c257621e 100644 --- a/awx/lib/site-packages/README +++ b/awx/lib/site-packages/README @@ -5,48 +5,49 @@ amqp==1.3.3 (amqp/*) anyjson==0.3.3 (anyjson/*) argparse==1.2.1 (argparse.py, needed for Python 2.6 support) Babel==1.3 (babel/*, excluded bin/pybabel) -billiard==3.3.0.6 (billiard/*, funtests/*, excluded _billiard.so) -boto==2.17.0 (boto/*, excluded bin/asadmin, bin/bundle_image, bin/cfadmin, +billiard==3.3.0.13 (billiard/*, funtests/*, excluded _billiard.so) +boto==2.21.2 (boto/*, excluded bin/asadmin, bin/bundle_image, bin/cfadmin, bin/cq, bin/cwutil, bin/dynamodb_dump, bin/dynamodb_load, bin/elbadmin, bin/fetch_file, bin/glacier, bin/instance_events, bin/kill_instance, bin/launch_instance, bin/list_instances, bin/lss3, bin/mturk, bin/pyami_sendmail, bin/route53, bin/s3put, bin/sdbadmin, bin/taskadmin) -celery==3.1.3 (celery/*, excluded bin/celery*) +celery==3.1.7 (celery/*, excluded bin/celery*) d2to1==0.2.11 (d2to1/*) distribute==0.7.3 (no files) -django-auth-ldap==1.1.6 (django_auth_ldap/*) +django-auth-ldap==1.1.7 (django_auth_ldap/*) django-celery==3.1.1 (djcelery/*) django-extensions==1.2.5 (django_extensions/*) -django-jsonfield==0.9.11 (jsonfield/*) +django-jsonfield==0.9.12 (jsonfield/*) django-split-settings==0.1.1 (split_settings/*) -django-taggit==0.10 (taggit/*) -djangorestframework==2.3.8 (rest_framework/*) +django-taggit==0.11.2 (taggit/*) +djangorestframework==2.3.10 (rest_framework/*) httplib2==0.8 (httplib2/*) importlib==1.0.2 (importlib/*, needed for Python 2.6 support) iso8601==0.1.8 (iso8601/*) -keyring==3.2 (keyring/*, excluded bin/keyring) -kombu==3.0.4 (kombu/*) +keyring==3.3 (keyring/*, excluded bin/keyring) +kombu==3.0.8 (kombu/*) Markdown==2.3.1 (markdown/*, excluded bin/markdown_py) mock==1.0.1 (mock.py) ordereddict==1.1 (ordereddict.py, needed for Python 2.6 support) os-diskconfig-python-novaclient-ext==0.1.1 (os_diskconfig_python_novaclient_ext/*) os-networksv2-python-novaclient-ext==0.21 (os_networksv2_python_novaclient_ext.py) +os-virtual-interfacesv2-python-novaclient-ext==0.14 (os_virtual_interfacesv2_python_novaclient_ext.py) pbr==0.5.23 (pbr/*) pexpect==3.0 (pexpect/*, excluded pxssh.py, fdpexpect.py, FSM.py, screen.py, ANSI.py) -pip==1.4.1 (pip/*, excluded bin/pip*) +pip==1.5 (pip/*, excluded bin/pip*) prettytable==0.7.2 (prettytable.py) pyrax==1.6.2 (pyrax/*) python-dateutil==2.2 (dateutil/*) python-novaclient==2.15.0 (novaclient/*, excluded bin/nova) python-swiftclient==1.8.0 (swiftclient/*, excluded bin/swift) pytz==2013.8 (pytz/*) -rackspace-auth-openstack==1.1 (rackspace_auth_openstack/*) -rackspace-novaclient==1.3 (no files) +rackspace-auth-openstack==1.2 (rackspace_auth_openstack/*) +rackspace-novaclient==1.4 (no files) rax-default-network-flags-python-novaclient-ext==0.1.3 (rax_default_network_flags_python_novaclient_ext/*) rax-scheduled-images-python-novaclient-ext==0.2.1 (rax_scheduled_images_python_novaclient_ext/*) -requests==2.0.1 (requests/*) -setuptools==1.3.2 (setuptools/*, _markerlib/*, pkg_resources.py, easy_install.py, excluded bin/easy_install*) +requests==2.1.0 (requests/*) +setuptools==2.0.2 (setuptools/*, _markerlib/*, pkg_resources.py, easy_install.py, excluded bin/easy_install*) simplejson==3.3.1 (simplejson/*, excluded simplejson/_speedups.so) six==1.4.1 (six.py) -South==0.8.3 (south/*) +South==0.8.4 (south/*) diff --git a/awx/lib/site-packages/billiard/__init__.py b/awx/lib/site-packages/billiard/__init__.py index ab5642cde7..b966c36fc6 100644 --- a/awx/lib/site-packages/billiard/__init__.py +++ b/awx/lib/site-packages/billiard/__init__.py @@ -19,8 +19,8 @@ from __future__ import absolute_import -VERSION = (3, 3, 0, 6) -__version__ = ".".join(map(str, VERSION[0:4])) + "".join(VERSION[4:]) +VERSION = (3, 3, 0, 13) +__version__ = '.'.join(map(str, VERSION[0:4])) + "".join(VERSION[4:]) __author__ = 'R Oudkerk / Python Software Foundation' __author_email__ = 'python-dev@python.org' __maintainer__ = 'Ask Solem', diff --git a/awx/lib/site-packages/billiard/_connection3.py b/awx/lib/site-packages/billiard/_connection3.py index 4cefcda5dd..f327f9244d 100644 --- a/awx/lib/site-packages/billiard/_connection3.py +++ b/awx/lib/site-packages/billiard/_connection3.py @@ -30,10 +30,17 @@ try: import _winapi from _winapi import ( WAIT_OBJECT_0, - WAIT_ABANDONED_0, WAIT_TIMEOUT, INFINITE, ) + # if we got here, we seem to be running on Windows. Handle probably + # missing WAIT_ABANDONED_0 constant: + try: + from _winapi import WAIT_ABANDONED_0 + except ImportError: + WAIT_ABANDONED_0 = 128 # _winapi seems to be not exporting + # this constant, fallback solution until + # exported in _winapi except ImportError: if sys.platform == 'win32': raise @@ -540,6 +547,7 @@ if sys.platform != 'win32': return c1, c2 else: + from billiard.forking import duplicate def Pipe(duplex=True, rnonblock=False, wnonblock=False): # noqa ''' @@ -574,9 +582,10 @@ else: _, err = overlapped.GetOverlappedResult(True) assert err == 0 - c1 = PipeConnection(h1, writable=duplex) - c2 = PipeConnection(h2, readable=duplex) - + c1 = PipeConnection(duplicate(h1, inheritable=True), writable=duplex) + c2 = PipeConnection(duplicate(h2, inheritable=True), readable=duplex) + _winapi.CloseHandle(h1) + _winapi.CloseHandle(h2) return c1, c2 # diff --git a/awx/lib/site-packages/billiard/_reduction.py b/awx/lib/site-packages/billiard/_reduction.py index 7230287fae..630923412f 100644 --- a/awx/lib/site-packages/billiard/_reduction.py +++ b/awx/lib/site-packages/billiard/_reduction.py @@ -23,7 +23,11 @@ from . import current_process from ._ext import _billiard, win32 from .util import register_after_fork, debug, sub_debug -if not(sys.platform == 'win32' or hasattr(_billiard, 'recvfd')): +is_win32 = sys.platform == 'win32' +is_pypy = hasattr(sys, 'pypy_version_info') +is_py3k = sys.version_info[0] == 3 + +if not(is_win32 or is_pypy or is_py3k or hasattr(_billiard, 'recvfd')): raise ImportError('pickling of connections not supported') close = win32.CloseHandle if sys.platform == 'win32' else os.close diff --git a/awx/lib/site-packages/billiard/common.py b/awx/lib/site-packages/billiard/common.py index 93e5a6015e..4b8ab82bfd 100644 --- a/awx/lib/site-packages/billiard/common.py +++ b/awx/lib/site-packages/billiard/common.py @@ -39,13 +39,20 @@ else: EX_SOFTWARE = 70 -TERMSIGS = ( +TERMSIGS_DEFAULT = ( + 'SIGHUP', + 'SIGQUIT', + 'SIGTERM', + 'SIGUSR1', + 'SIGUSR2' +) + +TERMSIGS_FULL = ( 'SIGHUP', 'SIGQUIT', 'SIGTRAP', 'SIGABRT', 'SIGEMT', - 'SIGBUS', 'SIGSYS', 'SIGPIPE', 'SIGALRM', @@ -88,8 +95,8 @@ def _shutdown_cleanup(signum, frame): sys.exit(-(256 - signum)) -def reset_signals(handler=_shutdown_cleanup): - for sig in TERMSIGS: +def reset_signals(handler=_shutdown_cleanup, full=False): + for sig in TERMSIGS_FULL if full else TERMSIGS_DEFAULT: try: signum = getattr(signal, sig) except AttributeError: diff --git a/awx/lib/site-packages/billiard/compat.py b/awx/lib/site-packages/billiard/compat.py index 113c121c6f..1300e33734 100644 --- a/awx/lib/site-packages/billiard/compat.py +++ b/awx/lib/site-packages/billiard/compat.py @@ -18,9 +18,9 @@ else: _winapi = None # noqa -try: +if sys.version_info > (2, 7, 5): buf_t, is_new_buffer = memoryview, True # noqa -except NameError: # Py2.6 +else: buf_t, is_new_buffer = buffer, False # noqa if hasattr(os, 'write'): @@ -31,7 +31,7 @@ if hasattr(os, 'write'): def send_offset(fd, buf, offset): return __write__(fd, buf[offset:]) - else: # Py2.6 + else: # Py<2.7.6 def send_offset(fd, buf, offset): # noqa return __write__(fd, buf_t(buf, offset)) diff --git a/awx/lib/site-packages/billiard/five.py b/awx/lib/site-packages/billiard/five.py index 1eeded46db..765b07ca13 100644 --- a/awx/lib/site-packages/billiard/five.py +++ b/awx/lib/site-packages/billiard/five.py @@ -38,11 +38,10 @@ if sys.version_info < (3, 3): if SYSTEM == 'Darwin': import ctypes + from ctypes.util import find_library libSystem = ctypes.CDLL('libSystem.dylib') - CoreServices = ctypes.CDLL( - '/System/Library/Frameworks/CoreServices.framework/CoreServices', - use_errno=True, - ) + CoreServices = ctypes.CDLL(find_library('CoreServices'), + use_errno=True) mach_absolute_time = libSystem.mach_absolute_time mach_absolute_time.restype = ctypes.c_uint64 absolute_to_nanoseconds = CoreServices.AbsoluteToNanoseconds diff --git a/awx/lib/site-packages/billiard/managers.py b/awx/lib/site-packages/billiard/managers.py index e9ac30abe3..0a8117a741 100644 --- a/awx/lib/site-packages/billiard/managers.py +++ b/awx/lib/site-packages/billiard/managers.py @@ -19,7 +19,6 @@ import sys import threading import array -from collections import Callable from traceback import format_exc from . import Process, current_process, active_children, Pool, util, connection @@ -123,7 +122,7 @@ def all_methods(obj): temp = [] for name in dir(obj): func = getattr(obj, name) - if isinstance(func, Callable): + if callable(func): temp.append(name) return temp @@ -492,8 +491,7 @@ class BaseManager(object): ''' assert self._state.value == State.INITIAL - if initializer is not None and \ - not isinstance(initializer, Callable): + if initializer is not None and not callable(initializer): raise TypeError('initializer must be a callable') # pipe over which we will retrieve address of server diff --git a/awx/lib/site-packages/billiard/pool.py b/awx/lib/site-packages/billiard/pool.py index 536787f8c1..4b71d51427 100644 --- a/awx/lib/site-packages/billiard/pool.py +++ b/awx/lib/site-packages/billiard/pool.py @@ -23,7 +23,7 @@ import threading import time import warnings -from collections import Callable, deque +from collections import deque from functools import partial from . import Event, Process, cpu_count @@ -86,6 +86,7 @@ ACK = 0 READY = 1 TASK = 2 NACK = 3 +DEATH = 4 # # Exit code constants @@ -236,13 +237,15 @@ class Worker(Process): _job_terminated = False def __init__(self, inq, outq, synq=None, initializer=None, initargs=(), - maxtasks=None, sentinel=None, on_exit=None): + maxtasks=None, sentinel=None, on_exit=None, + sigprotection=True): assert maxtasks is None or (type(maxtasks) == int and maxtasks > 0) self.initializer = initializer self.initargs = initargs self.maxtasks = maxtasks self._shutdown = sentinel self.on_exit = on_exit + self.sigprotection = sigprotection self.inq, self.outq, self.synq = inq, outq, synq self._make_shortcuts() @@ -295,7 +298,15 @@ class Worker(Process): if self.on_exit is not None: self.on_exit(pid, exitcode) - os._exit(exitcode) + + if sys.platform != 'win32': + try: + self.outq.put((DEATH, (pid, exitcode))) + time.sleep(1) + finally: + os._exit(exitcode) + else: + os._exit(exitcode) def on_loop_start(self, pid): pass @@ -378,7 +389,7 @@ class Worker(Process): # Make sure all exiting signals call finally: blocks. # This is important for the semaphore to be released. - reset_signals() + reset_signals(full=self.sigprotection) # install signal handler for soft timeouts. if SIG_SOFT_TIMEOUT is not None: @@ -760,8 +771,15 @@ class ResultHandler(PoolThread): except KeyError: pass + def on_death(pid, exitcode): + try: + os.kill(pid, signal.SIGTERM) + except OSError as exc: + if get_errno(exc) != errno.ESRCH: + raise + state_handlers = self.state_handlers = { - ACK: on_ack, READY: on_ready, + ACK: on_ack, READY: on_ready, DEATH: on_death } def on_state_change(task): @@ -934,12 +952,10 @@ class Pool(object): self.max_restarts = max_restarts or round(self._processes * 100) self.restart_state = restart_state(max_restarts, max_restart_freq or 1) - if initializer is not None and \ - not isinstance(initializer, Callable): + if initializer is not None and not callable(initializer): raise TypeError('initializer must be a callable') - if on_process_exit is not None and \ - not isinstance(on_process_exit, Callable): + if on_process_exit is not None and not callable(on_process_exit): raise TypeError('on_process_exit must be callable') self._pool = [] @@ -1034,6 +1050,9 @@ class Pool(object): w = self.Worker( inq, outq, synq, self._initializer, self._initargs, self._maxtasksperchild, sentinel, self._on_process_exit, + # Need to handle all signals if using the ipc semaphore, + # to make sure the semaphore is released. + sigprotection=self.threads, ) self._pool.append(w) self._process_register_queues(w, (inq, outq, synq)) @@ -1072,18 +1091,20 @@ class Pool(object): cleaned, exitcodes = {}, {} for i in reversed(range(len(self._pool))): worker = self._pool[i] - if worker.exitcode is not None: + exitcode = worker.exitcode + popen = worker._popen + if popen is None or exitcode is not None: # worker exited debug('Supervisor: cleaning up worker %d', i) worker.join() debug('Supervisor: worked %d joined', i) cleaned[worker.pid] = worker - exitcodes[worker.pid] = worker.exitcode - if worker.exitcode not in (EX_OK, EX_RECYCLE) and \ + exitcodes[worker.pid] = exitcode + if exitcode not in (EX_OK, EX_RECYCLE) and \ not getattr(worker, '_controlled_termination', False): error( 'Process %r pid:%r exited with exitcode %r', - worker.name, worker.pid, worker.exitcode, exc_info=0, + worker.name, worker.pid, exitcode, exc_info=0, ) self.process_flush_queues(worker) del self._pool[i] @@ -1100,9 +1121,9 @@ class Pool(object): if acked_by_gone: self.on_job_process_down(job, acked_by_gone) if not job.ready(): - exitcode = exitcodes[acked_by_gone] - if getattr(cleaned[acked_by_gone], - '_job_terminated', False): + exitcode = exitcodes.get(acked_by_gone) or 0 + proc = cleaned.get(acked_by_gone) + if proc and getattr(proc, '_job_terminated', False): job._set_terminated(exitcode) else: self.on_job_process_lost( @@ -1114,9 +1135,9 @@ class Pool(object): # was scheduled to write to sched_for = job._scheduled_for - if write_to and write_to.exitcode is not None: + if write_to and not write_to._is_alive(): self.on_job_process_down(job, write_to.pid) - elif sched_for and sched_for.exitcode is not None: + elif sched_for and not sched_for._is_alive(): self.on_job_process_down(job, sched_for.pid) for worker in values(cleaned): @@ -1551,7 +1572,7 @@ class Pool(object): if pool and hasattr(pool[0], 'terminate'): debug('terminating workers') for p in pool: - if p._popen is not None and p.exitcode is None: + if p._is_alive(): p.terminate() debug('joining task handler') @@ -1642,9 +1663,9 @@ class ApplyResult(object): def terminate(self, signum): self._terminated = signum - def _set_terminated(self, signum=0): + def _set_terminated(self, signum=None): try: - raise Terminated(-signum) + raise Terminated(-(signum or 0)) except Terminated: self._set(None, (False, ExceptionInfo())) diff --git a/awx/lib/site-packages/billiard/process.py b/awx/lib/site-packages/billiard/process.py index 8369072b99..f3d01d13f2 100644 --- a/awx/lib/site-packages/billiard/process.py +++ b/awx/lib/site-packages/billiard/process.py @@ -22,6 +22,8 @@ import binascii import logging import threading +from multiprocessing import process as _mproc + from .compat import bytes try: from _weakrefset import WeakSet @@ -46,6 +48,11 @@ def current_process(): return _current_process +def _set_current_process(process): + global _current_process + _current_process = _mproc._current_process = process + + def _cleanup(): # check for processes which have finished if _current_process is not None: @@ -122,8 +129,6 @@ class Process(object): assert self._popen is None, 'cannot start a process twice' assert self._parent_pid == os.getpid(), \ 'can only start a process object created by current process' - assert not _current_process._daemonic, \ - 'daemonic processes are not allowed to have children' _cleanup() if self._Popen is not None: Popen = self._Popen @@ -161,6 +166,11 @@ class Process(object): self._popen.poll() return self._popen.returncode is None + def _is_alive(self): + if self._popen is None: + return False + return self._popen.poll() is None + def _get_name(self): return self._name @@ -254,7 +264,7 @@ class Process(object): except (OSError, ValueError): pass old_process = _current_process - _current_process = self + _set_current_process(self) # Re-init logging system. # Workaround for http://bugs.python.org/issue6721/#msg140215 diff --git a/awx/lib/site-packages/billiard/tests/test_common.py b/awx/lib/site-packages/billiard/tests/test_common.py index 8fef4d1494..0eb3318911 100644 --- a/awx/lib/site-packages/billiard/tests/test_common.py +++ b/awx/lib/site-packages/billiard/tests/test_common.py @@ -21,13 +21,14 @@ def signo(name): @contextmanager -def termsigs(*sigs): +def termsigs(default, full): from billiard import common - prev, common.TERMSIGS = common.TERMSIGS, sigs + prev_def, common.TERMSIGS_DEFAULT = common.TERMSIGS_DEFAULT, default + prev_full, common.TERMSIGS_FULL = common.TERMSIGS_FULL, full try: yield finally: - common.TERMSIGS = prev + common.TERMSIGS_DEFAULT, common.TERMSIGS_FULL = prev_def, prev_full class test_reset_signals(Case): @@ -39,21 +40,21 @@ class test_reset_signals(Case): self.assertEqual(os.WTERMSIG(exit.call_args[0][0]), 15) def test_does_not_reset_ignored_signal(self, sigs=['SIGTERM']): - with self.assert_context(sigs, signal.SIG_IGN) as (_, SET): + with self.assert_context(sigs, [], signal.SIG_IGN) as (_, SET): self.assertFalse(SET.called) def test_does_not_reset_if_current_is_None(self, sigs=['SIGTERM']): - with self.assert_context(sigs, None) as (_, SET): + with self.assert_context(sigs, [], None) as (_, SET): self.assertFalse(SET.called) def test_resets_for_SIG_DFL(self, sigs=['SIGTERM', 'SIGINT', 'SIGUSR1']): - with self.assert_context(sigs, signal.SIG_DFL) as (_, SET): + with self.assert_context(sigs, [], signal.SIG_DFL) as (_, SET): SET.assert_has_calls([ call(signo(sig), _shutdown_cleanup) for sig in sigs ]) def test_resets_for_obj(self, sigs=['SIGTERM', 'SIGINT', 'SIGUSR1']): - with self.assert_context(sigs, object()) as (_, SET): + with self.assert_context(sigs, [], object()) as (_, SET): SET.assert_has_calls([ call(signo(sig), _shutdown_cleanup) for sig in sigs ]) @@ -61,19 +62,19 @@ class test_reset_signals(Case): def test_handles_errors(self, sigs=['SIGTERM']): for exc in (OSError(), AttributeError(), ValueError(), RuntimeError()): - with self.assert_context(sigs, signal.SIG_DFL, exc) as (_, SET): + with self.assert_context(sigs, [], signal.SIG_DFL, exc) as (_, SET): self.assertTrue(SET.called) @contextmanager - def assert_context(self, sigs, get_returns=None, set_effect=None): - with termsigs(*sigs): + def assert_context(self, default, full, get_returns=None, set_effect=None): + with termsigs(default, full): with patch('signal.getsignal') as GET: with patch('signal.signal') as SET: GET.return_value = get_returns SET.side_effect = set_effect reset_signals() GET.assert_has_calls([ - call(signo(sig)) for sig in sigs + call(signo(sig)) for sig in default ]) yield GET, SET diff --git a/awx/lib/site-packages/boto/__init__.py b/awx/lib/site-packages/boto/__init__.py index 786f0f858c..1b3c6517d8 100644 --- a/awx/lib/site-packages/boto/__init__.py +++ b/awx/lib/site-packages/boto/__init__.py @@ -27,6 +27,7 @@ from boto.pyami.config import Config, BotoConfigLocations from boto.storage_uri import BucketStorageUri, FileStorageUri import boto.plugin +import datetime import os import platform import re @@ -36,9 +37,12 @@ import logging.config import urlparse from boto.exception import InvalidUriError -__version__ = '2.17.0' +__version__ = '2.21.2' Version = __version__ # for backware compatibility +# http://bugs.python.org/issue7980 +datetime.datetime.strptime('', '') + UserAgent = 'Boto/%s Python/%s %s/%s' % ( __version__, platform.python_version(), @@ -744,6 +748,50 @@ def connect_cloudtrail(aws_access_key_id=None, ) +def connect_directconnect(aws_access_key_id=None, + aws_secret_access_key=None, + **kwargs): + """ + Connect to AWS DirectConnect + + :type aws_access_key_id: string + :param aws_access_key_id: Your AWS Access Key ID + + :type aws_secret_access_key: string + :param aws_secret_access_key: Your AWS Secret Access Key + + :rtype: :class:`boto.directconnect.layer1.DirectConnectConnection` + :return: A connection to the AWS DirectConnect service + """ + from boto.directconnect.layer1 import DirectConnectConnection + return DirectConnectConnection( + aws_access_key_id=aws_access_key_id, + aws_secret_access_key=aws_secret_access_key, + **kwargs + ) + +def connect_kinesis(aws_access_key_id=None, + aws_secret_access_key=None, + **kwargs): + """ + Connect to Amazon Kinesis + + :type aws_access_key_id: string + :param aws_access_key_id: Your AWS Access Key ID + + :type aws_secret_access_key: string + :param aws_secret_access_key: Your AWS Secret Access Key + + rtype: :class:`boto.kinesis.layer1.KinesisConnection` + :return: A connection to the Amazon Kinesis service + """ + from boto.kinesis.layer1 import KinesisConnection + return KinesisConnection( + aws_access_key_id=aws_access_key_id, + aws_secret_access_key=aws_secret_access_key, + **kwargs + ) + def storage_uri(uri_str, default_scheme='file', debug=0, validate=True, bucket_storage_uri_class=BucketStorageUri, suppress_consec_slashes=True, is_latest=False): diff --git a/awx/lib/site-packages/boto/auth.py b/awx/lib/site-packages/boto/auth.py index 0d4221d619..0f8b10cef7 100644 --- a/awx/lib/site-packages/boto/auth.py +++ b/awx/lib/site-packages/boto/auth.py @@ -39,35 +39,15 @@ import hmac import sys import time import urllib +import urlparse import posixpath from boto.auth_handler import AuthHandler from boto.exception import BotoClientError -# -# the following is necessary because of the incompatibilities -# between Python 2.4, 2.5, and 2.6 as well as the fact that some -# people running 2.4 have installed hashlib as a separate module -# this fix was provided by boto user mccormix. -# see: http://code.google.com/p/boto/issues/detail?id=172 -# for more details. -# + try: from hashlib import sha1 as sha from hashlib import sha256 as sha256 - - if sys.version[:3] == "2.4": - # we are using an hmac that expects a .new() method. - class Faker: - def __init__(self, which): - self.which = which - self.digest_size = self.which().digest_size - - def new(self, *args, **kwargs): - return self.which(*args, **kwargs) - - sha = Faker(sha) - sha256 = Faker(sha256) - except ImportError: import sha sha256 = None @@ -129,7 +109,7 @@ class AnonAuthHandler(AuthHandler, HmacKeys): capability = ['anon'] def __init__(self, host, config, provider): - AuthHandler.__init__(self, host, config, provider) + super(AnonAuthHandler, self).__init__(host, config, provider) def add_auth(self, http_request, **kwargs): pass @@ -373,10 +353,15 @@ class HmacAuthV4Handler(AuthHandler, HmacKeys): case, sorting them in alphabetical order and then joining them into a string, separated by newlines. """ - l = sorted(['%s:%s' % (n.lower().strip(), - ' '.join(headers_to_sign[n].strip().split())) - for n in headers_to_sign]) - return '\n'.join(l) + canonical = [] + + for header in headers_to_sign: + c_name = header.lower().strip() + raw_value = headers_to_sign[header] + c_value = ' '.join(raw_value.strip().split()) + canonical.append('%s:%s' % (c_name, c_value)) + + return '\n'.join(sorted(canonical)) def signed_headers(self, headers_to_sign): l = ['%s' % n.lower().strip() for n in headers_to_sign] @@ -421,14 +406,11 @@ class HmacAuthV4Handler(AuthHandler, HmacKeys): scope.append('aws4_request') return '/'.join(scope) - def credential_scope(self, http_request): - scope = [] - http_request.timestamp = http_request.headers['X-Amz-Date'][0:8] - scope.append(http_request.timestamp) - # The service_name and region_name either come from: - # * The service_name/region_name attrs or (if these values are None) - # * parsed from the endpoint ..amazonaws.com. - parts = http_request.host.split('.') + def split_host_parts(self, host): + return host.split('.') + + def determine_region_name(self, host): + parts = self.split_host_parts(host) if self.region_name is not None: region_name = self.region_name elif len(parts) > 1: @@ -442,11 +424,25 @@ class HmacAuthV4Handler(AuthHandler, HmacKeys): else: region_name = parts[0] + return region_name + + def determine_service_name(self, host): + parts = self.split_host_parts(host) if self.service_name is not None: service_name = self.service_name else: service_name = parts[0] + return service_name + def credential_scope(self, http_request): + scope = [] + http_request.timestamp = http_request.headers['X-Amz-Date'][0:8] + scope.append(http_request.timestamp) + # The service_name and region_name either come from: + # * The service_name/region_name attrs or (if these values are None) + # * parsed from the endpoint ..amazonaws.com. + region_name = self.determine_region_name(http_request.host) + service_name = self.determine_service_name(http_request.host) http_request.service_name = service_name http_request.region_name = region_name @@ -516,6 +512,153 @@ class HmacAuthV4Handler(AuthHandler, HmacKeys): req.headers['Authorization'] = ','.join(l) +class S3HmacAuthV4Handler(HmacAuthV4Handler, AuthHandler): + """ + Implements a variant of Version 4 HMAC authorization specific to S3. + """ + capability = ['hmac-v4-s3'] + + def __init__(self, *args, **kwargs): + super(S3HmacAuthV4Handler, self).__init__(*args, **kwargs) + + if self.region_name: + self.region_name = self.clean_region_name(self.region_name) + + def clean_region_name(self, region_name): + if region_name.startswith('s3-'): + return region_name[3:] + + return region_name + + def canonical_uri(self, http_request): + # S3 does **NOT** do path normalization that SigV4 typically does. + # Urlencode the path, **NOT** ``auth_path`` (because vhosting). + path = urlparse.urlparse(http_request.path) + encoded = urllib.quote(path.path) + return encoded + + def host_header(self, host, http_request): + port = http_request.port + secure = http_request.protocol == 'https' + if ((port == 80 and not secure) or (port == 443 and secure)): + return http_request.host + return '%s:%s' % (http_request.host, port) + + def headers_to_sign(self, http_request): + """ + Select the headers from the request that need to be included + in the StringToSign. + """ + host_header_value = self.host_header(self.host, http_request) + headers_to_sign = {} + headers_to_sign = {'Host': host_header_value} + for name, value in http_request.headers.items(): + lname = name.lower() + # Hooray for the only difference! The main SigV4 signer only does + # ``Host`` + ``x-amz-*``. But S3 wants pretty much everything + # signed, except for authorization itself. + if not lname in ['authorization']: + headers_to_sign[name] = value + return headers_to_sign + + def determine_region_name(self, host): + # S3's different format(s) of representing region/service from the + # rest of AWS makes this hurt too. + # + # Possible domain formats: + # - s3.amazonaws.com (Classic) + # - s3-us-west-2.amazonaws.com (Specific region) + # - bukkit.s3.amazonaws.com (Vhosted Classic) + # - bukkit.s3-ap-northeast-1.amazonaws.com (Vhosted specific region) + # - s3.cn-north-1.amazonaws.com.cn - (Bejing region) + # - bukkit.s3.cn-north-1.amazonaws.com.cn - (Vhosted Bejing region) + parts = self.split_host_parts(host) + + if self.region_name is not None: + region_name = self.region_name + else: + # Classic URLs - s3-us-west-2.amazonaws.com + if len(parts) == 3: + region_name = self.clean_region_name(parts[0]) + + # Special-case for Classic. + if region_name == 's3': + region_name = 'us-east-1' + else: + # Iterate over the parts in reverse order. + for offset, part in enumerate(reversed(parts)): + part = part.lower() + + # Look for the first thing starting with 's3'. + # Until there's a ``.s3`` TLD, we should be OK. :P + if part == 's3': + # If it's by itself, the region is the previous part. + region_name = parts[-offset] + break + elif part.startswith('s3-'): + region_name = self.clean_region_name(part) + break + + return region_name + + def determine_service_name(self, host): + # Should this signing mechanism ever be used for anything else, this + # will fail. Consider utilizing the logic from the parent class should + # you find yourself here. + return 's3' + + def mangle_path_and_params(self, req): + """ + Returns a copy of the request object with fixed ``auth_path/params`` + attributes from the original. + """ + modified_req = copy.copy(req) + + # Unlike the most other services, in S3, ``req.params`` isn't the only + # source of query string parameters. + # Because of the ``query_args``, we may already have a query string + # **ON** the ``path/auth_path``. + # Rip them apart, so the ``auth_path/params`` can be signed + # appropriately. + parsed_path = urlparse.urlparse(modified_req.auth_path) + modified_req.auth_path = parsed_path.path + + if modified_req.params is None: + modified_req.params = {} + + raw_qs = parsed_path.query + existing_qs = urlparse.parse_qs( + raw_qs, + keep_blank_values=True + ) + + # ``parse_qs`` will return lists. Don't do that unless there's a real, + # live list provided. + for key, value in existing_qs.items(): + if isinstance(value, (list, tuple)): + if len(value) == 1: + existing_qs[key] = value[0] + + modified_req.params.update(existing_qs) + return modified_req + + def payload(self, http_request): + if http_request.headers.get('x-amz-content-sha256'): + return http_request.headers['x-amz-content-sha256'] + + return super(S3HmacAuthV4Handler, self).payload(http_request) + + def add_auth(self, req, **kwargs): + if not 'x-amz-content-sha256' in req.headers: + if '_sha256' in req.headers: + req.headers['x-amz-content-sha256'] = req.headers.pop('_sha256') + else: + req.headers['x-amz-content-sha256'] = self.payload(req) + + req = self.mangle_path_and_params(req) + return super(S3HmacAuthV4Handler, self).add_auth(req, **kwargs) + + class QueryAuthHandler(AuthHandler): """ Provides pure query construction (no actual signing). @@ -742,3 +885,24 @@ def get_auth_handler(host, config, provider, requested_capability=None): # user could override this with a .boto config that includes user-specific # credentials (for access to user data). return ready_handlers[-1] + + +def detect_potential_sigv4(func): + def _wrapper(self): + if hasattr(self, 'region'): + if getattr(self.region, 'endpoint', ''): + if '.cn-' in self.region.endpoint: + return ['hmac-v4'] + + return func(self) + return _wrapper + + +def detect_potential_s3sigv4(func): + def _wrapper(self): + if hasattr(self, 'host'): + if '.cn-' in self.host: + return ['hmac-v4-s3'] + + return func(self) + return _wrapper diff --git a/awx/lib/site-packages/boto/beanstalk/layer1.py b/awx/lib/site-packages/boto/beanstalk/layer1.py index e63f70e714..f70a6b28b6 100644 --- a/awx/lib/site-packages/boto/beanstalk/layer1.py +++ b/awx/lib/site-packages/boto/beanstalk/layer1.py @@ -45,7 +45,7 @@ class Layer1(AWSQueryConnection): region = RegionInfo(self, self.DefaultRegionName, self.DefaultRegionEndpoint) self.region = region - AWSQueryConnection.__init__(self, aws_access_key_id, + super(Layer1, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, @@ -237,7 +237,8 @@ class Layer1(AWSQueryConnection): version_label=None, template_name=None, solution_stack_name=None, cname_prefix=None, description=None, option_settings=None, - options_to_remove=None): + options_to_remove=None, tier_name=None, + tier_type=None, tier_version='1.0'): """Launches an environment for the application using a configuration. :type application_name: string @@ -245,14 +246,6 @@ class Layer1(AWSQueryConnection): version to be deployed. If no application is found with this name, CreateEnvironment returns an InvalidParameterValue error. - :type version_label: string - :param version_label: The name of the application version to deploy. If - the specified application has no associated application versions, - AWS Elastic Beanstalk UpdateEnvironment returns an - InvalidParameterValue error. Default: If not specified, AWS - Elastic Beanstalk attempts to launch the most recently created - application version. - :type environment_name: string :param environment_name: A unique name for the deployment environment. Used in the application URL. Constraint: Must be from 4 to 23 @@ -264,6 +257,14 @@ class Layer1(AWSQueryConnection): name becomes part of the CNAME, and therefore part of the visible URL for your application. + :type version_label: string + :param version_label: The name of the application version to deploy. If + the specified application has no associated application versions, + AWS Elastic Beanstalk UpdateEnvironment returns an + InvalidParameterValue error. Default: If not specified, AWS + Elastic Beanstalk attempts to launch the most recently created + application version. + :type template_name: string :param template_name: The name of the configuration template to use in deployment. If no configuration template is found with this @@ -308,6 +309,25 @@ class Layer1(AWSQueryConnection): options to remove from the configuration set for this new environment. + :type tier_name: string + :param tier_name: The name of the tier. Valid values are + "WebServer" and "Worker". Defaults to "WebServer". + The ``tier_name`` and a ``tier_type`` parameters are + related and the values provided must be valid. + The possible combinations are: + + * "WebServer" and "Standard" (the default) + * "Worker" and "SQS/HTTP" + + :type tier_type: string + :param tier_type: The type of the tier. Valid values are + "Standard" if ``tier_name`` is "WebServer" and "SQS/HTTP" + if ``tier_name`` is "Worker". Defaults to "Standard". + + :type tier_version: string + :type tier_version: The version of the tier. Valid values + currently are "1.0". Defaults to "1.0". + :raises: TooManyEnvironmentsException, InsufficientPrivilegesException """ @@ -330,6 +350,10 @@ class Layer1(AWSQueryConnection): if options_to_remove: self.build_list_params(params, options_to_remove, 'OptionsToRemove.member') + if tier_name and tier_type and tier_version: + params['Tier.member.Name'] = tier_name + params['Tier.member.Type'] = tier_type + params['Tier.member.Version'] = tier_version return self._get_response('CreateEnvironment', params) def create_storage_location(self): @@ -848,9 +872,9 @@ class Layer1(AWSQueryConnection): return self._get_response('RetrieveEnvironmentInfo', params) def swap_environment_cnames(self, source_environment_id=None, - source_environment_name=None, - destination_environment_id=None, - destination_environment_name=None): + source_environment_name=None, + destination_environment_id=None, + destination_environment_name=None): """Swaps the CNAMEs of two environments. :type source_environment_id: string @@ -1021,7 +1045,8 @@ class Layer1(AWSQueryConnection): def update_environment(self, environment_id=None, environment_name=None, version_label=None, template_name=None, description=None, option_settings=None, - options_to_remove=None): + options_to_remove=None, tier_name=None, + tier_type=None, tier_version='1.0'): """ Updates the environment description, deploys a new application version, updates the configuration settings to an entirely new @@ -1073,6 +1098,25 @@ class Layer1(AWSQueryConnection): :param options_to_remove: A list of custom user-defined configuration options to remove from the configuration set for this environment. + :type tier_name: string + :param tier_name: The name of the tier. Valid values are + "WebServer" and "Worker". Defaults to "WebServer". + The ``tier_name`` and a ``tier_type`` parameters are + related and the values provided must be valid. + The possible combinations are: + + * "WebServer" and "Standard" (the default) + * "Worker" and "SQS/HTTP" + + :type tier_type: string + :param tier_type: The type of the tier. Valid values are + "Standard" if ``tier_name`` is "WebServer" and "SQS/HTTP" + if ``tier_name`` is "Worker". Defaults to "Standard". + + :type tier_version: string + :type tier_version: The version of the tier. Valid values + currently are "1.0". Defaults to "1.0". + :raises: InsufficientPrivilegesException """ params = {} @@ -1093,6 +1137,10 @@ class Layer1(AWSQueryConnection): if options_to_remove: self.build_list_params(params, options_to_remove, 'OptionsToRemove.member') + if tier_name and tier_type and tier_version: + params['Tier.member.Name'] = tier_name + params['Tier.member.Type'] = tier_type + params['Tier.member.Version'] = tier_version return self._get_response('UpdateEnvironment', params) def validate_configuration_settings(self, application_name, diff --git a/awx/lib/site-packages/boto/cloudformation/__init__.py b/awx/lib/site-packages/boto/cloudformation/__init__.py index d5de73e8d2..cf6679f944 100644 --- a/awx/lib/site-packages/boto/cloudformation/__init__.py +++ b/awx/lib/site-packages/boto/cloudformation/__init__.py @@ -32,6 +32,7 @@ RegionData = { 'ap-northeast-1': 'cloudformation.ap-northeast-1.amazonaws.com', 'ap-southeast-1': 'cloudformation.ap-southeast-1.amazonaws.com', 'ap-southeast-2': 'cloudformation.ap-southeast-2.amazonaws.com', + 'cn-north-1': 'cloudformation.cn-north-1.amazonaws.com.cn', } diff --git a/awx/lib/site-packages/boto/cloudformation/connection.py b/awx/lib/site-packages/boto/cloudformation/connection.py index 5970225fbb..5e6325d523 100644 --- a/awx/lib/site-packages/boto/cloudformation/connection.py +++ b/awx/lib/site-packages/boto/cloudformation/connection.py @@ -57,7 +57,7 @@ class CloudFormationConnection(AWSQueryConnection): region = RegionInfo(self, self.DefaultRegionName, self.DefaultRegionEndpoint, CloudFormationConnection) self.region = region - AWSQueryConnection.__init__(self, aws_access_key_id, + super(CloudFormationConnection, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, diff --git a/awx/lib/site-packages/boto/cloudformation/template.py b/awx/lib/site-packages/boto/cloudformation/template.py index f1f8501835..762efce55a 100644 --- a/awx/lib/site-packages/boto/cloudformation/template.py +++ b/awx/lib/site-packages/boto/cloudformation/template.py @@ -1,6 +1,6 @@ from boto.resultset import ResultSet -class Template: +class Template(object): def __init__(self, connection=None): self.connection = connection self.description = None @@ -19,7 +19,7 @@ class Template: else: setattr(self, name, value) -class TemplateParameter: +class TemplateParameter(object): def __init__(self, parent): self.parent = parent self.default_value = None diff --git a/awx/lib/site-packages/boto/cloudfront/__init__.py b/awx/lib/site-packages/boto/cloudfront/__init__.py index 9888f50f38..0fa4ae8134 100644 --- a/awx/lib/site-packages/boto/cloudfront/__init__.py +++ b/awx/lib/site-packages/boto/cloudfront/__init__.py @@ -44,7 +44,7 @@ class CloudFrontConnection(AWSAuthConnection): port=None, proxy=None, proxy_port=None, host=DefaultHost, debug=0, security_token=None, validate_certs=True): - AWSAuthConnection.__init__(self, host, + super(CloudFrontConnection, self).__init__(host, aws_access_key_id, aws_secret_access_key, True, port, proxy, proxy_port, debug=debug, security_token=security_token, diff --git a/awx/lib/site-packages/boto/cloudfront/distribution.py b/awx/lib/site-packages/boto/cloudfront/distribution.py index 423cb201ee..9992ab6ffb 100644 --- a/awx/lib/site-packages/boto/cloudfront/distribution.py +++ b/awx/lib/site-packages/boto/cloudfront/distribution.py @@ -176,7 +176,7 @@ class StreamingDistributionConfig(DistributionConfig): def __init__(self, connection=None, origin='', enabled=False, caller_reference='', cnames=None, comment='', trusted_signers=None, logging=None): - DistributionConfig.__init__(self, connection=connection, + super(StreamingDistributionConfig, self).__init__(connection=connection, origin=origin, enabled=enabled, caller_reference=caller_reference, cnames=cnames, comment=comment, @@ -684,8 +684,8 @@ class StreamingDistribution(Distribution): def __init__(self, connection=None, config=None, domain_name='', id='', last_modified_time=None, status=''): - Distribution.__init__(self, connection, config, domain_name, - id, last_modified_time, status) + super(StreamingDistribution, self).__init__(connection, config, + domain_name, id, last_modified_time, status) self._object_class = StreamingObject def startElement(self, name, attrs, connection): @@ -693,7 +693,8 @@ class StreamingDistribution(Distribution): self.config = StreamingDistributionConfig() return self.config else: - return Distribution.startElement(self, name, attrs, connection) + return super(StreamingDistribution, self).startElement(name, attrs, + connection) def update(self, enabled=None, cnames=None, comment=None): """ diff --git a/awx/lib/site-packages/boto/cloudfront/identity.py b/awx/lib/site-packages/boto/cloudfront/identity.py index 1571e87a0a..123773d15d 100644 --- a/awx/lib/site-packages/boto/cloudfront/identity.py +++ b/awx/lib/site-packages/boto/cloudfront/identity.py @@ -14,15 +14,14 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. import uuid -class OriginAccessIdentity: - +class OriginAccessIdentity(object): def __init__(self, connection=None, config=None, id='', s3_user_id='', comment=''): self.connection = connection @@ -31,7 +30,7 @@ class OriginAccessIdentity: self.s3_user_id = s3_user_id self.comment = comment self.etag = None - + def startElement(self, name, attrs, connection): if name == 'CloudFrontOriginAccessIdentityConfig': self.config = OriginAccessIdentityConfig() @@ -63,9 +62,9 @@ class OriginAccessIdentity: def uri(self): return 'origin-access-identity/cloudfront/%s' % self.id - -class OriginAccessIdentityConfig: + +class OriginAccessIdentityConfig(object): def __init__(self, connection=None, caller_reference='', comment=''): self.connection = connection if caller_reference: @@ -94,8 +93,8 @@ class OriginAccessIdentityConfig: else: setattr(self, name, value) -class OriginAccessIdentitySummary: +class OriginAccessIdentitySummary(object): def __init__(self, connection=None, id='', s3_user_id='', comment=''): self.connection = connection @@ -103,7 +102,7 @@ class OriginAccessIdentitySummary: self.s3_user_id = s3_user_id self.comment = comment self.etag = None - + def startElement(self, name, attrs, connection): return None @@ -119,4 +118,4 @@ class OriginAccessIdentitySummary: def get_origin_access_identity(self): return self.connection.get_origin_access_identity_info(self.id) - + diff --git a/awx/lib/site-packages/boto/cloudfront/object.py b/awx/lib/site-packages/boto/cloudfront/object.py index 3574d13634..24fc85064c 100644 --- a/awx/lib/site-packages/boto/cloudfront/object.py +++ b/awx/lib/site-packages/boto/cloudfront/object.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -24,7 +24,7 @@ from boto.s3.key import Key class Object(Key): def __init__(self, bucket, name=None): - Key.__init__(self, bucket, name=name) + super(Object, self).__init__(bucket, name=name) self.distribution = bucket.distribution def __repr__(self): @@ -43,6 +43,6 @@ class Object(Key): class StreamingObject(Object): def url(self, scheme='rtmp'): - return Object.url(self, scheme) + return super(StreamingObject, self).url(scheme) + - diff --git a/awx/lib/site-packages/boto/cloudfront/signers.py b/awx/lib/site-packages/boto/cloudfront/signers.py index 0b0cd50a76..dcc9fc9ea3 100644 --- a/awx/lib/site-packages/boto/cloudfront/signers.py +++ b/awx/lib/site-packages/boto/cloudfront/signers.py @@ -14,17 +14,16 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -class Signer: - +class Signer(object): def __init__(self): self.id = None self.key_pair_ids = [] - + def startElement(self, name, attrs, connection): return None @@ -35,9 +34,9 @@ class Signer: self.id = value elif name == 'KeyPairId': self.key_pair_ids.append(value) - -class ActiveTrustedSigners(list): + +class ActiveTrustedSigners(list): def startElement(self, name, attrs, connection): if name == 'Signer': s = Signer() @@ -47,8 +46,8 @@ class ActiveTrustedSigners(list): def endElement(self, name, value, connection): pass -class TrustedSigners(list): +class TrustedSigners(list): def startElement(self, name, attrs, connection): return None diff --git a/awx/lib/site-packages/boto/cloudtrail/layer1.py b/awx/lib/site-packages/boto/cloudtrail/layer1.py index e1e2145338..861c35904f 100644 --- a/awx/lib/site-packages/boto/cloudtrail/layer1.py +++ b/awx/lib/site-packages/boto/cloudtrail/layer1.py @@ -42,8 +42,8 @@ class CloudTrailConnection(AWSQueryConnection): CloudTrail is a web service that records AWS API calls for your AWS account and delivers log files to an Amazon S3 bucket. The recorded information includes the identity of the user, the start - time of the event, the source IP address, the request parameters, - and the response elements returned by the service. + time of the AWS API call, the source IP address, the request + parameters, and the response elements returned by the service. As an alternative to using the API, you can use one of the AWS SDKs, which consist of libraries and sample code for various @@ -52,11 +52,11 @@ class CloudTrailConnection(AWSQueryConnection): programmatic access to AWSCloudTrail. For example, the SDKs take care of cryptographically signing requests, managing errors, and retrying requests automatically. For information about the AWS - SDKs, including how to download and install them, see the Tools - for Amazon Web Services page. + SDKs, including how to download and install them, see the `Tools + for Amazon Web Services page`_. See the CloudTrail User Guide for information about the data that - is included with each event listed in the log files. + is included with each AWS API call listed in the log files. """ APIVersion = "2013-11-01" DefaultRegionName = "us-east-1" @@ -71,10 +71,9 @@ class CloudTrailConnection(AWSQueryConnection): "TrailAlreadyExistsException": exceptions.TrailAlreadyExistsException, "InsufficientSnsTopicPolicyException": exceptions.InsufficientSnsTopicPolicyException, "InvalidTrailNameException": exceptions.InvalidTrailNameException, - "InternalErrorException": exceptions.InternalErrorException, + "TrailNotProvidedException": exceptions.TrailNotProvidedException, "TrailNotFoundException": exceptions.TrailNotFoundException, "S3BucketDoesNotExistException": exceptions.S3BucketDoesNotExistException, - "TrailNotProvidedException": exceptions.TrailNotProvidedException, "InvalidS3PrefixException": exceptions.InvalidS3PrefixException, "MaximumNumberOfTrailsExceededException": exceptions.MaximumNumberOfTrailsExceededException, "InsufficientS3BucketPolicyException": exceptions.InsufficientS3BucketPolicyException, @@ -90,75 +89,71 @@ class CloudTrailConnection(AWSQueryConnection): if 'host' not in kwargs: kwargs['host'] = region.endpoint - AWSQueryConnection.__init__(self, **kwargs) + super(CloudTrailConnection, self).__init__(**kwargs) self.region = region def _required_auth_capability(self): return ['hmac-v4'] - def create_trail(self, trail=None): + def create_trail(self, name=None, s3_bucket_name=None, + s3_key_prefix=None, sns_topic_name=None, + include_global_service_events=None, trail=None): """ - From the command line, use create-subscription. + From the command line, use `create-subscription`. Creates a trail that specifies the settings for delivery of - log data to an Amazon S3 bucket. The request includes a Trail - structure that specifies the following: + log data to an Amazon S3 bucket. + Support for passing Trail as a parameter ends as early as + February 25, 2014. The request and response examples in this + topic show the use of parameters as well as a Trail object. + Until Trail is removed, you can use either Trail or the + parameter list. - + Trail name. - + The name of the Amazon S3 bucket to which CloudTrail - delivers your log files. - + The name of the Amazon S3 key prefix that precedes each log - file. - + The name of the Amazon SNS topic that notifies you that a - new file is available in your bucket. - + Whether the log file should include events from global - services. Currently, the only events included in CloudTrail - log files are from IAM and AWS STS. + :type name: string + :param name: Specifies the name of the trail. + :type s3_bucket_name: string + :param s3_bucket_name: Specifies the name of the Amazon S3 bucket + designated for publishing log files. - Returns the appropriate HTTP status code if successful. If - not, it returns either one of the CommonErrors or a - FrontEndException with one of the following error codes: + :type s3_key_prefix: string + :param s3_key_prefix: Specifies the Amazon S3 key prefix that precedes + the name of the bucket you have designated for log file delivery. - **MaximumNumberOfTrailsExceeded** + :type sns_topic_name: string + :param sns_topic_name: Specifies the name of the Amazon SNS topic + defined for notification of log file delivery. - An attempt was made to create more trails than allowed. You - can only create one trail for each account in each region. - - **TrailAlreadyExists** - - At attempt was made to create a trail with a name that already - exists. - - **S3BucketDoesNotExist** - - Specified Amazon S3 bucket does not exist. - - **InsufficientS3BucketPolicy** - - Policy on Amazon S3 bucket does not permit CloudTrail to write - to your bucket. See the AWS AWS CloudTrail User Guide for the - required bucket policy. - - **InsufficientSnsTopicPolicy** - - The policy on Amazon SNS topic does not permit CloudTrail to - write to it. Can also occur when an Amazon SNS topic does not - exist. + :type include_global_service_events: boolean + :param include_global_service_events: Specifies whether the trail is + publishing events from global services such as IAM to the log + files. :type trail: dict - :param trail: Contains the Trail structure that specifies the settings - for each trail. + :param trail: Support for passing a Trail object in the CreateTrail or + UpdateTrail actions will end as early as February 15, 2014. Instead + of the Trail object and its members, use the parameters listed for + these actions. """ params = {} + if name is not None: + params['Name'] = name + if s3_bucket_name is not None: + params['S3BucketName'] = s3_bucket_name + if s3_key_prefix is not None: + params['S3KeyPrefix'] = s3_key_prefix + if sns_topic_name is not None: + params['SnsTopicName'] = sns_topic_name + if include_global_service_events is not None: + params['IncludeGlobalServiceEvents'] = include_global_service_events if trail is not None: params['trail'] = trail return self.make_request(action='CreateTrail', body=json.dumps(params)) - def delete_trail(self, name=None): + def delete_trail(self, name): """ Deletes a trail. @@ -166,19 +161,17 @@ class CloudTrailConnection(AWSQueryConnection): :param name: The name of a trail to be deleted. """ - params = {} - if name is not None: - params['Name'] = name + params = {'Name': name, } return self.make_request(action='DeleteTrail', body=json.dumps(params)) def describe_trails(self, trail_name_list=None): """ Retrieves the settings for some or all trails associated with - an account. Returns a list of Trail structures in JSON format. + an account. :type trail_name_list: list - :param trail_name_list: The list of Trail object names. + :param trail_name_list: The list of trails. """ params = {} @@ -187,97 +180,153 @@ class CloudTrailConnection(AWSQueryConnection): return self.make_request(action='DescribeTrails', body=json.dumps(params)) - def get_trail_status(self, name=None): + def get_trail_status(self, name): """ - Returns GetTrailStatusResult, which contains a JSON-formatted - list of information about the trail specified in the request. - JSON fields include information such as delivery errors, - Amazon SNS and Amazon S3 errors, and times that logging - started and stopped for each trail. + Returns a JSON-formatted list of information about the + specified trail. Fields include information on delivery + errors, Amazon SNS and Amazon S3 errors, and start and stop + logging times for each trail. + + The CloudTrail API is currently undergoing revision. This + action currently returns both new fields and fields slated for + removal from the API. The following lists indicate the plans + for each field: + + **List of Members Planned for Ongoing Support** + + + + IsLogging + + LatestDeliveryTime + + LatestNotificationTime + + StartLoggingTime + + StopLoggingTime + + LatestNotificationError + + LatestDeliveryError + + + **List of Members Scheduled for Removal** + + + + **LatestDeliveryAttemptTime**: Use LatestDeliveryTime + instead. + + **LatestNotificationAttemptTime**: Use + LatestNotificationTime instead. + + **LatestDeliveryAttemptSucceeded**: No replacement. See the + note following this list. + + **LatestNotificationAttemptSucceeded**: No replacement. See + the note following this list. + + **TimeLoggingStarted**: Use StartLoggingTime instead. + + **TimeLoggingStopped**: Use StopLoggingtime instead. + + + No replacements have been created for + LatestDeliveryAttemptSucceeded and + LatestNotificationAttemptSucceeded . Use LatestDeliveryError + and LatestNotificationError to evaluate success or failure of + log delivery or notification. Empty values returned for these + fields indicate success. An error in LatestDeliveryError + generally indicates either a missing bucket or insufficient + permissions to write to the bucket. Similarly, an error in + LatestNotificationError indicates either a missing topic or + insufficient permissions. :type name: string :param name: The name of the trail for which you are requesting the current status. """ - params = {} - if name is not None: - params['Name'] = name + params = {'Name': name, } return self.make_request(action='GetTrailStatus', body=json.dumps(params)) - def start_logging(self, name=None): + def start_logging(self, name): """ - Starts the processing of recording user activity events and - log file delivery for a trail. + Starts the recording of AWS API calls and log file delivery + for a trail. :type name: string - :param name: The name of the Trail for which CloudTrail logs events. + :param name: The name of the trail for which CloudTrail logs AWS API + calls. """ - params = {} - if name is not None: - params['Name'] = name + params = {'Name': name, } return self.make_request(action='StartLogging', body=json.dumps(params)) - def stop_logging(self, name=None): + def stop_logging(self, name): """ - Suspends the recording of user activity events and log file - delivery for the specified trail. Under most circumstances, - there is no need to use this action. You can update a trail - without stopping it first. This action is the only way to stop - logging activity. + Suspends the recording of AWS API calls and log file delivery + for the specified trail. Under most circumstances, there is no + need to use this action. You can update a trail without + stopping it first. This action is the only way to stop + recording. :type name: string - :param name: Communicates to CloudTrail the name of the Trail for which - to stop logging events. + :param name: Communicates to CloudTrail the name of the trail for which + to stop logging AWS API calls. + + """ + params = {'Name': name, } + return self.make_request(action='StopLogging', + body=json.dumps(params)) + + def update_trail(self, name=None, s3_bucket_name=None, + s3_key_prefix=None, sns_topic_name=None, + include_global_service_events=None, trail=None): + """ + From the command line, use `update-subscription`. + + Updates the settings that specify delivery of log files. + Changes to a trail do not require stopping the CloudTrail + service. Use this action to designate an existing bucket for + log delivery. If the existing bucket has previously been a + target for CloudTrail log files, an IAM policy exists for the + bucket. + + Support for passing Trail as a parameter ends as early as + February 25, 2014. The request and response examples in this + topic show the use of parameters as well as a Trail object. + Until Trail is removed, you can use either Trail or the + parameter list. + + :type name: string + :param name: Specifies the name of the trail. + + :type s3_bucket_name: string + :param s3_bucket_name: Specifies the name of the Amazon S3 bucket + designated for publishing log files. + + :type s3_key_prefix: string + :param s3_key_prefix: Specifies the Amazon S3 key prefix that precedes + the name of the bucket you have designated for log file delivery. + + :type sns_topic_name: string + :param sns_topic_name: Specifies the name of the Amazon SNS topic + defined for notification of log file delivery. + + :type include_global_service_events: boolean + :param include_global_service_events: Specifies whether the trail is + publishing events from global services such as IAM to the log + files. + + :type trail: dict + :param trail: Support for passing a Trail object in the CreateTrail or + UpdateTrail actions will end as early as February 15, 2014. Instead + of the Trail object and its members, use the parameters listed for + these actions. """ params = {} if name is not None: params['Name'] = name - return self.make_request(action='StopLogging', - body=json.dumps(params)) - - def update_trail(self, trail=None): - """ - From the command line, use update-subscription. - - Updates the settings that specify delivery of log files. - Changes to a trail do not require stopping the CloudTrail - service. You can use this action to designate an existing - bucket for log delivery, or to create a new bucket and prefix. - If the existing bucket has previously been a target for - CloudTrail log files, an IAM policy exists for the bucket. If - you create a new bucket using UpdateTrail, you need to apply - the policy to the bucket using one of the means provided by - the Amazon S3 service. - - The request includes a Trail structure that specifies the - following: - - - + Trail name. - + The name of the Amazon S3 bucket to which CloudTrail - delivers your log files. - + The name of the Amazon S3 key prefix that precedes each log - file. - + The name of the Amazon SNS topic that notifies you that a - new file is available in your bucket. - + Whether the log file should include events from global - services, such as IAM or AWS STS. - - **CreateTrail** returns the appropriate HTTP status code if - successful. If not, it returns either one of the common errors - or one of the exceptions listed at the end of this page. - - :type trail: dict - :param trail: Represents the Trail structure that contains the - CloudTrail setting for an account. - - """ - params = {} + if s3_bucket_name is not None: + params['S3BucketName'] = s3_bucket_name + if s3_key_prefix is not None: + params['S3KeyPrefix'] = s3_key_prefix + if sns_topic_name is not None: + params['SnsTopicName'] = sns_topic_name + if include_global_service_events is not None: + params['IncludeGlobalServiceEvents'] = include_global_service_events if trail is not None: params['trail'] = trail return self.make_request(action='UpdateTrail', diff --git a/awx/lib/site-packages/boto/connection.py b/awx/lib/site-packages/boto/connection.py index 78c7a22370..592a0098bd 100644 --- a/awx/lib/site-packages/boto/connection.py +++ b/awx/lib/site-packages/boto/connection.py @@ -372,7 +372,8 @@ class HTTPRequest(object): for key in self.headers: val = self.headers[key] if isinstance(val, unicode): - self.headers[key] = urllib.quote_plus(val.encode('utf-8')) + safe = '!"#$%&\'()*+,/:;<=>?@[\\]^`{|}~' + self.headers[key] = urllib.quote_plus(val.encode('utf-8'), safe) connection._auth_handler.add_auth(self, **kwargs) @@ -839,6 +840,13 @@ class AWSAuthConnection(object): auth = base64.encodestring(self.proxy_user + ':' + self.proxy_pass) return {'Proxy-Authorization': 'Basic %s' % auth} + def set_host_header(self, request): + try: + request.headers['Host'] = \ + self._auth_handler.host_header(self.host, request) + except AttributeError: + request.headers['Host'] = self.host.split(':', 1)[0] + def _mexe(self, request, sender=None, override_num_retries=None, retry_handler=None): """ @@ -879,7 +887,8 @@ class AWSAuthConnection(object): # the port info. All others should be now be up to date and # not include the port. if 's3' not in self._required_auth_capability(): - request.headers['Host'] = self.host.split(':', 1)[0] + self.set_host_header(request) + if callable(sender): response = sender(connection, request.method, request.path, request.body, request.headers) @@ -1025,7 +1034,7 @@ class AWSQueryConnection(AWSAuthConnection): proxy_user=None, proxy_pass=None, host=None, debug=0, https_connection_factory=None, path='/', security_token=None, validate_certs=True): - AWSAuthConnection.__init__(self, host, aws_access_key_id, + super(AWSQueryConnection, self).__init__(host, aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, diff --git a/awx/lib/site-packages/boto/contrib/ymlmessage.py b/awx/lib/site-packages/boto/contrib/ymlmessage.py index b9a2c93262..6f3dd20cf5 100644 --- a/awx/lib/site-packages/boto/contrib/ymlmessage.py +++ b/awx/lib/site-packages/boto/contrib/ymlmessage.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -43,7 +43,7 @@ class YAMLMessage(Message): def __init__(self, queue=None, body='', xml_attrs=None): self.data = None - Message.__init__(self, queue, body) + super(YAMLMessage, self).__init__(queue, body) def set_body(self, body): self.data = yaml.load(body) diff --git a/awx/lib/site-packages/boto/datapipeline/layer1.py b/awx/lib/site-packages/boto/datapipeline/layer1.py index ff0c40041c..0d9043521e 100644 --- a/awx/lib/site-packages/boto/datapipeline/layer1.py +++ b/awx/lib/site-packages/boto/datapipeline/layer1.py @@ -90,7 +90,7 @@ class DataPipelineConnection(AWSQueryConnection): region = RegionInfo(self, self.DefaultRegionName, self.DefaultRegionEndpoint) kwargs['host'] = region.endpoint - AWSQueryConnection.__init__(self, **kwargs) + super(DataPipelineConnection, self).__init__(**kwargs) self.region = region def _required_auth_capability(self): diff --git a/awx/lib/site-packages/boto/directconnect/__init__.py b/awx/lib/site-packages/boto/directconnect/__init__.py new file mode 100644 index 0000000000..0fa314ca69 --- /dev/null +++ b/awx/lib/site-packages/boto/directconnect/__init__.py @@ -0,0 +1,66 @@ +# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. +# All Rights Reserved +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, dis- +# tribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the fol- +# lowing conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +from boto.regioninfo import RegionInfo + + +def regions(): + """ + Get all available regions for the AWS DirectConnect service. + + :rtype: list + :return: A list of :class:`boto.regioninfo.RegionInfo` + """ + from boto.directconnect.layer1 import DirectConnectConnection + + return [RegionInfo(name='us-east-1', + endpoint='directconnect.us-east-1.amazonaws.com', + connection_cls=DirectConnectConnection), + RegionInfo(name='us-west-1', + endpoint='directconnect.us-west-1.amazonaws.com', + connection_cls=DirectConnectConnection), + RegionInfo(name='us-west-2', + endpoint='directconnect.us-west-2.amazonaws.com', + connection_cls=DirectConnectConnection), + RegionInfo(name='eu-west-1', + endpoint='directconnect.eu-west-1.amazonaws.com', + connection_cls=DirectConnectConnection), + RegionInfo(name='ap-southeast-1', + endpoint='directconnect.ap-southeast-1.amazonaws.com', + connection_cls=DirectConnectConnection), + RegionInfo(name='ap-southeast-2', + endpoint='directconnect.ap-southeast-2.amazonaws.com', + connection_cls=DirectConnectConnection), + RegionInfo(name='ap-southeast-3', + endpoint='directconnect.ap-southeast-3.amazonaws.com', + connection_cls=DirectConnectConnection), + RegionInfo(name='sa-east-1', + endpoint='directconnect.sa-east-1.amazonaws.com', + connection_cls=DirectConnectConnection), + ] + + +def connect_to_region(region_name, **kw_params): + for region in regions(): + if region.name == region_name: + return region.connect(**kw_params) + return None diff --git a/awx/lib/site-packages/boto/directconnect/exceptions.py b/awx/lib/site-packages/boto/directconnect/exceptions.py new file mode 100644 index 0000000000..e3cac9ba3c --- /dev/null +++ b/awx/lib/site-packages/boto/directconnect/exceptions.py @@ -0,0 +1,28 @@ +# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, dis- +# tribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the fol- +# lowing conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# + +class DirectConnectClientException(Exception): + pass + + +class DirectConnectServerException(Exception): + pass diff --git a/awx/lib/site-packages/boto/directconnect/layer1.py b/awx/lib/site-packages/boto/directconnect/layer1.py new file mode 100644 index 0000000000..b225e18e50 --- /dev/null +++ b/awx/lib/site-packages/boto/directconnect/layer1.py @@ -0,0 +1,633 @@ +# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, dis- +# tribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the fol- +# lowing conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# + +try: + import json +except ImportError: + import simplejson as json + +import boto +from boto.connection import AWSQueryConnection +from boto.regioninfo import RegionInfo +from boto.exception import JSONResponseError +from boto.directconnect import exceptions + + +class DirectConnectConnection(AWSQueryConnection): + """ + AWS Direct Connect makes it easy to establish a dedicated network + connection from your premises to Amazon Web Services (AWS). Using + AWS Direct Connect, you can establish private connectivity between + AWS and your data center, office, or colocation environment, which + in many cases can reduce your network costs, increase bandwidth + throughput, and provide a more consistent network experience than + Internet-based connections. + + The AWS Direct Connect API Reference provides descriptions, + syntax, and usage examples for each of the actions and data types + for AWS Direct Connect. Use the following links to get started + using the AWS Direct Connect API Reference : + + + + `Actions`_: An alphabetical list of all AWS Direct Connect + actions. + + `Data Types`_: An alphabetical list of all AWS Direct Connect + data types. + + `Common Query Parameters`_: Parameters that all Query actions + can use. + + `Common Errors`_: Client and server errors that all actions can + return. + """ + APIVersion = "2012-10-25" + DefaultRegionName = "us-east-1" + DefaultRegionEndpoint = "directconnect.us-east-1.amazonaws.com" + ServiceName = "DirectConnect" + TargetPrefix = "OvertureService" + ResponseError = JSONResponseError + + _faults = { + "DirectConnectClientException": exceptions.DirectConnectClientException, + "DirectConnectServerException": exceptions.DirectConnectServerException, + } + + + def __init__(self, **kwargs): + region = kwargs.pop('region', None) + if not region: + region = RegionInfo(self, self.DefaultRegionName, + self.DefaultRegionEndpoint) + + if 'host' not in kwargs: + kwargs['host'] = region.endpoint + + super(DirectConnectConnection, self).__init__(**kwargs) + self.region = region + + def _required_auth_capability(self): + return ['hmac-v4'] + + def allocate_connection_on_interconnect(self, bandwidth, connection_name, + owner_account, interconnect_id, + vlan): + """ + Creates a hosted connection on an interconnect. + + Allocates a VLAN number and a specified amount of bandwidth + for use by a hosted connection on the given interconnect. + + :type bandwidth: string + :param bandwidth: Bandwidth of the connection. + Example: " 500Mbps " + + Default: None + + :type connection_name: string + :param connection_name: Name of the provisioned connection. + Example: " 500M Connection to AWS " + + Default: None + + :type owner_account: string + :param owner_account: Numeric account Id of the customer for whom the + connection will be provisioned. + Example: 123443215678 + + Default: None + + :type interconnect_id: string + :param interconnect_id: ID of the interconnect on which the connection + will be provisioned. + Example: dxcon-456abc78 + + Default: None + + :type vlan: integer + :param vlan: The dedicated VLAN provisioned to the connection. + Example: 101 + + Default: None + + """ + params = { + 'bandwidth': bandwidth, + 'connectionName': connection_name, + 'ownerAccount': owner_account, + 'interconnectId': interconnect_id, + 'vlan': vlan, + } + return self.make_request(action='AllocateConnectionOnInterconnect', + body=json.dumps(params)) + + def allocate_private_virtual_interface(self, connection_id, + owner_account, + new_private_virtual_interface_allocation): + """ + Provisions a private virtual interface to be owned by a + different customer. + + The owner of a connection calls this function to provision a + private virtual interface which will be owned by another AWS + customer. + + Virtual interfaces created using this function must be + confirmed by the virtual interface owner by calling + ConfirmPrivateVirtualInterface. Until this step has been + completed, the virtual interface will be in 'Confirming' + state, and will not be available for handling traffic. + + :type connection_id: string + :param connection_id: The connection ID on which the private virtual + interface is provisioned. + Default: None + + :type owner_account: string + :param owner_account: The AWS account that will own the new private + virtual interface. + Default: None + + :type new_private_virtual_interface_allocation: dict + :param new_private_virtual_interface_allocation: Detailed information + for the private virtual interface to be provisioned. + Default: None + + """ + params = { + 'connectionId': connection_id, + 'ownerAccount': owner_account, + 'newPrivateVirtualInterfaceAllocation': new_private_virtual_interface_allocation, + } + return self.make_request(action='AllocatePrivateVirtualInterface', + body=json.dumps(params)) + + def allocate_public_virtual_interface(self, connection_id, owner_account, + new_public_virtual_interface_allocation): + """ + Provisions a public virtual interface to be owned by a + different customer. + + The owner of a connection calls this function to provision a + public virtual interface which will be owned by another AWS + customer. + + Virtual interfaces created using this function must be + confirmed by the virtual interface owner by calling + ConfirmPublicVirtualInterface. Until this step has been + completed, the virtual interface will be in 'Confirming' + state, and will not be available for handling traffic. + + :type connection_id: string + :param connection_id: The connection ID on which the public virtual + interface is provisioned. + Default: None + + :type owner_account: string + :param owner_account: The AWS account that will own the new public + virtual interface. + Default: None + + :type new_public_virtual_interface_allocation: dict + :param new_public_virtual_interface_allocation: Detailed information + for the public virtual interface to be provisioned. + Default: None + + """ + params = { + 'connectionId': connection_id, + 'ownerAccount': owner_account, + 'newPublicVirtualInterfaceAllocation': new_public_virtual_interface_allocation, + } + return self.make_request(action='AllocatePublicVirtualInterface', + body=json.dumps(params)) + + def confirm_connection(self, connection_id): + """ + Confirm the creation of a hosted connection on an + interconnect. + + Upon creation, the hosted connection is initially in the + 'Ordering' state, and will remain in this state until the + owner calls ConfirmConnection to confirm creation of the + hosted connection. + + :type connection_id: string + :param connection_id: ID of the connection. + Example: dxcon-fg5678gh + + Default: None + + """ + params = {'connectionId': connection_id, } + return self.make_request(action='ConfirmConnection', + body=json.dumps(params)) + + def confirm_private_virtual_interface(self, virtual_interface_id, + virtual_gateway_id): + """ + Accept ownership of a private virtual interface created by + another customer. + + After the virtual interface owner calls this function, the + virtual interface will be created and attached to the given + virtual private gateway, and will be available for handling + traffic. + + :type virtual_interface_id: string + :param virtual_interface_id: ID of the virtual interface. + Example: dxvif-123dfg56 + + Default: None + + :type virtual_gateway_id: string + :param virtual_gateway_id: ID of the virtual private gateway that will + be attached to the virtual interface. + A virtual private gateway can be managed via the Amazon Virtual Private + Cloud (VPC) console or the `EC2 CreateVpnGateway`_ action. + + Default: None + + """ + params = { + 'virtualInterfaceId': virtual_interface_id, + 'virtualGatewayId': virtual_gateway_id, + } + return self.make_request(action='ConfirmPrivateVirtualInterface', + body=json.dumps(params)) + + def confirm_public_virtual_interface(self, virtual_interface_id): + """ + Accept ownership of a public virtual interface created by + another customer. + + After the virtual interface owner calls this function, the + specified virtual interface will be created and made available + for handling traffic. + + :type virtual_interface_id: string + :param virtual_interface_id: ID of the virtual interface. + Example: dxvif-123dfg56 + + Default: None + + """ + params = {'virtualInterfaceId': virtual_interface_id, } + return self.make_request(action='ConfirmPublicVirtualInterface', + body=json.dumps(params)) + + def create_connection(self, location, bandwidth, connection_name): + """ + Creates a new connection between the customer network and a + specific AWS Direct Connect location. + + A connection links your internal network to an AWS Direct + Connect location over a standard 1 gigabit or 10 gigabit + Ethernet fiber-optic cable. One end of the cable is connected + to your router, the other to an AWS Direct Connect router. An + AWS Direct Connect location provides access to Amazon Web + Services in the region it is associated with. You can + establish connections with AWS Direct Connect locations in + multiple regions, but a connection in one region does not + provide connectivity to other regions. + + :type location: string + :param location: Where the connection is located. + Example: EqSV5 + + Default: None + + :type bandwidth: string + :param bandwidth: Bandwidth of the connection. + Example: 1Gbps + + Default: None + + :type connection_name: string + :param connection_name: The name of the connection. + Example: " My Connection to AWS " + + Default: None + + """ + params = { + 'location': location, + 'bandwidth': bandwidth, + 'connectionName': connection_name, + } + return self.make_request(action='CreateConnection', + body=json.dumps(params)) + + def create_interconnect(self, interconnect_name, bandwidth, location): + """ + Creates a new interconnect between a AWS Direct Connect + partner's network and a specific AWS Direct Connect location. + + An interconnect is a connection which is capable of hosting + other connections. The AWS Direct Connect partner can use an + interconnect to provide sub-1Gbps AWS Direct Connect service + to tier 2 customers who do not have their own connections. + Like a standard connection, an interconnect links the AWS + Direct Connect partner's network to an AWS Direct Connect + location over a standard 1 Gbps or 10 Gbps Ethernet fiber- + optic cable. One end is connected to the partner's router, the + other to an AWS Direct Connect router. + + For each end customer, the AWS Direct Connect partner + provisions a connection on their interconnect by calling + AllocateConnectionOnInterconnect. The end customer can then + connect to AWS resources by creating a virtual interface on + their connection, using the VLAN assigned to them by the AWS + Direct Connect partner. + + :type interconnect_name: string + :param interconnect_name: The name of the interconnect. + Example: " 1G Interconnect to AWS " + + Default: None + + :type bandwidth: string + :param bandwidth: The port bandwidth + Example: 1Gbps + + Default: None + + Available values: 1Gbps,10Gbps + + :type location: string + :param location: Where the interconnect is located + Example: EqSV5 + + Default: None + + """ + params = { + 'interconnectName': interconnect_name, + 'bandwidth': bandwidth, + 'location': location, + } + return self.make_request(action='CreateInterconnect', + body=json.dumps(params)) + + def create_private_virtual_interface(self, connection_id, + new_private_virtual_interface): + """ + Creates a new private virtual interface. A virtual interface + is the VLAN that transports AWS Direct Connect traffic. A + private virtual interface supports sending traffic to a single + virtual private cloud (VPC). + + :type connection_id: string + :param connection_id: ID of the connection. + Example: dxcon-fg5678gh + + Default: None + + :type new_private_virtual_interface: dict + :param new_private_virtual_interface: Detailed information for the + private virtual interface to be created. + Default: None + + """ + params = { + 'connectionId': connection_id, + 'newPrivateVirtualInterface': new_private_virtual_interface, + } + return self.make_request(action='CreatePrivateVirtualInterface', + body=json.dumps(params)) + + def create_public_virtual_interface(self, connection_id, + new_public_virtual_interface): + """ + Creates a new public virtual interface. A virtual interface is + the VLAN that transports AWS Direct Connect traffic. A public + virtual interface supports sending traffic to public services + of AWS such as Amazon Simple Storage Service (Amazon S3). + + :type connection_id: string + :param connection_id: ID of the connection. + Example: dxcon-fg5678gh + + Default: None + + :type new_public_virtual_interface: dict + :param new_public_virtual_interface: Detailed information for the + public virtual interface to be created. + Default: None + + """ + params = { + 'connectionId': connection_id, + 'newPublicVirtualInterface': new_public_virtual_interface, + } + return self.make_request(action='CreatePublicVirtualInterface', + body=json.dumps(params)) + + def delete_connection(self, connection_id): + """ + Deletes the connection. + + Deleting a connection only stops the AWS Direct Connect port + hour and data transfer charges. You need to cancel separately + with the providers any services or charges for cross-connects + or network circuits that connect you to the AWS Direct Connect + location. + + :type connection_id: string + :param connection_id: ID of the connection. + Example: dxcon-fg5678gh + + Default: None + + """ + params = {'connectionId': connection_id, } + return self.make_request(action='DeleteConnection', + body=json.dumps(params)) + + def delete_interconnect(self, interconnect_id): + """ + Deletes the specified interconnect. + + :type interconnect_id: string + :param interconnect_id: The ID of the interconnect. + Example: dxcon-abc123 + + """ + params = {'interconnectId': interconnect_id, } + return self.make_request(action='DeleteInterconnect', + body=json.dumps(params)) + + def delete_virtual_interface(self, virtual_interface_id): + """ + Deletes a virtual interface. + + :type virtual_interface_id: string + :param virtual_interface_id: ID of the virtual interface. + Example: dxvif-123dfg56 + + Default: None + + """ + params = {'virtualInterfaceId': virtual_interface_id, } + return self.make_request(action='DeleteVirtualInterface', + body=json.dumps(params)) + + def describe_connections(self, connection_id=None): + """ + Displays all connections in this region. + + If a connection ID is provided, the call returns only that + particular connection. + + :type connection_id: string + :param connection_id: ID of the connection. + Example: dxcon-fg5678gh + + Default: None + + """ + params = {} + if connection_id is not None: + params['connectionId'] = connection_id + return self.make_request(action='DescribeConnections', + body=json.dumps(params)) + + def describe_connections_on_interconnect(self, interconnect_id): + """ + Return a list of connections that have been provisioned on the + given interconnect. + + :type interconnect_id: string + :param interconnect_id: ID of the interconnect on which a list of + connection is provisioned. + Example: dxcon-abc123 + + Default: None + + """ + params = {'interconnectId': interconnect_id, } + return self.make_request(action='DescribeConnectionsOnInterconnect', + body=json.dumps(params)) + + def describe_interconnects(self, interconnect_id=None): + """ + Returns a list of interconnects owned by the AWS account. + + If an interconnect ID is provided, it will only return this + particular interconnect. + + :type interconnect_id: string + :param interconnect_id: The ID of the interconnect. + Example: dxcon-abc123 + + """ + params = {} + if interconnect_id is not None: + params['interconnectId'] = interconnect_id + return self.make_request(action='DescribeInterconnects', + body=json.dumps(params)) + + def describe_locations(self): + """ + Returns the list of AWS Direct Connect locations in the + current AWS region. These are the locations that may be + selected when calling CreateConnection or CreateInterconnect. + """ + params = {} + return self.make_request(action='DescribeLocations', + body=json.dumps(params)) + + def describe_virtual_gateways(self): + """ + Returns a list of virtual private gateways owned by the AWS + account. + + You can create one or more AWS Direct Connect private virtual + interfaces linking to a virtual private gateway. A virtual + private gateway can be managed via Amazon Virtual Private + Cloud (VPC) console or the `EC2 CreateVpnGateway`_ action. + """ + params = {} + return self.make_request(action='DescribeVirtualGateways', + body=json.dumps(params)) + + def describe_virtual_interfaces(self, connection_id=None, + virtual_interface_id=None): + """ + Displays all virtual interfaces for an AWS account. Virtual + interfaces deleted fewer than 15 minutes before + DescribeVirtualInterfaces is called are also returned. If a + connection ID is included then only virtual interfaces + associated with this connection will be returned. If a virtual + interface ID is included then only a single virtual interface + will be returned. + + A virtual interface (VLAN) transmits the traffic between the + AWS Direct Connect location and the customer. + + If a connection ID is provided, only virtual interfaces + provisioned on the specified connection will be returned. If a + virtual interface ID is provided, only this particular virtual + interface will be returned. + + :type connection_id: string + :param connection_id: ID of the connection. + Example: dxcon-fg5678gh + + Default: None + + :type virtual_interface_id: string + :param virtual_interface_id: ID of the virtual interface. + Example: dxvif-123dfg56 + + Default: None + + """ + params = {} + if connection_id is not None: + params['connectionId'] = connection_id + if virtual_interface_id is not None: + params['virtualInterfaceId'] = virtual_interface_id + return self.make_request(action='DescribeVirtualInterfaces', + body=json.dumps(params)) + + def make_request(self, action, body): + headers = { + 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), + 'Host': self.region.endpoint, + 'Content-Type': 'application/x-amz-json-1.1', + 'Content-Length': str(len(body)), + } + http_request = self.build_base_http_request( + method='POST', path='/', auth_path='/', params={}, + headers=headers, data=body) + response = self._mexe(http_request, sender=None, + override_num_retries=10) + response_body = response.read() + boto.log.debug(response_body) + if response.status == 200: + if response_body: + return json.loads(response_body) + else: + json_body = json.loads(response_body) + fault_name = json_body.get('__type', None) + exception_class = self._faults.get(fault_name, self.ResponseError) + raise exception_class(response.status, response.reason, + body=json_body) + diff --git a/awx/lib/site-packages/boto/dynamodb/__init__.py b/awx/lib/site-packages/boto/dynamodb/__init__.py index 4619973291..a6bd27395e 100644 --- a/awx/lib/site-packages/boto/dynamodb/__init__.py +++ b/awx/lib/site-packages/boto/dynamodb/__init__.py @@ -59,6 +59,9 @@ def regions(): RegionInfo(name='sa-east-1', endpoint='dynamodb.sa-east-1.amazonaws.com', connection_cls=boto.dynamodb.layer2.Layer2), + RegionInfo(name='cn-north-1', + endpoint='dynamodb.cn-north-1.amazonaws.com.cn', + connection_cls=boto.dynamodb.layer2.Layer2), ] diff --git a/awx/lib/site-packages/boto/dynamodb/layer1.py b/awx/lib/site-packages/boto/dynamodb/layer1.py index 95c96a77f1..ca11ca43de 100644 --- a/awx/lib/site-packages/boto/dynamodb/layer1.py +++ b/awx/lib/site-packages/boto/dynamodb/layer1.py @@ -84,7 +84,7 @@ class Layer1(AWSAuthConnection): break self.region = region - AWSAuthConnection.__init__(self, self.region.endpoint, + super(Layer1, self).__init__(self.region.endpoint, aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, diff --git a/awx/lib/site-packages/boto/dynamodb2/__init__.py b/awx/lib/site-packages/boto/dynamodb2/__init__.py index 837f562000..23f4c5abfc 100644 --- a/awx/lib/site-packages/boto/dynamodb2/__init__.py +++ b/awx/lib/site-packages/boto/dynamodb2/__init__.py @@ -59,6 +59,9 @@ def regions(): RegionInfo(name='sa-east-1', endpoint='dynamodb.sa-east-1.amazonaws.com', connection_cls=DynamoDBConnection), + RegionInfo(name='cn-north-1', + endpoint='dynamodb.cn-north-1.amazonaws.com.cn', + connection_cls=DynamoDBConnection), ] diff --git a/awx/lib/site-packages/boto/dynamodb2/fields.py b/awx/lib/site-packages/boto/dynamodb2/fields.py index 25abffd49e..911a11b5b0 100644 --- a/awx/lib/site-packages/boto/dynamodb2/fields.py +++ b/awx/lib/site-packages/boto/dynamodb2/fields.py @@ -91,10 +91,10 @@ class RangeKey(BaseSchemaField): class BaseIndexField(object): """ - An abstract class for defining schema fields. + An abstract class for defining schema indexes. - Contains most of the core functionality for the field. Subclasses must - define an ``attr_type`` to pass to DynamoDB. + Contains most of the core functionality for the index. Subclasses must + define a ``projection_type`` to pass to DynamoDB. """ def __init__(self, name, parts): self.name = name @@ -139,7 +139,7 @@ class BaseIndexField(object): }, ], 'Projection': { - 'ProjectionType': 'KEYS_ONLY, + 'ProjectionType': 'KEYS_ONLY', } } @@ -210,3 +210,125 @@ class IncludeIndex(BaseIndexField): schema_data = super(IncludeIndex, self).schema() schema_data['Projection']['NonKeyAttributes'] = self.includes_fields return schema_data + + +class GlobalBaseIndexField(BaseIndexField): + """ + An abstract class for defining global indexes. + + Contains most of the core functionality for the index. Subclasses must + define a ``projection_type`` to pass to DynamoDB. + """ + throughput = { + 'read': 5, + 'write': 5, + } + + def __init__(self, *args, **kwargs): + throughput = kwargs.pop('throughput', None) + + if throughput is not None: + self.throughput = throughput + + super(GlobalBaseIndexField, self).__init__(*args, **kwargs) + + def schema(self): + """ + Returns the schema structure DynamoDB expects. + + Example:: + + >>> index.schema() + { + 'IndexName': 'LastNameIndex', + 'KeySchema': [ + { + 'AttributeName': 'username', + 'KeyType': 'HASH', + }, + ], + 'Projection': { + 'ProjectionType': 'KEYS_ONLY', + }, + 'ProvisionedThroughput': { + 'ReadCapacityUnits': 5, + 'WriteCapacityUnits': 5 + } + } + + """ + schema_data = super(GlobalBaseIndexField, self).schema() + schema_data['ProvisionedThroughput'] = { + 'ReadCapacityUnits': int(self.throughput['read']), + 'WriteCapacityUnits': int(self.throughput['write']), + } + return schema_data + + +class GlobalAllIndex(GlobalBaseIndexField): + """ + An index signifying all fields should be in the index. + + Example:: + + >>> GlobalAllIndex('MostRecentlyJoined', parts=[ + ... HashKey('username'), + ... RangeKey('date_joined') + ... ], + ... throughput={ + ... 'read': 2, + ... 'write': 1, + ... }) + + """ + projection_type = 'ALL' + + +class GlobalKeysOnlyIndex(GlobalBaseIndexField): + """ + An index signifying only key fields should be in the index. + + Example:: + + >>> GlobalKeysOnlyIndex('MostRecentlyJoined', parts=[ + ... HashKey('username'), + ... RangeKey('date_joined') + ... ], + ... throughput={ + ... 'read': 2, + ... 'write': 1, + ... }) + + """ + projection_type = 'KEYS_ONLY' + + +class GlobalIncludeIndex(GlobalBaseIndexField, IncludeIndex): + """ + An index signifying only certain fields should be in the index. + + Example:: + + >>> GlobalIncludeIndex('GenderIndex', parts=[ + ... HashKey('username'), + ... RangeKey('date_joined') + ... ], + ... includes=['gender'], + ... throughput={ + ... 'read': 2, + ... 'write': 1, + ... }) + + """ + projection_type = 'INCLUDE' + + def __init__(self, *args, **kwargs): + IncludeIndex.__init__(self, *args, **kwargs) + GlobalBaseIndexField.__init__(self, *args, **kwargs) + + def schema(self): + # Pick up the includes. + schema_data = IncludeIndex.schema(self) + # Also the throughput. + schema_data.update(GlobalBaseIndexField.schema(self)) + return schema_data \ No newline at end of file diff --git a/awx/lib/site-packages/boto/dynamodb2/items.py b/awx/lib/site-packages/boto/dynamodb2/items.py index 9f076afa13..257a745917 100644 --- a/awx/lib/site-packages/boto/dynamodb2/items.py +++ b/awx/lib/site-packages/boto/dynamodb2/items.py @@ -19,6 +19,9 @@ class Item(object): This object presents a dictionary-like interface for accessing/storing data. It also tries to intelligently track how data has changed throughout the life of the instance, to be as efficient as possible about updates. + + Empty items, or items that have no data, are considered falsey. + """ def __init__(self, table, data=None, loaded=False): """ @@ -105,6 +108,9 @@ class Item(object): def __contains__(self, key): return key in self._data + def __nonzero__(self): + return bool(self._data) + def _determine_alterations(self): """ Checks the ``-orig_data`` against the ``_data`` to determine what diff --git a/awx/lib/site-packages/boto/dynamodb2/layer1.py b/awx/lib/site-packages/boto/dynamodb2/layer1.py index 796a6a79b6..44dadecb2b 100644 --- a/awx/lib/site-packages/boto/dynamodb2/layer1.py +++ b/awx/lib/site-packages/boto/dynamodb2/layer1.py @@ -35,10 +35,9 @@ from boto.dynamodb2 import exceptions class DynamoDBConnection(AWSQueryConnection): """ - Amazon DynamoDB is a fast, highly scalable, highly available, - cost-effective non-relational database service. Amazon DynamoDB - removes traditional scalability limitations on data storage while - maintaining low latency and predictable performance. + Amazon DynamoDB **Overview** + This is the Amazon DynamoDB API Reference. This guide provides + descriptions and samples of the Amazon DynamoDB API. """ APIVersion = "2012-08-10" DefaultRegionName = "us-east-1" @@ -76,7 +75,7 @@ class DynamoDBConnection(AWSQueryConnection): if 'host' not in kwargs: kwargs['host'] = region.endpoint - AWSQueryConnection.__init__(self, **kwargs) + super(DynamoDBConnection, self).__init__(**kwargs) self.region = region self._validate_checksums = boto.config.getbool( 'DynamoDB', 'validate_checksums', validate_checksums) @@ -130,7 +129,7 @@ class DynamoDBConnection(AWSQueryConnection): result. Requests for nonexistent items consume the minimum read capacity units according to the type of read. For more information, see `Capacity Units Calculations`_ in the Amazon - DynamoDB Developer Guide . + DynamoDB Developer Guide. :type request_items: map :param request_items: @@ -150,7 +149,9 @@ class DynamoDBConnection(AWSQueryConnection): `False` (the default), an eventually consistent read is used. :type return_consumed_capacity: string - :param return_consumed_capacity: + :param return_consumed_capacity: If set to `TOTAL`, ConsumedCapacity is + included in the response; if set to `NONE` (the default), + ConsumedCapacity is not included. """ params = {'RequestItems': request_items, } @@ -256,7 +257,9 @@ class DynamoDBConnection(AWSQueryConnection): match those of the schema in the table's attribute definition. :type return_consumed_capacity: string - :param return_consumed_capacity: + :param return_consumed_capacity: If set to `TOTAL`, ConsumedCapacity is + included in the response; if set to `NONE` (the default), + ConsumedCapacity is not included. :type return_item_collection_metrics: string :param return_item_collection_metrics: If set to `SIZE`, statistics @@ -274,7 +277,8 @@ class DynamoDBConnection(AWSQueryConnection): body=json.dumps(params)) def create_table(self, attribute_definitions, table_name, key_schema, - provisioned_throughput, local_secondary_indexes=None): + provisioned_throughput, local_secondary_indexes=None, + global_secondary_indexes=None): """ The CreateTable operation adds a new table to your account. In an AWS account, table names must be unique within each region. @@ -306,7 +310,7 @@ class DynamoDBConnection(AWSQueryConnection): :param key_schema: Specifies the attributes that make up the primary key for the table. The attributes in KeySchema must also be defined in the AttributeDefinitions array. For more information, see `Data - Model`_ in the Amazon DynamoDB Developer Guide . + Model`_ in the Amazon DynamoDB Developer Guide. Each KeySchemaElement in the array is composed of: @@ -323,7 +327,7 @@ class DynamoDBConnection(AWSQueryConnection): KeyType of `RANGE`. For more information, see `Specifying the Primary Key`_ in the Amazon - DynamoDB Developer Guide . + DynamoDB Developer Guide. :type local_secondary_indexes: list :param local_secondary_indexes: @@ -360,8 +364,15 @@ class DynamoDBConnection(AWSQueryConnection): attribute into two different indexes, this counts as two distinct attributes when determining the total. + :type global_secondary_indexes: list + :param global_secondary_indexes: + :type provisioned_throughput: dict - :param provisioned_throughput: + :param provisioned_throughput: The provisioned throughput settings for + the specified table. The settings can be modified using the + UpdateTable operation. + For current minimum and maximum provisioned throughput values, see + `Limits`_ in the Amazon DynamoDB Developer Guide. """ params = { @@ -372,6 +383,8 @@ class DynamoDBConnection(AWSQueryConnection): } if local_secondary_indexes is not None: params['LocalSecondaryIndexes'] = local_secondary_indexes + if global_secondary_indexes is not None: + params['GlobalSecondaryIndexes'] = global_secondary_indexes return self.make_request(action='CreateTable', body=json.dumps(params)) @@ -459,7 +472,9 @@ class DynamoDBConnection(AWSQueryConnection): + `ALL_OLD` - The content of the old item is returned. :type return_consumed_capacity: string - :param return_consumed_capacity: + :param return_consumed_capacity: If set to `TOTAL`, ConsumedCapacity is + included in the response; if set to `NONE` (the default), + ConsumedCapacity is not included. :type return_item_collection_metrics: string :param return_item_collection_metrics: If set to `SIZE`, statistics @@ -496,15 +511,6 @@ class DynamoDBConnection(AWSQueryConnection): operations, such as GetItem and PutItem , on a table in the `DELETING` state until the table deletion is complete. - Tables are unique among those associated with the AWS Account - issuing the request, and the AWS region that receives the - request (such as dynamodb.us-east-1.amazonaws.com). Each - Amazon DynamoDB endpoint is entirely independent. For example, - if you have two tables called "MyTable," one in dynamodb.us- - east-1.amazonaws.com and one in dynamodb.us- - west-1.amazonaws.com, they are completely independent and do - not share any data; deleting one does not delete the other. - When you delete a table, any local secondary indexes on that table are also deleted. @@ -564,7 +570,9 @@ class DynamoDBConnection(AWSQueryConnection): are used. :type return_consumed_capacity: string - :param return_consumed_capacity: + :param return_consumed_capacity: If set to `TOTAL`, ConsumedCapacity is + included in the response; if set to `NONE` (the default), + ConsumedCapacity is not included. """ params = {'TableName': table_name, 'Key': key, } @@ -582,14 +590,6 @@ class DynamoDBConnection(AWSQueryConnection): Returns an array of all the tables associated with the current account and endpoint. - Each Amazon DynamoDB endpoint is entirely independent. For - example, if you have two tables called "MyTable," one in - dynamodb.us-east-1.amazonaws.com and one in dynamodb.us- - west-1.amazonaws.com , they are completely independent and do - not share any data. The ListTables operation returns all of - the table names associated with the account making the - request, for the endpoint that receives the request. - :type exclusive_start_table_name: string :param exclusive_start_table_name: The name of the table that starts the list. If you already ran a ListTables operation and received a @@ -639,7 +639,7 @@ class DynamoDBConnection(AWSQueryConnection): primary key attribute, or attributes. For more information about using this API, see `Working with - Items`_ in the Amazon DynamoDB Developer Guide . + Items`_ in the Amazon DynamoDB Developer Guide. :type table_name: string :param table_name: The name of the table to contain the item. @@ -653,7 +653,7 @@ class DynamoDBConnection(AWSQueryConnection): the table's attribute definition. For more information about primary keys, see `Primary Key`_ in the - Amazon DynamoDB Developer Guide . + Amazon DynamoDB Developer Guide. Each element in the Item map is an AttributeValue object. @@ -714,7 +714,9 @@ class DynamoDBConnection(AWSQueryConnection): the content of the old item is returned. :type return_consumed_capacity: string - :param return_consumed_capacity: + :param return_consumed_capacity: If set to `TOTAL`, ConsumedCapacity is + included in the response; if set to `NONE` (the default), + ConsumedCapacity is not included. :type return_item_collection_metrics: string :param return_item_collection_metrics: If set to `SIZE`, statistics @@ -834,7 +836,7 @@ class DynamoDBConnection(AWSQueryConnection): limit, it stops the operation and returns the matching values up to the limit, and a LastEvaluatedKey to apply in a subsequent operation to continue the operation. For more information see - `Query and Scan`_ in the Amazon DynamoDB Developer Guide . + `Query and Scan`_ in the Amazon DynamoDB Developer Guide. :type consistent_read: boolean :param consistent_read: If set to `True`, then the operation uses @@ -846,7 +848,7 @@ class DynamoDBConnection(AWSQueryConnection): The selection criteria for the query. For a query on a table, you can only have conditions on the table - primary key attributes. you must specify the hash key attribute + primary key attributes. You must specify the hash key attribute name and value as an `EQ` condition. You can optionally specify a second condition, referring to the range key attribute. @@ -878,7 +880,7 @@ class DynamoDBConnection(AWSQueryConnection): example, equals, greater than, less than, etc. Valid comparison operators for Query: `EQ | LE | LT | GE | GT | BEGINS_WITH | BETWEEN` For information on specifying data types in JSON, see - `JSON Data Format`_ in the Amazon DynamoDB Developer Guide . The + `JSON Data Format`_ in the Amazon DynamoDB Developer Guide. The following are descriptions of each comparison operator. + `EQ` : Equal. AttributeValueList can contain only one AttributeValue @@ -938,18 +940,16 @@ class DynamoDBConnection(AWSQueryConnection): ascending order. :type exclusive_start_key: map - :param exclusive_start_key: The primary key of the item from which to - continue an earlier operation. An earlier operation might provide - this value as the LastEvaluatedKey if that operation was - interrupted before completion; either because of the result set - size or because of the setting for Limit . The LastEvaluatedKey can - be passed back in a new request to continue the operation from that - point. + :param exclusive_start_key: The primary key of the first item that this + operation will evaluate. Use the value that was returned for + LastEvaluatedKey in the previous operation. The data type for ExclusiveStartKey must be String, Number or Binary. No set data types are allowed. :type return_consumed_capacity: string - :param return_consumed_capacity: + :param return_consumed_capacity: If set to `TOTAL`, ConsumedCapacity is + included in the response; if set to `NONE` (the default), + ConsumedCapacity is not included. """ params = {'TableName': table_name, } @@ -994,10 +994,10 @@ class DynamoDBConnection(AWSQueryConnection): The result set is eventually consistent. By default, Scan operations proceed sequentially; however, for - faster performance on large tables, applications can perform a + faster performance on large tables, applications can request a parallel Scan by specifying the Segment and TotalSegments parameters. For more information, see `Parallel Scan`_ in the - Amazon DynamoDB Developer Guide . + Amazon DynamoDB Developer Guide. :type table_name: string :param table_name: The name of the table containing the requested @@ -1020,7 +1020,7 @@ class DynamoDBConnection(AWSQueryConnection): limit, it stops the operation and returns the matching values up to the limit, and a LastEvaluatedKey to apply in a subsequent operation to continue the operation. For more information see - `Query and Scan`_ in the Amazon DynamoDB Developer Guide . + `Query and Scan`_ in the Amazon DynamoDB Developer Guide. :type select: string :param select: The attributes to be returned in the result. You can @@ -1084,7 +1084,7 @@ class DynamoDBConnection(AWSQueryConnection): operators for Scan: `EQ | NE | LE | LT | GE | GT | NOT_NULL | NULL | CONTAINS | NOT_CONTAINS | BEGINS_WITH | IN | BETWEEN` For information on specifying data types in JSON, see `JSON Data - Format`_ in the Amazon DynamoDB Developer Guide . The following are + Format`_ in the Amazon DynamoDB Developer Guide. The following are descriptions of each comparison operator. + `EQ` : Equal. AttributeValueList can contain only one AttributeValue @@ -1164,44 +1164,27 @@ class DynamoDBConnection(AWSQueryConnection): "2", "1"]}` :type exclusive_start_key: map - :param exclusive_start_key: The primary key of the item from which to - continue an earlier operation. An earlier operation might provide - this value as the LastEvaluatedKey if that operation was - interrupted before completion; either because of the result set - size or because of the setting for Limit . The LastEvaluatedKey can - be passed back in a new request to continue the operation from that - point. + :param exclusive_start_key: The primary key of the first item that this + operation will evaluate. Use the value that was returned for + LastEvaluatedKey in the previous operation. The data type for ExclusiveStartKey must be String, Number or Binary. No set data types are allowed. - If you are performing a parallel scan, the value of ExclusiveStartKey - must fall into the key space of the Segment being scanned. For - example, suppose that there are two application threads scanning a - table using the following Scan parameters - - - + Thread 0: Segment =0; TotalSegments =2 - + Thread 1: Segment =1; TotalSegments =2 - - - Now suppose that the Scan request for Thread 0 completed and returned a - LastEvaluatedKey of "X". Because "X" is part of Segment 0's key - space, it cannot be used anywhere else in the table. If Thread 1 - were to issue another Scan request with an ExclusiveStartKey of - "X", Amazon DynamoDB would throw an InputValidationError because - hash key "X" cannot be in Segment 1. + In a parallel scan, a Scan request that includes ExclusiveStartKey must + specify the same segment whose previous Scan returned the + corresponding value of LastEvaluatedKey . :type return_consumed_capacity: string - :param return_consumed_capacity: + :param return_consumed_capacity: If set to `TOTAL`, ConsumedCapacity is + included in the response; if set to `NONE` (the default), + ConsumedCapacity is not included. :type total_segments: integer - :param total_segments: For parallel Scan requests, TotalSegments - represents the total number of segments for a table that is being - scanned. Segments are a way to logically divide a table into - equally sized portions, for the duration of the Scan request. The - value of TotalSegments corresponds to the number of application - "workers" (such as threads or processes) that will perform the - parallel Scan . For example, if you want to scan a table using four + :param total_segments: For a parallel Scan request, TotalSegments + represents the total number of segments into which the Scan + operation will be divided. The value of TotalSegments corresponds + to the number of application workers that will perform the parallel + scan. For example, if you want to scan a table using four application threads, you would specify a TotalSegments value of 4. The value for TotalSegments must be greater than or equal to 1, and less than or equal to 4096. If you specify a TotalSegments value of @@ -1210,15 +1193,17 @@ class DynamoDBConnection(AWSQueryConnection): If you specify TotalSegments , you must also specify Segment . :type segment: integer - :param segment: For parallel Scan requests, Segment identifies an - individual segment to be scanned by an application "worker" (such - as a thread or a process). Each worker issues a Scan request with a - distinct value for the segment it will scan. + :param segment: For a parallel Scan request, Segment identifies an + individual segment to be scanned by an application worker. Segment IDs are zero-based, so the first segment is always 0. For example, if you want to scan a table using four application threads, the first thread would specify a Segment value of 0, the second thread would specify 1, and so on. + The value of LastEvaluatedKey returned from a parallel Scan request + must be used as ExclusiveStartKey with the same Segment ID in a + subsequent Scan operation. + The value for Segment must be greater than or equal to 0, and less than the value provided for TotalSegments . @@ -1411,7 +1396,9 @@ class DynamoDBConnection(AWSQueryConnection): returned. :type return_consumed_capacity: string - :param return_consumed_capacity: + :param return_consumed_capacity: If set to `TOTAL`, ConsumedCapacity is + included in the response; if set to `NONE` (the default), + ConsumedCapacity is not included. :type return_item_collection_metrics: string :param return_item_collection_metrics: If set to `SIZE`, statistics @@ -1434,7 +1421,8 @@ class DynamoDBConnection(AWSQueryConnection): return self.make_request(action='UpdateItem', body=json.dumps(params)) - def update_table(self, table_name, provisioned_throughput): + def update_table(self, table_name, provisioned_throughput=None, + global_secondary_index_updates=None): """ Updates the provisioned throughput for the given table. Setting the throughput for a table helps you manage @@ -1443,7 +1431,7 @@ class DynamoDBConnection(AWSQueryConnection): The provisioned throughput values can be upgraded or downgraded based on the maximums and minimums listed in the - `Limits`_ section in the Amazon DynamoDB Developer Guide . + `Limits`_ section in the Amazon DynamoDB Developer Guide. The table must be in the `ACTIVE` state for this operation to succeed. UpdateTable is an asynchronous operation; while @@ -1462,13 +1450,21 @@ class DynamoDBConnection(AWSQueryConnection): :param table_name: The name of the table to be updated. :type provisioned_throughput: dict - :param provisioned_throughput: + :param provisioned_throughput: The provisioned throughput settings for + the specified table. The settings can be modified using the + UpdateTable operation. + For current minimum and maximum provisioned throughput values, see + `Limits`_ in the Amazon DynamoDB Developer Guide. + + :type global_secondary_index_updates: list + :param global_secondary_index_updates: """ - params = { - 'TableName': table_name, - 'ProvisionedThroughput': provisioned_throughput, - } + params = {'TableName': table_name, } + if provisioned_throughput is not None: + params['ProvisionedThroughput'] = provisioned_throughput + if global_secondary_index_updates is not None: + params['GlobalSecondaryIndexUpdates'] = global_secondary_index_updates return self.make_request(action='UpdateTable', body=json.dumps(params)) diff --git a/awx/lib/site-packages/boto/dynamodb2/table.py b/awx/lib/site-packages/boto/dynamodb2/table.py index b8bc47302a..78cc121b32 100644 --- a/awx/lib/site-packages/boto/dynamodb2/table.py +++ b/awx/lib/site-packages/boto/dynamodb2/table.py @@ -1,7 +1,9 @@ import boto from boto.dynamodb2 import exceptions from boto.dynamodb2.fields import (HashKey, RangeKey, - AllIndex, KeysOnlyIndex, IncludeIndex) + AllIndex, KeysOnlyIndex, IncludeIndex, + GlobalAllIndex, GlobalKeysOnlyIndex, + GlobalIncludeIndex) from boto.dynamodb2.items import Item from boto.dynamodb2.layer1 import DynamoDBConnection from boto.dynamodb2.results import ResultSet, BatchGetResultSet @@ -21,7 +23,7 @@ class Table(object): max_batch_get = 100 def __init__(self, table_name, schema=None, throughput=None, indexes=None, - connection=None): + global_indexes=None, connection=None): """ Sets up a new in-memory ``Table``. @@ -48,6 +50,10 @@ class Table(object): Optionally accepts a ``indexes`` parameter, which should be a list of ``BaseIndexField`` subclasses representing the desired indexes. + Optionally accepts a ``global_indexes`` parameter, which should be a + list of ``GlobalBaseIndexField`` subclasses representing the desired + indexes. + Optionally accepts a ``connection`` parameter, which should be a ``DynamoDBConnection`` instance (or subclass). This is primarily useful for specifying alternate connection parameters. @@ -67,13 +73,22 @@ class Table(object): ... 'write': 10, ... }, indexes=[ ... KeysOnlyIndex('MostRecentlyJoined', parts=[ + ... HashKey('username') ... RangeKey('date_joined') ... ]), - ... ], - ... connection=dynamodb2.connect_to_region('us-west-2', - ... aws_access_key_id='key', - ... aws_secret_access_key='key', - ... )) + ... ], global_indexes=[ + ... GlobalAllIndex('UsersByZipcode', parts=[ + ... HashKey('zipcode'), + ... RangeKey('username'), + ... ], + ... throughput={ + ... 'read':10, + ... 'write":10, + ... }), + ... ], connection=dynamodb2.connect_to_region('us-west-2', + ... aws_access_key_id='key', + ... aws_secret_access_key='key', + ... )) """ self.table_name = table_name @@ -84,6 +99,7 @@ class Table(object): } self.schema = schema self.indexes = indexes + self.global_indexes = global_indexes if self.connection is None: self.connection = DynamoDBConnection() @@ -95,7 +111,7 @@ class Table(object): @classmethod def create(cls, table_name, schema, throughput=None, indexes=None, - connection=None): + global_indexes=None, connection=None): """ Creates a new table in DynamoDB & returns an in-memory ``Table`` object. @@ -127,6 +143,10 @@ class Table(object): Optionally accepts a ``indexes`` parameter, which should be a list of ``BaseIndexField`` subclasses representing the desired indexes. + Optionally accepts a ``global_indexes`` parameter, which should be a + list of ``GlobalBaseIndexField`` subclasses representing the desired + indexes. + Optionally accepts a ``connection`` parameter, which should be a ``DynamoDBConnection`` instance (or subclass). This is primarily useful for specifying alternate connection parameters. @@ -142,7 +162,15 @@ class Table(object): ... }, indexes=[ ... KeysOnlyIndex('MostRecentlyJoined', parts=[ ... RangeKey('date_joined') - ... ]), + ... ]), global_indexes=[ + ... GlobalAllIndex('UsersByZipcode', parts=[ + ... HashKey('zipcode'), + ... RangeKey('username'), + ... ], + ... throughput={ + ... 'read':10, + ... 'write":10, + ... }), ... ]) """ @@ -155,13 +183,18 @@ class Table(object): if indexes is not None: table.indexes = indexes + if global_indexes is not None: + table.global_indexes = global_indexes + # Prep the schema. raw_schema = [] attr_defs = [] + seen_attrs = set() for field in table.schema: raw_schema.append(field.schema()) # Build the attributes off what we know. + seen_attrs.add(field.name) attr_defs.append(field.definition()) raw_throughput = { @@ -170,23 +203,24 @@ class Table(object): } kwargs = {} - if table.indexes: - # Prep the LSIs. - raw_lsi = [] + kwarg_map = { + 'indexes': 'local_secondary_indexes', + 'global_indexes': 'global_secondary_indexes', + } + for index_attr in ('indexes', 'global_indexes'): + table_indexes = getattr(table, index_attr) + if table_indexes: + raw_indexes = [] + for index_field in table_indexes: + raw_indexes.append(index_field.schema()) + # Make sure all attributes specified in the indexes are + # added to the definition + for field in index_field.parts: + if field.name not in seen_attrs: + seen_attrs.add(field.name) + attr_defs.append(field.definition()) - for index_field in table.indexes: - raw_lsi.append(index_field.schema()) - # Again, build the attributes off what we know. - # HOWEVER, only add attributes *NOT* already seen. - attr_define = index_field.definition() - - for part in attr_define: - attr_names = [attr['AttributeName'] for attr in attr_defs] - - if not part['AttributeName'] in attr_names: - attr_defs.append(part) - - kwargs['local_secondary_indexes'] = raw_lsi + kwargs[kwarg_map[index_attr]] = raw_indexes table.connection.create_table( table_name=table.table_name, @@ -294,7 +328,7 @@ class Table(object): # This is leaky. return result - def update(self, throughput): + def update(self, throughput, global_indexes=None): """ Updates table attributes in DynamoDB. @@ -316,12 +350,46 @@ class Table(object): ... }) True + # To also update the global index(es) throughput. + >>> users.update(throughput={ + ... 'read': 20, + ... 'write': 10, + ... }, + ... global_secondary_indexes={ + ... 'TheIndexNameHere': { + ... 'read': 15, + ... 'write': 5, + ... } + ... }) + True + """ self.throughput = throughput - self.connection.update_table(self.table_name, { + data = { 'ReadCapacityUnits': int(self.throughput['read']), 'WriteCapacityUnits': int(self.throughput['write']), - }) + } + gsi_data = None + + if global_indexes: + gsi_data = [] + + for gsi_name, gsi_throughput in global_indexes.items(): + gsi_data.append({ + "Update": { + "IndexName": gsi_name, + "ProvisionedThroughput": { + "ReadCapacityUnits": int(gsi_throughput['read']), + "WriteCapacityUnits": int(gsi_throughput['write']), + }, + }, + }) + + self.connection.update_table( + self.table_name, + provisioned_throughput=data, + global_secondary_index_updates=gsi_data + ) return True def delete(self): @@ -424,7 +492,7 @@ class Table(object): with boto.dynamodb. Unlike get_item, it takes hash_key and range_key first, although you may still specify keyword arguments instead. - Also unlike the get_item command, if the returned item has no keys + Also unlike the get_item command, if the returned item has no keys (i.e., it does not exist in DynamoDB), a None result is returned, instead of an empty key object. @@ -668,6 +736,10 @@ class Table(object): lookup['AttributeValueList'].append( self._dynamizer.encode(value[1]) ) + # Special-case the ``IN`` case + elif field_bits[-1] == 'in': + for val in value: + lookup['AttributeValueList'].append(self._dynamizer.encode(val)) else: # Fix up the value for encoding, because it was built to only work # with ``set``s. diff --git a/awx/lib/site-packages/boto/ec2/__init__.py b/awx/lib/site-packages/boto/ec2/__init__.py index 4220c92ed9..d0e18bf5be 100644 --- a/awx/lib/site-packages/boto/ec2/__init__.py +++ b/awx/lib/site-packages/boto/ec2/__init__.py @@ -37,6 +37,7 @@ RegionData = { 'ap-northeast-1': 'ec2.ap-northeast-1.amazonaws.com', 'ap-southeast-1': 'ec2.ap-southeast-1.amazonaws.com', 'ap-southeast-2': 'ec2.ap-southeast-2.amazonaws.com', + 'cn-north-1': 'ec2.cn-north-1.amazonaws.com.cn', } diff --git a/awx/lib/site-packages/boto/ec2/address.py b/awx/lib/site-packages/boto/ec2/address.py index 27608a4ab6..3b82d11588 100644 --- a/awx/lib/site-packages/boto/ec2/address.py +++ b/awx/lib/site-packages/boto/ec2/address.py @@ -37,7 +37,7 @@ class Address(EC2Object): """ def __init__(self, connection=None, public_ip=None, instance_id=None): - EC2Object.__init__(self, connection) + super(Address, self).__init__(connection) self.connection = connection self.public_ip = public_ip self.instance_id = instance_id diff --git a/awx/lib/site-packages/boto/ec2/autoscale/__init__.py b/awx/lib/site-packages/boto/ec2/autoscale/__init__.py index 2a54adf15d..6e2c1036bd 100644 --- a/awx/lib/site-packages/boto/ec2/autoscale/__init__.py +++ b/awx/lib/site-packages/boto/ec2/autoscale/__init__.py @@ -55,6 +55,7 @@ RegionData = { 'ap-northeast-1': 'autoscaling.ap-northeast-1.amazonaws.com', 'ap-southeast-1': 'autoscaling.ap-southeast-1.amazonaws.com', 'ap-southeast-2': 'autoscaling.ap-southeast-2.amazonaws.com', + 'cn-north-1': 'autoscaling.cn-north-1.amazonaws.com.cn', } @@ -114,7 +115,7 @@ class AutoScaleConnection(AWSQueryConnection): self.DefaultRegionEndpoint, AutoScaleConnection) self.region = region - AWSQueryConnection.__init__(self, aws_access_key_id, + super(AutoScaleConnection, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, @@ -163,7 +164,7 @@ class AutoScaleConnection(AWSQueryConnection): # get availability zone information (required param) zones = as_group.availability_zones self.build_list_params(params, zones, 'AvailabilityZones') - if as_group.desired_capacity: + if as_group.desired_capacity is not None: params['DesiredCapacity'] = as_group.desired_capacity if as_group.vpc_zone_identifier: params['VPCZoneIdentifier'] = as_group.vpc_zone_identifier @@ -785,7 +786,7 @@ class AutoScaleConnection(AWSQueryConnection): params = {'AutoScalingGroupName': group_name, 'DesiredCapacity': desired_capacity} if honor_cooldown: - params['HonorCooldown'] = json.dumps('True') + params['HonorCooldown'] = 'true' return self.get_status('SetDesiredCapacity', params) diff --git a/awx/lib/site-packages/boto/ec2/autoscale/group.py b/awx/lib/site-packages/boto/ec2/autoscale/group.py index 12fdb20d25..d3646877f4 100644 --- a/awx/lib/site-packages/boto/ec2/autoscale/group.py +++ b/awx/lib/site-packages/boto/ec2/autoscale/group.py @@ -129,8 +129,8 @@ class AutoScalingGroup(object): :param health_check_type: The service you want the health status from, Amazon EC2 or Elastic Load Balancer. - :type launch_config_name: str or LaunchConfiguration - :param launch_config_name: Name of launch configuration (required). + :type launch_config: str or LaunchConfiguration + :param launch_config: Name of launch configuration (required). :type load_balancers: list :param load_balancers: List of load balancers. diff --git a/awx/lib/site-packages/boto/ec2/bundleinstance.py b/awx/lib/site-packages/boto/ec2/bundleinstance.py index 96519921e4..1bb4dd1692 100644 --- a/awx/lib/site-packages/boto/ec2/bundleinstance.py +++ b/awx/lib/site-packages/boto/ec2/bundleinstance.py @@ -14,21 +14,21 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. """ -Represents an EC2 Bundle Task +Represents an EC2 Bundle Task """ from boto.ec2.ec2object import EC2Object class BundleInstanceTask(EC2Object): - + def __init__(self, connection=None): - EC2Object.__init__(self, connection) + super(BundleInstanceTask, self).__init__(connection) self.id = None self.instance_id = None self.progress = None @@ -38,7 +38,7 @@ class BundleInstanceTask(EC2Object): self.prefix = None self.upload_policy = None self.upload_policy_signature = None - self.update_time = None + self.update_time = None self.code = None self.message = None diff --git a/awx/lib/site-packages/boto/ec2/cloudwatch/__init__.py b/awx/lib/site-packages/boto/ec2/cloudwatch/__init__.py index 82c529e4a0..6bfcdbf36c 100644 --- a/awx/lib/site-packages/boto/ec2/cloudwatch/__init__.py +++ b/awx/lib/site-packages/boto/ec2/cloudwatch/__init__.py @@ -41,6 +41,7 @@ RegionData = { 'ap-northeast-1': 'monitoring.ap-northeast-1.amazonaws.com', 'ap-southeast-1': 'monitoring.ap-southeast-1.amazonaws.com', 'ap-southeast-2': 'monitoring.ap-southeast-2.amazonaws.com', + 'cn-north-1': 'monitoring.cn-north-1.amazonaws.com.cn', } @@ -107,7 +108,7 @@ class CloudWatchConnection(AWSQueryConnection): if self.region.name == 'eu-west-1': validate_certs = False - AWSQueryConnection.__init__(self, aws_access_key_id, + super(CloudWatchConnection, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, @@ -117,7 +118,7 @@ class CloudWatchConnection(AWSQueryConnection): validate_certs=validate_certs) def _required_auth_capability(self): - return ['ec2'] + return ['hmac-v4'] def build_dimension_param(self, dimension, params): prefix = 'Dimensions.member' diff --git a/awx/lib/site-packages/boto/ec2/cloudwatch/metric.py b/awx/lib/site-packages/boto/ec2/cloudwatch/metric.py index 9c19b94194..f92f282a65 100644 --- a/awx/lib/site-packages/boto/ec2/cloudwatch/metric.py +++ b/awx/lib/site-packages/boto/ec2/cloudwatch/metric.py @@ -77,13 +77,6 @@ class Metric(object): :param statistics: A list of statistics names Valid values: Average | Sum | SampleCount | Maximum | Minimum - :type dimensions: dict - :param dimensions: A dictionary of dimension key/values where - the key is the dimension name and the value - is either a scalar value or an iterator - of values to be associated with that - dimension. - :type unit: string :param unit: The unit for the metric. Value values are: Seconds | Microseconds | Milliseconds | Bytes | Kilobytes | diff --git a/awx/lib/site-packages/boto/ec2/connection.py b/awx/lib/site-packages/boto/ec2/connection.py index 803f3fed8e..045a145138 100644 --- a/awx/lib/site-packages/boto/ec2/connection.py +++ b/awx/lib/site-packages/boto/ec2/connection.py @@ -31,6 +31,7 @@ from datetime import datetime from datetime import timedelta import boto +from boto.auth import detect_potential_sigv4 from boto.connection import AWSQueryConnection from boto.resultset import ResultSet from boto.ec2.image import Image, ImageAttribute, CopyImage @@ -62,6 +63,7 @@ from boto.ec2.instancestatus import InstanceStatusSet from boto.ec2.volumestatus import VolumeStatusSet from boto.ec2.networkinterface import NetworkInterface from boto.ec2.attributes import AccountAttribute, VPCAttribute +from boto.ec2.blockdevicemapping import BlockDeviceMapping, BlockDeviceType from boto.exception import EC2ResponseError #boto.set_stream_logger('ec2') @@ -69,7 +71,7 @@ from boto.exception import EC2ResponseError class EC2Connection(AWSQueryConnection): - APIVersion = boto.config.get('Boto', 'ec2_version', '2013-10-01') + APIVersion = boto.config.get('Boto', 'ec2_version', '2013-10-15') DefaultRegionName = boto.config.get('Boto', 'ec2_region_name', 'us-east-1') DefaultRegionEndpoint = boto.config.get('Boto', 'ec2_region_endpoint', 'ec2.us-east-1.amazonaws.com') @@ -89,7 +91,7 @@ class EC2Connection(AWSQueryConnection): region = RegionInfo(self, self.DefaultRegionName, self.DefaultRegionEndpoint) self.region = region - AWSQueryConnection.__init__(self, aws_access_key_id, + super(EC2Connection, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, @@ -100,6 +102,7 @@ class EC2Connection(AWSQueryConnection): if api_version: self.APIVersion = api_version + @detect_potential_sigv4 def _required_auth_capability(self): return ['ec2'] @@ -260,7 +263,9 @@ class EC2Connection(AWSQueryConnection): def register_image(self, name=None, description=None, image_location=None, architecture=None, kernel_id=None, ramdisk_id=None, root_device_name=None, block_device_map=None, - dry_run=False, virtualization_type=None): + dry_run=False, virtualization_type=None, + sriov_net_support=None, + snapshot_id=None): """ Register an image. @@ -299,6 +304,16 @@ class EC2Connection(AWSQueryConnection): * paravirtual * hvm + :type sriov_net_support: string + :param sriov_net_support: Advanced networking support. + Valid choices are: + * simple + + :type snapshot_id: string + :param snapshot_id: A snapshot ID for the snapshot to be used + as root device for the image. Mutually exclusive with + block_device_map, requires root_device_name + :rtype: string :return: The new image id """ @@ -317,12 +332,19 @@ class EC2Connection(AWSQueryConnection): params['ImageLocation'] = image_location if root_device_name: params['RootDeviceName'] = root_device_name + if snapshot_id: + root_vol = BlockDeviceType(snapshot_id=snapshot_id) + block_device_map = BlockDeviceMapping() + block_device_map[root_device_name] = root_vol if block_device_map: block_device_map.ec2_build_list_params(params) if dry_run: params['DryRun'] = 'true' if virtualization_type: params['VirtualizationType'] = virtualization_type + if sriov_net_support: + params['SriovNetSupport'] = sriov_net_support + rs = self.get_object('RegisterImage', params, ResultSet, verb='POST') image_id = getattr(rs, 'imageId', None) @@ -510,7 +532,8 @@ class EC2Connection(AWSQueryConnection): # Instance methods - def get_all_instances(self, instance_ids=None, filters=None, dry_run=False): + def get_all_instances(self, instance_ids=None, filters=None, dry_run=False, + max_results=None): """ Retrieve all the instance reservations associated with your account. @@ -535,6 +558,10 @@ class EC2Connection(AWSQueryConnection): :type dry_run: bool :param dry_run: Set to True if the operation should not actually run. + :type max_results: int + :param max_results: The maximum number of paginated instance + items per response. + :rtype: list :return: A list of :class:`boto.ec2.instance.Reservation` @@ -543,10 +570,11 @@ class EC2Connection(AWSQueryConnection): 'replaced with get_all_reservations.'), PendingDeprecationWarning) return self.get_all_reservations(instance_ids=instance_ids, - filters=filters, dry_run=dry_run) + filters=filters, dry_run=dry_run, + max_results=max_results) def get_only_instances(self, instance_ids=None, filters=None, - dry_run=False): + dry_run=False, max_results=None): # A future release should rename this method to get_all_instances # and make get_only_instances an alias for that. """ @@ -566,17 +594,22 @@ class EC2Connection(AWSQueryConnection): :type dry_run: bool :param dry_run: Set to True if the operation should not actually run. + :type max_results: int + :param max_results: The maximum number of paginated instance + items per response. + :rtype: list :return: A list of :class:`boto.ec2.instance.Instance` """ reservations = self.get_all_reservations(instance_ids=instance_ids, filters=filters, - dry_run=dry_run) + dry_run=dry_run, + max_results=max_results) return [instance for reservation in reservations for instance in reservation.instances] def get_all_reservations(self, instance_ids=None, filters=None, - dry_run=False): + dry_run=False, max_results=None): """ Retrieve all the instance reservations associated with your account. @@ -594,6 +627,10 @@ class EC2Connection(AWSQueryConnection): :type dry_run: bool :param dry_run: Set to True if the operation should not actually run. + :type max_results: int + :param max_results: The maximum number of paginated instance + items per response. + :rtype: list :return: A list of :class:`boto.ec2.instance.Reservation` """ @@ -612,6 +649,8 @@ class EC2Connection(AWSQueryConnection): self.build_filter_params(params, filters) if dry_run: params['DryRun'] = 'true' + if max_results is not None: + params['MaxResults'] = max_results return self.get_list('DescribeInstances', params, [('item', Reservation)], verb='POST') @@ -723,6 +762,16 @@ class EC2Connection(AWSQueryConnection): * cc1.4xlarge * cg1.4xlarge * cc2.8xlarge + * g2.2xlarge + * c3.large + * c3.xlarge + * c3.2xlarge + * c3.4xlarge + * c3.8xlarge + * i2.xlarge + * i2.2xlarge + * i2.4xlarge + * i2.8xlarge :type placement: string :param placement: The Availability Zone to launch the instance into. @@ -1028,6 +1077,7 @@ class EC2Connection(AWSQueryConnection): * sourceDestCheck * groupSet * ebsOptimized + * sriovNetSupport :type dry_run: bool :param dry_run: Set to True if the operation should not actually run. @@ -1137,6 +1187,7 @@ class EC2Connection(AWSQueryConnection): * sourceDestCheck - Boolean (true) * groupSet - Set of Security Groups or IDs * ebsOptimized - Boolean (false) + * sriovNetSupport - String - ie: 'simple' :type value: string :param value: The new value for the attribute @@ -1249,7 +1300,8 @@ class EC2Connection(AWSQueryConnection): def get_spot_price_history(self, start_time=None, end_time=None, instance_type=None, product_description=None, - availability_zone=None, dry_run=False): + availability_zone=None, dry_run=False, + max_results=None): """ Retrieve the recent history of spot instances pricing. @@ -1283,6 +1335,10 @@ class EC2Connection(AWSQueryConnection): :type dry_run: bool :param dry_run: Set to True if the operation should not actually run. + :type max_results: int + :param max_results: The maximum number of paginated items + per response. + :rtype: list :return: A list tuples containing price and timestamp. """ @@ -1299,6 +1355,8 @@ class EC2Connection(AWSQueryConnection): params['AvailabilityZone'] = availability_zone if dry_run: params['DryRun'] = 'true' + if max_results is not None: + params['MaxResults'] = max_results return self.get_list('DescribeSpotPriceHistory', params, [('item', SpotPriceHistory)], verb='POST') @@ -1361,16 +1419,34 @@ class EC2Connection(AWSQueryConnection): :type instance_type: string :param instance_type: The type of instance to run: + * t1.micro * m1.small + * m1.medium * m1.large * m1.xlarge + * m3.xlarge + * m3.2xlarge * c1.medium * c1.xlarge * m2.xlarge * m2.2xlarge * m2.4xlarge + * cr1.8xlarge + * hi1.4xlarge + * hs1.8xlarge * cc1.4xlarge - * t1.micro + * cg1.4xlarge + * cc2.8xlarge + * g2.2xlarge + * c3.large + * c3.xlarge + * c3.2xlarge + * c3.4xlarge + * c3.8xlarge + * i2.xlarge + * i2.2xlarge + * i2.4xlarge + * i2.8xlarge :type placement: string :param placement: The availability zone in which to launch @@ -2672,7 +2748,7 @@ class EC2Connection(AWSQueryConnection): def import_key_pair(self, key_name, public_key_material, dry_run=False): """ - mports the public key from an RSA key pair that you created + imports the public key from an RSA key pair that you created with a third-party tool. Supported formats: @@ -3931,7 +4007,7 @@ class EC2Connection(AWSQueryConnection): params['Tag.%d.Value'%i] = value i += 1 - def get_all_tags(self, filters=None, dry_run=False): + def get_all_tags(self, filters=None, dry_run=False, max_results=None): """ Retrieve all the metadata tags associated with your account. @@ -3948,6 +4024,10 @@ class EC2Connection(AWSQueryConnection): :type dry_run: bool :param dry_run: Set to True if the operation should not actually run. + :type max_results: int + :param max_results: The maximum number of paginated instance + items per response. + :rtype: list :return: A list of :class:`boto.ec2.tag.Tag` objects """ @@ -3956,6 +4036,8 @@ class EC2Connection(AWSQueryConnection): self.build_filter_params(params, filters) if dry_run: params['DryRun'] = 'true' + if max_results is not None: + params['MaxResults'] = max_results return self.get_list('DescribeTags', params, [('item', Tag)], verb='POST') diff --git a/awx/lib/site-packages/boto/ec2/ec2object.py b/awx/lib/site-packages/boto/ec2/ec2object.py index 265678c627..f697e66483 100644 --- a/awx/lib/site-packages/boto/ec2/ec2object.py +++ b/awx/lib/site-packages/boto/ec2/ec2object.py @@ -53,7 +53,7 @@ class TaggedEC2Object(EC2Object): """ def __init__(self, connection=None): - EC2Object.__init__(self, connection) + super(TaggedEC2Object, self).__init__(connection) self.tags = TagSet() def startElement(self, name, attrs, connection): diff --git a/awx/lib/site-packages/boto/ec2/elb/__init__.py b/awx/lib/site-packages/boto/ec2/elb/__init__.py index e5ae588655..1ad60f0a7f 100644 --- a/awx/lib/site-packages/boto/ec2/elb/__init__.py +++ b/awx/lib/site-packages/boto/ec2/elb/__init__.py @@ -44,6 +44,7 @@ RegionData = { 'ap-northeast-1': 'elasticloadbalancing.ap-northeast-1.amazonaws.com', 'ap-southeast-1': 'elasticloadbalancing.ap-southeast-1.amazonaws.com', 'ap-southeast-2': 'elasticloadbalancing.ap-southeast-2.amazonaws.com', + 'cn-north-1': 'elasticloadbalancing.cn-north-1.amazonaws.com.cn', } @@ -102,7 +103,7 @@ class ELBConnection(AWSQueryConnection): region = RegionInfo(self, self.DefaultRegionName, self.DefaultRegionEndpoint) self.region = region - AWSQueryConnection.__init__(self, aws_access_key_id, + super(ELBConnection, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, @@ -159,7 +160,7 @@ class ELBConnection(AWSQueryConnection): [SSLCertificateId]) where LoadBalancerPortNumber and InstancePortNumber are integer values between 1 and 65535, Protocol is a string containing either 'TCP', 'SSL', HTTP', or - 'HTTPS'; SSLCertificateID is the ARN of a AWS AIM + 'HTTPS'; SSLCertificateID is the ARN of a AWS IAM certificate, and must be specified when doing HTTPS. :type subnets: list of strings @@ -264,7 +265,7 @@ class ELBConnection(AWSQueryConnection): [SSLCertificateId]) where LoadBalancerPortNumber and InstancePortNumber are integer values between 1 and 65535, Protocol is a string containing either 'TCP', 'SSL', HTTP', or - 'HTTPS'; SSLCertificateID is the ARN of a AWS AIM + 'HTTPS'; SSLCertificateID is the ARN of a AWS IAM certificate, and must be specified when doing HTTPS. :type complex_listeners: List of tuples @@ -390,6 +391,76 @@ class ELBConnection(AWSQueryConnection): params, LoadBalancerZones) return obj.zones + def modify_lb_attribute(self, load_balancer_name, attribute, value): + """Changes an attribute of a Load Balancer + + :type load_balancer_name: string + :param load_balancer_name: The name of the Load Balancer + + :type attribute: string + :param attribute: The attribute you wish to change. + + * crossZoneLoadBalancing - Boolean (true) + + :type value: string + :param value: The new value for the attribute + + :rtype: bool + :return: Whether the operation succeeded or not + """ + + bool_reqs = ('crosszoneloadbalancing',) + if attribute.lower() in bool_reqs: + if isinstance(value, bool): + if value: + value = 'true' + else: + value = 'false' + + params = {'LoadBalancerName': load_balancer_name} + if attribute.lower() == 'crosszoneloadbalancing': + params['LoadBalancerAttributes.CrossZoneLoadBalancing.Enabled' + ] = value + else: + raise ValueError('InvalidAttribute', attribute) + return self.get_status('ModifyLoadBalancerAttributes', params, + verb='GET') + + def get_all_lb_attributes(self, load_balancer_name): + """Gets all Attributes of a Load Balancer + + :type load_balancer_name: string + :param load_balancer_name: The name of the Load Balancer + + :rtype: boto.ec2.elb.attribute.LbAttributes + :return: The attribute object of the ELB. + """ + from boto.ec2.elb.attributes import LbAttributes + params = {'LoadBalancerName': load_balancer_name} + return self.get_object('DescribeLoadBalancerAttributes', + params, LbAttributes) + + def get_lb_attribute(self, load_balancer_name, attribute): + """Gets an attribute of a Load Balancer + + This will make an EC2 call for each method call. + + :type load_balancer_name: string + :param load_balancer_name: The name of the Load Balancer + + :type attribute: string + :param attribute: The attribute you wish to see. + + * crossZoneLoadBalancing - Boolean + + :rtype: Attribute dependent + :return: The new value for the attribute + """ + attributes = self.get_all_lb_attributes(load_balancer_name) + if attribute.lower() == 'crosszoneloadbalancing': + return attributes.cross_zone_load_balancing.enabled + return None + def register_instances(self, load_balancer_name, instances): """ Add new Instances to an existing Load Balancer. diff --git a/awx/lib/site-packages/boto/ec2/elb/attributes.py b/awx/lib/site-packages/boto/ec2/elb/attributes.py new file mode 100644 index 0000000000..0d70a642f6 --- /dev/null +++ b/awx/lib/site-packages/boto/ec2/elb/attributes.py @@ -0,0 +1,61 @@ +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, dis- +# tribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the fol- +# lowing conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# Created by Chris Huegle for TellApart, Inc. + +class CrossZoneLoadBalancingAttribute(object): + """ + Represents the CrossZoneLoadBalancing segement of ELB Attributes. + """ + def __init__(self, connection=None): + self.enabled = None + + def __repr__(self): + return 'CrossZoneLoadBalancingAttribute(%s)' % ( + self.enabled) + + def startElement(self, name, attrs, connection): + pass + + def endElement(self, name, value, connection): + if name == 'Enabled': + if value.lower() == 'true': + self.enabled = True + else: + self.enabled = False + +class LbAttributes(object): + """ + Represents the Attributes of an Elastic Load Balancer. + """ + def __init__(self, connection=None): + self.connection = connection + self.cross_zone_load_balancing = CrossZoneLoadBalancingAttribute( + self.connection) + + def __repr__(self): + return 'LbAttributes(%s)' % ( + repr(self.cross_zone_load_balancing)) + + def startElement(self, name, attrs, connection): + if name == 'CrossZoneLoadBalancing': + return self.cross_zone_load_balancing + + def endElement(self, name, value, connection): + pass diff --git a/awx/lib/site-packages/boto/ec2/elb/loadbalancer.py b/awx/lib/site-packages/boto/ec2/elb/loadbalancer.py index fde9ac1f5d..f6ed3dec42 100644 --- a/awx/lib/site-packages/boto/ec2/elb/loadbalancer.py +++ b/awx/lib/site-packages/boto/ec2/elb/loadbalancer.py @@ -122,6 +122,7 @@ class LoadBalancer(object): self.vpc_id = None self.scheme = None self.backends = None + self._attributes = None def __repr__(self): return 'LoadBalancer:%s' % self.name @@ -203,6 +204,58 @@ class LoadBalancer(object): new_zones = self.connection.disable_availability_zones(self.name, zones) self.availability_zones = new_zones + def get_attributes(self, force=False): + """ + Gets the LbAttributes. The Attributes will be cached. + + :type force: bool + :param force: Ignore cache value and reload. + + :rtype: boto.ec2.elb.attributes.LbAttributes + :return: The LbAttribues object + """ + if not self._attributes or force: + self._attributes = self.connection.get_all_lb_attributes(self.name) + return self._attributes + + def is_cross_zone_load_balancing(self, force=False): + """ + Identifies if the ELB is current configured to do CrossZone Balancing. + + :type force: bool + :param force: Ignore cache value and reload. + + :rtype: bool + :return: True if balancing is enabled, False if not. + """ + return self.get_attributes(force).cross_zone_load_balancing.enabled + + def enable_cross_zone_load_balancing(self): + """ + Turns on CrossZone Load Balancing for this ELB. + + :rtype: bool + :return: True if successful, False if not. + """ + success = self.connection.modify_lb_attribute( + self.name, 'crossZoneLoadBalancing', True) + if success and self._attributes: + self._attributes.cross_zone_load_balancing.enabled = True + return success + + def disable_cross_zone_load_balancing(self): + """ + Turns off CrossZone Load Balancing for this ELB. + + :rtype: bool + :return: True if successful, False if not. + """ + success = self.connection.modify_lb_attribute( + self.name, 'crossZoneLoadBalancing', False) + if success and self._attributes: + self._attributes.cross_zone_load_balancing.enabled = False + return success + def register_instances(self, instances): """ Adds instances to this load balancer. All instances must be in the same diff --git a/awx/lib/site-packages/boto/ec2/group.py b/awx/lib/site-packages/boto/ec2/group.py index 9e017b8adc..fef549772e 100644 --- a/awx/lib/site-packages/boto/ec2/group.py +++ b/awx/lib/site-packages/boto/ec2/group.py @@ -15,13 +15,12 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -class Group: - +class Group(object): def __init__(self, parent=None): self.id = None self.name = None @@ -36,4 +35,4 @@ class Group: self.name = value else: setattr(self, name, value) - + diff --git a/awx/lib/site-packages/boto/ec2/image.py b/awx/lib/site-packages/boto/ec2/image.py index 3e4e3171d2..08203a25d7 100644 --- a/awx/lib/site-packages/boto/ec2/image.py +++ b/awx/lib/site-packages/boto/ec2/image.py @@ -23,8 +23,8 @@ from boto.ec2.ec2object import EC2Object, TaggedEC2Object from boto.ec2.blockdevicemapping import BlockDeviceMapping -class ProductCodes(list): +class ProductCodes(list): def startElement(self, name, attrs, connection): pass @@ -32,8 +32,8 @@ class ProductCodes(list): if name == 'productCode': self.append(value) -class BillingProducts(list): +class BillingProducts(list): def startElement(self, name, attrs, connection): pass @@ -47,7 +47,7 @@ class Image(TaggedEC2Object): """ def __init__(self, connection=None): - TaggedEC2Object.__init__(self, connection) + super(Image, self).__init__(connection) self.id = None self.location = None self.state = None @@ -70,12 +70,13 @@ class Image(TaggedEC2Object): self.virtualization_type = None self.hypervisor = None self.instance_lifecycle = None + self.sriov_net_support = None def __repr__(self): return 'Image:%s' % self.id def startElement(self, name, attrs, connection): - retval = TaggedEC2Object.startElement(self, name, attrs, connection) + retval = super(Image, self).startElement(name, attrs, connection) if retval is not None: return retval if name == 'blockDeviceMapping': @@ -136,6 +137,8 @@ class Image(TaggedEC2Object): self.hypervisor = value elif name == 'instanceLifecycle': self.instance_lifecycle = value + elif name == 'sriovNetSupport': + self.sriov_net_support = value else: setattr(self, name, value) @@ -218,6 +221,16 @@ class Image(TaggedEC2Object): * cc1.4xlarge * cg1.4xlarge * cc2.8xlarge + * g2.2xlarge + * c3.large + * c3.xlarge + * c3.2xlarge + * c3.4xlarge + * c3.8xlarge + * i2.xlarge + * i2.2xlarge + * i2.4xlarge + * i2.8xlarge :type placement: string :param placement: The Availability Zone to launch the instance into. @@ -365,8 +378,8 @@ class Image(TaggedEC2Object): ) return img_attrs.ramdisk -class ImageAttribute: +class ImageAttribute(object): def __init__(self, parent=None): self.name = None self.kernel = None diff --git a/awx/lib/site-packages/boto/ec2/instance.py b/awx/lib/site-packages/boto/ec2/instance.py index 430647e80f..eb7c9ec615 100644 --- a/awx/lib/site-packages/boto/ec2/instance.py +++ b/awx/lib/site-packages/boto/ec2/instance.py @@ -122,7 +122,7 @@ class Reservation(EC2Object): Reservation. """ def __init__(self, connection=None): - EC2Object.__init__(self, connection) + super(Reservation, self).__init__(connection) self.id = None self.owner_id = None self.groups = [] @@ -211,7 +211,7 @@ class Instance(TaggedEC2Object): """ def __init__(self, connection=None): - TaggedEC2Object.__init__(self, connection) + super(Instance, self).__init__(connection) self.id = None self.dns_name = None self.public_dns_name = None @@ -288,7 +288,7 @@ class Instance(TaggedEC2Object): return self._placement.tenancy def startElement(self, name, attrs, connection): - retval = TaggedEC2Object.startElement(self, name, attrs, connection) + retval = super(Instance, self).startElement(name, attrs, connection) if retval is not None: return retval if name == 'monitoring': @@ -606,8 +606,7 @@ class Instance(TaggedEC2Object): ) -class ConsoleOutput: - +class ConsoleOutput(object): def __init__(self, parent=None): self.parent = parent self.instance_id = None @@ -629,7 +628,6 @@ class ConsoleOutput: class InstanceAttribute(dict): - ValidValues = ['instanceType', 'kernel', 'ramdisk', 'userData', 'disableApiTermination', 'instanceInitiatedShutdownBehavior', @@ -668,7 +666,6 @@ class InstanceAttribute(dict): class SubParse(dict): - def __init__(self, section, parent=None): dict.__init__(self) self.section = section diff --git a/awx/lib/site-packages/boto/ec2/keypair.py b/awx/lib/site-packages/boto/ec2/keypair.py index c15a0984dc..9323c24a5a 100644 --- a/awx/lib/site-packages/boto/ec2/keypair.py +++ b/awx/lib/site-packages/boto/ec2/keypair.py @@ -30,7 +30,7 @@ from boto.exception import BotoClientError class KeyPair(EC2Object): def __init__(self, connection=None): - EC2Object.__init__(self, connection) + super(KeyPair, self).__init__(connection) self.name = None self.fingerprint = None self.material = None diff --git a/awx/lib/site-packages/boto/ec2/launchspecification.py b/awx/lib/site-packages/boto/ec2/launchspecification.py index 037a8b0907..f145ac4799 100644 --- a/awx/lib/site-packages/boto/ec2/launchspecification.py +++ b/awx/lib/site-packages/boto/ec2/launchspecification.py @@ -44,7 +44,7 @@ class GroupList(list): class LaunchSpecification(EC2Object): def __init__(self, connection=None): - EC2Object.__init__(self, connection) + super(LaunchSpecification, self).__init__(connection) self.key_name = None self.instance_type = None self.image_id = None diff --git a/awx/lib/site-packages/boto/ec2/networkinterface.py b/awx/lib/site-packages/boto/ec2/networkinterface.py index 98368050a6..b786edb688 100644 --- a/awx/lib/site-packages/boto/ec2/networkinterface.py +++ b/awx/lib/site-packages/boto/ec2/networkinterface.py @@ -99,7 +99,7 @@ class NetworkInterface(TaggedEC2Object): """ def __init__(self, connection=None): - TaggedEC2Object.__init__(self, connection) + super(NetworkInterface, self).__init__(connection) self.id = None self.subnet_id = None self.vpc_id = None @@ -119,7 +119,8 @@ class NetworkInterface(TaggedEC2Object): return 'NetworkInterface:%s' % self.id def startElement(self, name, attrs, connection): - retval = TaggedEC2Object.startElement(self, name, attrs, connection) + retval = super(NetworkInterface, self).startElement(name, attrs, + connection) if retval is not None: return retval if name == 'groupSet': diff --git a/awx/lib/site-packages/boto/ec2/placementgroup.py b/awx/lib/site-packages/boto/ec2/placementgroup.py index 79bd4c4643..65e3284483 100644 --- a/awx/lib/site-packages/boto/ec2/placementgroup.py +++ b/awx/lib/site-packages/boto/ec2/placementgroup.py @@ -27,7 +27,7 @@ from boto.exception import BotoClientError class PlacementGroup(EC2Object): def __init__(self, connection=None, name=None, strategy=None, state=None): - EC2Object.__init__(self, connection) + super(PlacementGroup, self).__init__(connection) self.name = name self.strategy = strategy self.state = state diff --git a/awx/lib/site-packages/boto/ec2/regioninfo.py b/awx/lib/site-packages/boto/ec2/regioninfo.py index 0b37b0eec1..1b6c6ad934 100644 --- a/awx/lib/site-packages/boto/ec2/regioninfo.py +++ b/awx/lib/site-packages/boto/ec2/regioninfo.py @@ -16,7 +16,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -27,8 +27,8 @@ class EC2RegionInfo(RegionInfo): """ Represents an EC2 Region """ - + def __init__(self, connection=None, name=None, endpoint=None): from boto.ec2.connection import EC2Connection - RegionInfo.__init__(self, connection, name, endpoint, + super(EC2RegionInfo, self).__init__(connection, name, endpoint, EC2Connection) diff --git a/awx/lib/site-packages/boto/ec2/reservedinstance.py b/awx/lib/site-packages/boto/ec2/reservedinstance.py index 1386c4146a..b76aaa87fe 100644 --- a/awx/lib/site-packages/boto/ec2/reservedinstance.py +++ b/awx/lib/site-packages/boto/ec2/reservedinstance.py @@ -31,7 +31,7 @@ class ReservedInstancesOffering(EC2Object): usage_price=None, description=None, instance_tenancy=None, currency_code=None, offering_type=None, recurring_charges=None, pricing_details=None): - EC2Object.__init__(self, connection) + super(ReservedInstancesOffering, self).__init__(connection) self.id = id self.instance_type = instance_type self.availability_zone = availability_zone @@ -128,9 +128,10 @@ class ReservedInstance(ReservedInstancesOffering): availability_zone=None, duration=None, fixed_price=None, usage_price=None, description=None, instance_count=None, state=None): - ReservedInstancesOffering.__init__(self, connection, id, instance_type, - availability_zone, duration, fixed_price, - usage_price, description) + super(ReservedInstance, self).__init__(connection, id, instance_type, + availability_zone, duration, + fixed_price, usage_price, + description) self.instance_count = instance_count self.state = state self.start = None @@ -148,7 +149,7 @@ class ReservedInstance(ReservedInstancesOffering): elif name == 'start': self.start = value else: - ReservedInstancesOffering.endElement(self, name, value, connection) + super(ReservedInstance, self).endElement(name, value, connection) class ReservedInstanceListing(EC2Object): diff --git a/awx/lib/site-packages/boto/ec2/securitygroup.py b/awx/lib/site-packages/boto/ec2/securitygroup.py index 9f437ebbc7..5674f4e919 100644 --- a/awx/lib/site-packages/boto/ec2/securitygroup.py +++ b/awx/lib/site-packages/boto/ec2/securitygroup.py @@ -31,7 +31,7 @@ class SecurityGroup(TaggedEC2Object): def __init__(self, connection=None, owner_id=None, name=None, description=None, id=None): - TaggedEC2Object.__init__(self, connection) + super(SecurityGroup, self).__init__(connection) self.id = id self.owner_id = owner_id self.name = name @@ -44,7 +44,8 @@ class SecurityGroup(TaggedEC2Object): return 'SecurityGroup:%s' % self.name def startElement(self, name, attrs, connection): - retval = TaggedEC2Object.startElement(self, name, attrs, connection) + retval = super(SecurityGroup, self).startElement(name, attrs, + connection) if retval is not None: return retval if name == 'ipPermissions': diff --git a/awx/lib/site-packages/boto/ec2/snapshot.py b/awx/lib/site-packages/boto/ec2/snapshot.py index 24bffe6bbf..6121d0c825 100644 --- a/awx/lib/site-packages/boto/ec2/snapshot.py +++ b/awx/lib/site-packages/boto/ec2/snapshot.py @@ -26,12 +26,12 @@ Represents an EC2 Elastic Block Store Snapshot from boto.ec2.ec2object import TaggedEC2Object from boto.ec2.zone import Zone -class Snapshot(TaggedEC2Object): +class Snapshot(TaggedEC2Object): AttrName = 'createVolumePermission' def __init__(self, connection=None): - TaggedEC2Object.__init__(self, connection) + super(Snapshot, self).__init__(connection) self.id = None self.volume_id = None self.status = None @@ -156,8 +156,7 @@ class Snapshot(TaggedEC2Object): ) -class SnapshotAttribute: - +class SnapshotAttribute(object): def __init__(self, parent=None): self.snapshot_id = None self.attrs = {} diff --git a/awx/lib/site-packages/boto/ec2/spotdatafeedsubscription.py b/awx/lib/site-packages/boto/ec2/spotdatafeedsubscription.py index 1b30a99f0f..26ef7adc4e 100644 --- a/awx/lib/site-packages/boto/ec2/spotdatafeedsubscription.py +++ b/awx/lib/site-packages/boto/ec2/spotdatafeedsubscription.py @@ -29,7 +29,7 @@ class SpotDatafeedSubscription(EC2Object): def __init__(self, connection=None, owner_id=None, bucket=None, prefix=None, state=None,fault=None): - EC2Object.__init__(self, connection) + super(SpotDatafeedSubscription, self).__init__(connection) self.owner_id = owner_id self.bucket = bucket self.prefix = prefix diff --git a/awx/lib/site-packages/boto/ec2/spotinstancerequest.py b/awx/lib/site-packages/boto/ec2/spotinstancerequest.py index c5b8bc95be..da087fefdb 100644 --- a/awx/lib/site-packages/boto/ec2/spotinstancerequest.py +++ b/awx/lib/site-packages/boto/ec2/spotinstancerequest.py @@ -120,7 +120,7 @@ class SpotInstanceRequest(TaggedEC2Object): """ def __init__(self, connection=None): - TaggedEC2Object.__init__(self, connection) + super(SpotInstanceRequest, self).__init__(connection) self.id = None self.price = None self.type = None @@ -141,7 +141,8 @@ class SpotInstanceRequest(TaggedEC2Object): return 'SpotInstanceRequest:%s' % self.id def startElement(self, name, attrs, connection): - retval = TaggedEC2Object.startElement(self, name, attrs, connection) + retval = super(SpotInstanceRequest, self).startElement(name, attrs, + connection) if retval is not None: return retval if name == 'launchSpecification': diff --git a/awx/lib/site-packages/boto/ec2/spotpricehistory.py b/awx/lib/site-packages/boto/ec2/spotpricehistory.py index 268d6b35a6..7bd0ce89b7 100644 --- a/awx/lib/site-packages/boto/ec2/spotpricehistory.py +++ b/awx/lib/site-packages/boto/ec2/spotpricehistory.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -26,9 +26,9 @@ Represents an EC2 Spot Instance Request from boto.ec2.ec2object import EC2Object class SpotPriceHistory(EC2Object): - + def __init__(self, connection=None): - EC2Object.__init__(self, connection) + super(SpotPriceHistory, self).__init__(connection) self.price = 0.0 self.instance_type = None self.product_description = None diff --git a/awx/lib/site-packages/boto/ec2/vmtype.py b/awx/lib/site-packages/boto/ec2/vmtype.py index fdb4f369cd..1ffbc191cb 100644 --- a/awx/lib/site-packages/boto/ec2/vmtype.py +++ b/awx/lib/site-packages/boto/ec2/vmtype.py @@ -35,7 +35,7 @@ class VmType(EC2Object): def __init__(self, connection=None, name=None, cores=None, memory=None, disk=None): - EC2Object.__init__(self, connection) + super(VmType, self).__init__(connection) self.connection = connection self.name = name self.cores = cores diff --git a/awx/lib/site-packages/boto/ec2/volume.py b/awx/lib/site-packages/boto/ec2/volume.py index 2127b260f9..95121fa813 100644 --- a/awx/lib/site-packages/boto/ec2/volume.py +++ b/awx/lib/site-packages/boto/ec2/volume.py @@ -47,7 +47,7 @@ class Volume(TaggedEC2Object): """ def __init__(self, connection=None): - TaggedEC2Object.__init__(self, connection) + super(Volume, self).__init__(connection) self.id = None self.create_time = None self.status = None @@ -62,7 +62,7 @@ class Volume(TaggedEC2Object): return 'Volume:%s' % self.id def startElement(self, name, attrs, connection): - retval = TaggedEC2Object.startElement(self, name, attrs, connection) + retval = super(Volume, self).startElement(name, attrs, connection) if retval is not None: return retval if name == 'attachmentSet': @@ -260,7 +260,6 @@ class AttachmentSet(object): :ivar attach_time: Attached since :ivar device: The device the instance has mapped """ - def __init__(self): self.id = None self.instance_id = None @@ -289,8 +288,7 @@ class AttachmentSet(object): setattr(self, name, value) -class VolumeAttribute: - +class VolumeAttribute(object): def __init__(self, parent=None): self.id = None self._key_name = None diff --git a/awx/lib/site-packages/boto/ec2/zone.py b/awx/lib/site-packages/boto/ec2/zone.py index 44068d4dde..725d176950 100644 --- a/awx/lib/site-packages/boto/ec2/zone.py +++ b/awx/lib/site-packages/boto/ec2/zone.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -38,7 +38,7 @@ class MessageSet(list): self.append(value) else: setattr(self, name, value) - + class Zone(EC2Object): """ Represents an Availability Zone. @@ -48,9 +48,9 @@ class Zone(EC2Object): :ivar region_name: The name of the region the zone is associated with. :ivar messages: A list of messages related to the zone. """ - + def __init__(self, connection=None): - EC2Object.__init__(self, connection) + super(Zone, self).__init__(connection) self.name = None self.state = None self.region_name = None @@ -64,7 +64,7 @@ class Zone(EC2Object): self.messages = MessageSet() return self.messages return None - + def endElement(self, name, value, connection): if name == 'zoneName': self.name = value diff --git a/awx/lib/site-packages/boto/ecs/__init__.py b/awx/lib/site-packages/boto/ecs/__init__.py index cbaf478a7a..f39ec5a50c 100644 --- a/awx/lib/site-packages/boto/ecs/__init__.py +++ b/awx/lib/site-packages/boto/ecs/__init__.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -42,7 +42,7 @@ class ECSConnection(AWSQueryConnection): is_secure=True, port=None, proxy=None, proxy_port=None, proxy_user=None, proxy_pass=None, host='ecs.amazonaws.com', debug=0, https_connection_factory=None, path='/'): - AWSQueryConnection.__init__(self, aws_access_key_id, aws_secret_access_key, + super(ECSConnection, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, host, debug, https_connection_factory, path) @@ -77,13 +77,13 @@ class ECSConnection(AWSQueryConnection): # # Group methods # - + def item_search(self, search_index, **params): """ - Returns items that satisfy the search criteria, including one or more search + Returns items that satisfy the search criteria, including one or more search indices. - For a full list of search terms, + For a full list of search terms, :see: http://docs.amazonwebservices.com/AWSECommerceService/2010-09-01/DG/index.html?ItemSearch.html """ params['SearchIndex'] = search_index diff --git a/awx/lib/site-packages/boto/ecs/item.py b/awx/lib/site-packages/boto/ecs/item.py index 29588b8618..d0cdb99017 100644 --- a/awx/lib/site-packages/boto/ecs/item.py +++ b/awx/lib/site-packages/boto/ecs/item.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -26,7 +26,7 @@ from StringIO import StringIO class ResponseGroup(xml.sax.ContentHandler): """A Generic "Response Group", which can - be anything from the entire list of Items to + be anything from the entire list of Items to specific response elements within an item""" def __init__(self, connection=None, nodename=None): @@ -45,7 +45,7 @@ class ResponseGroup(xml.sax.ContentHandler): # def get(self, name): return self.__dict__.get(name) - + def set(self, name, value): self.__dict__[name] = value @@ -90,14 +90,14 @@ class Item(ResponseGroup): def __init__(self, connection=None): """Initialize this Item""" - ResponseGroup.__init__(self, connection, "Item") + super(Item, self).__init__(connection, "Item") class ItemSet(ResponseGroup): """A special ResponseGroup that has built-in paging, and only creates new Items on the "Item" tag""" def __init__(self, connection, action, params, page=0): - ResponseGroup.__init__(self, connection, "Items") + super(ItemSet, self).__init__(connection, "Items") self.objs = [] self.iter = None self.page = page @@ -150,4 +150,4 @@ class ItemSet(ResponseGroup): """Override to first fetch everything""" for item in self: pass - return ResponseGroup.to_xml(self) + return super(ItemSet, self).to_xml() diff --git a/awx/lib/site-packages/boto/elasticache/__init__.py b/awx/lib/site-packages/boto/elasticache/__init__.py index acd0377762..1759a17ef5 100644 --- a/awx/lib/site-packages/boto/elasticache/__init__.py +++ b/awx/lib/site-packages/boto/elasticache/__init__.py @@ -55,6 +55,9 @@ def regions(): RegionInfo(name='sa-east-1', endpoint='elasticache.sa-east-1.amazonaws.com', connection_cls=ElastiCacheConnection), + RegionInfo(name='cn-north-1', + endpoint='elasticache.cn-north-1.amazonaws.com.cn', + connection_cls=ElastiCacheConnection), ] diff --git a/awx/lib/site-packages/boto/elasticache/layer1.py b/awx/lib/site-packages/boto/elasticache/layer1.py index f1dc3a2669..be7080d0e4 100644 --- a/awx/lib/site-packages/boto/elasticache/layer1.py +++ b/awx/lib/site-packages/boto/elasticache/layer1.py @@ -55,12 +55,12 @@ class ElastiCacheConnection(AWSQueryConnection): else: del kwargs['region'] kwargs['host'] = region.endpoint - AWSQueryConnection.__init__(self, **kwargs) + super(ElastiCacheConnection, self).__init__(**kwargs) self.region = region def _required_auth_capability(self): - return ['sign-v2'] + return ['hmac-v4'] def authorize_cache_security_group_ingress(self, cache_security_group_name, @@ -99,8 +99,8 @@ class ElastiCacheConnection(AWSQueryConnection): verb='POST', path='/', params=params) - def create_cache_cluster(self, cache_cluster_id, num_cache_nodes, - cache_node_type, engine, + def create_cache_cluster(self, cache_cluster_id, num_cache_nodes=None, + cache_node_type=None, engine=None, replication_group_id=None, engine_version=None, cache_parameter_group_name=None, cache_subnet_group_name=None, @@ -244,10 +244,13 @@ class ElastiCacheConnection(AWSQueryConnection): """ params = { 'CacheClusterId': cache_cluster_id, - 'NumCacheNodes': num_cache_nodes, - 'CacheNodeType': cache_node_type, - 'Engine': engine, } + if num_cache_nodes is not None: + params['NumCacheNodes'] = num_cache_nodes + if cache_node_type is not None: + params['CacheNodeType'] = cache_node_type + if engine is not None: + params['Engine'] = engine if replication_group_id is not None: params['ReplicationGroupId'] = replication_group_id if engine_version is not None: diff --git a/awx/lib/site-packages/boto/elastictranscoder/layer1.py b/awx/lib/site-packages/boto/elastictranscoder/layer1.py index 8799753cd6..e47c199c7e 100644 --- a/awx/lib/site-packages/boto/elastictranscoder/layer1.py +++ b/awx/lib/site-packages/boto/elastictranscoder/layer1.py @@ -55,7 +55,7 @@ class ElasticTranscoderConnection(AWSAuthConnection): else: del kwargs['region'] kwargs['host'] = region.endpoint - AWSAuthConnection.__init__(self, **kwargs) + super(ElasticTranscoderConnection, self).__init__(**kwargs) self.region = region def _required_auth_capability(self): @@ -523,26 +523,56 @@ class ElasticTranscoderConnection(AWSAuthConnection): return self.make_request('GET', uri, expected_status=200, params=params) - def list_pipelines(self): + def list_pipelines(self, ascending=None, page_token=None): """ The ListPipelines operation gets a list of the pipelines associated with the current AWS account. - - """ - uri = '/2012-09-25/pipelines' - return self.make_request('GET', uri, expected_status=200) + :type ascending: string + :param ascending: To list pipelines in chronological order by the date + and time that they were created, enter `True`. To list pipelines in + reverse chronological order, enter `False`. - def list_presets(self): + :type page_token: string + :param page_token: When Elastic Transcoder returns more than one page + of results, use `pageToken` in subsequent `GET` requests to get + each successive page of results. + + """ + uri = '/2012-09-25/pipelines'.format() + params = {} + if ascending is not None: + params['Ascending'] = ascending + if page_token is not None: + params['PageToken'] = page_token + return self.make_request('GET', uri, expected_status=200, + params=params) + + def list_presets(self, ascending=None, page_token=None): """ The ListPresets operation gets a list of the default presets included with Elastic Transcoder and the presets that you've added in an AWS region. - + :type ascending: string + :param ascending: To list presets in chronological order by the date + and time that they were created, enter `True`. To list presets in + reverse chronological order, enter `False`. + + :type page_token: string + :param page_token: When Elastic Transcoder returns more than one page + of results, use `pageToken` in subsequent `GET` requests to get + each successive page of results. + """ - uri = '/2012-09-25/presets' - return self.make_request('GET', uri, expected_status=200) + uri = '/2012-09-25/presets'.format() + params = {} + if ascending is not None: + params['Ascending'] = ascending + if page_token is not None: + params['PageToken'] = page_token + return self.make_request('GET', uri, expected_status=200, + params=params) def read_job(self, id=None): """ @@ -891,8 +921,8 @@ class ElasticTranscoderConnection(AWSAuthConnection): expected_status=None, params=None): if headers is None: headers = {} - response = AWSAuthConnection.make_request( - self, verb, resource, headers=headers, data=data) + response = super(ElasticTranscoderConnection, self).make_request( + verb, resource, headers=headers, data=data) body = json.load(response) if response.status == expected_status: return body diff --git a/awx/lib/site-packages/boto/emr/__init__.py b/awx/lib/site-packages/boto/emr/__init__.py index 562c582da7..0bd48ad3b3 100644 --- a/awx/lib/site-packages/boto/emr/__init__.py +++ b/awx/lib/site-packages/boto/emr/__init__.py @@ -63,6 +63,9 @@ def regions(): RegionInfo(name='sa-east-1', endpoint='sa-east-1.elasticmapreduce.amazonaws.com', connection_cls=EmrConnection), + RegionInfo(name='cn-north-1', + endpoint='elasticmapreduce.cn-north-1.amazonaws.com.cn', + connection_cls=EmrConnection), ] diff --git a/awx/lib/site-packages/boto/emr/connection.py b/awx/lib/site-packages/boto/emr/connection.py index 7b1c434eb4..e7b5b74782 100644 --- a/awx/lib/site-packages/boto/emr/connection.py +++ b/awx/lib/site-packages/boto/emr/connection.py @@ -60,7 +60,7 @@ class EmrConnection(AWSQueryConnection): region = RegionInfo(self, self.DefaultRegionName, self.DefaultRegionEndpoint) self.region = region - AWSQueryConnection.__init__(self, aws_access_key_id, + super(EmrConnection, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, @@ -267,6 +267,42 @@ class EmrConnection(AWSQueryConnection): self.get_object('ListSteps', params, StepSummaryList) + def add_tags(self, resource_id, tags): + """ + Create new metadata tags for the specified resource id. + + :type resource_id: str + :param resource_id: The cluster id + + :type tags: dict + :param tags: A dictionary containing the name/value pairs. + If you want to create only a tag name, the + value for that tag should be the empty string + (e.g. '') or None. + """ + assert isinstance(resource_id, basestring) + params = { + 'ResourceId': resource_id, + } + params.update(self._build_tag_list(tags)) + return self.get_status('AddTags', params, verb='POST') + + def remove_tags(self, resource_id, tags): + """ + Remove metadata tags for the specified resource id. + + :type resource_id: str + :param resource_id: The cluster id + + :type tags: list + :param tags: A list of tag names to remove. + """ + params = { + 'ResourceId': resource_id, + } + params.update(self._build_string_list('TagKeys', tags)) + return self.get_status('RemoveTags', params, verb='POST') + def terminate_jobflow(self, jobflow_id): """ Terminate an Elastic MapReduce job flow @@ -623,6 +659,27 @@ class EmrConnection(AWSQueryConnection): params['Steps.member.%s.%s' % (i+1, key)] = value return params + def _build_string_list(self, field, items): + if not isinstance(items, types.ListType): + items = [items] + + params = {} + for i, item in enumerate(items): + params['%s.member.%s' % (field, i + 1)] = item + return params + + def _build_tag_list(self, tags): + assert isinstance(tags, dict) + + params = {} + for i, key_value in enumerate(sorted(tags.iteritems()), start=1): + key, value = key_value + current_prefix = 'Tags.member.%s' % i + params['%s.Key' % current_prefix] = key + if value: + params['%s.Value' % current_prefix] = value + return params + def _build_instance_common_args(self, ec2_keyname, availability_zone, keep_alive, hadoop_version): """ diff --git a/awx/lib/site-packages/boto/emr/emrobject.py b/awx/lib/site-packages/boto/emr/emrobject.py index caf51f7629..a397a55a0d 100644 --- a/awx/lib/site-packages/boto/emr/emrobject.py +++ b/awx/lib/site-packages/boto/emr/emrobject.py @@ -256,6 +256,7 @@ class Cluster(EmrObject): self.status = None self.ec2instanceattributes = None self.applications = None + self.tags = None def startElement(self, name, attrs, connection): if name == 'Status': @@ -266,6 +267,9 @@ class Cluster(EmrObject): return self.ec2instanceattributes elif name == 'Applications': self.applications = ResultSet([('member', Application)]) + elif name == 'Tags': + self.tags = ResultSet([('member', KeyValue)]) + return self.tags else: return None diff --git a/awx/lib/site-packages/boto/emr/step.py b/awx/lib/site-packages/boto/emr/step.py index b17defbd0e..4cb7889819 100644 --- a/awx/lib/site-packages/boto/emr/step.py +++ b/awx/lib/site-packages/boto/emr/step.py @@ -204,7 +204,7 @@ class ScriptRunnerStep(JarStep): ScriptRunnerJar = 's3n://us-east-1.elasticmapreduce/libs/script-runner/script-runner.jar' def __init__(self, name, **kw): - JarStep.__init__(self, name, self.ScriptRunnerJar, **kw) + super(ScriptRunnerStep, self).__init__(name, self.ScriptRunnerJar, **kw) class PigBase(ScriptRunnerStep): @@ -225,7 +225,7 @@ class InstallPigStep(PigBase): step_args.extend(self.BaseArgs) step_args.extend(['--install-pig']) step_args.extend(['--pig-versions', pig_versions]) - ScriptRunnerStep.__init__(self, self.InstallPigName, step_args=step_args) + super(InstallPigStep, self).__init__(self.InstallPigName, step_args=step_args) class PigStep(PigBase): @@ -239,7 +239,7 @@ class PigStep(PigBase): step_args.extend(['--pig-versions', pig_versions]) step_args.extend(['--run-pig-script', '--args', '-f', pig_file]) step_args.extend(pig_args) - ScriptRunnerStep.__init__(self, name, step_args=step_args) + super(PigStep, self).__init__(name, step_args=step_args) class HiveBase(ScriptRunnerStep): @@ -261,7 +261,7 @@ class InstallHiveStep(HiveBase): step_args.extend(['--hive-versions', hive_versions]) if hive_site is not None: step_args.extend(['--hive-site=%s' % hive_site]) - ScriptRunnerStep.__init__(self, self.InstallHiveName, + super(InstallHiveStep, self).__init__(self.InstallHiveName, step_args=step_args) @@ -278,4 +278,4 @@ class HiveStep(HiveBase): step_args.extend(['--run-hive-script', '--args', '-f', hive_file]) if hive_args is not None: step_args.extend(hive_args) - ScriptRunnerStep.__init__(self, name, step_args=step_args) + super(HiveStep, self).__init__(name, step_args=step_args) diff --git a/awx/lib/site-packages/boto/exception.py b/awx/lib/site-packages/boto/exception.py index 419aac1539..53626bfebb 100644 --- a/awx/lib/site-packages/boto/exception.py +++ b/awx/lib/site-packages/boto/exception.py @@ -34,9 +34,8 @@ class BotoClientError(StandardError): """ General Boto Client error (error accessing AWS) """ - def __init__(self, reason, *args): - StandardError.__init__(self, reason, *args) + super(BotoClientError, self).__init__(reason, *args) self.reason = reason def __repr__(self): @@ -45,32 +44,35 @@ class BotoClientError(StandardError): def __str__(self): return 'BotoClientError: %s' % self.reason -class SDBPersistenceError(StandardError): +class SDBPersistenceError(StandardError): pass + class StoragePermissionsError(BotoClientError): """ Permissions error when accessing a bucket or key on a storage service. """ pass + class S3PermissionsError(StoragePermissionsError): """ Permissions error when accessing a bucket or key on S3. """ pass + class GSPermissionsError(StoragePermissionsError): """ Permissions error when accessing a bucket or key on GS. """ pass -class BotoServerError(StandardError): +class BotoServerError(StandardError): def __init__(self, status, reason, body=None, *args): - StandardError.__init__(self, status, reason, body, *args) + super(BotoServerError, self).__init__(status, reason, body, *args) self.status = status self.reason = reason self.body = body or '' @@ -134,8 +136,8 @@ class BotoServerError(StandardError): self.message = None self.box_usage = None -class ConsoleOutput: +class ConsoleOutput(object): def __init__(self, parent=None): self.parent = parent self.instance_id = None @@ -154,19 +156,20 @@ class ConsoleOutput: else: setattr(self, name, value) + class StorageCreateError(BotoServerError): """ Error creating a bucket or key on a storage service. """ def __init__(self, status, reason, body=None): self.bucket = None - BotoServerError.__init__(self, status, reason, body) + super(StorageCreateError, self).__init__(status, reason, body) def endElement(self, name, value, connection): if name == 'BucketName': self.bucket = value else: - return BotoServerError.endElement(self, name, value, connection) + return super(StorageCreateError, self).endElement(name, value, connection) class S3CreateError(StorageCreateError): """ @@ -174,30 +177,35 @@ class S3CreateError(StorageCreateError): """ pass + class GSCreateError(StorageCreateError): """ Error creating a bucket or key on GS. """ pass + class StorageCopyError(BotoServerError): """ Error copying a key on a storage service. """ pass + class S3CopyError(StorageCopyError): """ Error copying a key on S3. """ pass + class GSCopyError(StorageCopyError): """ Error copying a key on GS. """ pass + class SQSError(BotoServerError): """ General Error on Simple Queue Service. @@ -205,10 +213,10 @@ class SQSError(BotoServerError): def __init__(self, status, reason, body=None): self.detail = None self.type = None - BotoServerError.__init__(self, status, reason, body) + super(SQSError, self).__init__(status, reason, body) def startElement(self, name, attrs, connection): - return BotoServerError.startElement(self, name, attrs, connection) + return super(SQSError, self).startElement(name, attrs, connection) def endElement(self, name, value, connection): if name == 'Detail': @@ -216,19 +224,20 @@ class SQSError(BotoServerError): elif name == 'Type': self.type = value else: - return BotoServerError.endElement(self, name, value, connection) + return super(SQSError, self).endElement(name, value, connection) def _cleanupParsedProperties(self): - BotoServerError._cleanupParsedProperties(self) + super(SQSError, self)._cleanupParsedProperties() for p in ('detail', 'type'): setattr(self, p, None) + class SQSDecodeError(BotoClientError): """ Error when decoding an SQS message. """ def __init__(self, reason, message): - BotoClientError.__init__(self, reason, message) + super(SQSDecodeError, self).__init__(reason, message) self.message = message def __repr__(self): @@ -237,49 +246,54 @@ class SQSDecodeError(BotoClientError): def __str__(self): return 'SQSDecodeError: %s' % self.reason + class StorageResponseError(BotoServerError): """ Error in response from a storage service. """ def __init__(self, status, reason, body=None): self.resource = None - BotoServerError.__init__(self, status, reason, body) + super(StorageResponseError, self).__init__(status, reason, body) def startElement(self, name, attrs, connection): - return BotoServerError.startElement(self, name, attrs, connection) + return super(StorageResponseError, self).startElement(name, attrs, + connection) def endElement(self, name, value, connection): if name == 'Resource': self.resource = value else: - return BotoServerError.endElement(self, name, value, connection) + return super(StorageResponseError, self).endElement(name, value, + connection) def _cleanupParsedProperties(self): - BotoServerError._cleanupParsedProperties(self) + super(StorageResponseError, self)._cleanupParsedProperties() for p in ('resource'): setattr(self, p, None) + class S3ResponseError(StorageResponseError): """ Error in response from S3. """ pass + class GSResponseError(StorageResponseError): """ Error in response from GS. """ pass + class EC2ResponseError(BotoServerError): """ Error in response from EC2. """ - def __init__(self, status, reason, body=None): self.errors = None self._errorResultSet = [] - BotoServerError.__init__(self, status, reason, body) + super(EC2ResponseError, self).__init__(status, reason, body) self.errors = [ (e.error_code, e.error_message) \ for e in self._errorResultSet ] if len(self.errors): @@ -299,11 +313,12 @@ class EC2ResponseError(BotoServerError): return None # don't call subclass here def _cleanupParsedProperties(self): - BotoServerError._cleanupParsedProperties(self) + super(EC2ResponseError, self)._cleanupParsedProperties() self._errorResultSet = [] for p in ('errors'): setattr(self, p, None) + class JSONResponseError(BotoServerError): """ This exception expects the fully parsed and decoded JSON response @@ -342,8 +357,8 @@ class EmrResponseError(BotoServerError): """ pass -class _EC2Error: +class _EC2Error(object): def __init__(self, connection=None): self.connection = connection self.error_code = None @@ -360,6 +375,7 @@ class _EC2Error: else: return None + class SDBResponseError(BotoServerError): """ Error in responses from SDB. @@ -394,21 +410,21 @@ class InvalidUriError(Exception): """Exception raised when URI is invalid.""" def __init__(self, message): - Exception.__init__(self, message) + super(InvalidUriError, self).__init__(message) self.message = message class InvalidAclError(Exception): """Exception raised when ACL XML is invalid.""" def __init__(self, message): - Exception.__init__(self, message) + super(InvalidAclError, self).__init__(message) self.message = message class InvalidCorsError(Exception): """Exception raised when CORS XML is invalid.""" def __init__(self, message): - Exception.__init__(self, message) + super(InvalidCorsError, self).__init__(message) self.message = message class NoAuthHandlerFound(Exception): @@ -419,7 +435,7 @@ class InvalidLifecycleConfigError(Exception): """Exception raised when GCS lifecycle configuration XML is invalid.""" def __init__(self, message): - Exception.__init__(self, message) + super(InvalidLifecycleConfigError, self).__init__(message) self.message = message # Enum class for resumable upload failure disposition. @@ -454,7 +470,7 @@ class ResumableUploadException(Exception): """ def __init__(self, message, disposition): - Exception.__init__(self, message, disposition) + super(ResumableUploadException, self).__init__(message, disposition) self.message = message self.disposition = disposition @@ -470,7 +486,7 @@ class ResumableDownloadException(Exception): """ def __init__(self, message, disposition): - Exception.__init__(self, message, disposition) + super(ResumableDownloadException, self).__init__(message, disposition) self.message = message self.disposition = disposition @@ -485,7 +501,7 @@ class TooManyRecordsException(Exception): """ def __init__(self, message): - Exception.__init__(self, message) + super(TooManyRecordsException, self).__init__(message) self.message = message diff --git a/awx/lib/site-packages/boto/fps/connection.py b/awx/lib/site-packages/boto/fps/connection.py index 8f2aaee810..dd9b235184 100644 --- a/awx/lib/site-packages/boto/fps/connection.py +++ b/awx/lib/site-packages/boto/fps/connection.py @@ -109,7 +109,7 @@ class FPSConnection(AWSQueryConnection): def __init__(self, *args, **kw): self.currencycode = kw.pop('CurrencyCode', self.currencycode) kw.setdefault('host', 'fps.sandbox.amazonaws.com') - AWSQueryConnection.__init__(self, *args, **kw) + super(FPSConnection, self).__init__(*args, **kw) def _required_auth_capability(self): return ['fps'] diff --git a/awx/lib/site-packages/boto/fps/response.py b/awx/lib/site-packages/boto/fps/response.py index fa77b2d419..ef12b00f34 100644 --- a/awx/lib/site-packages/boto/fps/response.py +++ b/awx/lib/site-packages/boto/fps/response.py @@ -9,7 +9,7 @@ def ResponseFactory(action): # due to nodes receiving their closing tags def endElement(self, name, value, connection): if name != action + 'Response': - Response.endElement(self, name, value, connection) + super(FPSResponse, self).endElement(name, value, connection) return FPSResponse @@ -48,7 +48,7 @@ class Response(ResponseElement): elif name == self._action + 'Result': setattr(self, name, self._Result(name=name)) else: - return ResponseElement.startElement(self, name, attrs, connection) + return super(Response, self).startElement(name, attrs, connection) return getattr(self, name) @@ -66,12 +66,12 @@ class ComplexAmount(ResponseElement): if name not in ('CurrencyCode', 'Value'): message = 'Unrecognized tag {0} in ComplexAmount'.format(name) raise AssertionError(message) - return ResponseElement.startElement(self, name, attrs, connection) + return super(ComplexAmount, self).startElement(name, attrs, connection) def endElement(self, name, value, connection): if name == 'Value': value = Decimal(value) - ResponseElement.endElement(self, name, value, connection) + super(ComplexAmount, self).endElement(name, value, connection) class AmountCollection(ResponseElement): @@ -85,7 +85,7 @@ class AccountBalance(AmountCollection): if name == 'AvailableBalances': setattr(self, name, AmountCollection(name=name)) return getattr(self, name) - return AmountCollection.startElement(self, name, attrs, connection) + return super(AccountBalance, self).startElement(name, attrs, connection) class GetAccountBalanceResult(ResponseElement): @@ -93,7 +93,8 @@ class GetAccountBalanceResult(ResponseElement): if name == 'AccountBalance': setattr(self, name, AccountBalance(name=name)) return getattr(self, name) - return Response.startElement(self, name, attrs, connection) + return super(GetAccountBalanceResult, self).startElement(name, attrs, + connection) class GetTotalPrepaidLiabilityResult(ResponseElement): @@ -101,7 +102,8 @@ class GetTotalPrepaidLiabilityResult(ResponseElement): if name == 'OutstandingPrepaidLiability': setattr(self, name, AmountCollection(name=name)) return getattr(self, name) - return Response.startElement(self, name, attrs, connection) + return super(GetTotalPrepaidLiabilityResult, self).startElement(name, + attrs, connection) class GetPrepaidBalanceResult(ResponseElement): @@ -109,7 +111,8 @@ class GetPrepaidBalanceResult(ResponseElement): if name == 'PrepaidBalance': setattr(self, name, AmountCollection(name=name)) return getattr(self, name) - return Response.startElement(self, name, attrs, connection) + return super(GetPrepaidBalanceResult, self).startElement(name, attrs, + connection) class GetOutstandingDebtBalanceResult(ResponseElement): @@ -117,7 +120,8 @@ class GetOutstandingDebtBalanceResult(ResponseElement): if name == 'OutstandingDebt': setattr(self, name, AmountCollection(name=name)) return getattr(self, name) - return Response.startElement(self, name, attrs, connection) + return super(GetOutstandingDebtBalanceResult, self).startElement(name, + attrs, connection) class TransactionPart(ResponseElement): @@ -125,13 +129,14 @@ class TransactionPart(ResponseElement): if name == 'FeesPaid': setattr(self, name, ComplexAmount(name=name)) return getattr(self, name) - return ResponseElement.startElement(self, name, attrs, connection) + return super(TransactionPart, self).startElement(name, attrs, + connection) class Transaction(ResponseElement): def __init__(self, *args, **kw): self.TransactionPart = [] - ResponseElement.__init__(self, *args, **kw) + super(Transaction, self).__init__(*args, **kw) def startElement(self, name, attrs, connection): if name == 'TransactionPart': @@ -140,19 +145,20 @@ class Transaction(ResponseElement): if name in ('TransactionAmount', 'FPSFees', 'Balance'): setattr(self, name, ComplexAmount(name=name)) return getattr(self, name) - return ResponseElement.startElement(self, name, attrs, connection) + return super(Transaction, self).startElement(name, attrs, connection) class GetAccountActivityResult(ResponseElement): def __init__(self, *args, **kw): self.Transaction = [] - ResponseElement.__init__(self, *args, **kw) + super(GetAccountActivityResult, self).__init__(*args, **kw) def startElement(self, name, attrs, connection): if name == 'Transaction': getattr(self, name).append(Transaction(name=name)) return getattr(self, name)[-1] - return ResponseElement.startElement(self, name, attrs, connection) + return super(GetAccountActivityResult, self).startElement(name, attrs, + connection) class GetTransactionResult(ResponseElement): @@ -160,16 +166,18 @@ class GetTransactionResult(ResponseElement): if name == 'Transaction': setattr(self, name, Transaction(name=name)) return getattr(self, name) - return ResponseElement.startElement(self, name, attrs, connection) + return super(GetTransactionResult, self).startElement(name, attrs, + connection) class GetTokensResult(ResponseElement): def __init__(self, *args, **kw): self.Token = [] - ResponseElement.__init__(self, *args, **kw) + super(GetTokensResult, self).__init__(*args, **kw) def startElement(self, name, attrs, connection): if name == 'Token': getattr(self, name).append(ResponseElement(name=name)) return getattr(self, name)[-1] - return ResponseElement.startElement(self, name, attrs, connection) + return super(GetTokensResult, self).startElement(name, attrs, + connection) diff --git a/awx/lib/site-packages/boto/glacier/__init__.py b/awx/lib/site-packages/boto/glacier/__init__.py index 5224d3453d..ccf35b326d 100644 --- a/awx/lib/site-packages/boto/glacier/__init__.py +++ b/awx/lib/site-packages/boto/glacier/__init__.py @@ -50,6 +50,9 @@ def regions(): RegionInfo(name='ap-southeast-2', endpoint='glacier.ap-southeast-2.amazonaws.com', connection_cls=Layer2), + RegionInfo(name='cn-north-1', + endpoint='glacier.cn-north-1.amazonaws.com.cn', + connection_cls=Layer2), ] diff --git a/awx/lib/site-packages/boto/glacier/layer1.py b/awx/lib/site-packages/boto/glacier/layer1.py index e5a3963034..f6b05588bb 100644 --- a/awx/lib/site-packages/boto/glacier/layer1.py +++ b/awx/lib/site-packages/boto/glacier/layer1.py @@ -54,7 +54,7 @@ class Layer1(AWSAuthConnection): self.region = region self.account_id = account_id - AWSAuthConnection.__init__(self, region.endpoint, + super(Layer1, self).__init__(region.endpoint, aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, debug, @@ -72,7 +72,7 @@ class Layer1(AWSAuthConnection): headers = {} headers['x-amz-glacier-version'] = self.Version uri = '/%s/%s' % (self.account_id, resource) - response = AWSAuthConnection.make_request(self, verb, uri, + response = super(Layer1, self).make_request(verb, uri, params=params, headers=headers, sender=sender, diff --git a/awx/lib/site-packages/boto/gs/bucket.py b/awx/lib/site-packages/boto/gs/bucket.py index 9e9892588e..3b706408b8 100644 --- a/awx/lib/site-packages/boto/gs/bucket.py +++ b/awx/lib/site-packages/boto/gs/bucket.py @@ -221,6 +221,14 @@ class Bucket(S3Bucket): marker, generation_marker, headers) + def validate_get_all_versions_params(self, params): + """ + See documentation in boto/s3/bucket.py. + """ + self.validate_kwarg_names(params, + ['version_id_marker', 'delimiter', 'marker', + 'generation_marker', 'prefix', 'max_keys']) + def delete_key(self, key_name, headers=None, version_id=None, mfa_token=None, generation=None): """ diff --git a/awx/lib/site-packages/boto/gs/connection.py b/awx/lib/site-packages/boto/gs/connection.py index e7f2aeb6a3..4c31979c71 100644 --- a/awx/lib/site-packages/boto/gs/connection.py +++ b/awx/lib/site-packages/boto/gs/connection.py @@ -14,12 +14,12 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -from boto.gs.bucket import Bucket +from boto.gs.bucket import Bucket from boto.s3.connection import S3Connection from boto.s3.connection import SubdomainCallingFormat from boto.s3.connection import check_lowercase_bucketname @@ -40,7 +40,7 @@ class GSConnection(S3Connection): host=DefaultHost, debug=0, https_connection_factory=None, calling_format=SubdomainCallingFormat(), path='/', suppress_consec_slashes=True): - S3Connection.__init__(self, gs_access_key_id, gs_secret_access_key, + super(GSConnection, self).__init__(gs_access_key_id, gs_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, host, debug, https_connection_factory, calling_format, path, "google", Bucket, @@ -52,12 +52,12 @@ class GSConnection(S3Connection): """ Creates a new bucket. By default it's located in the USA. You can pass Location.EU to create bucket in the EU. You can also pass - a LocationConstraint for where the bucket should be located, and + a LocationConstraint for where the bucket should be located, and a StorageClass describing how the data should be stored. :type bucket_name: string :param bucket_name: The name of the new bucket. - + :type headers: dict :param headers: Additional headers to pass along with the request to GCS. @@ -70,7 +70,7 @@ class GSConnection(S3Connection): :type storage_class: string :param storage_class: Either 'STANDARD' or 'DURABLE_REDUCED_AVAILABILITY'. - + """ check_lowercase_bucketname(bucket_name) diff --git a/awx/lib/site-packages/boto/iam/__init__.py b/awx/lib/site-packages/boto/iam/__init__.py index f0444ac1e4..fac7b5db31 100644 --- a/awx/lib/site-packages/boto/iam/__init__.py +++ b/awx/lib/site-packages/boto/iam/__init__.py @@ -55,6 +55,9 @@ def regions(): connection_cls=IAMConnection), IAMRegionInfo(name='us-gov-west-1', endpoint='iam.us-gov.amazonaws.com', + connection_cls=IAMConnection), + IAMRegionInfo(name='cn-north-1', + endpoint='iam.cn-north-1.amazonaws.com.cn', connection_cls=IAMConnection) ] diff --git a/awx/lib/site-packages/boto/iam/connection.py b/awx/lib/site-packages/boto/iam/connection.py index 9cc15c6f5d..32b3ab2e3d 100644 --- a/awx/lib/site-packages/boto/iam/connection.py +++ b/awx/lib/site-packages/boto/iam/connection.py @@ -42,7 +42,7 @@ class IAMConnection(AWSQueryConnection): proxy_user=None, proxy_pass=None, host='iam.amazonaws.com', debug=0, https_connection_factory=None, path='/', security_token=None, validate_certs=True): - AWSQueryConnection.__init__(self, aws_access_key_id, + super(IAMConnection, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, @@ -51,7 +51,6 @@ class IAMConnection(AWSQueryConnection): validate_certs=validate_certs) def _required_auth_capability(self): - #return ['iam'] return ['hmac-v4'] def get_response(self, action, params, path='/', parent=None, @@ -65,11 +64,16 @@ class IAMConnection(AWSQueryConnection): body = response.read() boto.log.debug(body) if response.status == 200: - e = boto.jsonresponse.Element(list_marker=list_marker, - pythonize_name=True) - h = boto.jsonresponse.XmlHandler(e, parent) - h.parse(body) - return e + if body: + e = boto.jsonresponse.Element(list_marker=list_marker, + pythonize_name=True) + h = boto.jsonresponse.XmlHandler(e, parent) + h.parse(body) + return e + else: + # Support empty responses, e.g. deleting a SAML provider + # according to the official documentation. + return {} else: boto.log.error('%s %s' % (response.status, response.reason)) boto.log.error('%s' % body) @@ -1318,3 +1322,113 @@ class IAMConnection(AWSQueryConnection): return self.get_response('UpdateAssumeRolePolicy', {'RoleName': role_name, 'PolicyDocument': policy_document}) + + def create_saml_provider(self, saml_metadata_document, name): + """ + Creates an IAM entity to describe an identity provider (IdP) + that supports SAML 2.0. + + The SAML provider that you create with this operation can be + used as a principal in a role's trust policy to establish a + trust relationship between AWS and a SAML identity provider. + You can create an IAM role that supports Web-based single + sign-on (SSO) to the AWS Management Console or one that + supports API access to AWS. + + When you create the SAML provider, you upload an a SAML + metadata document that you get from your IdP and that includes + the issuer's name, expiration information, and keys that can + be used to validate the SAML authentication response + (assertions) that are received from the IdP. You must generate + the metadata document using the identity management software + that is used as your organization's IdP. + This operation requires `Signature Version 4`_. + For more information, see `Giving Console Access Using SAML`_ + and `Creating Temporary Security Credentials for SAML + Federation`_ in the Using Temporary Credentials guide. + + :type saml_metadata_document: string + :param saml_metadata_document: An XML document generated by an identity + provider (IdP) that supports SAML 2.0. The document includes the + issuer's name, expiration information, and keys that can be used to + validate the SAML authentication response (assertions) that are + received from the IdP. You must generate the metadata document + using the identity management software that is used as your + organization's IdP. + For more information, see `Creating Temporary Security Credentials for + SAML Federation`_ in the Using Temporary Security Credentials + guide. + + :type name: string + :param name: The name of the provider to create. + + """ + params = { + 'SAMLMetadataDocument': saml_metadata_document, + 'Name': name, + } + return self.get_response('CreateSAMLProvider', params) + + def list_saml_providers(self): + """ + Lists the SAML providers in the account. + This operation requires `Signature Version 4`_. + """ + return self.get_response('ListSAMLProviders', {}) + + def get_saml_provider(self, saml_provider_arn): + """ + Returns the SAML provider metadocument that was uploaded when + the provider was created or updated. + This operation requires `Signature Version 4`_. + + :type saml_provider_arn: string + :param saml_provider_arn: The Amazon Resource Name (ARN) of the SAML + provider to get information about. + + """ + params = {'SAMLProviderArn': saml_provider_arn } + return self.get_response('GetSAMLProvider', params) + + def update_saml_provider(self, saml_provider_arn, saml_metadata_document): + """ + Updates the metadata document for an existing SAML provider. + This operation requires `Signature Version 4`_. + + :type saml_provider_arn: string + :param saml_provider_arn: The Amazon Resource Name (ARN) of the SAML + provider to update. + + :type saml_metadata_document: string + :param saml_metadata_document: An XML document generated by an identity + provider (IdP) that supports SAML 2.0. The document includes the + issuer's name, expiration information, and keys that can be used to + validate the SAML authentication response (assertions) that are + received from the IdP. You must generate the metadata document + using the identity management software that is used as your + organization's IdP. + + """ + params = { + 'SAMLMetadataDocument': saml_metadata_document, + 'SAMLProviderArn': saml_provider_arn, + } + return self.get_response('UpdateSAMLProvider', params) + + def delete_saml_provider(self, saml_provider_arn): + """ + Deletes a SAML provider. + + Deleting the provider does not update any roles that reference + the SAML provider as a principal in their trust policies. Any + attempt to assume a role that references a SAML provider that + has been deleted will fail. + This operation requires `Signature Version 4`_. + + :type saml_provider_arn: string + :param saml_provider_arn: The Amazon Resource Name (ARN) of the SAML + provider to delete. + + """ + params = {'SAMLProviderArn': saml_provider_arn } + return self.get_response('DeleteSAMLProvider', params) diff --git a/awx/lib/site-packages/boto/kinesis/__init__.py b/awx/lib/site-packages/boto/kinesis/__init__.py new file mode 100644 index 0000000000..1c19a3b25e --- /dev/null +++ b/awx/lib/site-packages/boto/kinesis/__init__.py @@ -0,0 +1,45 @@ +# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. +# All Rights Reserved +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, dis- +# tribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the fol- +# lowing conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +from boto.regioninfo import RegionInfo + + +def regions(): + """ + Get all available regions for the Amazon Kinesis service. + + :rtype: list + :return: A list of :class:`boto.regioninfo.RegionInfo` + """ + from boto.kinesis.layer1 import KinesisConnection + + return [RegionInfo(name='us-east-1', + endpoint='kinesis.us-east-1.amazonaws.com', + connection_cls=KinesisConnection), + ] + + +def connect_to_region(region_name, **kw_params): + for region in regions(): + if region.name == region_name: + return region.connect(**kw_params) + return None diff --git a/awx/lib/site-packages/boto/kinesis/exceptions.py b/awx/lib/site-packages/boto/kinesis/exceptions.py new file mode 100644 index 0000000000..708f46369a --- /dev/null +++ b/awx/lib/site-packages/boto/kinesis/exceptions.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2012 Thomas Parslow http://almostobsolete.net/ +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, dis- +# tribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the fol- +# lowing conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +from boto.exception import BotoServerError + + +class ProvisionedThroughputExceededException(BotoServerError): + pass + + +class LimitExceededException(BotoServerError): + pass + + +class ExpiredIteratorException(BotoServerError): + pass + + +class ResourceInUseException(BotoServerError): + pass + + +class ResourceNotFoundException(BotoServerError): + pass + + +class InvalidArgumentException(BotoServerError): + pass + + +class SubscriptionRequiredException(BotoServerError): + pass diff --git a/awx/lib/site-packages/boto/kinesis/layer1.py b/awx/lib/site-packages/boto/kinesis/layer1.py new file mode 100644 index 0000000000..f282d89886 --- /dev/null +++ b/awx/lib/site-packages/boto/kinesis/layer1.py @@ -0,0 +1,707 @@ +# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, dis- +# tribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the fol- +# lowing conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# + +try: + import json +except ImportError: + import simplejson as json + +import base64 +import boto + +from boto.connection import AWSQueryConnection +from boto.regioninfo import RegionInfo +from boto.exception import JSONResponseError +from boto.kinesis import exceptions + + +class KinesisConnection(AWSQueryConnection): + """ + Amazon Kinesis Service API Reference + Amazon Kinesis is a managed service that scales elastically for + real time processing of streaming big data. + """ + APIVersion = "2013-12-02" + DefaultRegionName = "us-east-1" + DefaultRegionEndpoint = "kinesis.us-east-1.amazonaws.com" + ServiceName = "Kinesis" + TargetPrefix = "Kinesis_20131202" + ResponseError = JSONResponseError + + _faults = { + "ProvisionedThroughputExceededException": exceptions.ProvisionedThroughputExceededException, + "LimitExceededException": exceptions.LimitExceededException, + "ExpiredIteratorException": exceptions.ExpiredIteratorException, + "ResourceInUseException": exceptions.ResourceInUseException, + "ResourceNotFoundException": exceptions.ResourceNotFoundException, + "InvalidArgumentException": exceptions.InvalidArgumentException, + "SubscriptionRequiredException": exceptions.SubscriptionRequiredException + } + + + def __init__(self, **kwargs): + region = kwargs.pop('region', None) + if not region: + region = RegionInfo(self, self.DefaultRegionName, + self.DefaultRegionEndpoint) + if 'host' not in kwargs: + kwargs['host'] = region.endpoint + super(KinesisConnection, self).__init__(**kwargs) + self.region = region + + def _required_auth_capability(self): + return ['hmac-v4'] + + def create_stream(self, stream_name, shard_count): + """ + This operation adds a new Amazon Kinesis stream to your AWS + account. A stream captures and transports data records that + are continuously emitted from different data sources or + producers . Scale-out within an Amazon Kinesis stream is + explicitly supported by means of shards, which are uniquely + identified groups of data records in an Amazon Kinesis stream. + + You specify and control the number of shards that a stream is + composed of. Each shard can support up to 5 read transactions + per second up to a maximum total of 2 MB of data read per + second. Each shard can support up to 1000 write transactions + per second up to a maximum total of 1 MB data written per + second. You can add shards to a stream if the amount of data + input increases and you can remove shards if the amount of + data input decreases. + + The stream name identifies the stream. The name is scoped to + the AWS account used by the application. It is also scoped by + region. That is, two streams in two different accounts can + have the same name, and two streams in the same account, but + in two different regions, can have the same name. + + `CreateStream` is an asynchronous operation. Upon receiving a + `CreateStream` request, Amazon Kinesis immediately returns and + sets the stream status to CREATING. After the stream is + created, Amazon Kinesis sets the stream status to ACTIVE. You + should perform read and write operations only on an ACTIVE + stream. + + You receive a `LimitExceededException` when making a + `CreateStream` request if you try to do one of the following: + + + + Have more than five streams in the CREATING state at any + point in time. + + Create more shards than are authorized for your account. + + + **Note:** The default limit for an AWS account is two shards + per stream. If you need to create a stream with more than two + shards, contact AWS Support to increase the limit on your + account. + + You can use the `DescribeStream` operation to check the stream + status, which is returned in `StreamStatus`. + + `CreateStream` has a limit of 5 transactions per second per + account. + + :type stream_name: string + :param stream_name: A name to identify the stream. The stream name is + scoped to the AWS account used by the application that creates the + stream. It is also scoped by region. That is, two streams in two + different AWS accounts can have the same name, and two streams in + the same AWS account, but in two different regions, can have the + same name. + + :type shard_count: integer + :param shard_count: The number of shards that the stream will use. The + throughput of the stream is a function of the number of shards; + more shards are required for greater provisioned throughput. + **Note:** The default limit for an AWS account is two shards per + stream. If you need to create a stream with more than two shards, + contact AWS Support to increase the limit on your account. + + """ + params = { + 'StreamName': stream_name, + 'ShardCount': shard_count, + } + return self.make_request(action='CreateStream', + body=json.dumps(params)) + + def delete_stream(self, stream_name): + """ + This operation deletes a stream and all of its shards and + data. You must shut down any applications that are operating + on the stream before you delete the stream. If an application + attempts to operate on a deleted stream, it will receive the + exception `ResourceNotFoundException`. + + If the stream is in the ACTIVE state, you can delete it. After + a `DeleteStream` request, the specified stream is in the + DELETING state until Amazon Kinesis completes the deletion. + + **Note:** Amazon Kinesis might continue to accept data read + and write operations, such as PutRecord and GetRecords, on a + stream in the DELETING state until the stream deletion is + complete. + + When you delete a stream, any shards in that stream are also + deleted. + + You can use the DescribeStream operation to check the state of + the stream, which is returned in `StreamStatus`. + + `DeleteStream` has a limit of 5 transactions per second per + account. + + :type stream_name: string + :param stream_name: The name of the stream to delete. + + """ + params = {'StreamName': stream_name, } + return self.make_request(action='DeleteStream', + body=json.dumps(params)) + + def describe_stream(self, stream_name, limit=None, + exclusive_start_shard_id=None): + """ + This operation returns the following information about the + stream: the current status of the stream, the stream Amazon + Resource Name (ARN), and an array of shard objects that + comprise the stream. For each shard object there is + information about the hash key and sequence number ranges that + the shard spans, and the IDs of any earlier shards that played + in a role in a MergeShards or SplitShard operation that + created the shard. A sequence number is the identifier + associated with every record ingested in the Amazon Kinesis + stream. The sequence number is assigned by the Amazon Kinesis + service when a record is put into the stream. + + You can limit the number of returned shards using the `Limit` + parameter. The number of shards in a stream may be too large + to return from a single call to `DescribeStream`. You can + detect this by using the `HasMoreShards` flag in the returned + output. `HasMoreShards` is set to `True` when there is more + data available. + + If there are more shards available, you can request more + shards by using the shard ID of the last shard returned by the + `DescribeStream` request, in the `ExclusiveStartShardId` + parameter in a subsequent request to `DescribeStream`. + `DescribeStream` is a paginated operation. + + `DescribeStream` has a limit of 10 transactions per second per + account. + + :type stream_name: string + :param stream_name: The name of the stream to describe. + + :type limit: integer + :param limit: The maximum number of shards to return. + + :type exclusive_start_shard_id: string + :param exclusive_start_shard_id: The shard ID of the shard to start + with for the stream description. + + """ + params = {'StreamName': stream_name, } + if limit is not None: + params['Limit'] = limit + if exclusive_start_shard_id is not None: + params['ExclusiveStartShardId'] = exclusive_start_shard_id + return self.make_request(action='DescribeStream', + body=json.dumps(params)) + + def get_records(self, shard_iterator, limit=None, b64_decode=True): + """ + This operation returns one or more data records from a shard. + A `GetRecords` operation request can retrieve up to 10 MB of + data. + + You specify a shard iterator for the shard that you want to + read data from in the `ShardIterator` parameter. The shard + iterator specifies the position in the shard from which you + want to start reading data records sequentially. A shard + iterator specifies this position using the sequence number of + a data record in the shard. For more information about the + shard iterator, see GetShardIterator. + + `GetRecords` may return a partial result if the response size + limit is exceeded. You will get an error, but not a partial + result if the shard's provisioned throughput is exceeded, the + shard iterator has expired, or an internal processing failure + has occurred. Clients can request a smaller amount of data by + specifying a maximum number of returned records using the + `Limit` parameter. The `Limit` parameter can be set to an + integer value of up to 10,000. If you set the value to an + integer greater than 10,000, you will receive + `InvalidArgumentException`. + + A new shard iterator is returned by every `GetRecords` request + in `NextShardIterator`, which you use in the `ShardIterator` + parameter of the next `GetRecords` request. When you + repeatedly read from an Amazon Kinesis stream use a + GetShardIterator request to get the first shard iterator to + use in your first `GetRecords` request and then use the shard + iterator returned in `NextShardIterator` for subsequent reads. + + `GetRecords` can return `null` for the `NextShardIterator` to + reflect that the shard has been closed and that the requested + shard iterator would never have returned more data. + + If no items can be processed because of insufficient + provisioned throughput on the shard involved in the request, + `GetRecords` throws `ProvisionedThroughputExceededException`. + + :type shard_iterator: string + :param shard_iterator: The position in the shard from which you want to + start sequentially reading data records. + + :type limit: integer + :param limit: The maximum number of records to return, which can be set + to a value of up to 10,000. + + :type b64_decode: boolean + :param b64_decode: Decode the Base64-encoded ``Data`` field of records. + + """ + params = {'ShardIterator': shard_iterator, } + if limit is not None: + params['Limit'] = limit + + response = self.make_request(action='GetRecords', + body=json.dumps(params)) + + # Base64 decode the data + if b64_decode: + for record in response.get('Records', []): + record['Data'] = base64.b64decode(record['Data']) + + return response + + def get_shard_iterator(self, stream_name, shard_id, shard_iterator_type, + starting_sequence_number=None): + """ + This operation returns a shard iterator in `ShardIterator`. + The shard iterator specifies the position in the shard from + which you want to start reading data records sequentially. A + shard iterator specifies this position using the sequence + number of a data record in a shard. A sequence number is the + identifier associated with every record ingested in the Amazon + Kinesis stream. The sequence number is assigned by the Amazon + Kinesis service when a record is put into the stream. + + You must specify the shard iterator type in the + `GetShardIterator` request. For example, you can set the + `ShardIteratorType` parameter to read exactly from the + position denoted by a specific sequence number by using the + AT_SEQUENCE_NUMBER shard iterator type, or right after the + sequence number by using the AFTER_SEQUENCE_NUMBER shard + iterator type, using sequence numbers returned by earlier + PutRecord, GetRecords or DescribeStream requests. You can + specify the shard iterator type TRIM_HORIZON in the request to + cause `ShardIterator` to point to the last untrimmed record in + the shard in the system, which is the oldest data record in + the shard. Or you can point to just after the most recent + record in the shard, by using the shard iterator type LATEST, + so that you always read the most recent data in the shard. + + **Note:** Each shard iterator expires five minutes after it is + returned to the requester. + + When you repeatedly read from an Amazon Kinesis stream use a + GetShardIterator request to get the first shard iterator to to + use in your first `GetRecords` request and then use the shard + iterator returned by the `GetRecords` request in + `NextShardIterator` for subsequent reads. A new shard iterator + is returned by every `GetRecords` request in + `NextShardIterator`, which you use in the `ShardIterator` + parameter of the next `GetRecords` request. + + If a `GetShardIterator` request is made too often, you will + receive a `ProvisionedThroughputExceededException`. For more + information about throughput limits, see the `Amazon Kinesis + Developer Guide`_. + + `GetShardIterator` can return `null` for its `ShardIterator` + to indicate that the shard has been closed and that the + requested iterator will return no more data. A shard can be + closed by a SplitShard or MergeShards operation. + + `GetShardIterator` has a limit of 5 transactions per second + per account per shard. + + :type stream_name: string + :param stream_name: The name of the stream. + + :type shard_id: string + :param shard_id: The shard ID of the shard to get the iterator for. + + :type shard_iterator_type: string + :param shard_iterator_type: + Determines how the shard iterator is used to start reading data records + from the shard. + + The following are the valid shard iterator types: + + + + AT_SEQUENCE_NUMBER - Start reading exactly from the position denoted + by a specific sequence number. + + AFTER_SEQUENCE_NUMBER - Start reading right after the position + denoted by a specific sequence number. + + TRIM_HORIZON - Start reading at the last untrimmed record in the + shard in the system, which is the oldest data record in the shard. + + LATEST - Start reading just after the most recent record in the + shard, so that you always read the most recent data in the shard. + + :type starting_sequence_number: string + :param starting_sequence_number: The sequence number of the data record + in the shard from which to start reading from. + + """ + params = { + 'StreamName': stream_name, + 'ShardId': shard_id, + 'ShardIteratorType': shard_iterator_type, + } + if starting_sequence_number is not None: + params['StartingSequenceNumber'] = starting_sequence_number + return self.make_request(action='GetShardIterator', + body=json.dumps(params)) + + def list_streams(self, limit=None, exclusive_start_stream_name=None): + """ + This operation returns an array of the names of all the + streams that are associated with the AWS account making the + `ListStreams` request. A given AWS account can have many + streams active at one time. + + The number of streams may be too large to return from a single + call to `ListStreams`. You can limit the number of returned + streams using the `Limit` parameter. If you do not specify a + value for the `Limit` parameter, Amazon Kinesis uses the + default limit, which is currently 10. + + You can detect if there are more streams available to list by + using the `HasMoreStreams` flag from the returned output. If + there are more streams available, you can request more streams + by using the name of the last stream returned by the + `ListStreams` request in the `ExclusiveStartStreamName` + parameter in a subsequent request to `ListStreams`. The group + of stream names returned by the subsequent request is then + added to the list. You can continue this process until all the + stream names have been collected in the list. + + `ListStreams` has a limit of 5 transactions per second per + account. + + :type limit: integer + :param limit: The maximum number of streams to list. + + :type exclusive_start_stream_name: string + :param exclusive_start_stream_name: The name of the stream to start the + list with. + + """ + params = {} + if limit is not None: + params['Limit'] = limit + if exclusive_start_stream_name is not None: + params['ExclusiveStartStreamName'] = exclusive_start_stream_name + return self.make_request(action='ListStreams', + body=json.dumps(params)) + + def merge_shards(self, stream_name, shard_to_merge, + adjacent_shard_to_merge): + """ + This operation merges two adjacent shards in a stream and + combines them into a single shard to reduce the stream's + capacity to ingest and transport data. Two shards are + considered adjacent if the union of the hash key ranges for + the two shards form a contiguous set with no gaps. For + example, if you have two shards, one with a hash key range of + 276...381 and the other with a hash key range of 382...454, + then you could merge these two shards into a single shard that + would have a hash key range of 276...454. After the merge, the + single child shard receives data for all hash key values + covered by the two parent shards. + + `MergeShards` is called when there is a need to reduce the + overall capacity of a stream because of excess capacity that + is not being used. The operation requires that you specify the + shard to be merged and the adjacent shard for a given stream. + For more information about merging shards, see the `Amazon + Kinesis Developer Guide`_. + + If the stream is in the ACTIVE state, you can call + `MergeShards`. If a stream is in CREATING or UPDATING or + DELETING states, then Amazon Kinesis returns a + `ResourceInUseException`. If the specified stream does not + exist, Amazon Kinesis returns a `ResourceNotFoundException`. + + You can use the DescribeStream operation to check the state of + the stream, which is returned in `StreamStatus`. + + `MergeShards` is an asynchronous operation. Upon receiving a + `MergeShards` request, Amazon Kinesis immediately returns a + response and sets the `StreamStatus` to UPDATING. After the + operation is completed, Amazon Kinesis sets the `StreamStatus` + to ACTIVE. Read and write operations continue to work while + the stream is in the UPDATING state. + + You use the DescribeStream operation to determine the shard + IDs that are specified in the `MergeShards` request. + + If you try to operate on too many streams in parallel using + CreateStream, DeleteStream, `MergeShards` or SplitShard, you + will receive a `LimitExceededException`. + + `MergeShards` has limit of 5 transactions per second per + account. + + :type stream_name: string + :param stream_name: The name of the stream for the merge. + + :type shard_to_merge: string + :param shard_to_merge: The shard ID of the shard to combine with the + adjacent shard for the merge. + + :type adjacent_shard_to_merge: string + :param adjacent_shard_to_merge: The shard ID of the adjacent shard for + the merge. + + """ + params = { + 'StreamName': stream_name, + 'ShardToMerge': shard_to_merge, + 'AdjacentShardToMerge': adjacent_shard_to_merge, + } + return self.make_request(action='MergeShards', + body=json.dumps(params)) + + def put_record(self, stream_name, data, partition_key, + explicit_hash_key=None, + sequence_number_for_ordering=None, + exclusive_minimum_sequence_number=None, + b64_encode=True): + """ + This operation puts a data record into an Amazon Kinesis + stream from a producer. This operation must be called to send + data from the producer into the Amazon Kinesis stream for + real-time ingestion and subsequent processing. The `PutRecord` + operation requires the name of the stream that captures, + stores, and transports the data; a partition key; and the data + blob itself. The data blob could be a segment from a log file, + geographic/location data, website clickstream data, or any + other data type. + + The partition key is used to distribute data across shards. + Amazon Kinesis segregates the data records that belong to a + data stream into multiple shards, using the partition key + associated with each data record to determine which shard a + given data record belongs to. + + Partition keys are Unicode strings, with a maximum length + limit of 256 bytes. An MD5 hash function is used to map + partition keys to 128-bit integer values and to map associated + data records to shards using the hash key ranges of the + shards. You can override hashing the partition key to + determine the shard by explicitly specifying a hash value + using the `ExplicitHashKey` parameter. For more information, + see the `Amazon Kinesis Developer Guide`_. + + `PutRecord` returns the shard ID of where the data record was + placed and the sequence number that was assigned to the data + record. + + The `SequenceNumberForOrdering` sets the initial sequence + number for the partition key. Later `PutRecord` requests to + the same partition key (from the same client) will + automatically increase from `SequenceNumberForOrdering`, + ensuring strict sequential ordering. + + If a `PutRecord` request cannot be processed because of + insufficient provisioned throughput on the shard involved in + the request, `PutRecord` throws + `ProvisionedThroughputExceededException`. + + Data records are accessible for only 24 hours from the time + that they are added to an Amazon Kinesis stream. + + :type stream_name: string + :param stream_name: The name of the stream to put the data record into. + + :type data: blob + :param data: The data blob to put into the record, which will be Base64 + encoded. The maximum size of the data blob is 50 kilobytes (KB). + Set `b64_encode` to disable automatic Base64 encoding. + + :type partition_key: string + :param partition_key: Determines which shard in the stream the data + record is assigned to. Partition keys are Unicode strings with a + maximum length limit of 256 bytes. Amazon Kinesis uses the + partition key as input to a hash function that maps the partition + key and associated data to a specific shard. Specifically, an MD5 + hash function is used to map partition keys to 128-bit integer + values and to map associated data records to shards. As a result of + this hashing mechanism, all data records with the same partition + key will map to the same shard within the stream. + + :type explicit_hash_key: string + :param explicit_hash_key: The hash value used to explicitly determine + the shard the data record is assigned to by overriding the + partition key hash. + + :type sequence_number_for_ordering: string + :param sequence_number_for_ordering: The sequence number to use as the + initial number for the partition key. Subsequent calls to + `PutRecord` from the same client and for the same partition key + will increase from the `SequenceNumberForOrdering` value. + + :type b64_encode: boolean + :param b64_encode: Whether to Base64 encode `data`. Can be set to + ``False`` if `data` is already encoded to prevent double encoding. + + """ + params = { + 'StreamName': stream_name, + 'Data': data, + 'PartitionKey': partition_key, + } + if explicit_hash_key is not None: + params['ExplicitHashKey'] = explicit_hash_key + if sequence_number_for_ordering is not None: + params['SequenceNumberForOrdering'] = sequence_number_for_ordering + if b64_encode: + params['Data'] = base64.b64encode(params['Data']) + return self.make_request(action='PutRecord', + body=json.dumps(params)) + + def split_shard(self, stream_name, shard_to_split, new_starting_hash_key): + """ + This operation splits a shard into two new shards in the + stream, to increase the stream's capacity to ingest and + transport data. `SplitShard` is called when there is a need to + increase the overall capacity of stream because of an expected + increase in the volume of data records being ingested. + + `SplitShard` can also be used when a given shard appears to be + approaching its maximum utilization, for example, when the set + of producers sending data into the specific shard are suddenly + sending more than previously anticipated. You can also call + the `SplitShard` operation to increase stream capacity, so + that more Amazon Kinesis applications can simultaneously read + data from the stream for real-time processing. + + The `SplitShard` operation requires that you specify the shard + to be split and the new hash key, which is the position in the + shard where the shard gets split in two. In many cases, the + new hash key might simply be the average of the beginning and + ending hash key, but it can be any hash key value in the range + being mapped into the shard. For more information about + splitting shards, see the `Amazon Kinesis Developer Guide`_. + + You can use the DescribeStream operation to determine the + shard ID and hash key values for the `ShardToSplit` and + `NewStartingHashKey` parameters that are specified in the + `SplitShard` request. + + `SplitShard` is an asynchronous operation. Upon receiving a + `SplitShard` request, Amazon Kinesis immediately returns a + response and sets the stream status to UPDATING. After the + operation is completed, Amazon Kinesis sets the stream status + to ACTIVE. Read and write operations continue to work while + the stream is in the UPDATING state. + + You can use `DescribeStream` to check the status of the + stream, which is returned in `StreamStatus`. If the stream is + in the ACTIVE state, you can call `SplitShard`. If a stream is + in CREATING or UPDATING or DELETING states, then Amazon + Kinesis returns a `ResourceInUseException`. + + If the specified stream does not exist, Amazon Kinesis returns + a `ResourceNotFoundException`. If you try to create more + shards than are authorized for your account, you receive a + `LimitExceededException`. + + **Note:** The default limit for an AWS account is two shards + per stream. If you need to create a stream with more than two + shards, contact AWS Support to increase the limit on your + account. + + If you try to operate on too many streams in parallel using + CreateStream, DeleteStream, MergeShards or SplitShard, you + will receive a `LimitExceededException`. + + `SplitShard` has limit of 5 transactions per second per + account. + + :type stream_name: string + :param stream_name: The name of the stream for the shard split. + + :type shard_to_split: string + :param shard_to_split: The shard ID of the shard to split. + + :type new_starting_hash_key: string + :param new_starting_hash_key: A hash key value for the starting hash + key of one of the child shards created by the split. The hash key + range for a given shard constitutes a set of ordered contiguous + positive integers. The value for `NewStartingHashKey` must be in + the range of hash keys being mapped into the shard. The + `NewStartingHashKey` hash key value and all higher hash key values + in hash key range are distributed to one of the child shards. All + the lower hash key values in the range are distributed to the other + child shard. + + """ + params = { + 'StreamName': stream_name, + 'ShardToSplit': shard_to_split, + 'NewStartingHashKey': new_starting_hash_key, + } + return self.make_request(action='SplitShard', + body=json.dumps(params)) + + def make_request(self, action, body): + headers = { + 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), + 'Host': self.region.endpoint, + 'Content-Type': 'application/x-amz-json-1.1', + 'Content-Length': str(len(body)), + } + http_request = self.build_base_http_request( + method='POST', path='/', auth_path='/', params={}, + headers=headers, data=body) + response = self._mexe(http_request, sender=None, + override_num_retries=10) + response_body = response.read() + boto.log.debug(response.getheaders()) + boto.log.debug(response_body) + if response.status == 200: + if response_body: + return json.loads(response_body) + else: + json_body = json.loads(response_body) + fault_name = json_body.get('__type', None) + exception_class = self._faults.get(fault_name, self.ResponseError) + raise exception_class(response.status, response.reason, + body=json_body) + diff --git a/awx/lib/site-packages/boto/manage/server.py b/awx/lib/site-packages/boto/manage/server.py index 3acc4b2fd6..49ed55bbf5 100644 --- a/awx/lib/site-packages/boto/manage/server.py +++ b/awx/lib/site-packages/boto/manage/server.py @@ -15,7 +15,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -134,7 +134,7 @@ class CommandLineGetter(object): if ami.location.find('pyami') >= 0: my_amis.append((ami.location, ami)) return my_amis - + def get_region(self, params): region = params.get('region', None) if isinstance(region, str) or isinstance(region, unicode): @@ -171,7 +171,7 @@ class CommandLineGetter(object): prop = StringProperty(name='zone', verbose_name='EC2 Availability Zone', choices=self.ec2.get_all_zones) params['zone'] = propget.get(prop) - + def get_ami_id(self, params): valid = False while not valid: @@ -271,20 +271,20 @@ class Server(Model): """ Create a new instance based on the specified configuration file or the specified configuration and the passed in parameters. - - If the config_file argument is not None, the configuration is read from there. + + If the config_file argument is not None, the configuration is read from there. Otherwise, the cfg argument is used. - + The config file may include other config files with a #import reference. The included - config files must reside in the same directory as the specified file. - - The logical_volume argument, if supplied, will be used to get the current physical - volume ID and use that as an override of the value specified in the config file. This - may be useful for debugging purposes when you want to debug with a production config - file but a test Volume. - - The dictionary argument may be used to override any EC2 configuration values in the - config file. + config files must reside in the same directory as the specified file. + + The logical_volume argument, if supplied, will be used to get the current physical + volume ID and use that as an override of the value specified in the config file. This + may be useful for debugging purposes when you want to debug with a production config + file but a test Volume. + + The dictionary argument may be used to override any EC2 configuration values in the + config file. """ if config_file: cfg = Config(path=config_file) @@ -304,7 +304,7 @@ class Server(Model): zone = params.get('zone') # deal with possibly passed in logical volume: if logical_volume != None: - cfg.set('EBS', 'logical_volume_name', logical_volume.name) + cfg.set('EBS', 'logical_volume_name', logical_volume.name) cfg_fp = StringIO.StringIO() cfg.write(cfg_fp) # deal with the possibility that zone and/or keypair are strings read from the config file: @@ -328,7 +328,7 @@ class Server(Model): print 'Waiting for instance to start so we can set its elastic IP address...' # Sometimes we get a message from ec2 that says that the instance does not exist. # Hopefully the following delay will giv eec2 enough time to get to a stable state: - time.sleep(5) + time.sleep(5) while instance.update() != 'running': time.sleep(1) instance.use_ip(elastic_ip) @@ -346,7 +346,7 @@ class Server(Model): l.append(s) i += 1 return l - + @classmethod def create_from_instance_id(cls, instance_id, name, description=''): regions = boto.ec2.regions() @@ -393,9 +393,9 @@ class Server(Model): s.put() servers.append(s) return servers - + def __init__(self, id=None, **kw): - Model.__init__(self, id, **kw) + super(Server, self).__init__(id, **kw) self.ssh_key_file = None self.ec2 = None self._cmdshell = None @@ -421,7 +421,7 @@ class Server(Model): self._instance = instance except EC2ResponseError: pass - + def _status(self): status = '' if self._instance: @@ -484,14 +484,14 @@ class Server(Model): return kn def put(self): - Model.put(self) + super(Server, self).put() self._setup_ec2() def delete(self): if self.production: raise ValueError("Can't delete a production server") #self.stop() - Model.delete(self) + super(Server, self).delete() def stop(self): if self.production: @@ -553,4 +553,4 @@ class Server(Model): return self.run('apt-get -y install %s' % pkg) - + diff --git a/awx/lib/site-packages/boto/manage/task.py b/awx/lib/site-packages/boto/manage/task.py index 1c37c69715..8271529a30 100644 --- a/awx/lib/site-packages/boto/manage/task.py +++ b/awx/lib/site-packages/boto/manage/task.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -30,7 +30,7 @@ def check_hour(val): return if int(val) < 0 or int(val) > 23: raise ValueError - + class Task(Model): """ @@ -40,10 +40,10 @@ class Task(Model): To keep the operation reasonably efficient and not cause excessive polling, the minimum granularity of a Task is hourly. Some examples: - + hour='*' - the task would be executed each hour hour='3' - the task would be executed at 3AM GMT each day. - + """ name = StringProperty() hour = StringProperty(required=True, validator=check_hour, default='*') @@ -57,13 +57,13 @@ class Task(Model): def start_all(cls, queue_name): for task in cls.all(): task.start(queue_name) - + def __init__(self, id=None, **kw): - Model.__init__(self, id, **kw) + super(Task, self).__init__(id, **kw) self.hourly = self.hour == '*' self.daily = self.hour != '*' self.now = datetime.datetime.utcnow() - + def check(self): """ Determine how long until the next scheduled time for a Task. @@ -76,7 +76,7 @@ class Task(Model): if self.hourly and not self.last_executed: return 0 - + if self.daily and not self.last_executed: if int(self.hour) == self.now.hour: return 0 @@ -97,7 +97,7 @@ class Task(Model): return 82800 # 23 hours, just to be safe else: return max( (int(self.hour)-self.now.hour), (self.now.hour-int(self.hour)) )*60*60 - + def _run(self, msg, vtimeout): boto.log.info('Task[%s] - running:%s' % (self.name, self.command)) log_fp = StringIO.StringIO() @@ -170,6 +170,6 @@ class TaskPoller(object): - - + + diff --git a/awx/lib/site-packages/boto/manage/volume.py b/awx/lib/site-packages/boto/manage/volume.py index 49237d47ee..841c124769 100644 --- a/awx/lib/site-packages/boto/manage/volume.py +++ b/awx/lib/site-packages/boto/manage/volume.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -33,7 +33,7 @@ import datetime class CommandLineGetter(object): - + def get_region(self, params): if not params.get('region', None): prop = self.cls.find_property('region_name') @@ -44,7 +44,7 @@ class CommandLineGetter(object): prop = StringProperty(name='zone', verbose_name='EC2 Availability Zone', choices=self.ec2.get_all_zones) params['zone'] = propget.get(prop) - + def get_name(self, params): if not params.get('name', None): prop = self.cls.find_property('name') @@ -151,7 +151,7 @@ class Volume(Model): v.zone_name = self.zone_name v.put() return v - + def get_ec2_connection(self): if self.server: return self.server.ec2 @@ -396,7 +396,7 @@ class Volume(Model): boto.log.info('Deleting %s(%s) for %s' % (snap, snap.date, self.name)) snap.delete() return snaps - + def grow(self, size): pass @@ -411,10 +411,10 @@ class Volume(Model): self.detach() ec2 = self.get_ec2_connection() ec2.delete_volume(self.volume_id) - Model.delete(self) + super(Volume, self).delete() def archive(self): # snapshot volume, trim snaps, delete volume-id pass - + diff --git a/awx/lib/site-packages/boto/mashups/server.py b/awx/lib/site-packages/boto/mashups/server.py index aa564471c0..cb6d78a718 100644 --- a/awx/lib/site-packages/boto/mashups/server.py +++ b/awx/lib/site-packages/boto/mashups/server.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -87,7 +87,7 @@ class Server(Model): return s def __init__(self, id=None, **kw): - Model.__init__(self, id, **kw) + super(Server, self).__init__(id, **kw) self._reservation = None self._instance = None self._ssh_client = None @@ -123,13 +123,13 @@ class Server(Model): return self._instance instance = property(getInstance, setReadOnly, None, 'The Instance for the server') - + def getAMI(self): if self.instance: return self.instance.image_id ami = property(getAMI, setReadOnly, None, 'The AMI for the server') - + def getStatus(self): if self.instance: self.instance.update() @@ -137,7 +137,7 @@ class Server(Model): status = property(getStatus, setReadOnly, None, 'The status of the server') - + def getHostname(self): if self.instance: return self.instance.public_dns_name diff --git a/awx/lib/site-packages/boto/mturk/connection.py b/awx/lib/site-packages/boto/mturk/connection.py index ad6678497c..ed7ba9d23a 100644 --- a/awx/lib/site-packages/boto/mturk/connection.py +++ b/awx/lib/site-packages/boto/mturk/connection.py @@ -54,7 +54,7 @@ class MTurkConnection(AWSQueryConnection): host = 'mechanicalturk.amazonaws.com' self.debug = debug - AWSQueryConnection.__init__(self, aws_access_key_id, + super(MTurkConnection, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, host, debug, @@ -875,7 +875,7 @@ class MTurkConnection(AWSQueryConnection): return duration -class BaseAutoResultElement: +class BaseAutoResultElement(object): """ Base class to automatically add attributes when parsing XML """ @@ -955,7 +955,7 @@ class QualificationRequest(BaseAutoResultElement): """ def __init__(self, connection): - BaseAutoResultElement.__init__(self, connection) + super(QualificationRequest, self).__init__(connection) self.answers = [] def endElement(self, name, value, connection): @@ -967,7 +967,7 @@ class QualificationRequest(BaseAutoResultElement): xml.sax.parseString(value, h) self.answers.append(answer_rs) else: - BaseAutoResultElement.endElement(self, name, value, connection) + super(QualificationRequest, self).endElement(name, value, connection) class Assignment(BaseAutoResultElement): @@ -980,7 +980,7 @@ class Assignment(BaseAutoResultElement): """ def __init__(self, connection): - BaseAutoResultElement.__init__(self, connection) + super(Assignment, self).__init__(connection) self.answers = [] def endElement(self, name, value, connection): @@ -992,7 +992,7 @@ class Assignment(BaseAutoResultElement): xml.sax.parseString(value, h) self.answers.append(answer_rs) else: - BaseAutoResultElement.endElement(self, name, value, connection) + super(Assignment, self).endElement(name, value, connection) class QuestionFormAnswer(BaseAutoResultElement): @@ -1016,7 +1016,7 @@ class QuestionFormAnswer(BaseAutoResultElement): """ def __init__(self, connection): - BaseAutoResultElement.__init__(self, connection) + super(QuestionFormAnswer, self).__init__(connection) self.fields = [] self.qid = None diff --git a/awx/lib/site-packages/boto/mturk/layoutparam.py b/awx/lib/site-packages/boto/mturk/layoutparam.py index 16e5932896..781f981daa 100644 --- a/awx/lib/site-packages/boto/mturk/layoutparam.py +++ b/awx/lib/site-packages/boto/mturk/layoutparam.py @@ -14,12 +14,12 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -class LayoutParameters: +class LayoutParameters(object): def __init__(self, layoutParameters=None): if layoutParameters == None: @@ -46,7 +46,7 @@ class LayoutParameter(object): def __init__(self, name, value): self.name = name self.value = value - + def get_as_params(self): params = { "Name": self.name, diff --git a/awx/lib/site-packages/boto/mturk/notification.py b/awx/lib/site-packages/boto/mturk/notification.py index 02c93aab14..118daaab95 100644 --- a/awx/lib/site-packages/boto/mturk/notification.py +++ b/awx/lib/site-packages/boto/mturk/notification.py @@ -32,7 +32,7 @@ except ImportError: import base64 import re -class NotificationMessage: +class NotificationMessage(object): NOTIFICATION_WSDL = "http://mechanicalturk.amazonaws.com/AWSMechanicalTurk/2006-05-05/AWSMechanicalTurkRequesterNotification.wsdl" NOTIFICATION_VERSION = '2006-05-05' @@ -88,7 +88,7 @@ class NotificationMessage: signature_calc = base64.b64encode(h.digest()) return self.signature == signature_calc -class Event: +class Event(object): def __init__(self, d): self.event_type = d['EventType'] self.event_time_str = d['EventTime'] diff --git a/awx/lib/site-packages/boto/mturk/price.py b/awx/lib/site-packages/boto/mturk/price.py index 3c88a96549..8e194e422e 100644 --- a/awx/lib/site-packages/boto/mturk/price.py +++ b/awx/lib/site-packages/boto/mturk/price.py @@ -14,12 +14,12 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -class Price: +class Price(object): def __init__(self, amount=0.0, currency_code='USD'): self.amount = amount diff --git a/awx/lib/site-packages/boto/mturk/qualification.py b/awx/lib/site-packages/boto/mturk/qualification.py index 8272d6d1b9..4b518c89e5 100644 --- a/awx/lib/site-packages/boto/mturk/qualification.py +++ b/awx/lib/site-packages/boto/mturk/qualification.py @@ -14,12 +14,12 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -class Qualifications: +class Qualifications(object): def __init__(self, requirements=None): if requirements == None: @@ -49,7 +49,7 @@ class Requirement(object): self.comparator = comparator self.integer_value = integer_value self.required_to_preview = required_to_preview - + def get_as_params(self): params = { "QualificationTypeId": self.qualification_type_id, @@ -67,7 +67,7 @@ class PercentAssignmentsSubmittedRequirement(Requirement): """ def __init__(self, comparator, integer_value, required_to_preview=False): - Requirement.__init__(self, qualification_type_id="00000000000000000000", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) + super(PercentAssignmentsSubmittedRequirement, self).__init__(qualification_type_id="00000000000000000000", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) class PercentAssignmentsAbandonedRequirement(Requirement): """ @@ -75,7 +75,7 @@ class PercentAssignmentsAbandonedRequirement(Requirement): """ def __init__(self, comparator, integer_value, required_to_preview=False): - Requirement.__init__(self, qualification_type_id="00000000000000000070", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) + super(PercentAssignmentsAbandonedRequirement, self).__init__(qualification_type_id="00000000000000000070", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) class PercentAssignmentsReturnedRequirement(Requirement): """ @@ -83,7 +83,7 @@ class PercentAssignmentsReturnedRequirement(Requirement): """ def __init__(self, comparator, integer_value, required_to_preview=False): - Requirement.__init__(self, qualification_type_id="000000000000000000E0", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) + super(PercentAssignmentsReturnedRequirement, self).__init__(qualification_type_id="000000000000000000E0", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) class PercentAssignmentsApprovedRequirement(Requirement): """ @@ -91,7 +91,7 @@ class PercentAssignmentsApprovedRequirement(Requirement): """ def __init__(self, comparator, integer_value, required_to_preview=False): - Requirement.__init__(self, qualification_type_id="000000000000000000L0", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) + super(PercentAssignmentsApprovedRequirement, self).__init__(qualification_type_id="000000000000000000L0", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) class PercentAssignmentsRejectedRequirement(Requirement): """ @@ -99,15 +99,15 @@ class PercentAssignmentsRejectedRequirement(Requirement): """ def __init__(self, comparator, integer_value, required_to_preview=False): - Requirement.__init__(self, qualification_type_id="000000000000000000S0", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) + super(PercentAssignmentsRejectedRequirement, self).__init__(qualification_type_id="000000000000000000S0", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) class NumberHitsApprovedRequirement(Requirement): """ Specifies the total number of HITs submitted by a Worker that have been approved. The value is an integer greater than or equal to 0. """ - + def __init__(self, comparator, integer_value, required_to_preview=False): - Requirement.__init__(self, qualification_type_id="00000000000000000040", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) + super(NumberHitsApprovedRequirement, self).__init__(qualification_type_id="00000000000000000040", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) class LocaleRequirement(Requirement): """ @@ -115,7 +115,7 @@ class LocaleRequirement(Requirement): """ def __init__(self, comparator, locale, required_to_preview=False): - Requirement.__init__(self, qualification_type_id="00000000000000000071", comparator=comparator, integer_value=None, required_to_preview=required_to_preview) + super(LocaleRequirement, self).__init__(qualification_type_id="00000000000000000071", comparator=comparator, integer_value=None, required_to_preview=required_to_preview) self.locale = locale def get_as_params(self): @@ -132,6 +132,6 @@ class AdultRequirement(Requirement): """ Requires workers to acknowledge that they are over 18 and that they agree to work on potentially offensive content. The value type is boolean, 1 (required), 0 (not required, the default). """ - + def __init__(self, comparator, integer_value, required_to_preview=False): - Requirement.__init__(self, qualification_type_id="00000000000000000060", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) + super(AdultRequirement, self).__init__(qualification_type_id="00000000000000000060", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) diff --git a/awx/lib/site-packages/boto/mturk/question.py b/awx/lib/site-packages/boto/mturk/question.py index 90ab00dbd6..293b0782ed 100644 --- a/awx/lib/site-packages/boto/mturk/question.py +++ b/awx/lib/site-packages/boto/mturk/question.py @@ -82,12 +82,12 @@ class ExternalQuestion(ValidatingXML): return self.template % vars(self) -class XMLTemplate: +class XMLTemplate(object): def get_as_xml(self): return self.template % vars(self) -class SimpleField(object, XMLTemplate): +class SimpleField(XMLTemplate): """ A Simple name/value pair that can be easily rendered as XML. @@ -101,7 +101,7 @@ class SimpleField(object, XMLTemplate): self.value = value -class Binary(object, XMLTemplate): +class Binary(XMLTemplate): template = """%(type)s%(subtype)s%(url)s%(alt_text)s""" def __init__(self, type, subtype, url, alt_text): @@ -179,7 +179,7 @@ class Flash(Application): super(Flash, self).get_inner_content(content) -class FormattedContent(object, XMLTemplate): +class FormattedContent(XMLTemplate): schema_url = 'http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2006-07-14/FormattedContentXHTMLSubset.xsd' template = '' diff --git a/awx/lib/site-packages/boto/mws/connection.py b/awx/lib/site-packages/boto/mws/connection.py index 1c718af0fb..d9a2003558 100644 --- a/awx/lib/site-packages/boto/mws/connection.py +++ b/awx/lib/site-packages/boto/mws/connection.py @@ -251,7 +251,7 @@ class MWSConnection(AWSQueryConnection): kw.setdefault('host', 'mws.amazonservices.com') self.Merchant = kw.pop('Merchant', None) or kw.get('SellerId') self.SellerId = kw.pop('SellerId', None) or self.Merchant - AWSQueryConnection.__init__(self, *args, **kw) + super(MWSConnection, self).__init__(*args, **kw) def _required_auth_capability(self): return ['mws'] diff --git a/awx/lib/site-packages/boto/mws/response.py b/awx/lib/site-packages/boto/mws/response.py index 5c8ffb7365..064f5d7f1f 100644 --- a/awx/lib/site-packages/boto/mws/response.py +++ b/awx/lib/site-packages/boto/mws/response.py @@ -82,7 +82,7 @@ class Element(DeclarativeType): class SimpleList(DeclarativeType): def __init__(self, *args, **kw): - DeclarativeType.__init__(self, *args, **kw) + super(SimpleList, self).__init__(*args, **kw) self._value = [] def start(self, *args, **kw): @@ -108,16 +108,16 @@ class MemberList(Element): assert 'member' not in kw, message if _member is None: if _hint is None: - Element.__init__(self, *args, member=ElementList(**kw)) + super(MemberList, self).__init__(*args, member=ElementList(**kw)) else: - Element.__init__(self, _hint=_hint) + super(MemberList, self).__init__(_hint=_hint) else: if _hint is None: if issubclass(_member, DeclarativeType): member = _member(**kw) else: member = ElementList(_member, **kw) - Element.__init__(self, *args, member=member) + super(MemberList, self).__init__(*args, member=member) else: message = 'Nonsensical {0} hint {1!r}'.format(self.__class__.__name__, _hint) @@ -130,7 +130,7 @@ class MemberList(Element): if isinstance(self._value.member, DeclarativeType): self._value.member = [] self._value = self._value.member - Element.teardown(self, *args, **kw) + super(MemberList, self).teardown(*args, **kw) def ResponseFactory(action, force=None): @@ -231,7 +231,7 @@ class Response(ResponseElement): if name == self._name: self.update(attrs) else: - return ResponseElement.startElement(self, name, attrs, connection) + return super(Response, self).startElement(name, attrs, connection) @property def _result(self): @@ -247,7 +247,7 @@ class ResponseResultList(Response): def __init__(self, *args, **kw): setattr(self, self._action + 'Result', ElementList(self._ResultClass)) - Response.__init__(self, *args, **kw) + super(ResponseResultList, self).__init__(*args, **kw) class FeedSubmissionInfo(ResponseElement): @@ -374,13 +374,13 @@ class ComplexAmount(ResponseElement): if name not in ('CurrencyCode', self._amount): message = 'Unrecognized tag {0} in ComplexAmount'.format(name) raise AssertionError(message) - return ResponseElement.startElement(self, name, attrs, connection) + return super(ComplexAmount, self).startElement(name, attrs, connection) @strip_namespace def endElement(self, name, value, connection): if name == self._amount: value = Decimal(value) - ResponseElement.endElement(self, name, value, connection) + super(ComplexAmount, self).endElement(name, value, connection) class ComplexMoney(ComplexAmount): @@ -402,13 +402,13 @@ class ComplexWeight(ResponseElement): if name not in ('Unit', 'Value'): message = 'Unrecognized tag {0} in ComplexWeight'.format(name) raise AssertionError(message) - return ResponseElement.startElement(self, name, attrs, connection) + return super(ComplexWeight, self).startElement(name, attrs, connection) @strip_namespace def endElement(self, name, value, connection): if name == 'Value': value = Decimal(value) - ResponseElement.endElement(self, name, value, connection) + super(ComplexWeight, self).endElement(name, value, connection) class Dimension(ComplexType): @@ -501,7 +501,7 @@ class ItemAttributes(AttributeSet): 'MediaType', 'OperatingSystem', 'Platform') for name in names: setattr(self, name, SimpleList()) - AttributeSet.__init__(self, *args, **kw) + super(ItemAttributes, self).__init__(*args, **kw) class VariationRelationship(ResponseElement): @@ -605,7 +605,7 @@ class ProductCategory(ResponseElement): def __init__(self, *args, **kw): setattr(self, 'Parent', Element(ProductCategory)) - ResponseElement.__init__(self, *args, **kw) + super(ProductCategory, self).__init__(*args, **kw) class GetProductCategoriesResult(ResponseElement): diff --git a/awx/lib/site-packages/boto/opsworks/layer1.py b/awx/lib/site-packages/boto/opsworks/layer1.py index 0d79a05b03..6e8d24ba59 100644 --- a/awx/lib/site-packages/boto/opsworks/layer1.py +++ b/awx/lib/site-packages/boto/opsworks/layer1.py @@ -20,7 +20,11 @@ # IN THE SOFTWARE. # -import json +try: + import json +except ImportError: + import simplejson as json + import boto from boto.connection import AWSQueryConnection from boto.regioninfo import RegionInfo @@ -41,6 +45,23 @@ class OpsWorksConnection(AWSQueryConnection): lifecycle. For information about this product, go to the `AWS OpsWorks`_ details page. + **SDKs and CLI** + + The most common way to use the AWS OpsWorks API is by using the + AWS Command Line Interface (CLI) or by using one of the AWS SDKs + to implement applications in your preferred language. For more + information, see: + + + + `AWS CLI`_ + + `AWS SDK for Java`_ + + `AWS SDK for .NET`_ + + `AWS SDK for PHP 2`_ + + `AWS SDK for Ruby`_ + + `AWS SDK for Node.js`_ + + `AWS SDK for Python(Boto)`_ + + **Endpoints** AWS OpsWorks supports only one endpoint, opsworks.us- @@ -53,7 +74,8 @@ class OpsWorksConnection(AWSQueryConnection): When you call CreateStack, CloneStack, or UpdateStack we recommend you use the `ConfigurationManager` parameter to specify the Chef version, 0.9 or 11.4. The default value is currently 0.9. However, - we expect to change the default value to 11.4 in September 2013. + we expect to change the default value to 11.4 in October 2013. For + more information, see `Using AWS OpsWorks with Chef 11`_. """ APIVersion = "2013-02-18" DefaultRegionName = "us-east-1" @@ -74,7 +96,7 @@ class OpsWorksConnection(AWSQueryConnection): region = RegionInfo(self, self.DefaultRegionName, self.DefaultRegionEndpoint) kwargs['host'] = region.endpoint - AWSQueryConnection.__init__(self, **kwargs) + super(OpsWorksConnection, self).__init__(**kwargs) self.region = region def _required_auth_capability(self): @@ -85,7 +107,13 @@ class OpsWorksConnection(AWSQueryConnection): Assigns one of the stack's registered Amazon EBS volumes to a specified instance. The volume must first be registered with the stack by calling RegisterVolume. For more information, see - ``_. + `Resource Management`_. + + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. :type volume_id: string :param volume_id: The volume ID. @@ -105,7 +133,13 @@ class OpsWorksConnection(AWSQueryConnection): Associates one of the stack's registered Elastic IP addresses with a specified instance. The address must first be registered with the stack by calling RegisterElasticIp. For - more information, see ``_. + more information, see `Resource Management`_. + + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. :type elastic_ip: string :param elastic_ip: The Elastic IP address. @@ -131,6 +165,12 @@ class OpsWorksConnection(AWSQueryConnection): or CLI. For more information, see ` Elastic Load Balancing Developer Guide`_. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type elastic_load_balancer_name: string :param elastic_load_balancer_name: The Elastic Load Balancing instance's name. @@ -160,6 +200,11 @@ class OpsWorksConnection(AWSQueryConnection): Creates a clone of a specified stack. For more information, see `Clone a Stack`_. + **Required Permissions**: To use this action, an IAM user must + have an attached policy that explicitly grants permissions. + For more information on user permissions, see `Managing User + Permissions`_. + :type source_stack_id: string :param source_stack_id: The source stack ID. @@ -233,20 +278,20 @@ class OpsWorksConnection(AWSQueryConnection): :param hostname_theme: The stack's host name theme, with spaces are replaced by underscores. The theme is used to generate host names for the stack's instances. By default, `HostnameTheme` is set to - Layer_Dependent, which creates host names by appending integers to - the layer's short name. The other themes are: + `Layer_Dependent`, which creates host names by appending integers + to the layer's short name. The other themes are: - + Baked_Goods - + Clouds - + European_Cities - + Fruits - + Greek_Deities - + Legendary_Creatures_from_Japan - + Planets_and_Moons - + Roman_Deities - + Scottish_Islands - + US_Cities - + Wild_Cats + + `Baked_Goods` + + `Clouds` + + `European_Cities` + + `Fruits` + + `Greek_Deities` + + `Legendary_Creatures_from_Japan` + + `Planets_and_Moons` + + `Roman_Deities` + + `Scottish_Islands` + + `US_Cities` + + `Wild_Cats` To obtain a generated host name, call `GetHostNameSuggestion`, which @@ -359,6 +404,12 @@ class OpsWorksConnection(AWSQueryConnection): Creates an app for a specified stack. For more information, see `Creating Apps`_. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type stack_id: string :param stack_id: The stack ID. @@ -430,6 +481,12 @@ class OpsWorksConnection(AWSQueryConnection): For more information, see `Deploying Apps`_ and `Run Stack Commands`_. + **Required Permissions**: To use this action, an IAM user must + have a Deploy or Manage permissions level for the stack, or an + attached policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type stack_id: string :param stack_id: The stack ID. @@ -479,6 +536,12 @@ class OpsWorksConnection(AWSQueryConnection): Creates an instance in a specified stack. For more information, see `Adding an Instance to a Layer`_. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type stack_id: string :param stack_id: The stack ID. @@ -614,6 +677,12 @@ class OpsWorksConnection(AWSQueryConnection): number of custom layers, so you can call **CreateLayer** as many times as you like for that layer type. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type stack_id: string :param stack_id: The layer stack ID. @@ -736,6 +805,11 @@ class OpsWorksConnection(AWSQueryConnection): Creates a new stack. For more information, see `Create a New Stack`_. + **Required Permissions**: To use this action, an IAM user must + have an attached policy that explicitly grants permissions. + For more information on user permissions, see `Managing User + Permissions`_. + :type name: string :param name: The stack name. @@ -798,20 +872,20 @@ class OpsWorksConnection(AWSQueryConnection): :param hostname_theme: The stack's host name theme, with spaces are replaced by underscores. The theme is used to generate host names for the stack's instances. By default, `HostnameTheme` is set to - Layer_Dependent, which creates host names by appending integers to - the layer's short name. The other themes are: + `Layer_Dependent`, which creates host names by appending integers + to the layer's short name. The other themes are: - + Baked_Goods - + Clouds - + European_Cities - + Fruits - + Greek_Deities - + Legendary_Creatures_from_Japan - + Planets_and_Moons - + Roman_Deities - + Scottish_Islands - + US_Cities - + Wild_Cats + + `Baked_Goods` + + `Clouds` + + `European_Cities` + + `Fruits` + + `Greek_Deities` + + `Legendary_Creatures_from_Japan` + + `Planets_and_Moons` + + `Roman_Deities` + + `Scottish_Islands` + + `US_Cities` + + `Wild_Cats` To obtain a generated host name, call `GetHostNameSuggestion`, which @@ -902,10 +976,15 @@ class OpsWorksConnection(AWSQueryConnection): body=json.dumps(params)) def create_user_profile(self, iam_user_arn, ssh_username=None, - ssh_public_key=None): + ssh_public_key=None, allow_self_management=None): """ Creates a new user profile. + **Required Permissions**: To use this action, an IAM user must + have an attached policy that explicitly grants permissions. + For more information on user permissions, see `Managing User + Permissions`_. + :type iam_user_arn: string :param iam_user_arn: The user's IAM ARN. @@ -915,12 +994,19 @@ class OpsWorksConnection(AWSQueryConnection): :type ssh_public_key: string :param ssh_public_key: The user's public SSH key. + :type allow_self_management: boolean + :param allow_self_management: Whether users can specify their own SSH + public key through the My Settings page. For more information, see + ``_. + """ params = {'IamUserArn': iam_user_arn, } if ssh_username is not None: params['SshUsername'] = ssh_username if ssh_public_key is not None: params['SshPublicKey'] = ssh_public_key + if allow_self_management is not None: + params['AllowSelfManagement'] = allow_self_management return self.make_request(action='CreateUserProfile', body=json.dumps(params)) @@ -928,6 +1014,12 @@ class OpsWorksConnection(AWSQueryConnection): """ Deletes a specified app. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type app_id: string :param app_id: The app ID. @@ -943,6 +1035,12 @@ class OpsWorksConnection(AWSQueryConnection): you can delete it. For more information, see `Deleting Instances`_. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type instance_id: string :param instance_id: The instance ID. @@ -969,6 +1067,12 @@ class OpsWorksConnection(AWSQueryConnection): all associated instances. For more information, see `How to Delete a Layer`_. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type layer_id: string :param layer_id: The layer ID. @@ -983,6 +1087,12 @@ class OpsWorksConnection(AWSQueryConnection): instances, layers, and apps. For more information, see `Shut Down a Stack`_. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type stack_id: string :param stack_id: The stack ID. @@ -995,6 +1105,11 @@ class OpsWorksConnection(AWSQueryConnection): """ Deletes a user profile. + **Required Permissions**: To use this action, an IAM user must + have an attached policy that explicitly grants permissions. + For more information on user permissions, see `Managing User + Permissions`_. + :type iam_user_arn: string :param iam_user_arn: The user's IAM ARN. @@ -1007,7 +1122,13 @@ class OpsWorksConnection(AWSQueryConnection): """ Deregisters a specified Elastic IP address. The address can then be registered by another stack. For more information, see - ``_. + `Resource Management`_. + + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. :type elastic_ip: string :param elastic_ip: The Elastic IP address. @@ -1020,7 +1141,14 @@ class OpsWorksConnection(AWSQueryConnection): def deregister_volume(self, volume_id): """ Deregisters an Amazon EBS volume. The volume can then be - registered by another stack. For more information, see ``_. + registered by another stack. For more information, see + `Resource Management`_. + + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. :type volume_id: string :param volume_id: The volume ID. @@ -1036,6 +1164,12 @@ class OpsWorksConnection(AWSQueryConnection): You must specify at least one of the parameters. + **Required Permissions**: To use this action, an IAM user must + have a Show, Deploy, or Manage permissions level for the + stack, or an attached policy that explicitly grants + permissions. For more information on user permissions, see + `Managing User Permissions`_. + :type stack_id: string :param stack_id: The app stack ID. If you use this parameter, `DescribeApps` returns a description of the apps in the specified @@ -1062,6 +1196,12 @@ class OpsWorksConnection(AWSQueryConnection): You must specify at least one of the parameters. + **Required Permissions**: To use this action, an IAM user must + have a Show, Deploy, or Manage permissions level for the + stack, or an attached policy that explicitly grants + permissions. For more information on user permissions, see + `Managing User Permissions`_. + :type deployment_id: string :param deployment_id: The deployment ID. If you include this parameter, `DescribeCommands` returns a description of the commands associated @@ -1096,6 +1236,12 @@ class OpsWorksConnection(AWSQueryConnection): You must specify at least one of the parameters. + **Required Permissions**: To use this action, an IAM user must + have a Show, Deploy, or Manage permissions level for the + stack, or an attached policy that explicitly grants + permissions. For more information on user permissions, see + `Managing User Permissions`_. + :type stack_id: string :param stack_id: The stack ID. If you include this parameter, `DescribeDeployments` returns a description of the commands @@ -1129,6 +1275,12 @@ class OpsWorksConnection(AWSQueryConnection): You must specify at least one of the parameters. + **Required Permissions**: To use this action, an IAM user must + have a Show, Deploy, or Manage permissions level for the + stack, or an attached policy that explicitly grants + permissions. For more information on user permissions, see + `Managing User Permissions`_. + :type instance_id: string :param instance_id: The instance ID. If you include this parameter, `DescribeElasticIps` returns a description of the Elastic IP @@ -1162,6 +1314,12 @@ class OpsWorksConnection(AWSQueryConnection): You must specify at least one of the parameters. + **Required Permissions**: To use this action, an IAM user must + have a Show, Deploy, or Manage permissions level for the + stack, or an attached policy that explicitly grants + permissions. For more information on user permissions, see + `Managing User Permissions`_. + :type stack_id: string :param stack_id: A stack ID. The action describes the stack's Elastic Load Balancing instances. @@ -1186,6 +1344,12 @@ class OpsWorksConnection(AWSQueryConnection): You must specify at least one of the parameters. + **Required Permissions**: To use this action, an IAM user must + have a Show, Deploy, or Manage permissions level for the + stack, or an attached policy that explicitly grants + permissions. For more information on user permissions, see + `Managing User Permissions`_. + :type stack_id: string :param stack_id: A stack ID. If you use this parameter, `DescribeInstances` returns descriptions of the instances @@ -1220,6 +1384,12 @@ class OpsWorksConnection(AWSQueryConnection): You must specify at least one of the parameters. + **Required Permissions**: To use this action, an IAM user must + have a Show, Deploy, or Manage permissions level for the + stack, or an attached policy that explicitly grants + permissions. For more information on user permissions, see + `Managing User Permissions`_. + :type stack_id: string :param stack_id: The stack ID. @@ -1244,6 +1414,12 @@ class OpsWorksConnection(AWSQueryConnection): You must specify at least one of the parameters. + **Required Permissions**: To use this action, an IAM user must + have a Show, Deploy, or Manage permissions level for the + stack, or an attached policy that explicitly grants + permissions. For more information on user permissions, see + `Managing User Permissions`_. + :type layer_ids: list :param layer_ids: An array of layer IDs. @@ -1252,10 +1428,31 @@ class OpsWorksConnection(AWSQueryConnection): return self.make_request(action='DescribeLoadBasedAutoScaling', body=json.dumps(params)) - def describe_permissions(self, iam_user_arn, stack_id): + def describe_my_user_profile(self): + """ + Describes a user's SSH information. + + **Required Permissions**: To use this action, an IAM user must + have self-management enabled or an attached policy that + explicitly grants permissions. For more information on user + permissions, see `Managing User Permissions`_. + + + """ + params = {} + return self.make_request(action='DescribeMyUserProfile', + body=json.dumps(params)) + + def describe_permissions(self, iam_user_arn=None, stack_id=None): """ Describes the permissions for a specified stack. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type iam_user_arn: string :param iam_user_arn: The user's IAM ARN. For more information about IAM ARNs, see `Using Identifiers`_. @@ -1264,7 +1461,11 @@ class OpsWorksConnection(AWSQueryConnection): :param stack_id: The stack ID. """ - params = {'IamUserArn': iam_user_arn, 'StackId': stack_id, } + params = {} + if iam_user_arn is not None: + params['IamUserArn'] = iam_user_arn + if stack_id is not None: + params['StackId'] = stack_id return self.make_request(action='DescribePermissions', body=json.dumps(params)) @@ -1274,6 +1475,12 @@ class OpsWorksConnection(AWSQueryConnection): You must specify at least one of the parameters. + **Required Permissions**: To use this action, an IAM user must + have a Show, Deploy, or Manage permissions level for the + stack, or an attached policy that explicitly grants + permissions. For more information on user permissions, see + `Managing User Permissions`_. + :type instance_id: string :param instance_id: The instance ID. If you use this parameter, `DescribeRaidArrays` returns descriptions of the RAID arrays @@ -1299,6 +1506,12 @@ class OpsWorksConnection(AWSQueryConnection): """ Describes AWS OpsWorks service errors. + **Required Permissions**: To use this action, an IAM user must + have a Show, Deploy, or Manage permissions level for the + stack, or an attached policy that explicitly grants + permissions. For more information on user permissions, see + `Managing User Permissions`_. + :type stack_id: string :param stack_id: The stack ID. If you use this parameter, `DescribeServiceErrors` returns descriptions of the errors @@ -1326,10 +1539,36 @@ class OpsWorksConnection(AWSQueryConnection): return self.make_request(action='DescribeServiceErrors', body=json.dumps(params)) + def describe_stack_summary(self, stack_id): + """ + Describes the number of layers and apps in a specified stack, + and the number of instances in each state, such as + `running_setup` or `online`. + + **Required Permissions**: To use this action, an IAM user must + have a Show, Deploy, or Manage permissions level for the + stack, or an attached policy that explicitly grants + permissions. For more information on user permissions, see + `Managing User Permissions`_. + + :type stack_id: string + :param stack_id: The stack ID. + + """ + params = {'StackId': stack_id, } + return self.make_request(action='DescribeStackSummary', + body=json.dumps(params)) + def describe_stacks(self, stack_ids=None): """ Requests a description of one or more stacks. + **Required Permissions**: To use this action, an IAM user must + have a Show, Deploy, or Manage permissions level for the + stack, or an attached policy that explicitly grants + permissions. For more information on user permissions, see + `Managing User Permissions`_. + :type stack_ids: list :param stack_ids: An array of stack IDs that specify the stacks to be described. If you omit this parameter, `DescribeStacks` returns a @@ -1349,6 +1588,12 @@ class OpsWorksConnection(AWSQueryConnection): You must specify at least one of the parameters. + **Required Permissions**: To use this action, an IAM user must + have a Show, Deploy, or Manage permissions level for the + stack, or an attached policy that explicitly grants + permissions. For more information on user permissions, see + `Managing User Permissions`_. + :type instance_ids: list :param instance_ids: An array of instance IDs. @@ -1357,16 +1602,23 @@ class OpsWorksConnection(AWSQueryConnection): return self.make_request(action='DescribeTimeBasedAutoScaling', body=json.dumps(params)) - def describe_user_profiles(self, iam_user_arns): + def describe_user_profiles(self, iam_user_arns=None): """ Describe specified users. + **Required Permissions**: To use this action, an IAM user must + have an attached policy that explicitly grants permissions. + For more information on user permissions, see `Managing User + Permissions`_. + :type iam_user_arns: list :param iam_user_arns: An array of IAM user ARNs that identify the users to be described. """ - params = {'IamUserArns': iam_user_arns, } + params = {} + if iam_user_arns is not None: + params['IamUserArns'] = iam_user_arns return self.make_request(action='DescribeUserProfiles', body=json.dumps(params)) @@ -1377,6 +1629,12 @@ class OpsWorksConnection(AWSQueryConnection): You must specify at least one of the parameters. + **Required Permissions**: To use this action, an IAM user must + have a Show, Deploy, or Manage permissions level for the + stack, or an attached policy that explicitly grants + permissions. For more information on user permissions, see + `Managing User Permissions`_. + :type instance_id: string :param instance_id: The instance ID. If you use this parameter, `DescribeVolumes` returns descriptions of the volumes associated @@ -1415,6 +1673,12 @@ class OpsWorksConnection(AWSQueryConnection): Detaches a specified Elastic Load Balancing instance from its layer. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type elastic_load_balancer_name: string :param elastic_load_balancer_name: The Elastic Load Balancing instance's name. @@ -1435,7 +1699,13 @@ class OpsWorksConnection(AWSQueryConnection): """ Disassociates an Elastic IP address from its instance. The address remains registered with the stack. For more - information, see ``_. + information, see `Resource Management`_. + + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. :type elastic_ip: string :param elastic_ip: The Elastic IP address. @@ -1450,6 +1720,12 @@ class OpsWorksConnection(AWSQueryConnection): Gets a generated host name for the specified layer, based on the current host name theme. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type layer_id: string :param layer_id: The layer ID. @@ -1463,6 +1739,12 @@ class OpsWorksConnection(AWSQueryConnection): Reboots a specified instance. For more information, see `Starting, Stopping, and Rebooting Instances`_. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type instance_id: string :param instance_id: The instance ID. @@ -1477,7 +1759,13 @@ class OpsWorksConnection(AWSQueryConnection): address can be registered with only one stack at a time. If the address is already registered, you must first deregister it by calling DeregisterElasticIp. For more information, see - ``_. + `Resource Management`_. + + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. :type elastic_ip: string :param elastic_ip: The Elastic IP address. @@ -1495,7 +1783,14 @@ class OpsWorksConnection(AWSQueryConnection): Registers an Amazon EBS volume with a specified stack. A volume can be registered with only one stack at a time. If the volume is already registered, you must first deregister it by - calling DeregisterVolume. For more information, see ``_. + calling DeregisterVolume. For more information, see `Resource + Management`_. + + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. :type ec_2_volume_id: string :param ec_2_volume_id: The Amazon EBS volume ID. @@ -1523,6 +1818,12 @@ class OpsWorksConnection(AWSQueryConnection): you have created enough instances to handle the maximum anticipated load. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type layer_id: string :param layer_id: The layer ID. @@ -1553,11 +1854,17 @@ class OpsWorksConnection(AWSQueryConnection): body=json.dumps(params)) def set_permission(self, stack_id, iam_user_arn, allow_ssh=None, - allow_sudo=None): + allow_sudo=None, level=None): """ Specifies a stack's permissions. For more information, see `Security and Permissions`_. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type stack_id: string :param stack_id: The stack ID. @@ -1572,12 +1879,28 @@ class OpsWorksConnection(AWSQueryConnection): :param allow_sudo: The user is allowed to use **sudo** to elevate privileges. + :type level: string + :param level: The user's permission level, which must be set to one of + the following strings. You cannot set your own permissions level. + + + `deny` + + `show` + + `deploy` + + `manage` + + `iam_only` + + + For more information on the permissions associated with these levels, + see `Managing User Permissions`_ + """ params = {'StackId': stack_id, 'IamUserArn': iam_user_arn, } if allow_ssh is not None: params['AllowSsh'] = allow_ssh if allow_sudo is not None: params['AllowSudo'] = allow_sudo + if level is not None: + params['Level'] = level return self.make_request(action='SetPermission', body=json.dumps(params)) @@ -1588,6 +1911,12 @@ class OpsWorksConnection(AWSQueryConnection): specified instance. For more information, see `Managing Load with Time-based and Load-based Instances`_. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type instance_id: string :param instance_id: The instance ID. @@ -1607,6 +1936,12 @@ class OpsWorksConnection(AWSQueryConnection): Starts a specified instance. For more information, see `Starting, Stopping, and Rebooting Instances`_. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type instance_id: string :param instance_id: The instance ID. @@ -1619,6 +1954,12 @@ class OpsWorksConnection(AWSQueryConnection): """ Starts stack's instances. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type stack_id: string :param stack_id: The stack ID. @@ -1635,6 +1976,12 @@ class OpsWorksConnection(AWSQueryConnection): without losing data. For more information, see `Starting, Stopping, and Rebooting Instances`_. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type instance_id: string :param instance_id: The instance ID. @@ -1647,6 +1994,12 @@ class OpsWorksConnection(AWSQueryConnection): """ Stops a specified stack. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type stack_id: string :param stack_id: The stack ID. @@ -1658,7 +2011,14 @@ class OpsWorksConnection(AWSQueryConnection): def unassign_volume(self, volume_id): """ Unassigns an assigned Amazon EBS volume. The volume remains - registered with the stack. For more information, see ``_. + registered with the stack. For more information, see `Resource + Management`_. + + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. :type volume_id: string :param volume_id: The volume ID. @@ -1674,6 +2034,12 @@ class OpsWorksConnection(AWSQueryConnection): """ Updates a specified app. + **Required Permissions**: To use this action, an IAM user must + have a Deploy or Manage permissions level for the stack, or an + attached policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type app_id: string :param app_id: The app ID. @@ -1728,7 +2094,13 @@ class OpsWorksConnection(AWSQueryConnection): def update_elastic_ip(self, elastic_ip, name=None): """ Updates a registered Elastic IP address's name. For more - information, see ``_. + information, see `Resource Management`_. + + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. :type elastic_ip: string :param elastic_ip: The address. @@ -1751,6 +2123,12 @@ class OpsWorksConnection(AWSQueryConnection): """ Updates a specified instance. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type instance_id: string :param instance_id: The instance ID. @@ -1854,6 +2232,12 @@ class OpsWorksConnection(AWSQueryConnection): """ Updates a specified layer. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type layer_id: string :param layer_id: The layer ID. @@ -1947,6 +2331,25 @@ class OpsWorksConnection(AWSQueryConnection): return self.make_request(action='UpdateLayer', body=json.dumps(params)) + def update_my_user_profile(self, ssh_public_key=None): + """ + Updates a user's SSH public key. + + **Required Permissions**: To use this action, an IAM user must + have self-management enabled or an attached policy that + explicitly grants permissions. For more information on user + permissions, see `Managing User Permissions`_. + + :type ssh_public_key: string + :param ssh_public_key: The user's SSH public key. + + """ + params = {} + if ssh_public_key is not None: + params['SshPublicKey'] = ssh_public_key + return self.make_request(action='UpdateMyUserProfile', + body=json.dumps(params)) + def update_stack(self, stack_id, name=None, attributes=None, service_role_arn=None, default_instance_profile_arn=None, default_os=None, @@ -1958,6 +2361,12 @@ class OpsWorksConnection(AWSQueryConnection): """ Updates a specified stack. + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. + :type stack_id: string :param stack_id: The stack ID. @@ -1995,20 +2404,20 @@ class OpsWorksConnection(AWSQueryConnection): :param hostname_theme: The stack's new host name theme, with spaces are replaced by underscores. The theme is used to generate host names for the stack's instances. By default, `HostnameTheme` is set to - Layer_Dependent, which creates host names by appending integers to - the layer's short name. The other themes are: + `Layer_Dependent`, which creates host names by appending integers + to the layer's short name. The other themes are: - + Baked_Goods - + Clouds - + European_Cities - + Fruits - + Greek_Deities - + Legendary_Creatures_from_Japan - + Planets_and_Moons - + Roman_Deities - + Scottish_Islands - + US_Cities - + Wild_Cats + + `Baked_Goods` + + `Clouds` + + `European_Cities` + + `Fruits` + + `Greek_Deities` + + `Legendary_Creatures_from_Japan` + + `Planets_and_Moons` + + `Roman_Deities` + + `Scottish_Islands` + + `US_Cities` + + `Wild_Cats` To obtain a generated host name, call `GetHostNameSuggestion`, which @@ -2096,10 +2505,15 @@ class OpsWorksConnection(AWSQueryConnection): body=json.dumps(params)) def update_user_profile(self, iam_user_arn, ssh_username=None, - ssh_public_key=None): + ssh_public_key=None, allow_self_management=None): """ Updates a specified user profile. + **Required Permissions**: To use this action, an IAM user must + have an attached policy that explicitly grants permissions. + For more information on user permissions, see `Managing User + Permissions`_. + :type iam_user_arn: string :param iam_user_arn: The user IAM ARN. @@ -2109,19 +2523,32 @@ class OpsWorksConnection(AWSQueryConnection): :type ssh_public_key: string :param ssh_public_key: The user's new SSH public key. + :type allow_self_management: boolean + :param allow_self_management: Whether users can specify their own SSH + public key through the My Settings page. For more information, see + `Managing User Permissions`_. + """ params = {'IamUserArn': iam_user_arn, } if ssh_username is not None: params['SshUsername'] = ssh_username if ssh_public_key is not None: params['SshPublicKey'] = ssh_public_key + if allow_self_management is not None: + params['AllowSelfManagement'] = allow_self_management return self.make_request(action='UpdateUserProfile', body=json.dumps(params)) def update_volume(self, volume_id, name=None, mount_point=None): """ Updates an Amazon EBS volume's name or mount point. For more - information, see ``_. + information, see `Resource Management`_. + + **Required Permissions**: To use this action, an IAM user must + have a Manage permissions level for the stack, or an attached + policy that explicitly grants permissions. For more + information on user permissions, see `Managing User + Permissions`_. :type volume_id: string :param volume_id: The volume ID. diff --git a/awx/lib/site-packages/boto/provider.py b/awx/lib/site-packages/boto/provider.py index e27247cd3a..6f77faaf64 100644 --- a/awx/lib/site-packages/boto/provider.py +++ b/awx/lib/site-packages/boto/provider.py @@ -290,7 +290,7 @@ class Provider(object): # clear to users. metadata = get_instance_metadata( timeout=timeout, num_retries=attempts, - data='meta-data/iam/security-credentials') + data='meta-data/iam/security-credentials/') if metadata: # I'm assuming there's only one role on the instance profile. security = metadata.values()[0] diff --git a/awx/lib/site-packages/boto/pyami/bootstrap.py b/awx/lib/site-packages/boto/pyami/bootstrap.py index cd44682fc8..f0b353de21 100644 --- a/awx/lib/site-packages/boto/pyami/bootstrap.py +++ b/awx/lib/site-packages/boto/pyami/bootstrap.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -40,7 +40,7 @@ class Bootstrap(ScriptBase): def __init__(self): self.working_dir = '/mnt/pyami' self.write_metadata() - ScriptBase.__init__(self) + super(Bootstrap, self).__init__() def write_metadata(self): fp = open(os.path.expanduser(BotoConfigPath), 'w') diff --git a/awx/lib/site-packages/boto/pyami/config.py b/awx/lib/site-packages/boto/pyami/config.py index 08da6581e5..28b6f6d860 100644 --- a/awx/lib/site-packages/boto/pyami/config.py +++ b/awx/lib/site-packages/boto/pyami/config.py @@ -58,6 +58,8 @@ elif 'BOTO_PATH' in os.environ: class Config(ConfigParser.SafeConfigParser): def __init__(self, path=None, fp=None, do_load=True): + # We don't use ``super`` here, because ``ConfigParser`` still uses + # old-style classes. ConfigParser.SafeConfigParser.__init__(self, {'working_dir' : '/mnt/pyami', 'debug' : '0'}) if do_load: diff --git a/awx/lib/site-packages/boto/pyami/copybot.py b/awx/lib/site-packages/boto/pyami/copybot.py index ed397cb761..02d8bb22c8 100644 --- a/awx/lib/site-packages/boto/pyami/copybot.py +++ b/awx/lib/site-packages/boto/pyami/copybot.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -26,7 +26,7 @@ import os, StringIO class CopyBot(ScriptBase): def __init__(self): - ScriptBase.__init__(self) + super(CopyBot, self).__init__() self.wdir = boto.config.get('Pyami', 'working_dir') self.log_file = '%s.log' % self.instance_id self.log_path = os.path.join(self.wdir, self.log_file) @@ -80,7 +80,7 @@ class CopyBot(ScriptBase): def copy_log(self): key = self.dst.new_key(self.log_file) key.set_contents_from_filename(self.log_path) - + def main(self): fp = StringIO.StringIO() boto.config.dump_safe(fp) @@ -94,4 +94,4 @@ class CopyBot(ScriptBase): if boto.config.getbool(self.name, 'exit_on_completion', True): ec2 = boto.connect_ec2() ec2.terminate_instances([self.instance_id]) - + diff --git a/awx/lib/site-packages/boto/pyami/installers/ubuntu/ebs.py b/awx/lib/site-packages/boto/pyami/installers/ubuntu/ebs.py index 3e5b5c28d1..45f5dbbe59 100644 --- a/awx/lib/site-packages/boto/pyami/installers/ubuntu/ebs.py +++ b/awx/lib/site-packages/boto/pyami/installers/ubuntu/ebs.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -36,7 +36,7 @@ Config file section:: [EBS] volume_id = - logical_volume_name = device = @@ -86,7 +86,7 @@ from boto.manage.volume import Volume for v in Volume.all(): v.trim_snapshots(True) """ - + TagBasedBackupCleanupScript= """#!/usr/bin/env python import boto @@ -102,7 +102,7 @@ class EBSInstaller(Installer): """ def __init__(self, config_file=None): - Installer.__init__(self, config_file) + super(EBSInstaller, self).__init__(config_file) self.instance_id = boto.config.get('Instance', 'instance-id') self.device = boto.config.get('EBS', 'device', '/dev/sdp') self.volume_id = boto.config.get('EBS', 'volume_id') @@ -130,7 +130,7 @@ class EBSInstaller(Installer): attempt_attach = False except EC2ResponseError, e: if e.error_code != 'IncorrectState': - # if there's an EC2ResonseError with the code set to IncorrectState, delay a bit for ec2 + # if there's an EC2ResonseError with the code set to IncorrectState, delay a bit for ec2 # to realize the instance is running, then try again. Otherwise, raise the error: boto.log.info('Attempt to attach the EBS volume %s to this instance (%s) returned %s. Trying again in a bit.' % (self.volume_id, self.instance_id, e.errors)) time.sleep(2) @@ -198,7 +198,7 @@ class EBSInstaller(Installer): def install(self): # First, find and attach the volume self.attach() - + # Install the xfs tools self.run('apt-get -y install xfsprogs xfsdump') @@ -221,7 +221,7 @@ class EBSInstaller(Installer): hour = boto.config.get('EBS', 'backup_cleanup_cron_hour') if (minute != None) and (hour != None): # Snapshot clean up can either be done via the manage module, or via the new tag based - # snapshot code, if the snapshots have been tagged with the name of the associated + # snapshot code, if the snapshots have been tagged with the name of the associated # volume. Check for the presence of the new configuration flag, and use the appropriate # cleanup method / script: use_tag_based_cleanup = boto.config.has_option('EBS', 'use_tag_based_snapshot_cleanup') diff --git a/awx/lib/site-packages/boto/pyami/scriptbase.py b/awx/lib/site-packages/boto/pyami/scriptbase.py index 90522cad1a..8e8cb0c0fb 100644 --- a/awx/lib/site-packages/boto/pyami/scriptbase.py +++ b/awx/lib/site-packages/boto/pyami/scriptbase.py @@ -4,7 +4,7 @@ from boto.utils import ShellCommand, get_ts import boto import boto.utils -class ScriptBase: +class ScriptBase(object): def __init__(self, config_file=None): self.instance_id = boto.config.get('Instance', 'instance-id', 'default') @@ -41,4 +41,4 @@ class ScriptBase: def main(self): pass - + diff --git a/awx/lib/site-packages/boto/rds/__init__.py b/awx/lib/site-packages/boto/rds/__init__.py index 751c5d51b5..d08d445d45 100644 --- a/awx/lib/site-packages/boto/rds/__init__.py +++ b/awx/lib/site-packages/boto/rds/__init__.py @@ -57,6 +57,8 @@ def regions(): endpoint='rds.ap-southeast-1.amazonaws.com'), RDSRegionInfo(name='ap-southeast-2', endpoint='rds.ap-southeast-2.amazonaws.com'), + RDSRegionInfo(name='cn-north-1', + endpoint='rds.cn-north-1.amazonaws.com.cn'), ] @@ -97,7 +99,7 @@ class RDSConnection(AWSQueryConnection): region = RDSRegionInfo(self, self.DefaultRegionName, self.DefaultRegionEndpoint) self.region = region - AWSQueryConnection.__init__(self, aws_access_key_id, + super(RDSConnection, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, @@ -169,7 +171,7 @@ class RDSConnection(AWSQueryConnection): iops=None, vpc_security_groups=None, ): - # API version: 2012-09-17 + # API version: 2013-09-09 # Parameter notes: # ================= # id should be db_instance_identifier according to API docs but has been left @@ -196,20 +198,23 @@ class RDSConnection(AWSQueryConnection): :param allocated_storage: Initially allocated storage size, in GBs. Valid values are depending on the engine value. - * MySQL = 5--1024 - * oracle-se1 = 10--1024 - * oracle-se = 10--1024 - * oracle-ee = 10--1024 + * MySQL = 5--3072 + * oracle-se1 = 10--3072 + * oracle-se = 10--3072 + * oracle-ee = 10--3072 * sqlserver-ee = 200--1024 * sqlserver-se = 200--1024 * sqlserver-ex = 30--1024 * sqlserver-web = 30--1024 + * postgres = 5--3072 :type instance_class: str :param instance_class: The compute and memory capacity of the DBInstance. Valid values are: + * db.t1.micro * db.m1.small + * db.m1.medium * db.m1.large * db.m1.xlarge * db.m2.xlarge @@ -227,6 +232,7 @@ class RDSConnection(AWSQueryConnection): * sqlserver-se * sqlserver-ex * sqlserver-web + * postgres :type master_username: str :param master_username: Name of master user for the DBInstance. @@ -263,7 +269,10 @@ class RDSConnection(AWSQueryConnection): * Oracle defaults to 1521 - * SQL Server defaults to 1433 and _cannot_ be 1434 or 3389 + * SQL Server defaults to 1433 and _cannot_ be 1434, 3389, + 47001, 49152, and 49152 through 49156. + + * PostgreSQL defaults to 5432 :type db_name: str :param db_name: * MySQL: @@ -280,6 +289,15 @@ class RDSConnection(AWSQueryConnection): * SQL Server: Not applicable and must be None. + * PostgreSQL: + Name of a database to create when the DBInstance + is created. Default is to create no databases. + + Must contain 1--63 alphanumeric characters. Must + begin with a letter or an underscore. Subsequent + characters can be letters, underscores, or digits (0-9) + and cannot be a reserved PostgreSQL word. + :type param_group: str or ParameterGroup object :param param_group: Name of DBParameterGroup or ParameterGroup instance to associate with this DBInstance. If no groups are @@ -326,6 +344,8 @@ class RDSConnection(AWSQueryConnection): * SQL Server format example: 10.50.2789.0.v1 + * PostgreSQL format example: 9.3 + :type auto_minor_version_upgrade: bool :param auto_minor_version_upgrade: Indicates that minor engine upgrades will be applied @@ -443,7 +463,7 @@ class RDSConnection(AWSQueryConnection): # Remove any params set to None for k, v in params.items(): - if not v: del(params[k]) + if v is None: del(params[k]) return self.get_object('CreateDBInstance', params, DBInstance) @@ -516,6 +536,42 @@ class RDSConnection(AWSQueryConnection): return self.get_object('CreateDBInstanceReadReplica', params, DBInstance) + + def promote_read_replica(self, id, + backup_retention_period=None, + preferred_backup_window=None): + """ + Promote a Read Replica to a standalone DB Instance. + + :type id: str + :param id: Unique identifier for the new instance. + Must contain 1-63 alphanumeric characters. + First character must be a letter. + May not end with a hyphen or contain two consecutive hyphens + + :type backup_retention_period: int + :param backup_retention_period: The number of days for which automated + backups are retained. Setting this to + zero disables automated backups. + + :type preferred_backup_window: str + :param preferred_backup_window: The daily time range during which + automated backups are created (if + enabled). Must be in h24:mi-hh24:mi + format (UTC). + + :rtype: :class:`boto.rds.dbinstance.DBInstance` + :return: The new db instance. + """ + params = {'DBInstanceIdentifier': id} + if backup_retention_period is not None: + params['BackupRetentionPeriod'] = backup_retention_period + if preferred_backup_window: + params['PreferredBackupWindow'] = preferred_backup_window + + return self.get_object('PromoteReadReplica', params, DBInstance) + + def modify_dbinstance(self, id, param_group=None, security_groups=None, preferred_maintenance_window=None, master_password=None, allocated_storage=None, @@ -526,6 +582,7 @@ class RDSConnection(AWSQueryConnection): apply_immediately=False, iops=None, vpc_security_groups=None, + new_instance_id=None, ): """ Modify an existing DBInstance. @@ -606,6 +663,9 @@ class RDSConnection(AWSQueryConnection): :param vpc_security_groups: List of VPC security group ids or a VPCSecurityGroupMembership object this DBInstance should be a member of + :type new_instance_id: str + :param new_instance_id: New name to rename the DBInstance to. + :rtype: :class:`boto.rds.dbinstance.DBInstance` :return: The modified db instance. """ @@ -648,6 +708,8 @@ class RDSConnection(AWSQueryConnection): params['ApplyImmediately'] = 'true' if iops: params['Iops'] = iops + if new_instance_id: + params['NewDBInstanceIdentifier'] = new_instance_id return self.get_object('ModifyDBInstance', params, DBInstance) @@ -1043,6 +1105,23 @@ class RDSConnection(AWSQueryConnection): 'DBInstanceIdentifier': dbinstance_id} return self.get_object('CreateDBSnapshot', params, DBSnapshot) + def copy_dbsnapshot(self, source_snapshot_id, target_snapshot_id): + """ + Copies the specified DBSnapshot. + + :type source_snapshot_id: string + :param source_snapshot_id: The identifier for the source DB snapshot. + + :type target_snapshot_id: string + :param target_snapshot_id: The identifier for the copied snapshot. + + :rtype: :class:`boto.rds.dbsnapshot.DBSnapshot` + :return: The newly created DBSnapshot. + """ + params = {'SourceDBSnapshotIdentifier': source_snapshot_id, + 'TargetDBSnapshotIdentifier': target_snapshot_id} + return self.get_object('CopyDBSnapshot', params, DBSnapshot) + def delete_dbsnapshot(self, identifier): """ Delete a DBSnapshot diff --git a/awx/lib/site-packages/boto/rds/dbinstance.py b/awx/lib/site-packages/boto/rds/dbinstance.py index 043052ea7c..6a6385103d 100644 --- a/awx/lib/site-packages/boto/rds/dbinstance.py +++ b/awx/lib/site-packages/boto/rds/dbinstance.py @@ -22,6 +22,7 @@ from boto.rds.dbsecuritygroup import DBSecurityGroup from boto.rds.parametergroup import ParameterGroup from boto.rds.statusinfo import StatusInfo +from boto.rds.dbsubnetgroup import DBSubnetGroup from boto.rds.vpcsecuritygroupmembership import VPCSecurityGroupMembership from boto.resultset import ResultSet @@ -39,6 +40,8 @@ class DBInstance(object): :ivar engine: The database engine being used :ivar status: The status of the database in a string. e.g. "available" :ivar allocated_storage: The size of the disk in gigabytes (int). + :ivar auto_minor_version_upgrade: Indicates that minor version patches + are applied automatically. :ivar endpoint: A tuple that describes the hostname and port of the instance. This is only available when the database is in status "available". @@ -75,7 +78,14 @@ class DBInstance(object): :ivar read_replica_dbinstance_identifiers: List of read replicas associated with this DB instance. :ivar status_infos: The status of a Read Replica. If the instance is not a - for a read replica, this will be blank. + for a read replica, this will be blank. + :ivar character_set_name: If present, specifies the name of the character + set that this instance is associated with. + :ivar subnet_group: Specifies information on the subnet group associated + with the DB instance, including the name, description, and subnets + in the subnet group. + :ivar engine_version: Indicates the database engine version. + :ivar license_model: License model information for this DB instance. """ def __init__(self, connection=None, id=None): @@ -85,6 +95,7 @@ class DBInstance(object): self.engine = None self.status = None self.allocated_storage = None + self.auto_minor_version_upgrade = None self.endpoint = None self.instance_class = None self.master_username = None @@ -104,6 +115,10 @@ class DBInstance(object): self._port = None self._address = None self.status_infos = None + self.character_set_name = None + self.subnet_group = None + self.engine_version = None + self.license_model = None def __repr__(self): return 'DBInstance:%s' % self.id @@ -135,6 +150,9 @@ class DBInstance(object): ('DBInstanceStatusInfo', StatusInfo) ]) return self.status_infos + elif name == 'DBSubnetGroup': + self.subnet_group = DBSubnetGroup() + return self.subnet_group return None def endElement(self, name, value, connection): @@ -150,6 +168,8 @@ class DBInstance(object): self.status = value elif name == 'AllocatedStorage': self.allocated_storage = int(value) + elif name == 'AutoMinorVersionUpgrade': + self.auto_minor_version_upgrade = value.lower() == 'true' elif name == 'DBInstanceClass': self.instance_class = value elif name == 'MasterUsername': @@ -166,7 +186,7 @@ class DBInstance(object): elif name == 'AvailabilityZone': self.availability_zone = value elif name == 'BackupRetentionPeriod': - self.backup_retention_period = value + self.backup_retention_period = int(value) elif name == 'LatestRestorableTime': self.latest_restorable_time = value elif name == 'PreferredMaintenanceWindow': @@ -178,6 +198,12 @@ class DBInstance(object): self.multi_az = True elif name == 'Iops': self.iops = int(value) + elif name == 'CharacterSetName': + self.character_set_name = value + elif name == 'EngineVersion': + self.engine_version = value + elif name == 'LicenseModel': + self.license_model = value else: setattr(self, name, value) @@ -274,7 +300,8 @@ class DBInstance(object): multi_az=False, iops=None, vpc_security_groups=None, - apply_immediately=False): + apply_immediately=False, + new_instance_id=None): """ Modify this DBInstance. @@ -317,6 +344,9 @@ class DBInstance(object): :param apply_immediately: If true, the modifications will be applied as soon as possible rather than waiting for the next preferred maintenance window. + + :type new_instance_id: str + :param new_instance_id: The new DB instance identifier. :type backup_retention_period: int :param backup_retention_period: The number of days for which @@ -364,7 +394,8 @@ class DBInstance(object): multi_az, apply_immediately, iops, - vpc_security_groups) + vpc_security_groups, + new_instance_id) class PendingModifiedValues(dict): diff --git a/awx/lib/site-packages/boto/rds/dbsnapshot.py b/awx/lib/site-packages/boto/rds/dbsnapshot.py index acacd73dcd..16d8125be7 100644 --- a/awx/lib/site-packages/boto/rds/dbsnapshot.py +++ b/awx/lib/site-packages/boto/rds/dbsnapshot.py @@ -25,8 +25,8 @@ class DBSnapshot(object): Properties reference available from the AWS documentation at http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference/API_DBSnapshot.html - :ivar EngineVersion: Specifies the version of the database engine - :ivar LicenseModel: License model information for the restored DB instance + :ivar engine_version: Specifies the version of the database engine + :ivar license_model: License model information for the restored DB instance :ivar allocated_storage: Specifies the allocated storage size in gigabytes (GB) :ivar availability_zone: Specifies the name of the Availability Zone the DB Instance was located in at the time of the DB Snapshot :ivar connection: boto.rds.RDSConnection associated with the current object @@ -38,12 +38,19 @@ class DBSnapshot(object): :ivar port: Specifies the port that the database engine was listening on at the time of the snapshot :ivar snapshot_create_time: Provides the time (UTC) when the snapshot was taken :ivar status: Specifies the status of this DB Snapshot. Possible values are [ available, backing-up, creating, deleted, deleting, failed, modifying, rebooting, resetting-master-credentials ] + :ivar iops: Specifies the Provisioned IOPS (I/O operations per second) value of the DB instance at the time of the snapshot. + :ivar option_group_name: Provides the option group name for the DB snapshot. + :ivar percent_progress: The percentage of the estimated data that has been transferred. + :ivar snapshot_type: Provides the type of the DB snapshot. + :ivar source_region: The region that the DB snapshot was created in or copied from. + :ivar vpc_id: Provides the Vpc Id associated with the DB snapshot. """ def __init__(self, connection=None, id=None): self.connection = connection self.id = id self.engine = None + self.engine_version = None self.snapshot_create_time = None self.instance_create_time = None self.port = None @@ -53,6 +60,13 @@ class DBSnapshot(object): self.allocated_storage = None self.instance_id = None self.availability_zone = None + self.license_model = None + self.iops = None + self.option_group_name = None + self.percent_progress = None + self.snapshot_type = None + self.source_region = None + self.vpc_id = None def __repr__(self): return 'DBSnapshot:%s' % self.id @@ -63,6 +77,8 @@ class DBSnapshot(object): def endElement(self, name, value, connection): if name == 'Engine': self.engine = value + elif name == 'EngineVersion': + self.engine_version = value elif name == 'InstanceCreateTime': self.instance_create_time = value elif name == 'SnapshotCreateTime': @@ -83,6 +99,20 @@ class DBSnapshot(object): self.allocated_storage = int(value) elif name == 'SnapshotTime': self.time = value + elif name == 'LicenseModel': + self.license_model = value + elif name == 'Iops': + self.iops = int(value) + elif name == 'OptionGroupName': + self.option_group_name = value + elif name == 'PercentProgress': + self.percent_progress = int(value) + elif name == 'SnapshotType': + self.snapshot_type = value + elif name == 'SourceRegion': + self.source_region = value + elif name == 'VpcId': + self.vpc_id = value else: setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/rds/regioninfo.py b/awx/lib/site-packages/boto/rds/regioninfo.py index 7d186ae0cb..376dc9f047 100644 --- a/awx/lib/site-packages/boto/rds/regioninfo.py +++ b/awx/lib/site-packages/boto/rds/regioninfo.py @@ -16,7 +16,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -28,5 +28,5 @@ class RDSRegionInfo(RegionInfo): def __init__(self, connection=None, name=None, endpoint=None): from boto.rds import RDSConnection - RegionInfo.__init__(self, connection, name, endpoint, + super(RDSRegionInfo, self).__init__(connection, name, endpoint, RDSConnection) diff --git a/awx/lib/site-packages/boto/redshift/layer1.py b/awx/lib/site-packages/boto/redshift/layer1.py index 2f5a332a66..02aaff1588 100644 --- a/awx/lib/site-packages/boto/redshift/layer1.py +++ b/awx/lib/site-packages/boto/redshift/layer1.py @@ -142,7 +142,7 @@ class RedshiftConnection(AWSQueryConnection): self.DefaultRegionEndpoint) if 'host' not in kwargs: kwargs['host'] = region.endpoint - AWSQueryConnection.__init__(self, **kwargs) + super(RedshiftConnection, self).__init__(**kwargs) self.region = region def _required_auth_capability(self): diff --git a/awx/lib/site-packages/boto/roboto/awsqueryrequest.py b/awx/lib/site-packages/boto/roboto/awsqueryrequest.py index 6d9507189e..1e15c4f872 100644 --- a/awx/lib/site-packages/boto/roboto/awsqueryrequest.py +++ b/awx/lib/site-packages/boto/roboto/awsqueryrequest.py @@ -77,22 +77,22 @@ class RequiredParamError(boto.exception.BotoClientError): def __init__(self, required): self.required = required s = 'Required parameters are missing: %s' % self.required - boto.exception.BotoClientError.__init__(self, s) + super(RequiredParamError, self).__init__(s) class EncoderError(boto.exception.BotoClientError): def __init__(self, error_msg): s = 'Error encoding value (%s)' % error_msg - boto.exception.BotoClientError.__init__(self, s) - + super(EncoderError, self).__init__(s) + class FilterError(boto.exception.BotoClientError): def __init__(self, filters): self.filters = filters s = 'Unknown filters: %s' % self.filters - boto.exception.BotoClientError.__init__(self, s) - -class Encoder: + super(FilterError, self).__init__(s) + +class Encoder(object): @classmethod def encode(cls, p, rp, v, label=None): @@ -103,7 +103,7 @@ class Encoder: mthd(p, rp, v, label) except AttributeError: raise EncoderError('Unknown type: %s' % p.ptype) - + @classmethod def encode_string(cls, p, rp, v, l): if l: @@ -122,7 +122,7 @@ class Encoder: else: label = p.name rp[label] = '%d' % v - + @classmethod def encode_boolean(cls, p, rp, v, l): if l: @@ -134,7 +134,7 @@ class Encoder: else: v = 'false' rp[label] = v - + @classmethod def encode_datetime(cls, p, rp, v, l): if l: @@ -142,7 +142,7 @@ class Encoder: else: label = p.name rp[label] = v - + @classmethod def encode_array(cls, p, rp, v, l): v = boto.utils.mklist(v) @@ -153,7 +153,7 @@ class Encoder: label = label + '.%d' for i, value in enumerate(v): rp[label%(i+1)] = value - + class AWSQueryRequest(object): ServiceClass = None @@ -290,7 +290,7 @@ class AWSQueryRequest(object): elif fmt and fmt['type'] == 'array': self.list_markers.append(prev_name) self.item_markers.append(fmt['name']) - + def send(self, verb='GET', **args): self.process_args(**args) self.process_filters() @@ -371,7 +371,7 @@ class AWSQueryRequest(object): if a.doc: s += '\n\n\t%s - %s' % (a.long_name, a.doc) return s - + def build_cli_parser(self): self.parser = optparse.OptionParser(description=self.Description, usage=self.get_usage()) diff --git a/awx/lib/site-packages/boto/roboto/awsqueryservice.py b/awx/lib/site-packages/boto/roboto/awsqueryservice.py index 0ca78c2d7f..cb3a21d085 100644 --- a/awx/lib/site-packages/boto/roboto/awsqueryservice.py +++ b/awx/lib/site-packages/boto/roboto/awsqueryservice.py @@ -10,7 +10,7 @@ class NoCredentialsError(boto.exception.BotoClientError): def __init__(self): s = 'Unable to find credentials' - boto.exception.BotoClientError.__init__(self, s) + super(NoCredentialsError, self).__init__(s) class AWSQueryService(boto.connection.AWSQueryConnection): @@ -41,7 +41,7 @@ class AWSQueryService(boto.connection.AWSQueryConnection): if 'port' not in self.args: self.args['port'] = self.Port try: - boto.connection.AWSQueryConnection.__init__(self, **self.args) + super(AWSQueryService, self).__init__(**self.args) self.aws_response = None except boto.exception.NoAuthHandlerFound: raise NoCredentialsError() @@ -115,7 +115,7 @@ class AWSQueryService(boto.connection.AWSQueryConnection): if rslt.path and 'path' not in self.args: self.args['path'] = rslt.path - + def _required_auth_capability(self): return [self.Authentication] - + diff --git a/awx/lib/site-packages/boto/roboto/param.py b/awx/lib/site-packages/boto/roboto/param.py index 61364003a7..d4ddbd9f1b 100644 --- a/awx/lib/site-packages/boto/roboto/param.py +++ b/awx/lib/site-packages/boto/roboto/param.py @@ -23,7 +23,7 @@ import os class Converter(object): - + @classmethod def convert_string(cls, param, value): # TODO: could do length validation, etc. here @@ -35,7 +35,7 @@ class Converter(object): def convert_integer(cls, param, value): # TODO: could do range checking here return int(value) - + @classmethod def convert_boolean(cls, param, value): """ @@ -43,19 +43,19 @@ class Converter(object): of the option means True so just return True """ return True - + @classmethod def convert_file(cls, param, value): if os.path.isfile(value): return value raise ValueError - + @classmethod def convert_dir(cls, param, value): if os.path.isdir(value): return value raise ValueError - + @classmethod def convert(cls, param, value): try: @@ -66,7 +66,7 @@ class Converter(object): return mthd(param, value) except: raise ValidationException(param, '') - + class Param(object): def __init__(self, name=None, ptype='string', optional=True, @@ -142,6 +142,6 @@ class Param(object): :param value: The value to convert. This should always be a string. """ - return Converter.convert(self, value) + return super(Param, self).convert(value) diff --git a/awx/lib/site-packages/boto/route53/connection.py b/awx/lib/site-packages/boto/route53/connection.py index 8ba8cd78ea..398ff87097 100644 --- a/awx/lib/site-packages/boto/route53/connection.py +++ b/awx/lib/site-packages/boto/route53/connection.py @@ -64,7 +64,7 @@ class Route53Connection(AWSAuthConnection): port=None, proxy=None, proxy_port=None, host=DefaultHost, debug=0, security_token=None, validate_certs=True, https_connection_factory=None): - AWSAuthConnection.__init__(self, host, + super(Route53Connection, self).__init__(host, aws_access_key_id, aws_secret_access_key, True, port, proxy, proxy_port, debug=debug, security_token=security_token, @@ -82,7 +82,7 @@ class Route53Connection(AWSAuthConnection): continue pairs.append(key + '=' + urllib.quote(str(val))) path += '?' + '&'.join(pairs) - return AWSAuthConnection.make_request(self, action, path, + return super(Route53Connection, self).make_request(action, path, headers, data, retry_handler=self._retry_handler) diff --git a/awx/lib/site-packages/boto/route53/record.py b/awx/lib/site-packages/boto/route53/record.py index d26ca11953..17f38b94c8 100644 --- a/awx/lib/site-packages/boto/route53/record.py +++ b/awx/lib/site-packages/boto/route53/record.py @@ -54,7 +54,7 @@ class ResourceRecordSets(ResultSet): self.changes = [] self.next_record_name = None self.next_record_type = None - ResultSet.__init__(self, [('ResourceRecordSet', Record)]) + super(ResourceRecordSets, self).__init__([('ResourceRecordSet', Record)]) def __repr__(self): if self.changes: @@ -156,11 +156,11 @@ class ResourceRecordSets(ResultSet): elif name == 'NextRecordType': self.next_record_type = value else: - return ResultSet.endElement(self, name, value, connection) + return super(ResourceRecordSets, self).endElement(name, value, connection) def __iter__(self): """Override the next function to support paging""" - results = ResultSet.__iter__(self) + results = super(ResourceRecordSets, self).__iter__() truncated = self.is_truncated while results: for obj in results: diff --git a/awx/lib/site-packages/boto/s3/__init__.py b/awx/lib/site-packages/boto/s3/__init__.py index f7237157da..49a73ea7f4 100644 --- a/awx/lib/site-packages/boto/s3/__init__.py +++ b/awx/lib/site-packages/boto/s3/__init__.py @@ -77,6 +77,9 @@ def regions(): S3RegionInfo(name='sa-east-1', endpoint='s3-sa-east-1.amazonaws.com', connection_cls=S3Connection), + S3RegionInfo(name='cn-north-1', + endpoint='s3.cn-north-1.amazonaws.com.cn', + connection_cls=S3Connection), ] diff --git a/awx/lib/site-packages/boto/s3/acl.py b/awx/lib/site-packages/boto/s3/acl.py index a7bca8c97c..c54ddc6262 100644 --- a/awx/lib/site-packages/boto/s3/acl.py +++ b/awx/lib/site-packages/boto/s3/acl.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -28,7 +28,7 @@ CannedACLStrings = ['private', 'public-read', 'log-delivery-write'] -class Policy: +class Policy(object): def __init__(self, parent=None): self.parent = parent @@ -74,7 +74,7 @@ class Policy: s += '' return s -class ACL: +class ACL(object): def __init__(self, policy=None): self.policy = policy @@ -111,8 +111,8 @@ class ACL: s += grant.to_xml() s += '' return s - -class Grant: + +class Grant(object): NameSpace = 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' @@ -160,5 +160,5 @@ class Grant: s += '%s' % self.permission s += '' return s - - + + diff --git a/awx/lib/site-packages/boto/s3/bucket.py b/awx/lib/site-packages/boto/s3/bucket.py index 03d21e137c..a14fb8a72a 100644 --- a/awx/lib/site-packages/boto/s3/bucket.py +++ b/awx/lib/site-packages/boto/s3/bucket.py @@ -54,7 +54,7 @@ from collections import defaultdict # as per http://goo.gl/BDuud (02/19/2011) -class S3WebsiteEndpointTranslate: +class S3WebsiteEndpointTranslate(object): trans_region = defaultdict(lambda: 's3-website-us-east-1') trans_region['eu-west-1'] = 's3-website-eu-west-1' @@ -64,6 +64,7 @@ class S3WebsiteEndpointTranslate: trans_region['ap-northeast-1'] = 's3-website-ap-northeast-1' trans_region['ap-southeast-1'] = 's3-website-ap-southeast-1' trans_region['ap-southeast-2'] = 's3-website-ap-southeast-2' + trans_region['cn-north-1'] = 's3-website.cn-north-1' @classmethod def translate_region(self, reg): @@ -211,7 +212,8 @@ class Bucket(object): raise self.connection.provider.storage_response_error( response.status, response.reason, '') - def list(self, prefix='', delimiter='', marker='', headers=None): + def list(self, prefix='', delimiter='', marker='', headers=None, + encoding_type=None): """ List key objects within a bucket. This returns an instance of an BucketListResultSet that automatically handles all of the result @@ -243,13 +245,26 @@ class Bucket(object): :type marker: string :param marker: The "marker" of where you are in the result set + :param encoding_type: Requests Amazon S3 to encode the response and + specifies the encoding method to use. + + An object key can contain any Unicode character; however, XML 1.0 + parser cannot parse some characters, such as characters with an + ASCII value from 0 to 10. For characters that are not supported in + XML 1.0, you can add this parameter to request that Amazon S3 + encode the keys in the response. + + Valid options: ``url`` + :type encoding_type: string + :rtype: :class:`boto.s3.bucketlistresultset.BucketListResultSet` :return: an instance of a BucketListResultSet that handles paging, etc """ - return BucketListResultSet(self, prefix, delimiter, marker, headers) + return BucketListResultSet(self, prefix, delimiter, marker, headers, + encoding_type=encoding_type) def list_versions(self, prefix='', delimiter='', key_marker='', - version_id_marker='', headers=None): + version_id_marker='', headers=None, encoding_type=None): """ List version objects within a bucket. This returns an instance of an VersionedBucketListResultSet that automatically @@ -273,34 +288,63 @@ class Bucket(object): for more details. - :type marker: string - :param marker: The "marker" of where you are in the result set + :type key_marker: string + :param key_marker: The "marker" of where you are in the result set + + :param encoding_type: Requests Amazon S3 to encode the response and + specifies the encoding method to use. + + An object key can contain any Unicode character; however, XML 1.0 + parser cannot parse some characters, such as characters with an + ASCII value from 0 to 10. For characters that are not supported in + XML 1.0, you can add this parameter to request that Amazon S3 + encode the keys in the response. + + Valid options: ``url`` + :type encoding_type: string :rtype: :class:`boto.s3.bucketlistresultset.BucketListResultSet` :return: an instance of a BucketListResultSet that handles paging, etc """ return VersionedBucketListResultSet(self, prefix, delimiter, key_marker, version_id_marker, - headers) + headers, + encoding_type=encoding_type) def list_multipart_uploads(self, key_marker='', upload_id_marker='', - headers=None): + headers=None, encoding_type=None): """ List multipart upload objects within a bucket. This returns an instance of an MultiPartUploadListResultSet that automatically handles all of the result paging, etc. from S3. You just need to keep iterating until there are no more results. - :type marker: string - :param marker: The "marker" of where you are in the result set + :type key_marker: string + :param key_marker: The "marker" of where you are in the result set + + :type upload_id_marker: string + :param upload_id_marker: The upload identifier + + :param encoding_type: Requests Amazon S3 to encode the response and + specifies the encoding method to use. + + An object key can contain any Unicode character; however, XML 1.0 + parser cannot parse some characters, such as characters with an + ASCII value from 0 to 10. For characters that are not supported in + XML 1.0, you can add this parameter to request that Amazon S3 + encode the keys in the response. + + Valid options: ``url`` + :type encoding_type: string :rtype: :class:`boto.s3.bucketlistresultset.BucketListResultSet` :return: an instance of a BucketListResultSet that handles paging, etc """ return MultiPartUploadListResultSet(self, key_marker, upload_id_marker, - headers) + headers, + encoding_type=encoding_type) def _get_all_query_args(self, params, initial_query_string=''): pairs = [] @@ -342,10 +386,19 @@ class Bucket(object): raise self.connection.provider.storage_response_error( response.status, response.reason, body) - def _validate_kwarg_names(self, kwargs, names): + def validate_kwarg_names(self, kwargs, names): + """ + Checks that all named arguments are in the specified list of names. + + :type kwargs: dict + :param kwargs: Dictionary of kwargs to validate. + + :type names: list + :param names: List of possible named arguments. + """ for kwarg in kwargs: if kwarg not in names: - raise TypeError('Invalid argument %s!' % kwarg) + raise TypeError('Invalid argument "%s"!' % kwarg) def get_all_keys(self, headers=None, **params): """ @@ -372,12 +425,25 @@ class Bucket(object): element in the CommonPrefixes collection. These rolled-up keys are not returned elsewhere in the response. + :param encoding_type: Requests Amazon S3 to encode the response and + specifies the encoding method to use. + + An object key can contain any Unicode character; however, XML 1.0 + parser cannot parse some characters, such as characters with an + ASCII value from 0 to 10. For characters that are not supported in + XML 1.0, you can add this parameter to request that Amazon S3 + encode the keys in the response. + + Valid options: ``url`` + :type encoding_type: string + :rtype: ResultSet :return: The result from S3 listing the keys requested """ - self._validate_kwarg_names(params, ['maxkeys', 'max_keys', 'prefix', - 'marker', 'delimiter']) + self.validate_kwarg_names(params, ['maxkeys', 'max_keys', 'prefix', + 'marker', 'delimiter', + 'encoding_type']) return self._get_all([('Contents', self.key_class), ('CommonPrefixes', Prefix)], '', headers, **params) @@ -412,17 +478,39 @@ class Bucket(object): element in the CommonPrefixes collection. These rolled-up keys are not returned elsewhere in the response. + :param encoding_type: Requests Amazon S3 to encode the response and + specifies the encoding method to use. + + An object key can contain any Unicode character; however, XML 1.0 + parser cannot parse some characters, such as characters with an + ASCII value from 0 to 10. For characters that are not supported in + XML 1.0, you can add this parameter to request that Amazon S3 + encode the keys in the response. + + Valid options: ``url`` + :type encoding_type: string + :rtype: ResultSet :return: The result from S3 listing the keys requested """ - self._validate_kwarg_names(params, ['maxkeys', 'max_keys', 'prefix', - 'key_marker', 'version_id_marker', - 'delimiter']) + self.validate_get_all_versions_params(params) return self._get_all([('Version', self.key_class), ('CommonPrefixes', Prefix), ('DeleteMarker', DeleteMarker)], 'versions', headers, **params) + def validate_get_all_versions_params(self, params): + """ + Validate that the parameters passed to get_all_versions are valid. + Overridden by subclasses that allow a different set of parameters. + + :type params: dict + :param params: Parameters to validate. + """ + self.validate_kwarg_names( + params, ['maxkeys', 'max_keys', 'prefix', 'key_marker', + 'version_id_marker', 'delimiter', 'encoding_type']) + def get_all_multipart_uploads(self, headers=None, **params): """ A lower-level, version-aware method for listing active @@ -457,12 +545,24 @@ class Bucket(object): list only if they have an upload ID lexicographically greater than the specified upload_id_marker. + :param encoding_type: Requests Amazon S3 to encode the response and + specifies the encoding method to use. + + An object key can contain any Unicode character; however, XML 1.0 + parser cannot parse some characters, such as characters with an + ASCII value from 0 to 10. For characters that are not supported in + XML 1.0, you can add this parameter to request that Amazon S3 + encode the keys in the response. + + Valid options: ``url`` + :type encoding_type: string + :rtype: ResultSet :return: The result from S3 listing the uploads requested """ - self._validate_kwarg_names(params, ['max_uploads', 'key_marker', - 'upload_id_marker']) + self.validate_kwarg_names(params, ['max_uploads', 'key_marker', + 'upload_id_marker', 'encoding_type']) return self._get_all([('Upload', MultiPartUpload), ('CommonPrefixes', Prefix)], 'uploads', headers, **params) @@ -1530,6 +1630,15 @@ class Bucket(object): """ Start a multipart upload operation. + .. note:: + + Note: After you initiate multipart upload and upload one or more + parts, you must either complete or abort multipart upload in order + to stop getting charged for storage of the uploaded parts. Only + after you either complete or abort multipart upload, Amazon S3 + frees up the parts storage and stops charging you for the parts + storage. + :type key_name: string :param key_name: The name of the key that will ultimately result from this multipart upload operation. This will be @@ -1630,6 +1739,11 @@ class Bucket(object): response.status, response.reason, body) def cancel_multipart_upload(self, key_name, upload_id, headers=None): + """ + To verify that all parts have been removed, so you don't get charged + for the part storage, you should call the List Parts operation and + ensure the parts list is empty. + """ query_args = 'uploadId=%s' % upload_id response = self.connection.make_request('DELETE', self.name, key_name, query_args=query_args, diff --git a/awx/lib/site-packages/boto/s3/bucketlistresultset.py b/awx/lib/site-packages/boto/s3/bucketlistresultset.py index e11eb493a5..f0bc060276 100644 --- a/awx/lib/site-packages/boto/s3/bucketlistresultset.py +++ b/awx/lib/site-packages/boto/s3/bucketlistresultset.py @@ -14,12 +14,13 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -def bucket_lister(bucket, prefix='', delimiter='', marker='', headers=None): +def bucket_lister(bucket, prefix='', delimiter='', marker='', headers=None, + encoding_type=None): """ A generator function for listing keys in a bucket. """ @@ -27,14 +28,15 @@ def bucket_lister(bucket, prefix='', delimiter='', marker='', headers=None): k = None while more_results: rs = bucket.get_all_keys(prefix=prefix, marker=marker, - delimiter=delimiter, headers=headers) + delimiter=delimiter, headers=headers, + encoding_type=encoding_type) for k in rs: yield k if k: marker = rs.next_marker or k.name more_results= rs.is_truncated - -class BucketListResultSet: + +class BucketListResultSet(object): """ A resultset for listing keys within a bucket. Uses the bucket_lister generator function and implements the iterator interface. This @@ -43,20 +45,24 @@ class BucketListResultSet: keys in a reasonably efficient manner. """ - def __init__(self, bucket=None, prefix='', delimiter='', marker='', headers=None): + def __init__(self, bucket=None, prefix='', delimiter='', marker='', + headers=None, encoding_type=None): self.bucket = bucket self.prefix = prefix self.delimiter = delimiter self.marker = marker self.headers = headers + self.encoding_type = encoding_type def __iter__(self): return bucket_lister(self.bucket, prefix=self.prefix, delimiter=self.delimiter, marker=self.marker, - headers=self.headers) + headers=self.headers, + encoding_type=self.encoding_type) def versioned_bucket_lister(bucket, prefix='', delimiter='', - key_marker='', version_id_marker='', headers=None): + key_marker='', version_id_marker='', headers=None, + encoding_type=None): """ A generator function for listing versions in a bucket. """ @@ -66,14 +72,14 @@ def versioned_bucket_lister(bucket, prefix='', delimiter='', rs = bucket.get_all_versions(prefix=prefix, key_marker=key_marker, version_id_marker=version_id_marker, delimiter=delimiter, headers=headers, - max_keys=999) + max_keys=999, encoding_type=encoding_type) for k in rs: yield k key_marker = rs.next_key_marker version_id_marker = rs.next_version_id_marker more_results= rs.is_truncated - -class VersionedBucketListResultSet: + +class VersionedBucketListResultSet(object): """ A resultset for listing versions within a bucket. Uses the bucket_lister generator function and implements the iterator interface. This @@ -83,24 +89,26 @@ class VersionedBucketListResultSet: """ def __init__(self, bucket=None, prefix='', delimiter='', key_marker='', - version_id_marker='', headers=None): + version_id_marker='', headers=None, encoding_type=None): self.bucket = bucket self.prefix = prefix self.delimiter = delimiter self.key_marker = key_marker self.version_id_marker = version_id_marker self.headers = headers + self.encoding_type = encoding_type def __iter__(self): return versioned_bucket_lister(self.bucket, prefix=self.prefix, delimiter=self.delimiter, key_marker=self.key_marker, version_id_marker=self.version_id_marker, - headers=self.headers) + headers=self.headers, + encoding_type=self.encoding_type) def multipart_upload_lister(bucket, key_marker='', upload_id_marker='', - headers=None): + headers=None, encoding_type=None): """ A generator function for listing multipart uploads in a bucket. """ @@ -109,14 +117,15 @@ def multipart_upload_lister(bucket, key_marker='', while more_results: rs = bucket.get_all_multipart_uploads(key_marker=key_marker, upload_id_marker=upload_id_marker, - headers=headers) + headers=headers, + encoding_type=encoding_type) for k in rs: yield k key_marker = rs.next_key_marker upload_id_marker = rs.next_upload_id_marker more_results= rs.is_truncated - -class MultiPartUploadListResultSet: + +class MultiPartUploadListResultSet(object): """ A resultset for listing multipart uploads within a bucket. Uses the multipart_upload_lister generator function and @@ -126,14 +135,16 @@ class MultiPartUploadListResultSet: keys in a reasonably efficient manner. """ def __init__(self, bucket=None, key_marker='', - upload_id_marker='', headers=None): + upload_id_marker='', headers=None, encoding_type=None): self.bucket = bucket self.key_marker = key_marker self.upload_id_marker = upload_id_marker self.headers = headers + self.encoding_type = encoding_type def __iter__(self): return multipart_upload_lister(self.bucket, key_marker=self.key_marker, upload_id_marker=self.upload_id_marker, - headers=self.headers) + headers=self.headers, + encoding_type=self.encoding_type) diff --git a/awx/lib/site-packages/boto/s3/bucketlogging.py b/awx/lib/site-packages/boto/s3/bucketlogging.py index 9e3c050d28..ab3683926a 100644 --- a/awx/lib/site-packages/boto/s3/bucketlogging.py +++ b/awx/lib/site-packages/boto/s3/bucketlogging.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -22,7 +22,7 @@ import xml.sax.saxutils from acl import Grant -class BucketLogging: +class BucketLogging(object): def __init__(self, target=None, prefix=None, grants=None): self.target = target @@ -68,7 +68,7 @@ class BucketLogging: # caller is responsible to encode to utf-8 s = u'' s += u'' - if self.target is not None: + if self.target is not None: s += u'' s += u'%s' % self.target prefix = self.prefix or '' diff --git a/awx/lib/site-packages/boto/s3/connection.py b/awx/lib/site-packages/boto/s3/connection.py index 583fa16832..4a15809077 100644 --- a/awx/lib/site-packages/boto/s3/connection.py +++ b/awx/lib/site-packages/boto/s3/connection.py @@ -27,6 +27,7 @@ import urllib import base64 import time +from boto.auth import detect_potential_s3sigv4 import boto.utils from boto.connection import AWSAuthConnection from boto import handler @@ -134,7 +135,7 @@ class ProtocolIndependentOrdinaryCallingFormat(OrdinaryCallingFormat): return url_base -class Location: +class Location(object): DEFAULT = '' # US Classic Region EU = 'EU' @@ -144,6 +145,7 @@ class Location: APNortheast = 'ap-northeast-1' APSoutheast = 'ap-southeast-1' APSoutheast2 = 'ap-southeast-2' + CNNorth1 = 'cn-north-1' class S3Connection(AWSAuthConnection): @@ -165,7 +167,7 @@ class S3Connection(AWSAuthConnection): self.calling_format = calling_format self.bucket_class = bucket_class self.anon = anon - AWSAuthConnection.__init__(self, host, + super(S3Connection, self).__init__(host, aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, debug=debug, https_connection_factory=https_connection_factory, @@ -173,6 +175,7 @@ class S3Connection(AWSAuthConnection): suppress_consec_slashes=suppress_consec_slashes, validate_certs=validate_certs) + @detect_potential_s3sigv4 def _required_auth_capability(self): if self.anon: return ['anon'] @@ -540,8 +543,8 @@ class S3Connection(AWSAuthConnection): boto.log.debug('path=%s' % path) auth_path += '?' + query_args boto.log.debug('auth_path=%s' % auth_path) - return AWSAuthConnection.make_request( - self, method, path, headers, + return super(S3Connection, self).make_request( + method, path, headers, data, host, auth_path, sender, override_num_retries=override_num_retries, retry_handler=retry_handler diff --git a/awx/lib/site-packages/boto/s3/deletemarker.py b/awx/lib/site-packages/boto/s3/deletemarker.py index 5db4343a91..d8e7cc8b58 100644 --- a/awx/lib/site-packages/boto/s3/deletemarker.py +++ b/awx/lib/site-packages/boto/s3/deletemarker.py @@ -14,14 +14,14 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. from boto.s3.user import User -class DeleteMarker: +class DeleteMarker(object): def __init__(self, bucket=None, name=None): self.bucket = bucket self.name = name diff --git a/awx/lib/site-packages/boto/s3/key.py b/awx/lib/site-packages/boto/s3/key.py index 2b7ae73ae7..0849584d46 100644 --- a/awx/lib/site-packages/boto/s3/key.py +++ b/awx/lib/site-packages/boto/s3/key.py @@ -23,6 +23,7 @@ from __future__ import with_statement import errno +import hashlib import mimetypes import os import re @@ -40,7 +41,7 @@ from boto.provider import Provider from boto.s3.keyfile import KeyFile from boto.s3.user import User from boto import UserAgent -from boto.utils import compute_md5 +from boto.utils import compute_md5, compute_hash from boto.utils import find_matching_headers from boto.utils import merge_headers_by_name try: @@ -894,6 +895,12 @@ class Key(object): # headers['Trailer'] = "Content-MD5" else: headers['Content-Length'] = str(self.size) + # This is terrible. We need a SHA256 of the body for SigV4, but to do + # the chunked ``sender`` behavior above, the ``fp`` isn't available to + # the auth mechanism (because closures). Detect if it's SigV4 & embelish + # while we can before the auth calculations occur. + if 'hmac-v4-s3' in self.bucket.connection._required_auth_capability(): + headers['_sha256'] = compute_hash(fp, hash_algorithm=hashlib.sha256)[0] headers['Expect'] = '100-Continue' headers = boto.utils.merge_meta(headers, self.metadata, provider) resp = self.bucket.connection.make_request( @@ -1305,7 +1312,7 @@ class Key(object): reduced_redundancy, encrypt_key=encrypt_key) - def set_contents_from_string(self, s, headers=None, replace=True, + def set_contents_from_string(self, string_data, headers=None, replace=True, cb=None, num_cb=10, policy=None, md5=None, reduced_redundancy=False, encrypt_key=False): @@ -1362,9 +1369,9 @@ class Key(object): be encrypted on the server-side by S3 and will be stored in an encrypted form while at rest in S3. """ - if isinstance(s, unicode): - s = s.encode("utf-8") - fp = StringIO.StringIO(s) + if isinstance(string_data, unicode): + string_data = string_data.encode("utf-8") + fp = StringIO.StringIO(string_data) r = self.set_contents_from_file(fp, headers, replace, cb, num_cb, policy, md5, reduced_redundancy, encrypt_key=encrypt_key) @@ -1623,17 +1630,16 @@ class Key(object): with the stored object in the response. See http://goo.gl/EWOPb for details. """ - fp = open(filename, 'wb') try: - self.get_contents_to_file(fp, headers, cb, num_cb, torrent=torrent, - version_id=version_id, - res_download_handler=res_download_handler, - response_headers=response_headers) + with open(filename, 'wb') as fp: + self.get_contents_to_file(fp, headers, cb, num_cb, + torrent=torrent, + version_id=version_id, + res_download_handler=res_download_handler, + response_headers=response_headers) except Exception: os.remove(filename) raise - finally: - fp.close() # if last_modified date was sent from s3, try to set file's timestamp if self.last_modified != None: try: diff --git a/awx/lib/site-packages/boto/s3/multipart.py b/awx/lib/site-packages/boto/s3/multipart.py index fae3389ef7..ba89d7359c 100644 --- a/awx/lib/site-packages/boto/s3/multipart.py +++ b/awx/lib/site-packages/boto/s3/multipart.py @@ -199,7 +199,8 @@ class MultiPartUpload(object): else: setattr(self, name, value) - def get_all_parts(self, max_parts=None, part_number_marker=None): + def get_all_parts(self, max_parts=None, part_number_marker=None, + encoding_type=None): """ Return the uploaded parts of this MultiPart Upload. This is a lower-level method that requires you to manually page through @@ -213,6 +214,8 @@ class MultiPartUpload(object): query_args += '&max-parts=%d' % max_parts if part_number_marker: query_args += '&part-number-marker=%s' % part_number_marker + if encoding_type: + query_args += '&encoding-type=%s' % encoding_type response = self.bucket.connection.make_request('GET', self.bucket.name, self.key_name, query_args=query_args) @@ -227,6 +230,14 @@ class MultiPartUpload(object): """ Upload another part of this MultiPart Upload. + .. note:: + + After you initiate multipart upload and upload one or more parts, + you must either complete or abort multipart upload in order to stop + getting charged for storage of the uploaded parts. Only after you + either complete or abort multipart upload, Amazon S3 frees up the + parts storage and stops charging you for the parts storage. + :type fp: file :param fp: The file object you want to upload. diff --git a/awx/lib/site-packages/boto/s3/user.py b/awx/lib/site-packages/boto/s3/user.py index f45f038130..f2cbbb7f8f 100644 --- a/awx/lib/site-packages/boto/s3/user.py +++ b/awx/lib/site-packages/boto/s3/user.py @@ -14,12 +14,12 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -class User: +class User(object): def __init__(self, parent=None, id='', display_name=''): if parent: parent.owner = self @@ -46,4 +46,4 @@ class User: s += '%s' % self.id s += '%s' % self.display_name s += '' % element_name - return s + return s diff --git a/awx/lib/site-packages/boto/sdb/connection.py b/awx/lib/site-packages/boto/sdb/connection.py index dc5e01d55d..04212df81d 100644 --- a/awx/lib/site-packages/boto/sdb/connection.py +++ b/awx/lib/site-packages/boto/sdb/connection.py @@ -48,7 +48,7 @@ class ItemThread(threading.Thread): :class:`Domain `. :ivar list items: A list of items retrieved. Starts as empty list. """ - threading.Thread.__init__(self, name=name) + super(ItemThread, self).__init__(name=name) #print 'starting %s with %d items' % (name, len(item_names)) self.domain_name = domain_name self.conn = SDBConnection() @@ -111,7 +111,7 @@ class SDBConnection(AWSQueryConnection): break self.region = region - AWSQueryConnection.__init__(self, aws_access_key_id, + super(SDBConnection, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, diff --git a/awx/lib/site-packages/boto/sdb/db/manager/xmlmanager.py b/awx/lib/site-packages/boto/sdb/db/manager/xmlmanager.py index 04210db85e..c4cc5d3e7c 100644 --- a/awx/lib/site-packages/boto/sdb/db/manager/xmlmanager.py +++ b/awx/lib/site-packages/boto/sdb/db/manager/xmlmanager.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -27,7 +27,7 @@ from xml.dom.minidom import getDOMImplementation, parse, parseString, Node ISO8601 = '%Y-%m-%dT%H:%M:%SZ' -class XMLConverter: +class XMLConverter(object): """ Responsible for converting base Python types to format compatible with underlying database. For SimpleDB, that means everything needs to be converted to a string @@ -179,7 +179,7 @@ class XMLConverter: class XMLManager(object): - + def __init__(self, cls, db_name, db_user, db_passwd, db_host, db_port, db_table, ddl_dir, enable_ssl): self.cls = cls @@ -260,7 +260,7 @@ class XMLManager(object): def get_doc(self): return self.doc - + def encode_value(self, prop, value): return self.converter.encode_prop(prop, value) @@ -324,8 +324,8 @@ class XMLManager(object): if value != None: props[prop.name] = value return (cls, props, id) - - + + def get_object(self, cls, id): if not self.connection: self._connect() @@ -352,7 +352,7 @@ class XMLManager(object): query = str(self._build_query(cls, filters, limit, order_by)) if query: url = "/%s?%s" % (self.db_name, urlencode({"query": query})) - else: + else: url = "/%s" % self.db_name resp = self._make_request('GET', url) if resp.status == 200: @@ -471,7 +471,7 @@ class XMLManager(object): else: doc = parse(fp) return self.get_object_from_doc(cls, id, doc) - + def unmarshal_props(self, fp, cls=None, id=None): """ Same as unmarshalling an object, except it returns @@ -499,7 +499,7 @@ class XMLManager(object): return a[name] else: return None - + def get_raw_item(self, obj): return self.domain.get_item(obj.id) diff --git a/awx/lib/site-packages/boto/sdb/db/property.py b/awx/lib/site-packages/boto/sdb/db/property.py index b8610cfeff..44dab47d71 100644 --- a/awx/lib/site-packages/boto/sdb/db/property.py +++ b/awx/lib/site-packages/boto/sdb/db/property.py @@ -127,7 +127,7 @@ class StringProperty(Property): def __init__(self, verbose_name=None, name=None, default='', required=False, validator=validate_string, choices=None, unique=False): - Property.__init__(self, verbose_name, name, default, required, + super(StringProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) @@ -138,7 +138,7 @@ class TextProperty(Property): def __init__(self, verbose_name=None, name=None, default='', required=False, validator=None, choices=None, unique=False, max_length=None): - Property.__init__(self, verbose_name, name, default, required, + super(TextProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) self.max_length = max_length @@ -207,7 +207,7 @@ class PasswordProperty(StringProperty): The remaining parameters are passed through to StringProperty.__init__""" - StringProperty.__init__(self, verbose_name, name, default, required, + super(PasswordProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) self.hashfunc = hashfunc @@ -216,7 +216,7 @@ class PasswordProperty(StringProperty): return p def get_value_for_datastore(self, model_instance): - value = StringProperty.get_value_for_datastore(self, model_instance) + value = super(PasswordProperty, self).get_value_for_datastore(model_instance) if value and len(value): return str(value) else: @@ -227,13 +227,13 @@ class PasswordProperty(StringProperty): p = self.data_type(hashfunc=self.hashfunc) p.set(value) value = p - Property.__set__(self, obj, value) + super(PasswordProperty, self).__set__(obj, value) def __get__(self, obj, objtype): - return self.data_type(StringProperty.__get__(self, obj, objtype), hashfunc=self.hashfunc) + return self.data_type(super(PasswordProperty, self).__get__(obj, objtype), hashfunc=self.hashfunc) def validate(self, value): - value = Property.validate(self, value) + value = super(PasswordProperty, self).validate(value) if isinstance(value, self.data_type): if len(value) > 1024: raise ValueError('Length of value greater than maxlength') @@ -254,7 +254,7 @@ class BlobProperty(Property): id = oldb.id b = Blob(value=value, id=id) value = b - Property.__set__(self, obj, value) + super(BlobProperty, self).__set__(obj, value) class S3KeyProperty(Property): @@ -265,7 +265,7 @@ class S3KeyProperty(Property): def __init__(self, verbose_name=None, name=None, default=None, required=False, validator=None, choices=None, unique=False): - Property.__init__(self, verbose_name, name, default, required, + super(S3KeyProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) def validate(self, value): @@ -280,7 +280,7 @@ class S3KeyProperty(Property): raise TypeError('Validation Error, expecting %s, got %s' % (self.data_type, type(value))) def __get__(self, obj, objtype): - value = Property.__get__(self, obj, objtype) + value = super(S3KeyProperty, self).__get__(obj, objtype) if value: if isinstance(value, self.data_type): return value @@ -297,7 +297,7 @@ class S3KeyProperty(Property): return value def get_value_for_datastore(self, model_instance): - value = Property.get_value_for_datastore(self, model_instance) + value = super(S3KeyProperty, self).get_value_for_datastore(model_instance) if value: return "s3://%s/%s" % (value.bucket.name, value.name) else: @@ -311,13 +311,13 @@ class IntegerProperty(Property): def __init__(self, verbose_name=None, name=None, default=0, required=False, validator=None, choices=None, unique=False, max=2147483647, min=-2147483648): - Property.__init__(self, verbose_name, name, default, required, validator, choices, unique) + super(IntegerProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) self.max = max self.min = min def validate(self, value): value = int(value) - value = Property.validate(self, value) + value = super(IntegerProperty, self).validate(value) if value > self.max: raise ValueError('Maximum value is %d' % self.max) if value < self.min: @@ -330,7 +330,7 @@ class IntegerProperty(Property): def __set__(self, obj, value): if value == "" or value == None: value = 0 - return Property.__set__(self, obj, value) + return super(IntegerProperty, self).__set__(obj, value) class LongProperty(Property): @@ -340,11 +340,11 @@ class LongProperty(Property): def __init__(self, verbose_name=None, name=None, default=0, required=False, validator=None, choices=None, unique=False): - Property.__init__(self, verbose_name, name, default, required, validator, choices, unique) + super(LongProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) def validate(self, value): value = long(value) - value = Property.validate(self, value) + value = super(LongProperty, self).validate(value) min = -9223372036854775808 max = 9223372036854775807 if value > max: @@ -364,7 +364,7 @@ class BooleanProperty(Property): def __init__(self, verbose_name=None, name=None, default=False, required=False, validator=None, choices=None, unique=False): - Property.__init__(self, verbose_name, name, default, required, validator, choices, unique) + super(BooleanProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) def empty(self, value): return value is None @@ -377,11 +377,11 @@ class FloatProperty(Property): def __init__(self, verbose_name=None, name=None, default=0.0, required=False, validator=None, choices=None, unique=False): - Property.__init__(self, verbose_name, name, default, required, validator, choices, unique) + super(FloatProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) def validate(self, value): value = float(value) - value = Property.validate(self, value) + value = super(FloatProperty, self).validate(value) return value def empty(self, value): @@ -398,14 +398,14 @@ class DateTimeProperty(Property): def __init__(self, verbose_name=None, auto_now=False, auto_now_add=False, name=None, default=None, required=False, validator=None, choices=None, unique=False): - Property.__init__(self, verbose_name, name, default, required, validator, choices, unique) + super(DateTimeProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) self.auto_now = auto_now self.auto_now_add = auto_now_add def default_value(self): if self.auto_now or self.auto_now_add: return self.now() - return Property.default_value(self) + return super(DateTimeProperty, self).default_value() def validate(self, value): if value == None: @@ -417,7 +417,7 @@ class DateTimeProperty(Property): def get_value_for_datastore(self, model_instance): if self.auto_now: setattr(model_instance, self.name, self.now()) - return Property.get_value_for_datastore(self, model_instance) + return super(DateTimeProperty, self).get_value_for_datastore(model_instance) def now(self): return datetime.datetime.utcnow() @@ -430,14 +430,14 @@ class DateProperty(Property): def __init__(self, verbose_name=None, auto_now=False, auto_now_add=False, name=None, default=None, required=False, validator=None, choices=None, unique=False): - Property.__init__(self, verbose_name, name, default, required, validator, choices, unique) + super(DateProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) self.auto_now = auto_now self.auto_now_add = auto_now_add def default_value(self): if self.auto_now or self.auto_now_add: return self.now() - return Property.default_value(self) + return super(DateProperty, self).default_value() def validate(self, value): value = super(DateProperty, self).validate(value) @@ -449,7 +449,7 @@ class DateProperty(Property): def get_value_for_datastore(self, model_instance): if self.auto_now: setattr(model_instance, self.name, self.now()) - val = Property.get_value_for_datastore(self, model_instance) + val = super(DateProperty, self).get_value_for_datastore(model_instance) if isinstance(val, datetime.datetime): val = val.date() return val @@ -464,7 +464,7 @@ class TimeProperty(Property): def __init__(self, verbose_name=None, name=None, default=None, required=False, validator=None, choices=None, unique=False): - Property.__init__(self, verbose_name, name, default, required, validator, choices, unique) + super(TimeProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) def validate(self, value): value = super(TimeProperty, self).validate(value) @@ -481,7 +481,7 @@ class ReferenceProperty(Property): def __init__(self, reference_class=None, collection_name=None, verbose_name=None, name=None, default=None, required=False, validator=None, choices=None, unique=False): - Property.__init__(self, verbose_name, name, default, required, validator, choices, unique) + super(ReferenceProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) self.reference_class = reference_class self.collection_name = collection_name @@ -506,7 +506,7 @@ class ReferenceProperty(Property): return super(ReferenceProperty, self).__set__(obj, value) def __property_config__(self, model_class, property_name): - Property.__property_config__(self, model_class, property_name) + super(ReferenceProperty, self).__property_config__(model_class, property_name) if self.collection_name is None: self.collection_name = '%s_%s_set' % (model_class.__name__.lower(), self.name) if hasattr(self.reference_class, self.collection_name): @@ -576,7 +576,7 @@ class CalculatedProperty(Property): def __init__(self, verbose_name=None, name=None, default=None, required=False, validator=None, choices=None, calculated_type=int, unique=False, use_method=False): - Property.__init__(self, verbose_name, name, default, required, + super(CalculatedProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) self.calculated_type = calculated_type self.use_method = use_method @@ -617,7 +617,7 @@ class ListProperty(Property): if default is None: default = [] self.item_type = item_type - Property.__init__(self, verbose_name, name, default=default, required=True, **kwds) + super(ListProperty, self).__init__(verbose_name, name, default=default, required=True, **kwds) def validate(self, value): if self.validator: @@ -672,7 +672,7 @@ class MapProperty(Property): if default is None: default = {} self.item_type = item_type - Property.__init__(self, verbose_name, name, default=default, required=True, **kwds) + super(MapProperty, self).__init__(verbose_name, name, default=default, required=True, **kwds) def validate(self, value): value = super(MapProperty, self).validate(value) diff --git a/awx/lib/site-packages/boto/sdb/domain.py b/awx/lib/site-packages/boto/sdb/domain.py index d4faf04620..6f0489e2ad 100644 --- a/awx/lib/site-packages/boto/sdb/domain.py +++ b/awx/lib/site-packages/boto/sdb/domain.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -24,7 +24,7 @@ Represents an SDB Domain """ from boto.sdb.queryresultset import SelectResultSet -class Domain: +class Domain(object): def __init__(self, connection=None, name=None): self.connection = connection @@ -64,19 +64,19 @@ class Domain: :type expected_value: list :param expected_value: If supplied, this is a list or tuple consisting - of a single attribute name and expected value. The list can be + of a single attribute name and expected value. The list can be of the form: * ['name', 'value'] - In which case the call will first verify that the attribute + In which case the call will first verify that the attribute "name" of this item has a value of "value". If it does, the delete - will proceed, otherwise a ConditionalCheckFailed error will be + will proceed, otherwise a ConditionalCheckFailed error will be returned. The list can also be of the form: - + * ['name', True|False] - - which will simply check for the existence (True) or non-existence + + which will simply check for the existence (True) or non-existence (False) of the attribute. :type replace: bool @@ -144,22 +144,22 @@ class Domain: a dict or Item containing the attribute names and keys and list of values to delete as the value. If no value is supplied, all attribute name/values for the item will be deleted. - + :type expected_value: list :param expected_value: If supplied, this is a list or tuple consisting - of a single attribute name and expected value. The list can be of + of a single attribute name and expected value. The list can be of the form: * ['name', 'value'] In which case the call will first verify that the attribute "name" of this item has a value of "value". If it does, the delete - will proceed, otherwise a ConditionalCheckFailed error will be + will proceed, otherwise a ConditionalCheckFailed error will be returned. The list can also be of the form: * ['name', True|False] - which will simply check for the existence (True) or + which will simply check for the existence (True) or non-existence (False) of the attribute. :rtype: bool @@ -171,7 +171,7 @@ class Domain: def batch_delete_attributes(self, items): """ Delete multiple items in this domain. - + :type items: dict or dict-like object :param items: A dictionary-like object. The keys of the dictionary are the item names and the values are either: @@ -182,7 +182,7 @@ class Domain: will only be deleted if they match the name/value pairs passed in. * None which means that all attributes associated - with the item should be deleted. + with the item should be deleted. :rtype: bool :return: True if successful @@ -209,12 +209,12 @@ class Domain: def get_item(self, item_name, consistent_read=False): """ Retrieves an item from the domain, along with all of its attributes. - + :param string item_name: The name of the item to retrieve. :rtype: :class:`boto.sdb.item.Item` or ``None`` - :keyword bool consistent_read: When set to true, ensures that the most + :keyword bool consistent_read: When set to true, ensures that the most recent data is returned. - :return: The requested item, or ``None`` if there was no match found + :return: The requested item, or ``None`` if there was no match found """ item = self.get_attributes(item_name, consistent_read=consistent_read) if item: @@ -279,7 +279,7 @@ class Domain: return self.connection.delete_domain(self) -class DomainMetaData: +class DomainMetaData(object): def __init__(self, domain=None): self.domain = domain @@ -364,7 +364,7 @@ class UploaderThread(Thread): def __init__(self, domain): self.db = domain self.items = {} - Thread.__init__(self) + super(UploaderThread, self).__init__() def run(self): try: diff --git a/awx/lib/site-packages/boto/sdb/queryresultset.py b/awx/lib/site-packages/boto/sdb/queryresultset.py index 10bafd1c92..f943949fe3 100644 --- a/awx/lib/site-packages/boto/sdb/queryresultset.py +++ b/awx/lib/site-packages/boto/sdb/queryresultset.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -34,8 +34,8 @@ def query_lister(domain, query='', max_items=None, attr_names=None): num_results += 1 next_token = rs.next_token more_results = next_token != None - -class QueryResultSet: + +class QueryResultSet(object): def __init__(self, domain=None, query='', max_items=None, attr_names=None): self.max_items = max_items @@ -60,7 +60,7 @@ def select_lister(domain, query='', max_items=None): num_results += 1 next_token = rs.next_token more_results = next_token != None - + class SelectResultSet(object): def __init__(self, domain=None, query='', max_items=None, diff --git a/awx/lib/site-packages/boto/sdb/regioninfo.py b/awx/lib/site-packages/boto/sdb/regioninfo.py index 5c32864d28..769be555ee 100644 --- a/awx/lib/site-packages/boto/sdb/regioninfo.py +++ b/awx/lib/site-packages/boto/sdb/regioninfo.py @@ -16,7 +16,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -28,5 +28,5 @@ class SDBRegionInfo(RegionInfo): def __init__(self, connection=None, name=None, endpoint=None): from boto.sdb.connection import SDBConnection - RegionInfo.__init__(self, connection, name, endpoint, + super(SDBRegionInfo, self).__init__(connection, name, endpoint, SDBConnection) diff --git a/awx/lib/site-packages/boto/services/result.py b/awx/lib/site-packages/boto/services/result.py index 4854976478..5f6d800d91 100644 --- a/awx/lib/site-packages/boto/services/result.py +++ b/awx/lib/site-packages/boto/services/result.py @@ -15,7 +15,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -25,8 +25,8 @@ from datetime import datetime, timedelta from boto.utils import parse_ts import boto -class ResultProcessor: - +class ResultProcessor(object): + LogFileName = 'log.csv' def __init__(self, batch_name, sd, mimetype_files=None): @@ -133,4 +133,4 @@ class ResultProcessor: print 'Elapsed Time: %d' % self.elapsed_time.seconds tput = 1.0 / ((self.elapsed_time.seconds/60.0) / self.num_files) print 'Throughput: %f transactions / minute' % tput - + diff --git a/awx/lib/site-packages/boto/services/service.py b/awx/lib/site-packages/boto/services/service.py index e0e987ce86..e1a04c8ec2 100644 --- a/awx/lib/site-packages/boto/services/service.py +++ b/awx/lib/site-packages/boto/services/service.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -35,7 +35,7 @@ class Service(ScriptBase): ProcessingTime = 60 def __init__(self, config_file=None, mimetype_files=None): - ScriptBase.__init__(self, config_file) + super(Service, self).__init__(config_file) self.name = self.__class__.__name__ self.working_dir = boto.config.get('Pyami', 'working_dir') self.sd = ServiceDef(config_file) @@ -100,7 +100,7 @@ class Service(ScriptBase): key = self.put_file(output_bucket, file, key_name) output_keys.append('%s;type=%s' % (key.name, type)) output_message['OutputKey'] = ','.join(output_keys) - + # write message to each output queue def write_message(self, message): message['Service-Write'] = get_ts() diff --git a/awx/lib/site-packages/boto/services/servicedef.py b/awx/lib/site-packages/boto/services/servicedef.py index 1cb01aa754..a43b3f342a 100644 --- a/awx/lib/site-packages/boto/services/servicedef.py +++ b/awx/lib/site-packages/boto/services/servicedef.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -26,7 +26,7 @@ import boto class ServiceDef(Config): def __init__(self, config_file, aws_access_key_id=None, aws_secret_access_key=None): - Config.__init__(self, config_file) + super(ServiceDef, self).__init__(config_file) self.aws_access_key_id = aws_access_key_id self.aws_secret_access_key = aws_secret_access_key script = Config.get(self, 'Pyami', 'scripts') @@ -37,22 +37,22 @@ class ServiceDef(Config): def get(self, name, default=None): - return Config.get(self, self.name, name, default) + return super(ServiceDef, self).get(self.name, name, default) def has_option(self, option): - return Config.has_option(self, self.name, option) + return super(ServiceDef, self).has_option(self.name, option) def getint(self, option, default=0): try: - val = Config.get(self, self.name, option) + val = super(ServiceDef, self).get(self.name, option) val = int(val) except: val = int(default) return val - + def getbool(self, option, default=False): try: - val = Config.get(self, self.name, option) + val = super(ServiceDef, self).get(self.name, option) if val.lower() == 'true': val = True else: @@ -60,7 +60,7 @@ class ServiceDef(Config): except: val = default return val - + def get_obj(self, name): """ Returns the AWS object associated with a given option. @@ -88,4 +88,4 @@ class ServiceDef(Config): obj = None return obj - + diff --git a/awx/lib/site-packages/boto/services/sonofmmm.py b/awx/lib/site-packages/boto/services/sonofmmm.py index acb7e61067..3ef60838b8 100644 --- a/awx/lib/site-packages/boto/services/sonofmmm.py +++ b/awx/lib/site-packages/boto/services/sonofmmm.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -28,7 +28,7 @@ import mimetypes class SonOfMMM(Service): def __init__(self, config_file=None): - Service.__init__(self, config_file) + super(SonOfMMM, self).__init__(config_file) self.log_file = '%s.log' % self.instance_id self.log_path = os.path.join(self.working_dir, self.log_file) boto.set_file_logger(self.name, self.log_path) @@ -78,4 +78,4 @@ class SonOfMMM(Service): if self.output_bucket: key = self.output_bucket.new_key(self.log_file) key.set_contents_from_filename(self.log_path) - Service.shutdown(self) + super(SonOfMMM, self).shutdown() diff --git a/awx/lib/site-packages/boto/services/submit.py b/awx/lib/site-packages/boto/services/submit.py index 89c439c525..2bc72241c3 100644 --- a/awx/lib/site-packages/boto/services/submit.py +++ b/awx/lib/site-packages/boto/services/submit.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -23,7 +23,7 @@ import time import os -class Submitter: +class Submitter(object): def __init__(self, sd): self.sd = sd diff --git a/awx/lib/site-packages/boto/ses/connection.py b/awx/lib/site-packages/boto/ses/connection.py index 8652042db1..5425ef3515 100644 --- a/awx/lib/site-packages/boto/ses/connection.py +++ b/awx/lib/site-packages/boto/ses/connection.py @@ -47,7 +47,7 @@ class SESConnection(AWSAuthConnection): region = RegionInfo(self, self.DefaultRegionName, self.DefaultRegionEndpoint) self.region = region - AWSAuthConnection.__init__(self, self.region.endpoint, + super(SESConnection, self).__init__(self.region.endpoint, aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, debug, diff --git a/awx/lib/site-packages/boto/sns/__init__.py b/awx/lib/site-packages/boto/sns/__init__.py index 4ed0539ab5..4764a94f17 100644 --- a/awx/lib/site-packages/boto/sns/__init__.py +++ b/awx/lib/site-packages/boto/sns/__init__.py @@ -60,6 +60,9 @@ def regions(): RegionInfo(name='ap-southeast-2', endpoint='sns.ap-southeast-2.amazonaws.com', connection_cls=SNSConnection), + RegionInfo(name='cn-north-1', + endpoint=' sns.cn-north-1.amazonaws.com.cn', + connection_cls=SNSConnection), ] diff --git a/awx/lib/site-packages/boto/sns/connection.py b/awx/lib/site-packages/boto/sns/connection.py index 701892ce86..1d459311fe 100644 --- a/awx/lib/site-packages/boto/sns/connection.py +++ b/awx/lib/site-packages/boto/sns/connection.py @@ -62,7 +62,7 @@ class SNSConnection(AWSQueryConnection): self.DefaultRegionEndpoint, connection_cls=SNSConnection) self.region = region - AWSQueryConnection.__init__(self, aws_access_key_id, + super(SNSConnection, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, @@ -274,7 +274,7 @@ class SNSConnection(AWSQueryConnection): * For http, this would be a URL beginning with http * For https, this would be a URL beginning with https * For sqs, this would be the ARN of an SQS Queue - * For sms, this would be a phone number of an SMS-enabled device + * For sms, this would be a phone number of an SMS-enabled device """ params = {'TopicArn': topic, 'Protocol': protocol, diff --git a/awx/lib/site-packages/boto/sqs/__init__.py b/awx/lib/site-packages/boto/sqs/__init__.py index 973b8ba55e..35e6c2bdec 100644 --- a/awx/lib/site-packages/boto/sqs/__init__.py +++ b/awx/lib/site-packages/boto/sqs/__init__.py @@ -47,7 +47,9 @@ def regions(): SQSRegionInfo(name='ap-southeast-1', endpoint='ap-southeast-1.queue.amazonaws.com'), SQSRegionInfo(name='ap-southeast-2', - endpoint='ap-southeast-2.queue.amazonaws.com') + endpoint='ap-southeast-2.queue.amazonaws.com'), + SQSRegionInfo(name='cn-north-1', + endpoint='sqs.cn-north-1.amazonaws.com.cn'), ] diff --git a/awx/lib/site-packages/boto/sqs/bigmessage.py b/awx/lib/site-packages/boto/sqs/bigmessage.py new file mode 100644 index 0000000000..e47ec045a1 --- /dev/null +++ b/awx/lib/site-packages/boto/sqs/bigmessage.py @@ -0,0 +1,119 @@ +# Copyright (c) 2013 Mitch Garnaat http://garnaat.org/ +# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, dis- +# tribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the fol- +# lowing conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import uuid + +import boto +from boto.sqs.message import RawMessage +from boto.exception import SQSDecodeError + + +class BigMessage(RawMessage): + """ + The BigMessage class provides large payloads (up to 5GB) + by storing the payload itself in S3 and then placing a reference + to the S3 object in the actual SQS message payload. + + To create a BigMessage, you should create a BigMessage object + and pass in a file-like object as the ``body`` param and also + pass in the an S3 URL specifying the bucket in which to store + the message body:: + + import boto.sqs + from boto.sqs.bigmessage import BigMessage + + sqs = boto.sqs.connect_to_region('us-west-2') + queue = sqs.get_queue('myqueue') + fp = open('/path/to/bigmessage/data') + msg = BigMessage(queue, fp, 's3://mybucket') + queue.write(msg) + + Passing in a fully-qualified S3 URL (e.g. s3://mybucket/foo) + is interpreted to mean that the body of the message is already + stored in S3 and the that S3 URL is then used directly with no + content uploaded by BigMessage. + """ + + def __init__(self, queue=None, body=None, s3_url=None): + self.s3_url = s3_url + super(BigMessage, self).__init__(queue, body) + + def _get_bucket_key(self, s3_url): + bucket_name = key_name = None + if s3_url: + if s3_url.startswith('s3://'): + # We need to split out the bucket from the key (if + # supplied). We also have to be aware that someone + # may provide a trailing '/' character as in: + # s3://foo/ and we want to handle that. + s3_components = s3_url[5:].split('/', 1) + bucket_name = s3_components[0] + if len(s3_components) > 1: + if s3_components[1]: + key_name = s3_components[1] + else: + msg = 's3_url parameter should start with s3://' + raise SQSDecodeError(msg, self) + return bucket_name, key_name + + def encode(self, value): + """ + :type value: file-like object + :param value: A file-like object containing the content + of the message. The actual content will be stored + in S3 and a link to the S3 object will be stored in + the message body. + """ + bucket_name, key_name = self._get_bucket_key(self.s3_url) + if bucket_name and key_name: + return self.s3_url + key_name = uuid.uuid4() + s3_conn = boto.connect_s3() + s3_bucket = s3_conn.get_bucket(bucket_name) + key = s3_bucket.new_key(key_name) + key.set_contents_from_file(value) + self.s3_url = 's3://%s/%s' % (bucket_name, key_name) + return self.s3_url + + def _get_s3_object(self, s3_url): + bucket_name, key_name = self._get_bucket_key(s3_url) + if bucket_name and key_name: + s3_conn = boto.connect_s3() + s3_bucket = s3_conn.get_bucket(bucket_name) + key = s3_bucket.get_key(key_name) + return key + else: + msg = 'Unable to decode S3 URL: %s' % s3_url + raise SQSDecodeError(msg, self) + + def decode(self, value): + self.s3_url = value + key = self._get_s3_object(value) + return key.get_contents_as_string() + + def delete(self): + # Delete the object in S3 first, then delete the SQS message + if self.s3_url: + key = self._get_s3_object(self.s3_url) + key.delete() + super(BigMessage, self).delete() + diff --git a/awx/lib/site-packages/boto/sqs/connection.py b/awx/lib/site-packages/boto/sqs/connection.py index 5e8d5d029d..f403d639cc 100644 --- a/awx/lib/site-packages/boto/sqs/connection.py +++ b/awx/lib/site-packages/boto/sqs/connection.py @@ -48,7 +48,7 @@ class SQSConnection(AWSQueryConnection): region = SQSRegionInfo(self, self.DefaultRegionName, self.DefaultRegionEndpoint) self.region = region - AWSQueryConnection.__init__(self, aws_access_key_id, + super(SQSConnection, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, diff --git a/awx/lib/site-packages/boto/sqs/message.py b/awx/lib/site-packages/boto/sqs/message.py index f7aa6980f9..a036471298 100644 --- a/awx/lib/site-packages/boto/sqs/message.py +++ b/awx/lib/site-packages/boto/sqs/message.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -28,7 +28,7 @@ Message are here: http://docs.amazonwebservices.com/AWSSimpleQueueService/2008-01-01/SQSDeveloperGuide/Query_QuerySendMessage.html So, at it's simplest level a Message just needs to allow a developer to store bytes in it and get the bytes -back out. However, to allow messages to have richer semantics, the Message class must support the +back out. However, to allow messages to have richer semantics, the Message class must support the following interfaces: The constructor for the Message class must accept a keyword parameter "queue" which is an instance of a @@ -69,14 +69,14 @@ from boto.sqs.attributes import Attributes from boto.exception import SQSDecodeError import boto -class RawMessage: +class RawMessage(object): """ Base class for SQS messages. RawMessage does not encode the message in any way. Whatever you store in the body of the message is what will be written to SQS and whatever is returned from SQS is stored directly into the body of the message. """ - + def __init__(self, queue=None, body=''): self.queue = queue self.set_body(body) @@ -115,14 +115,14 @@ class RawMessage: def decode(self, value): """Transform seralized byte array into any object.""" return value - + def set_body(self, body): """Override the current body for this object, using decoded format.""" self._body = body def get_body(self): return self._body - + def get_body_encoded(self): """ This method is really a semi-private method used by the Queue.write @@ -140,7 +140,7 @@ class RawMessage: self.queue.connection.change_message_visibility(self.queue, self.receipt_handle, visibility_timeout) - + class Message(RawMessage): """ The default Message class used for SQS queues. This class automatically @@ -152,7 +152,7 @@ class Message(RawMessage): for details on why this is a good idea. The encode/decode is meant to be transparent to the end-user. """ - + def encode(self, value): return base64.b64encode(value) @@ -179,7 +179,7 @@ class MHMessage(Message): def __init__(self, queue=None, body=None, xml_attrs=None): if body == None or body == '': body = {} - Message.__init__(self, queue, body) + super(MHMessage, self).__init__(queue, body) def decode(self, value): try: @@ -251,9 +251,9 @@ class EncodedMHMessage(MHMessage): value = base64.b64decode(value) except: raise SQSDecodeError('Unable to decode message', self) - return MHMessage.decode(self, value) + return super(EncodedMHMessage, self).decode(value) def encode(self, value): - value = MHMessage.encode(self, value) + value = super(EncodedMHMessage, self).encode(value) return base64.b64encode(value) - + diff --git a/awx/lib/site-packages/boto/sqs/queue.py b/awx/lib/site-packages/boto/sqs/queue.py index 603faaaea6..054b839e33 100644 --- a/awx/lib/site-packages/boto/sqs/queue.py +++ b/awx/lib/site-packages/boto/sqs/queue.py @@ -27,7 +27,7 @@ import urlparse from boto.sqs.message import Message -class Queue: +class Queue(object): def __init__(self, connection=None, url=None, message_class=Message): self.connection = connection @@ -238,7 +238,7 @@ class Queue: """ return self.connection.send_message_batch(self, messages) - def new_message(self, body=''): + def new_message(self, body='', **kwargs): """ Create new message of appropriate class. @@ -248,7 +248,7 @@ class Queue: :rtype: :class:`boto.sqs.message.Message` :return: A new Message object """ - m = self.message_class(self, body) + m = self.message_class(self, body, **kwargs) m.queue = self return m diff --git a/awx/lib/site-packages/boto/sqs/regioninfo.py b/awx/lib/site-packages/boto/sqs/regioninfo.py index 66d6733629..9f7d7f12fa 100644 --- a/awx/lib/site-packages/boto/sqs/regioninfo.py +++ b/awx/lib/site-packages/boto/sqs/regioninfo.py @@ -16,7 +16,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -28,5 +28,5 @@ class SQSRegionInfo(RegionInfo): def __init__(self, connection=None, name=None, endpoint=None): from boto.sqs.connection import SQSConnection - RegionInfo.__init__(self, connection, name, endpoint, + super(SQSRegionInfo, self).__init__(connection, name, endpoint, SQSConnection) diff --git a/awx/lib/site-packages/boto/sts/__init__.py b/awx/lib/site-packages/boto/sts/__init__.py index 0b7a8de23c..d7c26f56ec 100644 --- a/awx/lib/site-packages/boto/sts/__init__.py +++ b/awx/lib/site-packages/boto/sts/__init__.py @@ -36,8 +36,10 @@ def regions(): connection_cls=STSConnection), RegionInfo(name='us-gov-west-1', endpoint='sts.us-gov-west-1.amazonaws.com', - connection_cls=STSConnection) - + connection_cls=STSConnection), + RegionInfo(name='cn-north-1', + endpoint='sts.cn-north-1.amazonaws.com.cn', + connection_cls=STSConnection), ] diff --git a/awx/lib/site-packages/boto/sts/connection.py b/awx/lib/site-packages/boto/sts/connection.py index 5f488e2631..7c480a3fbf 100644 --- a/awx/lib/site-packages/boto/sts/connection.py +++ b/awx/lib/site-packages/boto/sts/connection.py @@ -69,7 +69,8 @@ class STSConnection(AWSQueryConnection): is_secure=True, port=None, proxy=None, proxy_port=None, proxy_user=None, proxy_pass=None, debug=0, https_connection_factory=None, region=None, path='/', - converter=None, validate_certs=True, anon=False): + converter=None, validate_certs=True, anon=False, + security_token=None): if not region: region = RegionInfo(self, self.DefaultRegionName, self.DefaultRegionEndpoint, @@ -77,13 +78,14 @@ class STSConnection(AWSQueryConnection): self.region = region self.anon = anon self._mutex = threading.Semaphore() - AWSQueryConnection.__init__(self, aws_access_key_id, + super(STSConnection, self).__init__(aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, self.region.endpoint, debug, https_connection_factory, path, - validate_certs=validate_certs) + validate_certs=validate_certs, + security_token=security_token) def _required_auth_capability(self): if self.anon: @@ -338,6 +340,115 @@ class STSConnection(AWSQueryConnection): params['ExternalId'] = external_id return self.get_object('AssumeRole', params, AssumedRole, verb='POST') + def assume_role_with_saml(self, role_arn, principal_arn, saml_assertion, + policy=None, duration_seconds=None): + """ + Returns a set of temporary security credentials for users who + have been authenticated via a SAML authentication response. + This operation provides a mechanism for tying an enterprise + identity store or directory to role-based AWS access without + user-specific credentials or configuration. + + The temporary security credentials returned by this operation + consist of an access key ID, a secret access key, and a + security token. Applications can use these temporary security + credentials to sign calls to AWS services. The credentials are + valid for the duration that you specified when calling + `AssumeRoleWithSAML`, which can be up to 3600 seconds (1 hour) + or until the time specified in the SAML authentication + response's `NotOnOrAfter` value, whichever is shorter. + + The maximum duration for a session is 1 hour, and the minimum + duration is 15 minutes, even if values outside this range are + specified. + + Optionally, you can pass an AWS IAM access policy to this + operation. The temporary security credentials that are + returned by the operation have the permissions that are + associated with the access policy of the role being assumed, + except for any permissions explicitly denied by the policy you + pass. This gives you a way to further restrict the permissions + for the federated user. These policies and any applicable + resource-based policies are evaluated when calls to AWS are + made using the temporary security credentials. + + Before your application can call `AssumeRoleWithSAML`, you + must configure your SAML identity provider (IdP) to issue the + claims required by AWS. Additionally, you must use AWS + Identity and Access Management (AWS IAM) to create a SAML + provider entity in your AWS account that represents your + identity provider, and create an AWS IAM role that specifies + this SAML provider in its trust policy. + + Calling `AssumeRoleWithSAML` does not require the use of AWS + security credentials. The identity of the caller is validated + by using keys in the metadata document that is uploaded for + the SAML provider entity for your identity provider. + + For more information, see the following resources: + + + + `Creating Temporary Security Credentials for SAML + Federation`_ in the Using Temporary Security Credentials + guide. + + `SAML Providers`_ in the Using IAM guide. + + `Configuring a Relying Party and Claims in the Using IAM + guide. `_ + + `Creating a Role for SAML-Based Federation`_ in the Using + IAM guide. + + :type role_arn: string + :param role_arn: The Amazon Resource Name (ARN) of the role that the + caller is assuming. + + :type principal_arn: string + :param principal_arn: The Amazon Resource Name (ARN) of the SAML + provider in AWS IAM that describes the IdP. + + :type saml_assertion: string + :param saml_assertion: The base-64 encoded SAML authentication response + provided by the IdP. + For more information, see `Configuring a Relying Party and Adding + Claims`_ in the Using IAM guide. + + :type policy: string + :param policy: + An AWS IAM policy in JSON format. + + The temporary security credentials that are returned by this operation + have the permissions that are associated with the access policy of + the role being assumed, except for any permissions explicitly + denied by the policy you pass. These policies and any applicable + resource-based policies are evaluated when calls to AWS are made + using the temporary security credentials. + + The policy must be 2048 bytes or shorter, and its packed size must be + less than 450 bytes. + + :type duration_seconds: integer + :param duration_seconds: + The duration, in seconds, of the role session. The value can range from + 900 seconds (15 minutes) to 3600 seconds (1 hour). By default, the + value is set to 3600 seconds. An expiration can also be specified + in the SAML authentication response's `NotOnOrAfter` value. The + actual expiration time is whichever value is shorter. + + The maximum duration for a session is 1 hour, and the minimum duration + is 15 minutes, even if values outside this range are specified. + + """ + params = { + 'RoleArn': role_arn, + 'PrincipalArn': principal_arn, + 'SAMLAssertion': saml_assertion, + } + if policy is not None: + params['Policy'] = policy + if duration_seconds is not None: + params['DurationSeconds'] = duration_seconds + return self.get_object('AssumeRoleWithSAML', params, AssumedRole, + verb='POST') + def assume_role_with_web_identity(self, role_arn, role_session_name, web_identity_token, provider_id=None, policy=None, duration_seconds=None): diff --git a/awx/lib/site-packages/boto/support/layer1.py b/awx/lib/site-packages/boto/support/layer1.py index 5e73db262a..3b52efd90b 100644 --- a/awx/lib/site-packages/boto/support/layer1.py +++ b/awx/lib/site-packages/boto/support/layer1.py @@ -20,7 +20,11 @@ # IN THE SOFTWARE. # -import json +try: + import json +except ImportError: + import simplejson as json + import boto from boto.connection import AWSQueryConnection from boto.regioninfo import RegionInfo @@ -33,10 +37,9 @@ class SupportConnection(AWSQueryConnection): AWS Support The AWS Support API reference is intended for programmers who need detailed information about the AWS Support actions and data types. - This service enables you to manage with your AWS Support cases - programmatically. It is built on the AWS Query API programming - model and provides HTTP methods that take parameters and return - results in JSON format. + This service enables you to manage your AWS Support cases + programmatically. It uses HTTP methods that return results in JSON + format. The AWS Support service also exposes a set of `Trusted Advisor`_ features. You can retrieve a list of checks you can run on your @@ -55,34 +58,35 @@ class SupportConnection(AWSQueryConnection): + **Case Creation, case details, and case resolution**. The actions `CreateCase`_, `DescribeCases`_, and `ResolveCase`_ enable you to create AWS Support cases, retrieve them, and resolve them. - + **Case communication**. The actions - `DescribeCaseCommunications`_ and `AddCommunicationToCase`_ enable - you to retrieve and add communication to AWS Support cases. + + **Case communication**. The actions `DescribeCommunications`_ + and `AddCommunicationToCase`_ enable you to retrieve and add + communication to AWS Support cases. The following list describes the actions available from the AWS Support service for Trusted Advisor: - + `DescribeTrustedAdviserChecks`_ returns the list of checks that you can run against your AWS - resources. + + `DescribeTrustedAdvisorChecks`_ returns the list of checks that + you can run against your AWS resources. + Using the CheckId for a specific check returned by - DescribeTrustedAdviserChecks, you can call + DescribeTrustedAdvisorChecks, you can call `DescribeTrustedAdvisorCheckResult`_ and obtain a new result for the check you specified. + Using `DescribeTrustedAdvisorCheckSummaries`_, you can get summaries for a set of Trusted Advisor checks. + `RefreshTrustedAdvisorCheck`_ enables you to request that Trusted Advisor run the check again. - + ``_ gets statuses on the checks you are running. + + `DescribeTrustedAdvisorCheckRefreshStatuses`_ gets statuses on + the checks you are running. For authentication of requests, the AWS Support uses `Signature Version 4 Signing Process`_. - See the AWS Support Developer Guide for information about how to - use this service to manage create and manage your support cases, - and how to call Trusted Advisor for results of checks on your - resources. + See the AWS Support `Developer Guide`_ for information about how + to use this service to manage create and manage your support + cases, and how to call Trusted Advisor for results of checks on + your resources. """ APIVersion = "2013-04-15" DefaultRegionName = "us-east-1" @@ -104,7 +108,7 @@ class SupportConnection(AWSQueryConnection): region = RegionInfo(self, self.DefaultRegionName, self.DefaultRegionEndpoint) kwargs['host'] = region.endpoint - AWSQueryConnection.__init__(self, **kwargs) + super(SupportConnection, self).__init__(**kwargs) self.region = region def _required_auth_capability(self): @@ -127,13 +131,18 @@ class SupportConnection(AWSQueryConnection): Support `Your Support Cases`_ web form. :type case_id: string - :param case_id: + :param case_id: String that indicates the AWS Support caseID requested + or returned in the call. The caseID is an alphanumeric string + formatted as shown in this example CaseId: + case-12345678910-2013-c4c1d2bf33c5cf47 :type communication_body: string - :param communication_body: + :param communication_body: Represents the body of an email + communication added to the support case. :type cc_email_addresses: list - :param cc_email_addresses: + :param cc_email_addresses: Represents any email addresses contained in + the CC line of an email added to the support case. """ params = {'communicationBody': communication_body, } @@ -144,8 +153,8 @@ class SupportConnection(AWSQueryConnection): return self.make_request(action='AddCommunicationToCase', body=json.dumps(params)) - def create_case(self, subject, service_code, category_code, - communication_body, severity_code=None, + def create_case(self, subject, communication_body, service_code=None, + severity_code=None, category_code=None, cc_email_addresses=None, language=None, issue_type=None): """ Creates a new case in the AWS Support Center. This action is @@ -179,6 +188,10 @@ class SupportConnection(AWSQueryConnection): passing the AWS Credentials in the HTTP POST method or in a method or function call from one of the programming languages supported by an `AWS SDK`_. + #. **IssueType**. Indicates the type of issue for the case. + You can specify either "customer-service" or "technical." If + you do not indicate a value, this parameter defaults to + "technical." The AWS Support API does not currently support the ability to @@ -190,38 +203,55 @@ class SupportConnection(AWSQueryConnection): retrieve existing AWS Support support cases. :type subject: string - :param subject: + :param subject: Title of the AWS Support case. :type service_code: string - :param service_code: + :param service_code: Code for the AWS service returned by the call to + `DescribeServices`_. :type severity_code: string :param severity_code: + Code for the severity level returned by the call to + `DescribeSeverityLevels`_. + + The availability of severity levels depends on each customer's support + subscription. In other words, your subscription may not necessarily + require the urgent level of response time. :type category_code: string - :param category_code: + :param category_code: Specifies the category of problem for the AWS + Support case. :type communication_body: string - :param communication_body: + :param communication_body: Parameter that represents the communication + body text when you create an AWS Support case by calling + `CreateCase`_. :type cc_email_addresses: list - :param cc_email_addresses: + :param cc_email_addresses: List of email addresses that AWS Support + copies on case correspondence. :type language: string - :param language: + :param language: Specifies the ISO 639-1 code for the language in which + AWS provides support. AWS Support currently supports English and + Japanese, for which the codes are en and ja , respectively. + Language parameters must be passed explicitly for operations that + take them. :type issue_type: string - :param issue_type: + :param issue_type: Field passed as a parameter in a `CreateCase`_ call. """ params = { 'subject': subject, - 'serviceCode': service_code, - 'categoryCode': category_code, 'communicationBody': communication_body, } + if service_code is not None: + params['serviceCode'] = service_code if severity_code is not None: params['severityCode'] = severity_code + if category_code is not None: + params['categoryCode'] = category_code if cc_email_addresses is not None: params['ccEmailAddresses'] = cc_email_addresses if language is not None: @@ -247,28 +277,40 @@ class SupportConnection(AWSQueryConnection): to paginate the returned records represented by CaseDetails . :type case_id_list: list - :param case_id_list: + :param case_id_list: A list of Strings comprising ID numbers for + support cases you want returned. The maximum number of cases is + 100. :type display_id: string - :param display_id: + :param display_id: String that corresponds to the ID value displayed + for a case in the AWS Support Center user interface. :type after_time: string - :param after_time: + :param after_time: Start date for a filtered date search on support + case communications. :type before_time: string - :param before_time: + :param before_time: End date for a filtered date search on support case + communications. :type include_resolved_cases: boolean - :param include_resolved_cases: + :param include_resolved_cases: Boolean that indicates whether or not + resolved support cases should be listed in the `DescribeCases`_ + search. :type next_token: string - :param next_token: + :param next_token: Defines a resumption point for pagination. :type max_results: integer - :param max_results: + :param max_results: Integer that sets the maximum number of results to + return before paginating. :type language: string - :param language: + :param language: Specifies the ISO 639-1 code for the language in which + AWS provides support. AWS Support currently supports English and + Japanese, for which the codes are en and ja , respectively. + Language parameters must be passed explicitly for operations that + take them. """ params = {} @@ -306,19 +348,25 @@ class SupportConnection(AWSQueryConnection): specify the resumption of pagination. :type case_id: string - :param case_id: + :param case_id: String that indicates the AWS Support caseID requested + or returned in the call. The caseID is an alphanumeric string + formatted as shown in this example CaseId: + case-12345678910-2013-c4c1d2bf33c5cf47 :type before_time: string - :param before_time: + :param before_time: End date for a filtered date search on support case + communications. :type after_time: string - :param after_time: + :param after_time: Start date for a filtered date search on support + case communications. :type next_token: string - :param next_token: + :param next_token: Defines a resumption point for pagination. :type max_results: integer - :param max_results: + :param max_results: Integer that sets the maximum number of results to + return before paginating. """ params = {'caseId': case_id, } @@ -351,10 +399,15 @@ class SupportConnection(AWSQueryConnection): category codes. :type service_code_list: list - :param service_code_list: + :param service_code_list: List in JSON format of service codes + available for AWS services. :type language: string - :param language: + :param language: Specifies the ISO 639-1 code for the language in which + AWS provides support. AWS Support currently supports English and + Japanese, for which the codes are en and ja , respectively. + Language parameters must be passed explicitly for operations that + take them. """ params = {} @@ -373,7 +426,11 @@ class SupportConnection(AWSQueryConnection): any `CreateCase`_ request. :type language: string - :param language: + :param language: Specifies the ISO 639-1 code for the language in which + AWS provides support. AWS Support currently supports English and + Japanese, for which the codes are en and ja , respectively. + Language parameters must be passed explicitly for operations that + take them. """ params = {} @@ -382,29 +439,15 @@ class SupportConnection(AWSQueryConnection): return self.make_request(action='DescribeSeverityLevels', body=json.dumps(params)) - def resolve_case(self, case_id=None): - """ - Takes a CaseId and returns the initial state of the case along - with the state of the case after the call to `ResolveCase`_ - completed. - - :type case_id: string - :param case_id: - - """ - params = {} - if case_id is not None: - params['caseId'] = case_id - return self.make_request(action='ResolveCase', - body=json.dumps(params)) - def describe_trusted_advisor_check_refresh_statuses(self, check_ids): """ Returns the status of all refresh requests Trusted Advisor checks called using `RefreshTrustedAdvisorCheck`_. :type check_ids: list - :param check_ids: + :param check_ids: List of the CheckId values for the Trusted Advisor + checks for which you want to refresh the status. You obtain the + CheckId values by calling `DescribeTrustedAdvisorChecks`_. """ params = {'checkIds': check_ids, } @@ -443,7 +486,11 @@ class SupportConnection(AWSQueryConnection): :param check_id: :type language: string - :param language: + :param language: Specifies the ISO 639-1 code for the language in which + AWS provides support. AWS Support currently supports English and + Japanese, for which the codes are en and ja , respectively. + Language parameters must be passed explicitly for operations that + take them. """ params = {'checkId': check_id, } @@ -464,7 +511,7 @@ class SupportConnection(AWSQueryConnection): `TrustedAdvisorCheckSummary`_ objects. :type check_ids: list - :param check_ids: + :param check_ids: Unique identifier for a Trusted Advisor check. """ params = {'checkIds': check_ids, } @@ -480,7 +527,11 @@ class SupportConnection(AWSQueryConnection): objects. :type language: string - :param language: + :param language: Specifies the ISO 639-1 code for the language in which + AWS provides support. AWS Support currently supports English and + Japanese, for which the codes are en and ja , respectively. + Language parameters must be passed explicitly for operations that + take them. """ params = {'language': language, } @@ -503,6 +554,25 @@ class SupportConnection(AWSQueryConnection): return self.make_request(action='RefreshTrustedAdvisorCheck', body=json.dumps(params)) + def resolve_case(self, case_id=None): + """ + Takes a CaseId and returns the initial state of the case along + with the state of the case after the call to `ResolveCase`_ + completed. + + :type case_id: string + :param case_id: String that indicates the AWS Support caseID requested + or returned in the call. The caseID is an alphanumeric string + formatted as shown in this example CaseId: + case-12345678910-2013-c4c1d2bf33c5cf47 + + """ + params = {} + if case_id is not None: + params['caseId'] = case_id + return self.make_request(action='ResolveCase', + body=json.dumps(params)) + def make_request(self, action, body): headers = { 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), diff --git a/awx/lib/site-packages/boto/swf/__init__.py b/awx/lib/site-packages/boto/swf/__init__.py index 3594444d30..fc6ebfe29c 100644 --- a/awx/lib/site-packages/boto/swf/__init__.py +++ b/awx/lib/site-packages/boto/swf/__init__.py @@ -35,6 +35,7 @@ REGION_ENDPOINTS = { 'ap-northeast-1': 'swf.ap-northeast-1.amazonaws.com', 'ap-southeast-1': 'swf.ap-southeast-1.amazonaws.com', 'ap-southeast-2': 'swf.ap-southeast-2.amazonaws.com', + 'cn-north-1': 'swf.cn-north-1.amazonaws.com.cn', } diff --git a/awx/lib/site-packages/boto/swf/layer1.py b/awx/lib/site-packages/boto/swf/layer1.py index 264016bd8f..d027abd4ef 100644 --- a/awx/lib/site-packages/boto/swf/layer1.py +++ b/awx/lib/site-packages/boto/swf/layer1.py @@ -79,7 +79,7 @@ class Layer1(AWSAuthConnection): break self.region = region - AWSAuthConnection.__init__(self, self.region.endpoint, + super(Layer1, self).__init__(self.region.endpoint, aws_access_key_id, aws_secret_access_key, is_secure, port, proxy, proxy_port, debug, session_token) diff --git a/awx/lib/site-packages/boto/swf/layer1_decisions.py b/awx/lib/site-packages/boto/swf/layer1_decisions.py index 6c273aa14d..7649da1729 100644 --- a/awx/lib/site-packages/boto/swf/layer1_decisions.py +++ b/awx/lib/site-packages/boto/swf/layer1_decisions.py @@ -3,7 +3,7 @@ Helper class for creating decision responses. """ -class Layer1Decisions: +class Layer1Decisions(object): """ Use this object to build a list of decisions for a decision response. Each method call will add append a new decision. Retrieve the list diff --git a/awx/lib/site-packages/boto/utils.py b/awx/lib/site-packages/boto/utils.py index 6d89b21f5f..ec81f4da2f 100644 --- a/awx/lib/site-packages/boto/utils.py +++ b/awx/lib/site-packages/boto/utils.py @@ -50,6 +50,7 @@ import logging.handlers import boto import boto.provider import tempfile +import random import smtplib import datetime import re @@ -75,6 +76,11 @@ except ImportError: from boto.compat import json +try: + from boto.compat.json import JSONDecodeError +except ImportError: + JSONDecodeError = ValueError + # List of Query String Arguments of Interest qsa_of_interest = ['acl', 'cors', 'defaultObjectAcl', 'location', 'logging', 'partNumber', 'policy', 'requestPayment', 'torrent', @@ -89,7 +95,8 @@ qsa_of_interest = ['acl', 'cors', 'defaultObjectAcl', 'location', 'logging', # having it listed here should cause no problems because # GET bucket?storageClass is not part of the S3 API.) 'storageClass', - # websiteConfig is a QSA for buckets in Google Cloud Storage. + # websiteConfig is a QSA for buckets in Google Cloud + # Storage. 'websiteConfig', # compose is a QSA for objects in Google Cloud Storage. 'compose'] @@ -117,8 +124,9 @@ def canonical_string(method, path, headers, expires=None, interesting_headers = {} for key in headers: lk = key.lower() - if headers[key] != None and (lk in ['content-md5', 'content-type', 'date'] or - lk.startswith(provider.header_prefix)): + if headers[key] is not None and \ + (lk in ['content-md5', 'content-type', 'date'] or + lk.startswith(provider.header_prefix)): interesting_headers[lk] = str(headers[key]).strip() # these keys get empty strings if they don't exist @@ -156,7 +164,7 @@ def canonical_string(method, path, headers, expires=None, qsa = [a.split('=', 1) for a in qsa] qsa = [unquote_v(a) for a in qsa if a[0] in qsa_of_interest] if len(qsa) > 0: - qsa.sort(cmp=lambda x, y:cmp(x[0], y[0])) + qsa.sort(cmp=lambda x, y: cmp(x[0], y[0])) qsa = ['='.join(a) for a in qsa] buf += '?' buf += '&'.join(qsa) @@ -272,15 +280,48 @@ class LazyLoadMetadata(dict): if key in self._leaves: resource = self._leaves[key] - val = boto.utils.retry_url(self._url + urllib.quote(resource, - safe="/:"), - num_retries=self._num_retries) - if val and val[0] == '{': - val = json.loads(val) + + for i in range(0, self._num_retries): + try: + val = boto.utils.retry_url( + self._url + urllib.quote(resource, + safe="/:"), + num_retries=self._num_retries) + if val and val[0] == '{': + val = json.loads(val) + break + else: + p = val.find('\n') + if p > 0: + val = val.split('\n') + break + + except JSONDecodeError, e: + boto.log.debug( + "encountered '%s' exception: %s" % ( + e.__class__.__name__, e)) + boto.log.debug( + 'corrupted JSON data found: %s' % val) + + except Exception, e: + boto.log.debug("encountered unretryable" + + " '%s' exception, re-raising" % ( + e.__class__.__name__)) + raise + + boto.log.error("Caught exception reading meta data" + + " for the '%s' try" % (i + 1)) + + if i + 1 != self._num_retries: + next_sleep = random.random() * (2 ** i) + time.sleep(next_sleep) else: - p = val.find('\n') - if p > 0: - val = val.split('\n') + boto.log.error('Unable to read meta data, giving up') + boto.log.error( + "encountered '%s' exception: %s" % ( + e.__class__.__name__, e)) + raise + self[key] = val elif key in self._dicts: self[key] = LazyLoadMetadata(self._url + key + '/', @@ -315,19 +356,28 @@ def _build_instance_metadata_url(url, version, path): """ Builds an EC2 metadata URL for fetching information about an instance. - Requires the following arguments: a URL, a version and a path. - Example: - >>> _build_instance_metadata_url('http://169.254.169.254', 'latest', 'meta-data') + >>> _build_instance_metadata_url('http://169.254.169.254', 'latest', 'meta-data/') http://169.254.169.254/latest/meta-data/ + :type url: string + :param url: URL to metadata service, e.g. 'http://169.254.169.254' + + :type version: string + :param version: Version of the metadata to get, e.g. 'latest' + + :type path: string + :param path: Path of the metadata to get, e.g. 'meta-data/'. If a trailing + slash is required it must be passed in with the path. + + :return: The full metadata URL """ - return '%s/%s/%s/' % (url, version, path) + return '%s/%s/%s' % (url, version, path) def get_instance_metadata(version='latest', url='http://169.254.169.254', - data='meta-data', timeout=None, num_retries=5): + data='meta-data/', timeout=None, num_retries=5): """ Returns the instance metadata as a nested Python dictionary. Simple values (e.g. local_hostname, hostname, etc.) will be @@ -358,7 +408,8 @@ def get_instance_identity(version='latest', url='http://169.254.169.254', Returns the instance identity as a nested Python dictionary. """ iid = {} - base_url = _build_instance_metadata_url(url, version, 'dynamic/instance-identity') + base_url = _build_instance_metadata_url(url, version, + 'dynamic/instance-identity/') if timeout is not None: original = socket.getdefaulttimeout() socket.setdefaulttimeout(timeout) @@ -396,6 +447,7 @@ ISO8601 = '%Y-%m-%dT%H:%M:%SZ' ISO8601_MS = '%Y-%m-%dT%H:%M:%S.%fZ' RFC1123 = '%a, %d %b %Y %H:%M:%S %Z' + def get_ts(ts=None): if not ts: ts = time.gmtime() @@ -415,6 +467,7 @@ def parse_ts(ts): dt = datetime.datetime.strptime(ts, RFC1123) return dt + def find_class(module_name, class_name=None): if class_name: module_name = "%s.%s" % (module_name, class_name) @@ -444,13 +497,13 @@ def update_dme(username, password, dme_id, ip_address): def fetch_file(uri, file=None, username=None, password=None): """ - Fetch a file based on the URI provided. If you do not pass in a file pointer - a tempfile.NamedTemporaryFile, or None if the file could not be - retrieved is returned. + Fetch a file based on the URI provided. + If you do not pass in a file pointer a tempfile.NamedTemporaryFile, + or None if the file could not be retrieved is returned. The URI can be either an HTTP url, or "s3://bucket_name/key_name" """ boto.log.info('Fetching %s' % uri) - if file == None: + if file is None: file = tempfile.NamedTemporaryFile() try: if uri.startswith('s3://'): @@ -495,7 +548,7 @@ class ShellCommand(object): stderr=subprocess.PIPE, cwd=cwd) if(self.wait): - while self.process.poll() == None: + while self.process.poll() is None: time.sleep(1) t = self.process.communicate() self.log_fp.write(t[0]) @@ -504,7 +557,8 @@ class ShellCommand(object): self.exit_code = self.process.returncode if self.fail_fast and self.exit_code != 0: - raise Exception("Command " + self.command + " failed with status " + self.exit_code) + raise Exception("Command " + self.command + + " failed with status " + self.exit_code) return self.exit_code @@ -514,12 +568,14 @@ class ShellCommand(object): def getStatus(self): return self.exit_code - status = property(getStatus, setReadOnly, None, 'The exit code for the command') + status = property(getStatus, setReadOnly, None, + 'The exit code for the command') def getOutput(self): return self.log_fp.getvalue() - output = property(getOutput, setReadOnly, None, 'The STDIN and STDERR output of the command') + output = property(getOutput, setReadOnly, None, + 'The STDIN and STDERR output of the command') class AuthSMTPHandler(logging.handlers.SMTPHandler): @@ -544,7 +600,7 @@ class AuthSMTPHandler(logging.handlers.SMTPHandler): We have extended the constructor to accept a username/password for SMTP authentication. """ - logging.handlers.SMTPHandler.__init__(self, mailhost, fromaddr, + super(AuthSMTPHandler, self).__init__(mailhost, fromaddr, toaddrs, subject) self.username = username self.password = password @@ -565,10 +621,10 @@ class AuthSMTPHandler(logging.handlers.SMTPHandler): smtp.login(self.username, self.password) msg = self.format(record) msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\nDate: %s\r\n\r\n%s" % ( - self.fromaddr, - ','.join(self.toaddrs), - self.getSubject(record), - email.utils.formatdate(), msg) + self.fromaddr, + ','.join(self.toaddrs), + self.getSubject(record), + email.utils.formatdate(), msg) smtp.sendmail(self.fromaddr, self.toaddrs, msg) smtp.quit() except (KeyboardInterrupt, SystemExit): @@ -710,7 +766,7 @@ class Password(object): """ self.str = str if hashfunc: - self.hashfunc = hashfunc + self.hashfunc = hashfunc def set(self, value): self.str = self.hashfunc(value).hexdigest() @@ -719,7 +775,7 @@ class Password(object): return str(self.str) def __eq__(self, other): - if other == None: + if other is None: return False return str(self.hashfunc(other).hexdigest()) == str(self.str) @@ -734,12 +790,14 @@ def notify(subject, body=None, html_body=None, to_string=None, attachments=None, append_instance_id=True): attachments = attachments or [] if append_instance_id: - subject = "[%s] %s" % (boto.config.get_value("Instance", "instance-id"), subject) + subject = "[%s] %s" % ( + boto.config.get_value("Instance", "instance-id"), subject) if not to_string: to_string = boto.config.get_value('Notification', 'smtp_to', None) if to_string: try: - from_string = boto.config.get_value('Notification', 'smtp_from', 'boto') + from_string = boto.config.get_value('Notification', + 'smtp_from', 'boto') msg = email.mime.multipart.MIMEMultipart() msg['From'] = from_string msg['Reply-To'] = from_string @@ -759,11 +817,13 @@ def notify(subject, body=None, html_body=None, to_string=None, for part in attachments: msg.attach(part) - smtp_host = boto.config.get_value('Notification', 'smtp_host', 'localhost') + smtp_host = boto.config.get_value('Notification', + 'smtp_host', 'localhost') # Alternate port support if boto.config.get_value("Notification", "smtp_port"): - server = smtplib.SMTP(smtp_host, int(boto.config.get_value("Notification", "smtp_port"))) + server = smtplib.SMTP(smtp_host, int( + boto.config.get_value("Notification", "smtp_port"))) else: server = smtplib.SMTP(smtp_host) @@ -874,7 +934,7 @@ def guess_mime_type(content, deftype): :rtype: : :return: """ - #Mappings recognized by cloudinit + # Mappings recognized by cloudinit starts_with_mappings = { '#include': 'text/x-include-url', '#!': 'text/x-shellscript', diff --git a/awx/lib/site-packages/boto/vpc/__init__.py b/awx/lib/site-packages/boto/vpc/__init__.py index 7b3ea9d290..7e7c0ef977 100644 --- a/awx/lib/site-packages/boto/vpc/__init__.py +++ b/awx/lib/site-packages/boto/vpc/__init__.py @@ -571,7 +571,7 @@ class VPCConnection(EC2Connection): current network ACL with the default. :type subnet_id: str - :param association_id: The ID of the subnet to which the ACL belongs. + :param subnet_id: The ID of the subnet to which the ACL belongs. :type vpc_id: str :param vpc_id: The ID of the VPC to which the ACL/subnet belongs. Queries EC2 if omitted. diff --git a/awx/lib/site-packages/boto/vpc/customergateway.py b/awx/lib/site-packages/boto/vpc/customergateway.py index 76c34831a9..8f19a81a56 100644 --- a/awx/lib/site-packages/boto/vpc/customergateway.py +++ b/awx/lib/site-packages/boto/vpc/customergateway.py @@ -29,7 +29,7 @@ from boto.ec2.ec2object import TaggedEC2Object class CustomerGateway(TaggedEC2Object): def __init__(self, connection=None): - TaggedEC2Object.__init__(self, connection) + super(CustomerGateway, self).__init__(connection) self.id = None self.type = None self.state = None diff --git a/awx/lib/site-packages/boto/vpc/dhcpoptions.py b/awx/lib/site-packages/boto/vpc/dhcpoptions.py index 7484683822..758d452ceb 100644 --- a/awx/lib/site-packages/boto/vpc/dhcpoptions.py +++ b/awx/lib/site-packages/boto/vpc/dhcpoptions.py @@ -14,7 +14,7 @@ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. @@ -33,7 +33,7 @@ class DhcpValueSet(list): def endElement(self, name, value, connection): if name == 'value': self.append(value) - + class DhcpConfigSet(dict): def startElement(self, name, attrs, connection): @@ -45,19 +45,19 @@ class DhcpConfigSet(dict): def endElement(self, name, value, connection): if name == 'key': self._name = value - + class DhcpOptions(TaggedEC2Object): def __init__(self, connection=None): - TaggedEC2Object.__init__(self, connection) + super(DhcpOptions, self).__init__(connection) self.id = None self.options = None def __repr__(self): return 'DhcpOptions:%s' % self.id - + def startElement(self, name, attrs, connection): - retval = TaggedEC2Object.startElement(self, name, attrs, connection) + retval = super(DhcpOptions, self).startElement(name, attrs, connection) if retval is not None: return retval if name == 'dhcpConfigurationSet': diff --git a/awx/lib/site-packages/boto/vpc/internetgateway.py b/awx/lib/site-packages/boto/vpc/internetgateway.py index 011fdee1af..09f1fe04e7 100644 --- a/awx/lib/site-packages/boto/vpc/internetgateway.py +++ b/awx/lib/site-packages/boto/vpc/internetgateway.py @@ -28,7 +28,7 @@ from boto.resultset import ResultSet class InternetGateway(TaggedEC2Object): def __init__(self, connection=None): - TaggedEC2Object.__init__(self, connection) + super(InternetGateway, self).__init__(connection) self.id = None self.attachments = [] diff --git a/awx/lib/site-packages/boto/vpc/networkacl.py b/awx/lib/site-packages/boto/vpc/networkacl.py index 4771479176..d38e0283e8 100644 --- a/awx/lib/site-packages/boto/vpc/networkacl.py +++ b/awx/lib/site-packages/boto/vpc/networkacl.py @@ -51,7 +51,7 @@ class Icmp(object): class NetworkAcl(TaggedEC2Object): def __init__(self, connection=None): - TaggedEC2Object.__init__(self, connection) + super(NetworkAcl, self).__init__(connection) self.id = None self.vpc_id = None self.network_acl_entries = [] diff --git a/awx/lib/site-packages/boto/vpc/routetable.py b/awx/lib/site-packages/boto/vpc/routetable.py index b3f0055349..7f83717e55 100644 --- a/awx/lib/site-packages/boto/vpc/routetable.py +++ b/awx/lib/site-packages/boto/vpc/routetable.py @@ -29,7 +29,7 @@ from boto.resultset import ResultSet class RouteTable(TaggedEC2Object): def __init__(self, connection=None): - TaggedEC2Object.__init__(self, connection) + super(RouteTable, self).__init__(connection) self.id = None self.vpc_id = None self.routes = [] diff --git a/awx/lib/site-packages/boto/vpc/subnet.py b/awx/lib/site-packages/boto/vpc/subnet.py index f87d72c289..4d6f902539 100644 --- a/awx/lib/site-packages/boto/vpc/subnet.py +++ b/awx/lib/site-packages/boto/vpc/subnet.py @@ -28,7 +28,7 @@ from boto.ec2.ec2object import TaggedEC2Object class Subnet(TaggedEC2Object): def __init__(self, connection=None): - TaggedEC2Object.__init__(self, connection) + super(Subnet, self).__init__(connection) self.id = None self.vpc_id = None self.state = None diff --git a/awx/lib/site-packages/boto/vpc/vpc.py b/awx/lib/site-packages/boto/vpc/vpc.py index 2eb480d192..575a1c4570 100644 --- a/awx/lib/site-packages/boto/vpc/vpc.py +++ b/awx/lib/site-packages/boto/vpc/vpc.py @@ -39,7 +39,7 @@ class VPC(TaggedEC2Object): :ivar is_default: Indicates whether the VPC is the default VPC. :ivar instance_tenancy: The allowed tenancy of instances launched into the VPC. """ - TaggedEC2Object.__init__(self, connection) + super(VPC, self).__init__(connection) self.id = None self.dhcp_options_id = None self.state = None diff --git a/awx/lib/site-packages/boto/vpc/vpnconnection.py b/awx/lib/site-packages/boto/vpc/vpnconnection.py index c36492f53c..cd8b11a62b 100644 --- a/awx/lib/site-packages/boto/vpc/vpnconnection.py +++ b/awx/lib/site-packages/boto/vpc/vpnconnection.py @@ -152,7 +152,7 @@ class VpnConnection(TaggedEC2Object): """ def __init__(self, connection=None): - TaggedEC2Object.__init__(self, connection) + super(VpnConnection, self).__init__(connection) self.id = None self.state = None self.customer_gateway_configuration = None diff --git a/awx/lib/site-packages/boto/vpc/vpngateway.py b/awx/lib/site-packages/boto/vpc/vpngateway.py index fe476d935b..80598109c3 100644 --- a/awx/lib/site-packages/boto/vpc/vpngateway.py +++ b/awx/lib/site-packages/boto/vpc/vpngateway.py @@ -45,7 +45,7 @@ class Attachment(object): class VpnGateway(TaggedEC2Object): def __init__(self, connection=None): - TaggedEC2Object.__init__(self, connection) + super(VpnGateway, self).__init__(connection) self.id = None self.type = None self.state = None @@ -56,7 +56,7 @@ class VpnGateway(TaggedEC2Object): return 'VpnGateway:%s' % self.id def startElement(self, name, attrs, connection): - retval = TaggedEC2Object.startElement(self, name, attrs, connection) + retval = super(VpnGateway, self).startElement(name, attrs, connection) if retval is not None: return retval if name == 'item': diff --git a/awx/lib/site-packages/celery/__init__.py b/awx/lib/site-packages/celery/__init__.py index 5a26442f98..c7f9df1cbc 100644 --- a/awx/lib/site-packages/celery/__init__.py +++ b/awx/lib/site-packages/celery/__init__.py @@ -7,9 +7,15 @@ from __future__ import absolute_import +from collections import namedtuple + +version_info_t = namedtuple( + 'version_info_t', ('major', 'minor', 'micro', 'releaselevel', 'serial'), +) + SERIES = 'Cipater' -VERSION = (3, 1, 3) -__version__ = '.'.join(str(p) for p in VERSION[0:3]) + ''.join(VERSION[3:]) +VERSION = version_info_t(3, 1, 7, '', '') +__version__ = '{0.major}.{0.minor}.{0.micro}{0.releaselevel}'.format(VERSION) __author__ = 'Ask Solem' __contact__ = 'ask@celeryproject.org' __homepage__ = 'http://celeryproject.org' diff --git a/awx/lib/site-packages/celery/__main__.py b/awx/lib/site-packages/celery/__main__.py index 7fc3121154..04448e239b 100644 --- a/awx/lib/site-packages/celery/__main__.py +++ b/awx/lib/site-packages/celery/__main__.py @@ -24,7 +24,8 @@ def _warn_deprecated(new): def main(): - maybe_patch_concurrency() + if 'multi' not in sys.argv: + maybe_patch_concurrency() from celery.bin.celery import main main() @@ -37,7 +38,6 @@ def _compat_worker(): def _compat_multi(): - maybe_patch_concurrency() _warn_deprecated('celery multi') from celery.bin.multi import main main() diff --git a/awx/lib/site-packages/celery/_state.py b/awx/lib/site-packages/celery/_state.py index 73367a1869..3af39bf919 100644 --- a/awx/lib/site-packages/celery/_state.py +++ b/awx/lib/site-packages/celery/_state.py @@ -19,6 +19,31 @@ import weakref from celery.local import Proxy from celery.utils.threads import LocalStack +try: + from weakref import WeakSet as AppSet +except ImportError: # XXX Py2.6 + + class AppSet(object): # noqa + + def __init__(self): + self._refs = set() + + def add(self, app): + self._refs.add(weakref.ref(app)) + + def __iter__(self): + dirty = [] + try: + for appref in self._refs: + app = appref() + if app is None: + dirty.append(appref) + else: + yield app + finally: + while dirty: + self._refs.discard(dirty.pop()) + __all__ = ['set_default_app', 'get_current_app', 'get_current_task', 'get_current_worker_task', 'current_app', 'current_task'] @@ -26,14 +51,14 @@ __all__ = ['set_default_app', 'get_current_app', 'get_current_task', default_app = None #: List of all app instances (weakrefs), must not be used directly. -_apps = set() +_apps = AppSet() _task_join_will_block = False def _set_task_join_will_block(blocks): global _task_join_will_block - _task_join_will_block = True + _task_join_will_block = blocks def task_join_will_block(): @@ -62,6 +87,7 @@ def _get_current_app(): set_default_app(Celery( 'default', loader=os.environ.get('CELERY_LOADER') or 'default', + fixups=[], set_as_current=False, accept_magic_kwargs=True, )) return _tls.current_app or default_app @@ -104,18 +130,8 @@ current_task = Proxy(get_current_task) def _register_app(app): - _apps.add(weakref.ref(app)) + _apps.add(app) def _get_active_apps(): - dirty = [] - try: - for appref in _apps: - app = appref() - if app is None: - dirty.append(appref) - else: - yield app - finally: - while dirty: - _apps.discard(dirty.pop()) + return _apps diff --git a/awx/lib/site-packages/celery/app/__init__.py b/awx/lib/site-packages/celery/app/__init__.py index 5ea07eca62..426fed6ce8 100644 --- a/awx/lib/site-packages/celery/app/__init__.py +++ b/awx/lib/site-packages/celery/app/__init__.py @@ -10,8 +10,6 @@ from __future__ import absolute_import import os -from collections import Callable - from celery.local import Proxy from celery import _state from celery._state import ( @@ -148,6 +146,6 @@ def shared_task(*args, **kwargs): return Proxy(task_by_cons) return __inner - if len(args) == 1 and isinstance(args[0], Callable): + if len(args) == 1 and callable(args[0]): return create_shared_task(**kwargs)(args[0]) return create_shared_task(*args, **kwargs) diff --git a/awx/lib/site-packages/celery/app/amqp.py b/awx/lib/site-packages/celery/app/amqp.py index 850771636e..a058ff93f7 100644 --- a/awx/lib/site-packages/celery/app/amqp.py +++ b/awx/lib/site-packages/celery/app/amqp.py @@ -21,6 +21,7 @@ from kombu.utils.functional import maybe_list from celery import signals from celery.five import items, string_t from celery.utils.text import indent as textindent +from celery.utils.timeutils import to_utc from . import app_or_default from . import routes as _routes @@ -249,12 +250,12 @@ class TaskProducer(Producer): now = now or self.app.now() eta = now + timedelta(seconds=countdown) if self.utc: - eta = eta.replace(tzinfo=self.app.timezone) + eta = to_utc(eta).astimezone(self.app.timezone) if isinstance(expires, (int, float)): now = now or self.app.now() expires = now + timedelta(seconds=expires) if self.utc: - expires = expires.replace(tzinfo=self.app.timezone) + expires = to_utc(expires).astimezone(self.app.timezone) eta = eta and eta.isoformat() expires = expires and expires.isoformat() diff --git a/awx/lib/site-packages/celery/app/base.py b/awx/lib/site-packages/celery/app/base.py index 790d197e63..f37155b081 100644 --- a/awx/lib/site-packages/celery/app/base.py +++ b/awx/lib/site-packages/celery/app/base.py @@ -12,19 +12,22 @@ import os import threading import warnings -from collections import Callable, defaultdict, deque +from collections import defaultdict, deque from contextlib import contextmanager from copy import deepcopy from operator import attrgetter +from amqp import promise from billiard.util import register_after_fork from kombu.clocks import LamportClock from kombu.common import oid_from from kombu.utils import cached_property, uuid from celery import platforms +from celery import signals from celery._state import ( - _task_stack, _tls, get_current_app, _register_app, get_current_worker_task, + _task_stack, _tls, get_current_app, set_default_app, + _register_app, get_current_worker_task, ) from celery.exceptions import AlwaysEagerIgnored, ImproperlyConfigured from celery.five import items, values @@ -32,7 +35,6 @@ from celery.loaders import get_loader_cls from celery.local import PromiseProxy, maybe_evaluate from celery.utils.functional import first, maybe_list from celery.utils.imports import instantiate, symbol_by_name -from celery.utils.log import ensure_process_aware_logger from celery.utils.objects import mro_lookup from .annotations import prepare as prepare_annotations @@ -83,13 +85,16 @@ class Celery(object): control_cls = 'celery.app.control:Control' task_cls = 'celery.app.task:Task' registry_cls = TaskRegistry + _fixups = None _pool = None + builtin_fixups = BUILTIN_FIXUPS def __init__(self, main=None, loader=None, backend=None, amqp=None, events=None, log=None, control=None, set_as_current=True, accept_magic_kwargs=False, tasks=None, broker=None, include=None, changes=None, - config_source=None, fixups=None, task_cls=None, **kwargs): + config_source=None, fixups=None, task_cls=None, + autofinalize=True, **kwargs): self.clock = LamportClock() self.main = main self.amqp_cls = amqp or self.amqp_cls @@ -103,10 +108,11 @@ class Celery(object): self.registry_cls = symbol_by_name(self.registry_cls) self.accept_magic_kwargs = accept_magic_kwargs self.user_options = defaultdict(set) - self._config_source = config_source self.steps = defaultdict(set) + self.autofinalize = autofinalize self.configured = False + self._config_source = config_source self._pending_defaults = deque() self.finalized = False @@ -129,27 +135,23 @@ class Celery(object): if include: self._preconf['CELERY_IMPORTS'] = include - # Apply fixups. - self.fixups = set(fixups or ()) - for fixup in self.fixups | BUILTIN_FIXUPS: - symbol_by_name(fixup)(self) + # - Apply fixups. + self.fixups = set(self.builtin_fixups) if fixups is None else fixups + # ...store fixup instances in _fixups to keep weakrefs alive. + self._fixups = [symbol_by_name(fixup)(self) for fixup in self.fixups] if self.set_as_current: self.set_current() - # See Issue #1126 - # this is used when pickling the app object so that configuration - # is reread without having to pickle the contents - # (which is often unpickleable anyway) - if self._config_source: - self.config_from_object(self._config_source) - self.on_init() _register_app(self) def set_current(self): _tls.current_app = self + def set_default(self): + set_default_app(self) + def __enter__(self): return self @@ -211,14 +213,19 @@ class Celery(object): return _create_task_cls - if len(args) == 1 and isinstance(args[0], Callable): - return inner_create_task_cls(**opts)(*args) + if len(args) == 1: + if callable(args[0]): + return inner_create_task_cls(**opts)(*args) + raise TypeError('argument 1 to @task() must be a callable') if args: raise TypeError( - 'task() takes no arguments (%s given)' % (len(args, ))) + '@task() takes exactly 1 argument ({0} given)'.format( + sum([len(args), len(opts)]))) return inner_create_task_cls(**opts) def _task_from_fun(self, fun, **options): + if not self.finalized and not self.autofinalize: + raise RuntimeError('Contract breach: app not finalized') base = options.pop('base', None) or self.Task bind = options.pop('bind', False) @@ -232,9 +239,11 @@ class Celery(object): task = self._tasks[T.name] # return global instance. return task - def finalize(self): + def finalize(self, auto=False): with self._finalize_mutex: if not self.finalized: + if auto and not self.autofinalize: + raise RuntimeError('Contract breach: app not finalized') self.finalized = True load_shared_tasks(self) @@ -246,24 +255,25 @@ class Celery(object): task.bind(self) def add_defaults(self, fun): - if not isinstance(fun, Callable): + if not callable(fun): d, fun = fun, lambda: d if self.configured: return self.conf.add_defaults(fun()) self._pending_defaults.append(fun) - def config_from_object(self, obj, silent=False): - del(self.conf) + def config_from_object(self, obj, silent=False, force=False): self._config_source = obj - return self.loader.config_from_object(obj, silent=silent) + if force or self.configured: + del(self.conf) + return self.loader.config_from_object(obj, silent=silent) - def config_from_envvar(self, variable_name, silent=False): + def config_from_envvar(self, variable_name, silent=False, force=False): module_name = os.environ.get(variable_name) if not module_name: if silent: return False raise ImproperlyConfigured(ERR_ENVVAR_NOT_SET.format(module_name)) - return self.config_from_object(module_name, silent=silent) + return self.config_from_object(module_name, silent=silent, force=force) def config_from_cmdline(self, argv, namespace='celery'): self.conf.update(self.loader.cmdline_config_parser(argv, namespace)) @@ -274,13 +284,16 @@ class Celery(object): return setup_security(allowed_serializers, key, cert, store, digest, serializer, app=self) - def autodiscover_tasks(self, packages, related_name='tasks'): - if self.conf.CELERY_FORCE_BILLIARD_LOGGING: - # we'll use billiard's processName instead of - # multiprocessing's one in all the loggers - # created after this call - ensure_process_aware_logger() + def autodiscover_tasks(self, packages, related_name='tasks', force=False): + if force: + return self._autodiscover_tasks(packages, related_name) + signals.import_modules.connect(promise( + self._autodiscover_tasks, (packages, related_name), + ), weak=False, sender=self) + def _autodiscover_tasks(self, packages, related_name='tasks', **kwargs): + # argument may be lazy + packages = packages() if callable(packages) else packages self.loader.autodiscover_tasks(packages, related_name) def send_task(self, name, args=None, kwargs=None, countdown=None, @@ -294,7 +307,8 @@ class Celery(object): conf = self.conf if conf.CELERY_ALWAYS_EAGER: # pragma: no cover warnings.warn(AlwaysEagerIgnored( - 'CELERY_ALWAYS_EAGER has no effect on send_task')) + 'CELERY_ALWAYS_EAGER has no effect on send_task', + ), stacklevel=2) options = router.route(options, name, args, kwargs) if connection: producer = self.amqp.TaskProducer(connection) @@ -410,6 +424,8 @@ class Celery(object): def _get_config(self): self.on_configure() + if self._config_source: + self.loader.config_from_object(self._config_source) self.configured = True s = Settings({}, [self.prepare_config(self.loader.conf), deepcopy(DEFAULTS)]) @@ -430,8 +446,8 @@ class Celery(object): if self._pool: self._pool.force_close_all() self._pool = None - amqp = self.amqp - if amqp._producer_pool: + amqp = self.__dict__.get('amqp') + if amqp is not None and amqp._producer_pool is not None: amqp._producer_pool.force_close_all() amqp._producer_pool = None @@ -613,7 +629,7 @@ class Celery(object): @cached_property def tasks(self): - self.finalize() + self.finalize(auto=True) return self._tasks @cached_property diff --git a/awx/lib/site-packages/celery/app/builtins.py b/awx/lib/site-packages/celery/app/builtins.py index f6ecba4acd..8bb5133093 100644 --- a/awx/lib/site-packages/celery/app/builtins.py +++ b/awx/lib/site-packages/celery/app/builtins.py @@ -66,7 +66,7 @@ def add_unlock_chord_task(app): """ from celery.canvas import signature from celery.exceptions import ChordError - from celery.result import result_from_tuple + from celery.result import allow_join_result, result_from_tuple default_propagate = app.conf.CELERY_CHORD_PROPAGATES @@ -95,7 +95,8 @@ def add_unlock_chord_task(app): if deps.ready(): callback = signature(callback, app=app) try: - ret = j(propagate=propagate) + with allow_join_result(): + ret = j(timeout=3.0, propagate=propagate) except Exception as exc: try: culprit = next(deps._failed_join_report()) @@ -117,8 +118,8 @@ def add_unlock_chord_task(app): exc=ChordError('Callback error: {0!r}'.format(exc)), ) else: - return unlock_chord.retry(countdown=interval, - max_retries=max_retries) + raise unlock_chord.retry(countdown=interval, + max_retries=max_retries) return unlock_chord @@ -222,7 +223,10 @@ def add_group_task(app): @shared_task def add_chain_task(app): - from celery.canvas import Signature, chord, group, maybe_signature + from celery.canvas import ( + Signature, chain, chord, group, maybe_signature, maybe_unroll_group, + ) + _app = app class Chain(app.Task): @@ -244,7 +248,14 @@ def add_chain_task(app): res = task.freeze() i += 1 - if isinstance(task, group) and steps and \ + if isinstance(task, group): + task = maybe_unroll_group(task) + if isinstance(task, chain): + # splice the chain + steps.extendleft(reversed(task.tasks)) + continue + + elif isinstance(task, group) and steps and \ not isinstance(steps[0], group): # automatically upgrade group(..) | s to chord(group, s) try: @@ -344,17 +355,11 @@ def add_chord_task(app): results = [AsyncResult(prepare_member(task, body, group_id)) for task in header.tasks] - # - fallback implementations schedules the chord_unlock task here - app.backend.on_chord_apply(group_id, body, - interval=interval, - countdown=countdown, - max_retries=max_retries, - propagate=propagate, - result=results) - # - call the header group, returning the GroupResult. - final_res = header(*partial_args, task_id=group_id) - - return final_res + return self.backend.apply_chord( + header, partial_args, group_id, + body, interval=interval, countdown=countdown, + max_retries=max_retries, propagate=propagate, result=results, + ) def _prepare_member(self, task, body, group_id): opts = task.options @@ -373,7 +378,7 @@ def add_chord_task(app): return self.apply(args, kwargs, **options) header = kwargs.pop('header') body = kwargs.pop('body') - header, body = (list(maybe_signature(header, app=app)), + header, body = (maybe_signature(header, app=app), maybe_signature(body, app=app)) # forward certain options to body if chord is not None: diff --git a/awx/lib/site-packages/celery/app/defaults.py b/awx/lib/site-packages/celery/app/defaults.py index 1e004fdf2a..6cf03cd467 100644 --- a/awx/lib/site-packages/celery/app/defaults.py +++ b/awx/lib/site-packages/celery/app/defaults.py @@ -100,7 +100,6 @@ NAMESPACES = { 'ACKS_LATE': Option(False, type='bool'), 'ALWAYS_EAGER': Option(False, type='bool'), 'ANNOTATIONS': Option(type='any'), - 'FORCE_BILLIARD_LOGGING': Option(True, type='bool'), 'BROADCAST_QUEUE': Option('celeryctl'), 'BROADCAST_EXCHANGE': Option('celeryctl'), 'BROADCAST_EXCHANGE_TYPE': Option('fanout'), diff --git a/awx/lib/site-packages/celery/app/task.py b/awx/lib/site-packages/celery/app/task.py index 0c1f3c96c8..6d4c08659d 100644 --- a/awx/lib/site-packages/celery/app/task.py +++ b/awx/lib/site-packages/celery/app/task.py @@ -153,9 +153,11 @@ class TaskType(type): # in the '_app' attribute. Previously this was a regular attribute, # so we should support classes defining it. app = attrs.pop('_app', None) or attrs.pop('app', None) + + # Attempt to inherit app from one the bases if not isinstance(app, Proxy) and app is None: for base in bases: - if base._app: + if getattr(base, '_app', None): app = base._app break else: @@ -311,6 +313,14 @@ class Task(object): #: :setting:`CELERY_ACKS_LATE` setting. acks_late = None + #: List/tuple of expected exceptions. + #: + #: These are errors that are expected in normal operation + #: and that should not be regarded as a real error by the worker. + #: Currently this means that the state will be updated to an error + #: state, but the worker will not log the event as an error. + throws = () + #: Default task expiry time. expires = None @@ -759,6 +769,11 @@ class Task(object): from celery import xstarmap return xstarmap(self.s(), it, app=self.app) + def send_event(self, type_, **fields): + req = self.request + with self.app.events.default_dispatcher(hostname=req.hostname) as d: + return d.send(type_, uuid=req.id, **fields) + def update_state(self, task_id=None, state=None, meta=None): """Update task state. diff --git a/awx/lib/site-packages/celery/app/trace.py b/awx/lib/site-packages/celery/app/trace.py index cc28cb5bee..0066ef7e9e 100644 --- a/awx/lib/site-packages/celery/app/trace.py +++ b/awx/lib/site-packages/celery/app/trace.py @@ -22,6 +22,7 @@ import sys from warnings import warn from billiard.einfo import ExceptionInfo +from kombu.exceptions import EncodeError from kombu.utils import kwdict from celery import current_app @@ -193,8 +194,27 @@ def build_tracer(name, task, loader=None, hostname=None, store_errors=True, from celery import canvas signature = canvas.maybe_signature # maybe_ does not clone if already + def on_error(request, exc, uuid, state=FAILURE, call_errbacks=True): + if propagate: + raise + I = Info(state, exc) + R = I.handle_error_state(task, eager=eager) + if call_errbacks: + [signature(errback, app=app).apply_async((uuid, )) + for errback in request.errbacks or []] + return I, R, I.state, I.retval + def trace_task(uuid, args, kwargs, request=None): - R = I = None + # R - is the possibly prepared return value. + # I - is the Info object. + # retval - is the always unmodified return value. + # state - is the resulting task state. + + # This function is very long because we have unrolled all the calls + # for performance reasons, and because the function is so long + # we want the main variables (I, and R) to stand out visually from the + # the rest of the variables, so breaking PEP8 is worth it ;) + R = I = retval = state = None kwargs = kwdict(kwargs) try: push_task(task) @@ -224,32 +244,30 @@ def build_tracer(name, task, loader=None, hostname=None, store_errors=True, I, R = Info(IGNORED, exc), ExceptionInfo(internal=True) state, retval = I.state, I.retval except Retry as exc: - I = Info(RETRY, exc) - state, retval = I.state, I.retval - R = I.handle_error_state(task, eager=eager) + I, R, state, retval = on_error( + task_request, exc, uuid, RETRY, call_errbacks=False, + ) except Exception as exc: - if propagate: - raise - I = Info(FAILURE, exc) - state, retval = I.state, I.retval - R = I.handle_error_state(task, eager=eager) - [signature(errback, app=app).apply_async((uuid, )) - for errback in task_request.errbacks or []] + I, R, state, retval = on_error(task_request, exc, uuid) except BaseException as exc: raise else: - # callback tasks must be applied before the result is - # stored, so that result.children is populated. - [signature(callback, app=app).apply_async((retval, )) - for callback in task_request.callbacks or []] - if publish_result: - store_result( - uuid, retval, SUCCESS, request=task_request, - ) - if task_on_success: - task_on_success(retval, uuid, args, kwargs) - if success_receivers: - send_success(sender=task, result=retval) + try: + # callback tasks must be applied before the result is + # stored, so that result.children is populated. + [signature(callback, app=app).apply_async((retval, )) + for callback in task_request.callbacks or []] + if publish_result: + store_result( + uuid, retval, SUCCESS, request=task_request, + ) + except EncodeError as exc: + I, R, state, retval = on_error(task_request, exc, uuid) + else: + if task_on_success: + task_on_success(retval, uuid, args, kwargs) + if success_receivers: + send_success(sender=task, result=retval) # -* POST *- if state not in IGNORE_STATES: @@ -259,22 +277,24 @@ def build_tracer(name, task, loader=None, hostname=None, store_errors=True, task_after_return( state, retval, uuid, args, kwargs, None, ) + finally: + try: if postrun_receivers: send_postrun(sender=task, task_id=uuid, task=task, args=args, kwargs=kwargs, retval=retval, state=state) - finally: - pop_task() - pop_request() - if not eager: - try: - backend_cleanup() - loader_cleanup() - except (KeyboardInterrupt, SystemExit, MemoryError): - raise - except Exception as exc: - _logger.error('Process cleanup failed: %r', exc, - exc_info=True) + finally: + pop_task() + pop_request() + if not eager: + try: + backend_cleanup() + loader_cleanup() + except (KeyboardInterrupt, SystemExit, MemoryError): + raise + except Exception as exc: + _logger.error('Process cleanup failed: %r', exc, + exc_info=True) except MemoryError: raise except Exception as exc: diff --git a/awx/lib/site-packages/celery/app/utils.py b/awx/lib/site-packages/celery/app/utils.py index 5238cad0b6..defdca7b8e 100644 --- a/awx/lib/site-packages/celery/app/utils.py +++ b/awx/lib/site-packages/celery/app/utils.py @@ -13,16 +13,18 @@ import platform as _platform import re from collections import Mapping +from types import ModuleType from celery.datastructures import ConfigurationView -from celery.five import items, string_t +from celery.five import items, string_t, values from celery.platforms import pyimplementation from celery.utils.text import pretty -from celery.utils.imports import qualname +from celery.utils.imports import import_from_cwd, symbol_by_name, qualname from .defaults import find -__all__ = ['appstr', 'Settings', 'filter_hidden_settings', 'bugreport'] +__all__ = ['Settings', 'appstr', 'bugreport', + 'filter_hidden_settings', 'find_app'] #: Format used to generate bugreport information. BUGREPORT_INFO = """ @@ -175,7 +177,7 @@ def filter_hidden_settings(conf): return filter_hidden_settings(value) if isinstance(value, string_t) and HIDDEN_SETTINGS.search(key): return mask - if 'BROKER_URL' in key.upper(): + if isinstance(key, string_t) and 'BROKER_URL' in key.upper(): from kombu import Connection return Connection(value).as_uri(mask=mask) return value @@ -211,3 +213,41 @@ def bugreport(app): human_settings=app.conf.humanize(), loader=qualname(app.loader.__class__), ) + + +def find_app(app, symbol_by_name=symbol_by_name, imp=import_from_cwd): + from .base import Celery + + try: + sym = symbol_by_name(app, imp=imp) + except AttributeError: + # last part was not an attribute, but a module + sym = imp(app) + if isinstance(sym, ModuleType) and ':' not in app: + try: + found = sym.app + if isinstance(found, ModuleType): + raise AttributeError() + except AttributeError: + try: + found = sym.celery + if isinstance(found, ModuleType): + raise AttributeError() + except AttributeError: + if getattr(sym, '__path__', None): + try: + return find_app( + '{0}.celery'.format(app), + symbol_by_name=symbol_by_name, imp=imp, + ) + except ImportError: + pass + for suspect in values(vars(sym)): + if isinstance(suspect, Celery): + return suspect + raise + else: + return found + else: + return found + return sym diff --git a/awx/lib/site-packages/celery/apps/beat.py b/awx/lib/site-packages/celery/apps/beat.py index a2ca02234f..d4ab6e303c 100644 --- a/awx/lib/site-packages/celery/apps/beat.py +++ b/awx/lib/site-packages/celery/apps/beat.py @@ -10,7 +10,7 @@ and so on. """ -from __future__ import absolute_import +from __future__ import absolute_import, unicode_literals import socket import sys diff --git a/awx/lib/site-packages/celery/apps/worker.py b/awx/lib/site-packages/celery/apps/worker.py index 15b47eae8f..61162769bb 100644 --- a/awx/lib/site-packages/celery/apps/worker.py +++ b/awx/lib/site-packages/celery/apps/worker.py @@ -10,7 +10,7 @@ platform tweaks, and so on. """ -from __future__ import absolute_import, print_function +from __future__ import absolute_import, print_function, unicode_literals import logging import os @@ -24,10 +24,11 @@ from billiard import current_process from kombu.utils.encoding import safe_str from celery import VERSION_BANNER, platforms, signals +from celery.app import trace from celery.exceptions import CDeprecationWarning, SystemTerminate from celery.five import string, string_t from celery.loaders.app import AppLoader -from celery.app import trace +from celery.platforms import check_privileges from celery.utils import cry, isatty from celery.utils.imports import qualname from celery.utils.log import get_logger, in_sighandler, set_in_sighandler @@ -40,23 +41,6 @@ logger = get_logger(__name__) is_jython = sys.platform.startswith('java') is_pypy = hasattr(sys, 'pypy_version_info') -C_FORCE_ROOT = os.environ.get('C_FORCE_ROOT', False) - -ROOT_DISALLOWED = """\ -Running a worker with superuser privileges when the -worker accepts messages serialized with pickle is a very bad idea! - -If you really want to continue then you have to set the C_FORCE_ROOT -environment variable (but please think about this before you do). -""" - -ROOT_DISCOURAGED = """\ -You are running the worker with superuser privileges, which is -absolutely not recommended! - -Please specify a different user using the -u option. -""" - W_PICKLE_DEPRECATED = """ Starting from version 3.2 Celery will refuse to accept pickle by default. @@ -107,10 +91,10 @@ BANNER = """\ {platform} [config] -.> broker: {conninfo} .> app: {app} +.> transport: {conninfo} +.> results: {results} .> concurrency: {concurrency} -.> events: {events} [queues] {queues} @@ -133,6 +117,7 @@ class Worker(WorkController): sender=self.hostname, instance=self, conf=self.app.conf, options=kwargs, ) + check_privileges(self.app.conf.CELERY_ACCEPT_CONTENT) def on_after_init(self, purge=False, no_color=None, redirect_stdouts=None, redirect_stdouts_level=None, @@ -170,14 +155,6 @@ class Worker(WorkController): sender=self.hostname, instance=self, conf=self.app.conf, ) - if getattr(os, 'getuid', None) and os.getuid() == 0: - accept_encoding = self.app.conf.CELERY_ACCEPT_CONTENT - if ('pickle' in accept_encoding or - 'application/x-python-serialize' in accept_encoding): - if not C_FORCE_ROOT: - raise RuntimeError(ROOT_DISALLOWED) - warnings.warn(RuntimeWarning(ROOT_DISCOURAGED)) - if not self.app.conf.value_set_for('CELERY_ACCEPT_CONTENT'): warnings.warn(CDeprecationWarning(W_PICKLE_DEPRECATED)) @@ -186,10 +163,10 @@ class Worker(WorkController): # Dump configuration to screen so we have some basic information # for when users sends bug reports. - sys.__stdout__.write( - str(self.colored.cyan(' \n', self.startup_info())) + - str(self.colored.reset(self.extra_info() or '')) + '\n' - ) + print(''.join([ + string(self.colored.cyan(' \n', self.startup_info())), + string(self.colored.reset(self.extra_info() or '')), + ]), file=sys.__stdout__) self.set_process_status('-active-') self.install_platform_tweaks(self) @@ -248,6 +225,7 @@ class Worker(WorkController): hostname=safe_str(self.hostname), version=VERSION_BANNER, conninfo=self.app.connection().as_uri(), + results=self.app.conf.CELERY_RESULT_BACKEND or 'disabled', concurrency=concurrency, platform=safe_str(_platform.platform()), events=events, @@ -311,7 +289,7 @@ def _shutdown_handler(worker, sig='TERM', how='Warm', 'Cold': 'should_terminate'}[how], True) else: raise exc() - _handle_request.__name__ = 'worker_' + how + _handle_request.__name__ = str('worker_{0}'.format(how)) platforms.signals[sig] = _handle_request install_worker_term_handler = partial( _shutdown_handler, sig='SIGTERM', how='Warm', exc=SystemExit, diff --git a/awx/lib/site-packages/celery/backends/amqp.py b/awx/lib/site-packages/celery/backends/amqp.py index cc07f55361..88f3490e9f 100644 --- a/awx/lib/site-packages/celery/backends/amqp.py +++ b/awx/lib/site-packages/celery/backends/amqp.py @@ -55,6 +55,7 @@ class AMQPBackend(BaseBackend): BacklogLimitExceeded = BacklogLimitExceeded + persistent = True supports_autoexpire = True supports_native_join = True diff --git a/awx/lib/site-packages/celery/backends/base.py b/awx/lib/site-packages/celery/backends/base.py index c9a028ed16..ecb35108ae 100644 --- a/awx/lib/site-packages/celery/backends/base.py +++ b/awx/lib/site-packages/celery/backends/base.py @@ -311,7 +311,11 @@ class BaseBackend(object): self.app.tasks['celery.chord_unlock'].apply_async( (group_id, body, ), kwargs, countdown=countdown, ) - on_chord_apply = fallback_chord_unlock + + def apply_chord(self, header, partial_args, group_id, body, **options): + result = header(*partial_args, task_id=group_id) + self.fallback_chord_unlock(group_id, body, **options) + return result def current_task_children(self, request=None): request = request or getattr(current_task(), 'request', None) @@ -324,11 +328,25 @@ BaseDictBackend = BaseBackend # XXX compat class KeyValueStoreBackend(BaseBackend): - task_keyprefix = ensure_bytes('celery-task-meta-') - group_keyprefix = ensure_bytes('celery-taskset-meta-') - chord_keyprefix = ensure_bytes('chord-unlock-') + key_t = ensure_bytes + task_keyprefix = 'celery-task-meta-' + group_keyprefix = 'celery-taskset-meta-' + chord_keyprefix = 'chord-unlock-' implements_incr = False + def __init__(self, *args, **kwargs): + if hasattr(self.key_t, '__func__'): + self.key_t = self.key_t.__func__ # remove binding + self._encode_prefixes() + super(KeyValueStoreBackend, self).__init__(*args, **kwargs) + if self.implements_incr: + self.apply_chord = self._apply_chord_incr + + def _encode_prefixes(self): + self.task_keyprefix = self.key_t(self.task_keyprefix) + self.group_keyprefix = self.key_t(self.group_keyprefix) + self.chord_keyprefix = self.key_t(self.chord_keyprefix) + def get(self, key): raise NotImplementedError('Must implement the get method.') @@ -349,19 +367,19 @@ class KeyValueStoreBackend(BaseBackend): def get_key_for_task(self, task_id): """Get the cache key for a task by id.""" - return self.task_keyprefix + ensure_bytes(task_id) + return self.task_keyprefix + self.key_t(task_id) def get_key_for_group(self, group_id): """Get the cache key for a group by id.""" - return self.group_keyprefix + ensure_bytes(group_id) + return self.group_keyprefix + self.key_t(group_id) def get_key_for_chord(self, group_id): """Get the cache key for the chord waiting on group with given id.""" - return self.chord_keyprefix + ensure_bytes(group_id) + return self.chord_keyprefix + self.key_t(group_id) def _strip_prefix(self, key): """Takes bytes, emits string.""" - key = ensure_bytes(key) + key = self.key_t(key) for prefix in self.task_keyprefix, self.group_keyprefix: if key.startswith(prefix): return bytes_to_str(key[len(prefix):]) @@ -447,17 +465,16 @@ class KeyValueStoreBackend(BaseBackend): meta['result'] = result_from_tuple(result, self.app) return meta - def on_chord_apply(self, group_id, body, result=None, **kwargs): - if self.implements_incr: - self.save_group(group_id, self.app.GroupResult(group_id, result)) - else: - self.fallback_chord_unlock(group_id, body, result, **kwargs) + def _apply_chord_incr(self, header, partial_args, group_id, body, + result=None, **options): + self.save_group(group_id, self.app.GroupResult(group_id, result)) + return header(*partial_args, task_id=group_id) def on_chord_part_return(self, task, propagate=None): if not self.implements_incr: return from celery import maybe_signature - from celery.result import GroupResult + from celery.result import GroupResult, allow_join_result app = self.app if propagate is None: propagate = self.app.conf.CELERY_CHORD_PROPAGATES @@ -490,7 +507,8 @@ class KeyValueStoreBackend(BaseBackend): callback = maybe_signature(task.request.chord, app=self.app) j = deps.join_native if deps.supports_native_join else deps.join try: - ret = j(propagate=propagate) + with allow_join_result(): + ret = j(timeout=3.0, propagate=propagate) except Exception as exc: try: culprit = next(deps._failed_join_report()) diff --git a/awx/lib/site-packages/celery/backends/cache.py b/awx/lib/site-packages/celery/backends/cache.py index 3f42d1acf1..ac87100990 100644 --- a/awx/lib/site-packages/celery/backends/cache.py +++ b/awx/lib/site-packages/celery/backends/cache.py @@ -8,7 +8,10 @@ """ from __future__ import absolute_import +import sys + from kombu.utils import cached_property +from kombu.utils.encoding import bytes_to_str, ensure_bytes from celery.exceptions import ImproperlyConfigured from celery.utils.functional import LRUCache @@ -19,6 +22,8 @@ __all__ = ['CacheBackend'] _imp = [None] +PY3 = sys.version_info[0] == 3 + REQUIRES_BACKEND = """\ The memcached backend requires either pylibmc or python-memcached.\ """ @@ -31,7 +36,7 @@ Please use one of the following backends instead: {1}\ def import_best_memcache(): if _imp[0] is None: - is_pylibmc = False + is_pylibmc, memcache_key_t = False, ensure_bytes try: import pylibmc as memcache is_pylibmc = True @@ -40,17 +45,22 @@ def import_best_memcache(): import memcache # noqa except ImportError: raise ImproperlyConfigured(REQUIRES_BACKEND) - _imp[0] = (is_pylibmc, memcache) + if PY3: + memcache_key_t = bytes_to_str + _imp[0] = (is_pylibmc, memcache, memcache_key_t) return _imp[0] def get_best_memcache(*args, **kwargs): - behaviors = kwargs.pop('behaviors', None) - is_pylibmc, memcache = import_best_memcache() - client = memcache.Client(*args, **kwargs) - if is_pylibmc and behaviors is not None: - client.behaviors = behaviors - return client + is_pylibmc, memcache, key_t = import_best_memcache() + Client = _Client = memcache.Client + + if not is_pylibmc: + def Client(*args, **kwargs): # noqa + kwargs.pop('behaviors', None) + return _Client(*args, **kwargs) + + return Client, key_t class DummyClient(object): @@ -75,10 +85,10 @@ class DummyClient(object): return self.cache.incr(key, delta) -backends = {'memcache': lambda: get_best_memcache, - 'memcached': lambda: get_best_memcache, - 'pylibmc': lambda: get_best_memcache, - 'memory': lambda: DummyClient} +backends = {'memcache': get_best_memcache, + 'memcached': get_best_memcache, + 'pylibmc': get_best_memcache, + 'memory': lambda: (DummyClient, ensure_bytes)} class CacheBackend(KeyValueStoreBackend): @@ -100,10 +110,11 @@ class CacheBackend(KeyValueStoreBackend): self.servers = servers.rstrip('/').split(';') self.expires = self.prepare_expires(expires, type=int) try: - self.Client = backends[self.backend]() + self.Client, self.key_t = backends[self.backend]() except KeyError: raise ImproperlyConfigured(UNKNOWN_BACKEND.format( self.backend, ', '.join(backends))) + self._encode_prefixes() # rencode the keyprefixes def get(self, key): return self.client.get(key) @@ -117,9 +128,11 @@ class CacheBackend(KeyValueStoreBackend): def delete(self, key): return self.client.delete(key) - def on_chord_apply(self, group_id, body, result=None, **kwargs): + def _apply_chord_incr(self, header, partial_args, group_id, body, **opts): self.client.set(self.get_key_for_chord(group_id), '0', time=86400) - self.save_group(group_id, self.app.GroupResult(group_id, result)) + return super(CacheBackend, self)._apply_chord_incr( + header, partial_args, group_id, body, **opts + ) def incr(self, key): return self.client.incr(key) diff --git a/awx/lib/site-packages/celery/backends/database/models.py b/awx/lib/site-packages/celery/backends/database/models.py index 45acb97ef2..2802a007c0 100644 --- a/awx/lib/site-packages/celery/backends/database/models.py +++ b/awx/lib/site-packages/celery/backends/database/models.py @@ -57,7 +57,7 @@ class TaskSet(ResultModelBase): id = sa.Column(sa.Integer, sa.Sequence('taskset_id_sequence'), autoincrement=True, primary_key=True) taskset_id = sa.Column(sa.String(255), unique=True) - result = sa.Column(sa.PickleType, nullable=True) + result = sa.Column(PickleType, nullable=True) date_done = sa.Column(sa.DateTime, default=datetime.utcnow, nullable=True) diff --git a/awx/lib/site-packages/celery/backends/redis.py b/awx/lib/site-packages/celery/backends/redis.py index 4b09802e31..f7b36ee6e8 100644 --- a/awx/lib/site-packages/celery/backends/redis.py +++ b/awx/lib/site-packages/celery/backends/redis.py @@ -12,6 +12,9 @@ from kombu.utils import cached_property from kombu.utils.url import _parse_url from celery.exceptions import ImproperlyConfigured +from celery.five import string_t +from celery.utils import deprecated_property +from celery.utils.functional import dictfilter from .base import KeyValueStoreBackend @@ -35,18 +38,6 @@ class RedisBackend(KeyValueStoreBackend): #: redis-py client module. redis = redis - #: default Redis server hostname (`localhost`). - host = 'localhost' - - #: default Redis server port (6379) - port = 6379 - - #: default Redis db number (0) - db = 0 - - #: default Redis password (:const:`None`) - password = None - #: Maximium number of connections in the pool. max_connections = None @@ -69,20 +60,54 @@ class RedisBackend(KeyValueStoreBackend): except KeyError: pass if host and '://' in host: - url, host = host, None - self.url = url - uhost = uport = upass = udb = None + url = host + host = None + + self.max_connections = ( + max_connections or _get('MAX_CONNECTIONS') or self.max_connections + ) + + self.connparams = { + 'host': _get('HOST') or 'localhost', + 'port': _get('PORT') or 6379, + 'db': _get('DB') or 0, + 'password': _get('PASSWORD'), + 'max_connections': max_connections, + } if url: - _, uhost, uport, _, upass, udb, _ = _parse_url(url) - udb = udb.strip('/') if udb else 0 - self.host = uhost or host or _get('HOST') or self.host - self.port = int(uport or port or _get('PORT') or self.port) - self.db = udb or db or _get('DB') or self.db - self.password = upass or password or _get('PASSWORD') or self.password + self.connparams = self._params_from_url(url, self.connparams) + self.url = url self.expires = self.prepare_expires(expires, type=int) - self.max_connections = (max_connections - or _get('MAX_CONNECTIONS') - or self.max_connections) + + def _params_from_url(self, url, defaults): + scheme, host, port, user, password, path, query = _parse_url(url) + connparams = dict( + defaults, **dictfilter({ + 'host': host, 'port': port, 'password': password, + 'db': query.pop('virtual_host', None)}) + ) + + if scheme == 'socket': + # use 'path' as path to the socket… in this case + # the database number should be given in 'query' + connparams.update({ + 'connection_class': self.redis.UnixDomainSocketConnection, + 'path': '/' + path, + }) + # host+port are invalid options when using this connection type. + connparams.pop('host', None) + connparams.pop('port', None) + else: + connparams['db'] = path + + # db may be string and start with / like in kombu. + db = connparams.get('db') or 0 + db = db.strip('/') if isinstance(db, string_t) else db + connparams['db'] = int(db) + + # Query parameters override other parameters + connparams.update(query) + return connparams def get(self, key): return self.client.get(key) @@ -92,7 +117,7 @@ class RedisBackend(KeyValueStoreBackend): def set(self, key, value): client = self.client - if self.expires is not None: + if self.expires: client.setex(key, value, self.expires) else: client.set(key, value) @@ -109,17 +134,26 @@ class RedisBackend(KeyValueStoreBackend): @cached_property def client(self): - pool = self.redis.ConnectionPool(host=self.host, port=self.port, - db=self.db, password=self.password, - max_connections=self.max_connections) - return self.redis.Redis(connection_pool=pool) + return self.redis.Redis( + connection_pool=self.redis.ConnectionPool(**self.connparams)) def __reduce__(self, args=(), kwargs={}): - kwargs.update( - dict(host=self.host, - port=self.port, - db=self.db, - password=self.password, - expires=self.expires, - max_connections=self.max_connections)) - return super(RedisBackend, self).__reduce__(args, kwargs) + return super(RedisBackend, self).__reduce__( + (self.url, ), {'expires': self.expires}, + ) + + @deprecated_property(3.2, 3.3) + def host(self): + return self.connparams['host'] + + @deprecated_property(3.2, 3.3) + def port(self): + return self.connparams['port'] + + @deprecated_property(3.2, 3.3) + def db(self): + return self.connparams['db'] + + @deprecated_property(3.2, 3.3) + def password(self): + return self.connparams['password'] diff --git a/awx/lib/site-packages/celery/beat.py b/awx/lib/site-packages/celery/beat.py index 14101aab2a..f93e3bbf9b 100644 --- a/awx/lib/site-packages/celery/beat.py +++ b/awx/lib/site-packages/celery/beat.py @@ -18,6 +18,7 @@ import traceback from threading import Event, Thread from billiard import Process, ensure_multiprocessing +from billiard.common import reset_signals from kombu.utils import cached_property, reprcall from kombu.utils.functional import maybe_evaluate @@ -244,7 +245,7 @@ class Scheduler(object): except Exception as exc: reraise(SchedulingError, SchedulingError( "Couldn't apply scheduled task {0.name}: {exc}".format( - entry, exc)), sys.exc_info()[2]) + entry, exc=exc)), sys.exc_info()[2]) finally: if self.should_sync(): self._do_sync() @@ -501,7 +502,7 @@ else: self.name = 'Beat' def run(self): - platforms.signals.reset('SIGTERM') + reset_signals(full=False) platforms.close_open_fds([ sys.__stdin__, sys.__stdout__, sys.__stderr__, ] + list(iter_open_logger_fds())) diff --git a/awx/lib/site-packages/celery/bin/amqp.py b/awx/lib/site-packages/celery/bin/amqp.py index 8dcb34c136..c14f91d1a8 100644 --- a/awx/lib/site-packages/celery/bin/amqp.py +++ b/awx/lib/site-packages/celery/bin/amqp.py @@ -5,18 +5,18 @@ The :program:`celery amqp` command. .. program:: celery amqp """ -from __future__ import absolute_import, print_function +from __future__ import absolute_import, print_function, unicode_literals import cmd import sys import shlex import pprint -from collections import Callable from functools import partial from itertools import count from amqp import Message +from kombu.utils.encoding import safe_str from celery.utils.functional import padlist @@ -67,14 +67,7 @@ class Spec(object): self.returns = kwargs.get('returns') def coerce(self, index, value): - """Coerce value for argument at index. - - E.g. if :attr:`args` is `[('is_active', bool)]`: - - >>> coerce(0, 'False') - False - - """ + """Coerce value for argument at index.""" arg_info = self.args[index] arg_type = arg_info[1] # Might be a custom way to coerce the string value, @@ -98,7 +91,7 @@ class Spec(object): """Format the return value of this command in a human-friendly way.""" if not self.returns: return 'ok.' if response is None else response - if isinstance(self.returns, Callable): + if callable(self.returns): return self.returns(response) return self.returns.format(response) @@ -260,7 +253,7 @@ class AMQShell(cmd.Cmd): Lookup order is: :attr:`builtins` -> :attr:`amqp`. """ - arglist = shlex.split(argline) + arglist = shlex.split(safe_str(argline)) if cmd in self.builtins: return getattr(self, self.builtins[cmd])(*arglist) fun, args, formatter = self.get_amqp_api_command(cmd, arglist) diff --git a/awx/lib/site-packages/celery/bin/base.py b/awx/lib/site-packages/celery/bin/base.py index e08677198a..2a27c68384 100644 --- a/awx/lib/site-packages/celery/bin/base.py +++ b/awx/lib/site-packages/celery/bin/base.py @@ -63,9 +63,10 @@ in any command that also has a `--detach` option. Optional directory to change to after detaching. """ -from __future__ import absolute_import, print_function +from __future__ import absolute_import, print_function, unicode_literals import os +import random import re import socket import sys @@ -77,15 +78,15 @@ from heapq import heappush from inspect import getargspec from optparse import OptionParser, IndentedHelpFormatter, make_option as Option from pprint import pformat -from types import ModuleType from celery import VERSION_BANNER, Celery, maybe_patch_concurrency from celery import signals from celery.exceptions import CDeprecationWarning, CPendingDeprecationWarning -from celery.five import items, string, string_t, values +from celery.five import items, string, string_t from celery.platforms import EX_FAILURE, EX_OK, EX_USAGE from celery.utils import term from celery.utils import text +from celery.utils import NODENAME_DEFAULT, nodesplit from celery.utils.imports import symbol_by_name, import_from_cwd # always enable DeprecationWarnings, so our users can see them. @@ -259,6 +260,7 @@ class Command(object): pass def __call__(self, *args, **kwargs): + random.seed() # maybe we were forked. self.verify_args(args) try: ret = self.run(*args, **kwargs) @@ -432,7 +434,7 @@ class Command(object): if self.enable_config_from_cmdline: argv = self.process_cmdline_config(argv) else: - self.app = Celery() + self.app = Celery(fixups=[]) user_preload = tuple(self.app.user_options['preload'] or ()) if user_preload: @@ -445,33 +447,11 @@ class Command(object): return argv def find_app(self, app): - try: - sym = self.symbol_by_name(app) - except AttributeError: - # last part was not an attribute, but a module - sym = import_from_cwd(app) - if isinstance(sym, ModuleType): - try: - return sym.app - except AttributeError: - try: - return sym.celery - except AttributeError: - if getattr(sym, '__path__', None): - try: - return self.find_app( - '{0}.celery:'.format(app.replace(':', '')), - ) - except ImportError: - pass - for suspect in values(vars(sym)): - if isinstance(suspect, Celery): - return suspect - raise - return sym + from celery.app.utils import find_app + return find_app(app, symbol_by_name=self.symbol_by_name) - def symbol_by_name(self, name): - return symbol_by_name(name, imp=import_from_cwd) + def symbol_by_name(self, name, imp=import_from_cwd): + return symbol_by_name(name, imp=imp) get_cls_by_name = symbol_by_name # XXX compat def process_cmdline_config(self, argv): @@ -504,7 +484,12 @@ class Command(object): acc[opt.dest] = value else: opt = opts.get(arg) - if opt and opt.action == 'store_true': + if opt and opt.takes_value(): + # optparse also supports ['--opt', 'value'] + # (Issue #1668) + acc[opt.dest] = args[index + 1] + index += 1 + elif opt and opt.action == 'store_true': acc[opt.dest] = True elif arg.startswith('-'): opt = opts.get(arg) @@ -540,9 +525,17 @@ class Command(object): """ pass - def simple_format(self, s, match=find_sformat, expand=r'\1', **keys): + def node_format(self, s, nodename, **extra): + name, host = nodesplit(nodename) + return self._simple_format( + s, host, n=name or NODENAME_DEFAULT, **extra) + + def simple_format(self, s, **extra): + return self._simple_format(s, socket.gethostname(), **extra) + + def _simple_format(self, s, host, + match=find_sformat, expand=r'\1', **keys): if s: - host = socket.gethostname() name, _, domain = host.partition('.') keys = dict({'%': '%', 'h': host, 'n': name, 'd': domain}, **keys) return match.sub(lambda m: keys[m.expand(expand)], s) diff --git a/awx/lib/site-packages/celery/bin/beat.py b/awx/lib/site-packages/celery/bin/beat.py index e0a54d7371..3049668b9d 100644 --- a/awx/lib/site-packages/celery/bin/beat.py +++ b/awx/lib/site-packages/celery/bin/beat.py @@ -42,7 +42,7 @@ from __future__ import absolute_import from functools import partial -from celery.platforms import detached +from celery.platforms import detached, maybe_drop_privileges from celery.bin.base import Command, Option, daemon_options @@ -65,6 +65,8 @@ class beat(Command): def run(self, detach=False, logfile=None, pidfile=None, uid=None, gid=None, umask=None, working_directory=None, **kwargs): + if not detach: + maybe_drop_privileges(uid=uid, gid=gid) workdir = working_directory kwargs.pop('app', None) beat = partial(self.app.Beat, diff --git a/awx/lib/site-packages/celery/bin/celery.py b/awx/lib/site-packages/celery/bin/celery.py index 33a1e70798..3b35bb10c2 100644 --- a/awx/lib/site-packages/celery/bin/celery.py +++ b/awx/lib/site-packages/celery/bin/celery.py @@ -319,10 +319,7 @@ class _RemoteControl(Command): if destination and isinstance(destination, string_t): destination = [dest.strip() for dest in destination.split(',')] - try: - handler = getattr(self, method) - except AttributeError: - handler = self.call + handler = getattr(self, method, self.call) replies = handler(method, *args[1:], timeout=timeout, destination=destination, @@ -423,22 +420,22 @@ class control(_RemoteControl): def rate_limit(self, method, task_name, rate_limit, **kwargs): """ (e.g. 5/s | 5/m | 5/h)>""" - return self.call(method, task_name, rate_limit, reply=True, **kwargs) + return self.call(method, task_name, rate_limit, **kwargs) def time_limit(self, method, task_name, soft, hard=None, **kwargs): """ [hard_secs]""" return self.call(method, task_name, - float(soft), float(hard), reply=True, **kwargs) + float(soft), float(hard), **kwargs) def add_consumer(self, method, queue, exchange=None, exchange_type='direct', routing_key=None, **kwargs): """ [exchange [type [routing_key]]]""" return self.call(method, queue, exchange, - exchange_type, routing_key, reply=True, **kwargs) + exchange_type, routing_key, **kwargs) def cancel_consumer(self, method, queue, **kwargs): """""" - return self.call(method, queue, reply=True, **kwargs) + return self.call(method, queue, **kwargs) class status(Command): @@ -542,7 +539,8 @@ class shell(Command): # pragma: no cover import celery import celery.task.base self.app.loader.import_default_modules() - self.locals = {'celery': self.app, + self.locals = {'app': self.app, + 'celery': self.app, 'Task': celery.Task, 'chord': celery.chord, 'group': celery.group, @@ -594,7 +592,7 @@ class shell(Command): # pragma: no cover def invoke_ipython_shell(self): try: - from IPython.frontend.terminal import embed + from IPython.terminal import embed embed.TerminalInteractiveShell(user_ns=self.locals).mainloop() except ImportError: # ipython < 0.11 from IPython.Shell import IPShell @@ -686,16 +684,18 @@ class CeleryCommand(Command): self=self, command=command, ))) - def remove_options_at_beginning(self, argv, index=0): + def _relocate_args_from_start(self, argv, index=0): if argv: + rest = [] while index < len(argv): value = argv[index] if value.startswith('--'): - pass + rest.append(value) elif value.startswith('-'): + rest.extend([value] + [argv[index + 1]]) index += 1 else: - return argv[index:] + return argv[index:] + rest index += 1 return [] @@ -706,7 +706,7 @@ class CeleryCommand(Command): def handle_argv(self, prog_name, argv): self.prog_name = self.prepare_prog_name(prog_name) - argv = self.remove_options_at_beginning(argv) + argv = self._relocate_args_from_start(argv) _, argv = self.prepare_args(None, argv) try: command = argv[0] diff --git a/awx/lib/site-packages/celery/bin/events.py b/awx/lib/site-packages/celery/bin/events.py index f0142ffdc9..2bca74b65b 100644 --- a/awx/lib/site-packages/celery/bin/events.py +++ b/awx/lib/site-packages/celery/bin/events.py @@ -35,7 +35,7 @@ The :program:`celery events` command. `ERROR`, `CRITICAL`, or `FATAL`. Default is INFO. """ -from __future__ import absolute_import +from __future__ import absolute_import, unicode_literals import sys diff --git a/awx/lib/site-packages/celery/bin/multi.py b/awx/lib/site-packages/celery/bin/multi.py index e2a583f3b8..9e0789d986 100644 --- a/awx/lib/site-packages/celery/bin/multi.py +++ b/awx/lib/site-packages/celery/bin/multi.py @@ -91,7 +91,7 @@ Examples celery worker -n xuzzy@myhost -c 3 """ -from __future__ import absolute_import, print_function +from __future__ import absolute_import, print_function, unicode_literals import errno import os @@ -228,9 +228,9 @@ class MultiTool(object): def show(self, argv, cmd): p = NamespacedOptionParser(argv) - self.note('> Starting nodes...') + self.with_detacher_default_options(p) self.say('\n'.join( - ' '.join(n.argv) for n in multi_args(p, cmd)), + ' '.join([sys.executable] + n.argv) for n in multi_args(p, cmd)), ) def start(self, argv, cmd): diff --git a/awx/lib/site-packages/celery/bin/worker.py b/awx/lib/site-packages/celery/bin/worker.py index 3c3065d901..f18b85c3ef 100644 --- a/awx/lib/site-packages/celery/bin/worker.py +++ b/awx/lib/site-packages/celery/bin/worker.py @@ -130,7 +130,7 @@ The :program:`celery worker` command (previously known as ``celeryd``) Don't do execv after multiprocessing child fork. """ -from __future__ import absolute_import +from __future__ import absolute_import, unicode_literals import sys @@ -138,6 +138,8 @@ from celery import concurrency from celery.bin.base import Command, Option, daemon_options from celery.bin.celeryd_detach import detached_celeryd from celery.five import string_t +from celery.platforms import maybe_drop_privileges +from celery.utils import default_nodename from celery.utils.log import LOG_LEVELS, mlevel __all__ = ['worker', 'main'] @@ -179,8 +181,10 @@ class worker(Command): detached_celeryd(self.app).execute_from_commandline(argv) raise SystemExit(0) - def run(self, hostname=None, pool_cls=None, loglevel=None, - app=None, **kwargs): + def run(self, hostname=None, pool_cls=None, app=None, uid=None, gid=None, + loglevel=None, logfile=None, pidfile=None, state_db=None, + **kwargs): + maybe_drop_privileges(uid=uid, gid=gid) # Pools like eventlet/gevent needs to patch libs as early # as possible. pool_cls = (concurrency.get_implementation(pool_cls) or @@ -188,7 +192,7 @@ class worker(Command): if self.app.IS_WINDOWS and kwargs.get('beat'): self.die('-B option does not work on Windows. ' 'Please run celery beat as a separate service.') - hostname = self.simple_format(hostname) + hostname = self.simple_format(default_nodename(hostname)) if loglevel: try: loglevel = mlevel(loglevel) @@ -198,7 +202,10 @@ class worker(Command): l for l in LOG_LEVELS if isinstance(l, string_t)))) return self.app.Worker( - hostname=hostname, pool_cls=pool_cls, loglevel=loglevel, **kwargs + hostname=hostname, pool_cls=pool_cls, loglevel=loglevel, + logfile=self.node_format(logfile, hostname), + pidfile=self.node_format(pidfile, hostname), + state_db=self.node_format(state_db, hostname), **kwargs ).start() def with_pool_option(self, argv): diff --git a/awx/lib/site-packages/celery/bootsteps.py b/awx/lib/site-packages/celery/bootsteps.py index be6247abe6..7796afb60e 100644 --- a/awx/lib/site-packages/celery/bootsteps.py +++ b/awx/lib/site-packages/celery/bootsteps.py @@ -18,7 +18,6 @@ from .datastructures import DependencyGraph, GraphFormatter from .five import values, with_metaclass from .utils.imports import instantiate, qualname from .utils.log import get_logger -from .utils.threads import default_socket_timeout try: from greenlet import GreenletExit @@ -28,9 +27,6 @@ except ImportError: # pragma: no cover __all__ = ['Blueprint', 'Step', 'StartStopStep', 'ConsumerStep'] -#: Default socket timeout at shutdown. -SHUTDOWN_SOCKET_TIMEOUT = 5.0 - #: States RUN = 0x1 CLOSE = 0x2 @@ -147,24 +143,23 @@ class Blueprint(object): def send_all(self, parent, method, description=None, reverse=True, propagate=True, args=()): - description = description or method.capitalize() + description = description or method.replace('_', ' ') steps = reversed(parent.steps) if reverse else parent.steps - with default_socket_timeout(SHUTDOWN_SOCKET_TIMEOUT): # Issue 975 - for step in steps: - if step: + for step in steps: + if step: + fun = getattr(step, method, None) + if fun is not None: self._debug('%s %s...', description.capitalize(), step.alias) - fun = getattr(step, method, None) - if fun: - try: - fun(parent, *args) - except Exception as exc: - if propagate: - raise - logger.error( - 'Error while %s %s: %r', - description, step.alias, exc, exc_info=1, - ) + try: + fun(parent, *args) + except Exception as exc: + if propagate: + raise + logger.error( + 'Error on %s %s: %r', + description, step.alias, exc, exc_info=1, + ) def stop(self, parent, close=True, terminate=False): what = 'terminating' if terminate else 'stopping' @@ -410,11 +405,17 @@ class ConsumerStep(StartStopStep): consumer.consume() def stop(self, c): + self._close(c, True) + + def shutdown(self, c): + self._close(c, False) + + def _close(self, c, cancel_consumers=True): channels = set() for consumer in self.consumers or []: - ignore_errors(c.connection, consumer.cancel) + if cancel_consumers: + ignore_errors(c.connection, consumer.cancel) if consumer.channel: channels.add(consumer.channel) for channel in channels: ignore_errors(c.connection, channel.close) - shutdown = stop diff --git a/awx/lib/site-packages/celery/canvas.py b/awx/lib/site-packages/celery/canvas.py index b35239e9fa..6b323776cf 100644 --- a/awx/lib/site-packages/celery/canvas.py +++ b/awx/lib/site-packages/celery/canvas.py @@ -82,6 +82,22 @@ class _getitem_property(object): self._path(obj)[self.key] = value +def maybe_unroll_group(g): + """Unroll group with only one member.""" + # Issue #1656 + try: + size = len(g.tasks) + except TypeError: + try: + size = g.tasks.__length_hint__() + except (AttributeError, TypeError): + pass + else: + return list(g.tasks)[0] if size == 1 else g + else: + return g.tasks[0] if size == 1 else g + + class Signature(dict): """Class that wraps the arguments and execution options for a single task invocation. @@ -209,12 +225,16 @@ class Signature(dict): self.immutable = immutable def apply_async(self, args=(), kwargs={}, **options): + try: + _apply = self._apply_async + except IndexError: # no tasks for chain, etc to find type + return # For callbacks: extra args are prepended to the stored args. if args or kwargs or options: args, kwargs, options = self._merge(args, kwargs, options) else: args, kwargs, options = self.args, self.kwargs, self.options - return self._apply_async(args, kwargs, **options) + return _apply(args, kwargs, **options) def append_to_list_option(self, key, value): items = self.options.setdefault(key, []) @@ -236,6 +256,8 @@ class Signature(dict): ))) def __or__(self, other): + if isinstance(other, group): + other = maybe_unroll_group(other) if not isinstance(self, chain) and isinstance(other, chain): return chain((self, ) + other.tasks, app=self._app) elif isinstance(other, chain): @@ -455,11 +477,7 @@ class group(Signature): tasks = _maybe_clone(self.tasks, app=self._app) if not tasks: return self.freeze() - # taking the app from the first task in the list, - # there may be a better solution to this, e.g. - # consolidate tasks with the same app and apply them in - # batches. - type = tasks[0].type.app.tasks[self['task']] + type = self.type return type(*type.prepare(dict(self.options, **options), tasks, args)) @@ -513,7 +531,13 @@ class group(Signature): @property def type(self): - return self._type or self.tasks[0].type.app.tasks[self['task']] + if self._type: + return self._type + # taking the app from the first task in the list, there may be a + # better solution for this, e.g. to consolidate tasks with the same + # app and apply them in batches. + app = self._app if self._app else self.tasks[0].type.app + return app.tasks[self['task']] @Signature.register_type @@ -541,15 +565,25 @@ class chord(Signature): @property def type(self): - return self._type or self.tasks[0].type.app.tasks['celery.chord'] + if self._type: + return self._type + # we will be able to fix this mess in 3.2 when we no longer + # require an actual task implementation for chord/group + if self._app: + app = self._app + else: + try: + app = self.tasks[0].type.app + except IndexError: + app = self.body.type.app + return app.tasks['celery.chord'] def apply_async(self, args=(), kwargs={}, task_id=None, **options): body = kwargs.get('body') or self.kwargs['body'] kwargs = dict(self.kwargs, **kwargs) body = body.clone(**options) - _chord = self._type or body.type.app.tasks['celery.chord'] - + _chord = self.type if _chord.app.conf.CELERY_ALWAYS_EAGER: return self.apply((), kwargs, task_id=task_id, **options) res = body.freeze(task_id) @@ -601,10 +635,14 @@ subtask = signature # XXX compat def maybe_signature(d, app=None): - if d is not None and isinstance(d, dict): - if not isinstance(d, Signature): - return signature(d, app=app) + if d is not None: + if isinstance(d, dict): + if not isinstance(d, Signature): + return signature(d, app=app) + elif isinstance(d, list): + return [maybe_signature(s, app=app) for s in d] if app is not None: d._app = app return d + maybe_subtask = maybe_signature # XXX compat diff --git a/awx/lib/site-packages/celery/concurrency/asynpool.py b/awx/lib/site-packages/celery/concurrency/asynpool.py index ce0f38ea76..081d3118e7 100644 --- a/awx/lib/site-packages/celery/concurrency/asynpool.py +++ b/awx/lib/site-packages/celery/concurrency/asynpool.py @@ -85,6 +85,9 @@ UNAVAIL = frozenset([errno.EAGAIN, errno.EINTR]) #: Constant sent by child process when started (ready to accept work) WORKER_UP = 15 +#: A process must have started before this timeout (in secs.) expires. +PROC_ALIVE_TIMEOUT = 4.0 + SCHED_STRATEGY_PREFETCH = 1 SCHED_STRATEGY_FAIR = 4 @@ -93,6 +96,8 @@ SCHED_STRATEGIES = { 'fair': SCHED_STRATEGY_FAIR, } +RESULT_MAXLEN = 128 + Ack = namedtuple('Ack', ('id', 'fd', 'payload')) @@ -165,9 +170,9 @@ class Worker(_pool.Worker): # is writable. self.outq.put((WORKER_UP, (pid, ))) - def prepare_result(self, result): + def prepare_result(self, result, RESULT_MAXLEN=RESULT_MAXLEN): if not isinstance(result, ExceptionInfo): - return truncate(repr(result), 46) + return truncate(repr(result), RESULT_MAXLEN) return result @@ -356,7 +361,7 @@ class AsynPool(_pool.Pool): # sent a WORKER_UP message. If a process fails to send # this message within proc_up_timeout we terminate it # and hope the next process will recover. - self._proc_alive_timeout = 2.0 + self._proc_alive_timeout = PROC_ALIVE_TIMEOUT self._waiting_to_start = set() # denormalized set of all inqueues. @@ -493,7 +498,7 @@ class AsynPool(_pool.Pool): waiting_to_start = self._waiting_to_start def verify_process_alive(proc): - if proc.exitcode is None and proc in waiting_to_start: + if proc._is_alive() and proc in waiting_to_start: assert proc.outqR_fd in fileno_to_outq assert fileno_to_outq[proc.outqR_fd] is proc assert proc.outqR_fd in hub.readers @@ -728,7 +733,7 @@ class AsynPool(_pool.Pool): def on_not_recovering(proc, fd, job): error('Process inqueue damaged: %r %r' % (proc, proc.exitcode)) - if proc.exitcode is not None: + if proc._is_alive(): proc.terminate() hub.remove(fd) self._put_back(job) @@ -886,7 +891,7 @@ class AsynPool(_pool.Pool): pass else: job_proc = job._write_to - if job_proc.exitcode is None: + if job_proc._is_alive(): self._flush_writer(job_proc, gen) # workers may have exited in the meantime. self.maintain_pool() @@ -901,7 +906,7 @@ class AsynPool(_pool.Pool): fds = set([proc.inq._writer]) try: while fds: - if proc.exitcode: + if not proc._is_alive(): break # process exited readable, writable, again = _select( writers=fds, err=fds, timeout=0.5, @@ -973,10 +978,10 @@ class AsynPool(_pool.Pool): def on_job_process_down(self, job, pid_gone): """Handler called for each job when the process it was assigned to exits.""" - if job._write_to and job._write_to.exitcode: + if job._write_to and not job._write_to._is_alive(): # job was partially written self.on_partial_read(job, job._write_to) - elif job._scheduled_for and job._scheduled_for.exitcode: + elif job._scheduled_for and not job._scheduled_for._is_alive(): # job was only scheduled to be written to this process, # but no data was sent so put it back on the outbound_buffer. self._put_back(job) @@ -1020,12 +1025,16 @@ class AsynPool(_pool.Pool): def _stop_task_handler(task_handler): """Called at shutdown to tell processes that we are shutting down.""" for proc in task_handler.pool: - setblocking(proc.inq._writer, 1) try: - proc.inq.put(None) - except OSError as exc: - if get_errno(exc) != errno.EBADF: - raise + setblocking(proc.inq._writer, 1) + except (OSError, IOError): + pass + else: + try: + proc.inq.put(None) + except OSError as exc: + if get_errno(exc) != errno.EBADF: + raise def create_result_handler(self): return super(AsynPool, self).create_result_handler( @@ -1075,6 +1084,13 @@ class AsynPool(_pool.Pool): try: task = resq.recv() except (OSError, IOError, EOFError) as exc: + if get_errno(exc) == errno.EINTR: + continue + elif get_errno(exc) == errno.EAGAIN: + break + else: + debug('got %r while flushing process %r', + exc, proc, exc_info=1) if get_errno(exc) not in UNAVAIL: debug('got %r while flushing process %r', exc, proc, exc_info=1) @@ -1120,7 +1136,7 @@ class AsynPool(_pool.Pool): def destroy_queues(self, queues, proc): """Destroy queues that can no longer be used, so that they be replaced by new sockets.""" - assert proc.exitcode is not None + assert not proc._is_alive() self._waiting_to_start.discard(proc) removed = 1 try: diff --git a/awx/lib/site-packages/celery/concurrency/prefork.py b/awx/lib/site-packages/celery/concurrency/prefork.py index 6b9c881c9b..75eb28efce 100644 --- a/awx/lib/site-packages/celery/concurrency/prefork.py +++ b/awx/lib/site-packages/celery/concurrency/prefork.py @@ -9,7 +9,6 @@ from __future__ import absolute_import import os -import sys from billiard import forking_enable from billiard.pool import RUN, CLOSE, Pool as BlockingPool @@ -20,6 +19,7 @@ from celery._state import set_default_app, _set_task_join_will_block from celery.app import trace from celery.concurrency.base import BasePool from celery.five import items +from celery.utils.functional import noop from celery.utils.log import get_logger from .asynpool import AsynPool @@ -36,11 +36,6 @@ WORKER_SIGRESET = frozenset(['SIGTERM', #: List of signals to ignore when a child process starts. WORKER_SIGIGNORE = frozenset(['SIGINT']) -MAXTASKS_NO_BILLIARD = """\ - maxtasksperchild enabled but billiard C extension not installed! - This may lead to a deadlock, so please install the billiard C extension. -""" - logger = get_logger(__name__) warning, debug = logger.warning, logger.debug @@ -107,14 +102,6 @@ class TaskPool(BasePool): Will pre-fork all workers so they're ready to accept tasks. """ - if self.options.get('maxtasksperchild') and sys.platform != 'win32': - try: - from billiard.connection import Connection - Connection.send_offset - except (ImportError, AttributeError): - # billiard C extension not installed - warning(MAXTASKS_NO_BILLIARD) - forking_enable(self.forking_enable) Pool = (self.BlockingPool if self.options.get('threads', True) else self.Pool) @@ -131,7 +118,10 @@ class TaskPool(BasePool): self.grow = P.grow self.shrink = P.shrink self.flush = getattr(P, 'flush', None) # FIXME add to billiard - self.restart = P.restart + + def restart(self): + self._pool.restart() + self._pool.apply_async(noop) def did_start_ok(self): return self._pool.did_start_ok() diff --git a/awx/lib/site-packages/celery/datastructures.py b/awx/lib/site-packages/celery/datastructures.py index 03d6cd1664..9f7c34f71f 100644 --- a/awx/lib/site-packages/celery/datastructures.py +++ b/awx/lib/site-packages/celery/datastructures.py @@ -24,10 +24,11 @@ from celery.five import items from celery.utils.functional import LRUCache, first, uniq # noqa try: - from django.utils.functional import LazyObject + from django.utils.functional import LazyObject, LazySettings except ImportError: class LazyObject(object): # noqa pass + LazySettings = LazyObject # noqa DOT_HEAD = """ {IN}{type} {id} {{ @@ -46,7 +47,7 @@ __all__ = ['GraphFormatter', 'CycleError', 'DependencyGraph', def force_mapping(m): - if isinstance(m, LazyObject): + if isinstance(m, (LazyObject, LazySettings)): m = m._wrapped return DictAttribute(m) if not isinstance(m, Mapping) else m diff --git a/awx/lib/site-packages/celery/events/__init__.py b/awx/lib/site-packages/celery/events/__init__.py index 1b8407f23e..931f3953ec 100644 --- a/awx/lib/site-packages/celery/events/__init__.py +++ b/awx/lib/site-packages/celery/events/__init__.py @@ -12,7 +12,6 @@ from __future__ import absolute_import import os import time -import socket import threading import warnings @@ -27,7 +26,7 @@ from kombu.mixins import ConsumerMixin from kombu.utils import cached_property from celery.app import app_or_default -from celery.utils import uuid +from celery.utils import anon_nodename, uuid from celery.utils.functional import dictfilter from celery.utils.timeutils import adjust_timestamp, utcoffset, maybe_s_to_ms @@ -45,6 +44,8 @@ so timestamps will not work. Please uninstall yajl or force anyjson to use a different library. """ +CLIENT_CLOCK_SKEW = -1 + def get_exchange(conn): ex = copy(event_exchange) @@ -90,7 +91,8 @@ class EventDispatcher(object): :param connection: Connection to the broker. :keyword hostname: Hostname to identify ourselves as, - by default uses the hostname returned by :func:`socket.gethostname`. + by default uses the hostname returned by + :func:`~celery.utils.anon_nodename`. :keyword groups: List of groups to send events for. :meth:`send` will ignore send requests to groups not in this list. @@ -126,7 +128,7 @@ class EventDispatcher(object): self.app = app_or_default(app or self.app) self.connection = connection self.channel = channel - self.hostname = hostname or socket.gethostname() + self.hostname = hostname or anon_nodename() self.buffer_while_offline = buffer_while_offline self.mutex = threading.Lock() self.producer = None @@ -279,7 +281,8 @@ class EventReceiver(ConsumerMixin): app = None def __init__(self, channel, handlers=None, routing_key='#', - node_id=None, app=None, queue_prefix='celeryev'): + node_id=None, app=None, queue_prefix='celeryev', + accept=None): self.app = app_or_default(app or self.app) self.channel = maybe_channel(channel) self.handlers = {} if handlers is None else handlers @@ -293,7 +296,12 @@ class EventReceiver(ConsumerMixin): auto_delete=True, durable=False, queue_arguments=self._get_queue_arguments()) - self.adjust_clock = self.app.clock.adjust + self.clock = self.app.clock + self.adjust_clock = self.clock.adjust + self.forward_clock = self.clock.forward + if accept is None: + accept = set([self.app.conf.CELERY_EVENT_SERIALIZER, 'json']) + self.accept = accept def _get_queue_arguments(self): conf = self.app.conf @@ -311,7 +319,7 @@ class EventReceiver(ConsumerMixin): def get_consumers(self, Consumer, channel): return [Consumer(queues=[self.queue], callbacks=[self._receive], no_ack=True, - accept=['application/json'])] + accept=self.accept)] def on_consume_ready(self, connection, channel, consumers, wakeup=True, **kwargs): @@ -337,11 +345,20 @@ class EventReceiver(ConsumerMixin): def event_from_message(self, body, localize=True, now=time.time, tzfields=_TZGETTER, - adjust_timestamp=adjust_timestamp): - type = body.get('type', '').lower() - clock = body.get('clock') - if clock: - self.adjust_clock(clock) + adjust_timestamp=adjust_timestamp, + CLIENT_CLOCK_SKEW=CLIENT_CLOCK_SKEW): + type = body['type'] + if type == 'task-sent': + # clients never sync so cannot use their clock value + _c = body['clock'] = (self.clock.value or 1) + CLIENT_CLOCK_SKEW + self.adjust_clock(_c) + else: + try: + clock = body['clock'] + except KeyError: + body['clock'] = self.forward_clock() + else: + self.adjust_clock(clock) if localize: try: @@ -350,7 +367,8 @@ class EventReceiver(ConsumerMixin): pass else: body['timestamp'] = adjust_timestamp(timestamp, offset) - return type, Event(type, body, local_received=now()) + body['local_received'] = now() + return type, body def _receive(self, body, message): self.process(*self.event_from_message(body)) diff --git a/awx/lib/site-packages/celery/events/state.py b/awx/lib/site-packages/celery/events/state.py index d68f8bf32b..05bb4f95c7 100644 --- a/awx/lib/site-packages/celery/events/state.py +++ b/awx/lib/site-packages/celery/events/state.py @@ -18,22 +18,28 @@ """ from __future__ import absolute_import +import sys import threading from datetime import datetime -from heapq import heappush, heappop +from decimal import Decimal +from heapq import heapify, heappush, heappop from itertools import islice +from operator import itemgetter from time import time +from weakref import ref from kombu.clocks import timetuple -from kombu.utils import kwdict +from kombu.utils import cached_property, kwdict from celery import states -from celery.datastructures import AttributeDict -from celery.five import items, values +from celery.five import class_property, items, values +from celery.utils import deprecated from celery.utils.functional import LRUCache from celery.utils.log import get_logger +PYPY = hasattr(sys, 'pypy_version_info') + # The window (in percentage) is added to the workers heartbeat # frequency. If the time between updates exceeds this window, # then the worker is considered to be offline. @@ -48,19 +54,31 @@ Substantial drift from %s may mean clocks are out of sync. Current drift is %s seconds. [orig: %s recv: %s] """ +CAN_KWDICT = sys.version_info >= (2, 6, 5) + logger = get_logger(__name__) warn = logger.warning R_STATE = '' -R_WORKER = ' HEARTBEAT_DRIFT_MAX: - warn(DRIFT_WARNING, self.hostname, drift, - datetime.fromtimestamp(received), - datetime.fromtimestamp(timestamp)) - heartbeats, hbmax = self.heartbeats, self.heartbeat_max - if not heartbeats or (received and received > heartbeats[-1]): - heappush(heartbeats, received) - if len(heartbeats) > hbmax: - heartbeats[:] = heartbeats[hbmax:] + def event(type_, timestamp=None, + local_received=None, fields=None, + max_drift=HEARTBEAT_DRIFT_MAX, items=items, abs=abs, + heappush=heappush, heappop=heappop, int=int, len=len): + fields = fields or {} + for k, v in items(fields): + _set(self, k, v) + if type_ == 'offline': + heartbeats[:] = [] + else: + if not local_received or not timestamp: + return + drift = abs(int(local_received) - int(timestamp)) + if drift > HEARTBEAT_DRIFT_MAX: + warn(DRIFT_WARNING, self.hostname, drift, + datetime.fromtimestamp(local_received), + datetime.fromtimestamp(timestamp)) + if not heartbeats or ( + local_received and local_received > heartbeats[-1]): + heappush(heartbeats, local_received) + if len(heartbeats) > hbmax: + heappop(heartbeats) + return event + + def update(self, f, **kw): + for k, v in items(dict(f, **kw) if kw else f): + setattr(self, k, v) def __repr__(self): return R_WORKER.format(self) @@ -139,17 +183,53 @@ class Worker(AttributeDict): self.freq, self.expire_window) @property - def alive(self): - return bool(self.heartbeats and time() < self.heartbeat_expires) + def alive(self, nowfun=time): + return bool(self.heartbeats and nowfun() < self.heartbeat_expires) @property def id(self): return '{0.hostname}.{0.pid}'.format(self) + @deprecated(3.2, 3.3) + def update_heartbeat(self, received, timestamp): + self.event(None, timestamp, received) + + @deprecated(3.2, 3.3) + def on_online(self, timestamp=None, local_received=None, **fields): + self.event('online', timestamp, local_received, fields) + + @deprecated(3.2, 3.3) + def on_offline(self, timestamp=None, local_received=None, **fields): + self.event('offline', timestamp, local_received, fields) + + @deprecated(3.2, 3.3) + def on_heartbeat(self, timestamp=None, local_received=None, **fields): + self.event('heartbeat', timestamp, local_received, fields) + + @class_property + def _defaults(cls): + """Deprecated, to be removed in 3.3""" + source = cls() + return dict((k, getattr(source, k)) for k in cls._fields) + @with_unique_field('uuid') -class Task(AttributeDict): +class Task(object): """Task State.""" + name = received = sent = started = succeeded = failed = retried = \ + revoked = args = kwargs = eta = expires = retries = worker = result = \ + exception = timestamp = runtime = traceback = exchange = \ + routing_key = client = None + state = states.PENDING + clock = 0 + + _fields = ('uuid', 'name', 'state', 'received', 'sent', 'started', + 'succeeded', 'failed', 'retried', 'revoked', 'args', 'kwargs', + 'eta', 'expires', 'retries', 'worker', 'result', 'exception', + 'timestamp', 'runtime', 'traceback', 'exchange', 'routing_key', + 'clock', 'client') + if not PYPY: + __slots__ = ('__dict__', '__weakref__') #: How to merge out of order events. #: Disorder is detected by logical ordering (e.g. :event:`task-received` @@ -163,87 +243,56 @@ class Task(AttributeDict): 'retries', 'eta', 'expires')} #: meth:`info` displays these fields by default. - _info_fields = ('args', 'kwargs', 'retries', 'result', - 'eta', 'runtime', 'expires', 'exception', - 'exchange', 'routing_key') + _info_fields = ('args', 'kwargs', 'retries', 'result', 'eta', 'runtime', + 'expires', 'exception', 'exchange', 'routing_key') - #: Default values. - _defaults = dict(uuid=None, name=None, state=states.PENDING, - received=False, sent=False, started=False, - succeeded=False, failed=False, retried=False, - revoked=False, args=None, kwargs=None, eta=None, - expires=None, retries=None, worker=None, result=None, - exception=None, timestamp=None, runtime=None, - traceback=None, exchange=None, routing_key=None, - clock=0) + def __init__(self, uuid=None, **kwargs): + self.uuid = uuid + if kwargs: + for k, v in items(kwargs): + setattr(self, k, v) - def __init__(self, **fields): - dict.__init__(self, self._defaults, **fields) + def event(self, type_, timestamp=None, local_received=None, fields=None, + precedence=states.precedence, items=items, dict=dict, + PENDING=states.PENDING, RECEIVED=states.RECEIVED, + STARTED=states.STARTED, FAILURE=states.FAILURE, + RETRY=states.RETRY, SUCCESS=states.SUCCESS, + REVOKED=states.REVOKED): + fields = fields or {} + if type_ == 'sent': + state, self.sent = PENDING, timestamp + elif type_ == 'received': + state, self.received = RECEIVED, timestamp + elif type_ == 'started': + state, self.started = STARTED, timestamp + elif type_ == 'failed': + state, self.failed = FAILURE, timestamp + elif type_ == 'retried': + state, self.retried = RETRY, timestamp + elif type_ == 'succeeded': + state, self.succeeded = SUCCESS, timestamp + elif type_ == 'revoked': + state, self.revoked = REVOKED, timestamp + else: + state = type_.upper() - def update(self, state, timestamp, fields, _state=states.state): - """Update state from new event. - - :param state: State from event. - :param timestamp: Timestamp from event. - :param fields: Event data. - - """ - time_received = fields.get('local_received') or 0 - if self.worker and time_received: - self.worker.update_heartbeat(time_received, timestamp) - if state != states.RETRY and self.state != states.RETRY and \ - _state(state) < _state(self.state): + # note that precedence here is reversed + # see implementation in celery.states.state.__lt__ + if state != RETRY and self.state != RETRY and \ + precedence(state) > precedence(self.state): # this state logically happens-before the current state, so merge. - self.merge(state, timestamp, fields) + keep = self.merge_rules.get(state) + if keep is not None: + fields = dict( + (k, v) for k, v in items(fields) if k in keep + ) + for key, value in items(fields): + setattr(self, key, value) else: self.state = state self.timestamp = timestamp - super(Task, self).update(fields) - - def merge(self, state, timestamp, fields): - """Merge with out of order event.""" - keep = self.merge_rules.get(state) - if keep is not None: - fields = dict((key, fields.get(key)) for key in keep) - super(Task, self).update(fields) - - def on_sent(self, timestamp=None, **fields): - """Callback for the :event:`task-sent` event.""" - self.sent = timestamp - self.update(states.PENDING, timestamp, fields) - - def on_received(self, timestamp=None, **fields): - """Callback for the :event:`task-received` event.""" - self.received = timestamp - self.update(states.RECEIVED, timestamp, fields) - - def on_started(self, timestamp=None, **fields): - """Callback for the :event:`task-started` event.""" - self.started = timestamp - self.update(states.STARTED, timestamp, fields) - - def on_failed(self, timestamp=None, **fields): - """Callback for the :event:`task-failed` event.""" - self.failed = timestamp - self.update(states.FAILURE, timestamp, fields) - - def on_retried(self, timestamp=None, **fields): - """Callback for the :event:`task-retried` event.""" - self.retried = timestamp - self.update(states.RETRY, timestamp, fields) - - def on_succeeded(self, timestamp=None, **fields): - """Callback for the :event:`task-succeeded` event.""" - self.succeeded = timestamp - self.update(states.SUCCESS, timestamp, fields) - - def on_revoked(self, timestamp=None, **fields): - """Callback for the :event:`task-revoked` event.""" - self.revoked = timestamp - self.update(states.REVOKED, timestamp, fields) - - def on_unknown_event(self, shortype, timestamp=None, **fields): - self.update(shortype.upper(), timestamp, fields) + for key, value in items(fields): + setattr(self, key, value) def info(self, fields=None, extra=[]): """Information about this task suitable for on-screen display.""" @@ -260,19 +309,87 @@ class Task(AttributeDict): def __repr__(self): return R_TASK.format(self) + def as_dict(self): + get = object.__getattribute__ + return dict( + (k, get(self, k)) for k in self._fields + ) + + def __reduce__(self): + return _depickle_task, (self.__class__, self.as_dict()) + + @property + def origin(self): + return self.client if self.worker is None else self.worker.id + @property def ready(self): return self.state in states.READY_STATES + @deprecated(3.2, 3.3) + def on_sent(self, timestamp=None, **fields): + self.event('sent', timestamp, fields) + + @deprecated(3.2, 3.3) + def on_received(self, timestamp=None, **fields): + self.event('received', timestamp, fields) + + @deprecated(3.2, 3.3) + def on_started(self, timestamp=None, **fields): + self.event('started', timestamp, fields) + + @deprecated(3.2, 3.3) + def on_failed(self, timestamp=None, **fields): + self.event('failed', timestamp, fields) + + @deprecated(3.2, 3.3) + def on_retried(self, timestamp=None, **fields): + self.event('retried', timestamp, fields) + + @deprecated(3.2, 3.3) + def on_succeeded(self, timestamp=None, **fields): + self.event('succeeded', timestamp, fields) + + @deprecated(3.2, 3.3) + def on_revoked(self, timestamp=None, **fields): + self.event('revoked', timestamp, fields) + + @deprecated(3.2, 3.3) + def on_unknown_event(self, shortype, timestamp=None, **fields): + self.event(shortype, timestamp, fields) + + @deprecated(3.2, 3.3) + def update(self, state, timestamp, fields, + _state=states.state, RETRY=states.RETRY): + return self.event(state, timestamp, None, fields) + + @deprecated(3.2, 3.3) + def merge(self, state, timestamp, fields): + keep = self.merge_rules.get(state) + if keep is not None: + fields = dict((k, v) for k, v in items(fields) if k in keep) + for key, value in items(fields): + setattr(self, key, value) + + @class_property + def _defaults(cls): + """Deprecated, to be removed in 3.3.""" + source = cls() + return dict((k, getattr(source, k)) for k in source._fields) + class State(object): """Records clusters state.""" + Worker = Worker + Task = Task event_count = 0 task_count = 0 + heap_multiplier = 4 def __init__(self, callback=None, workers=None, tasks=None, taskheap=None, - max_workers_in_memory=5000, max_tasks_in_memory=10000): + max_workers_in_memory=5000, max_tasks_in_memory=10000, + on_node_join=None, on_node_leave=None): self.event_callback = callback self.workers = (LRUCache(max_workers_in_memory) if workers is None else workers) @@ -281,10 +398,16 @@ class State(object): self._taskheap = [] if taskheap is None else taskheap self.max_workers_in_memory = max_workers_in_memory self.max_tasks_in_memory = max_tasks_in_memory + self.on_node_join = on_node_join + self.on_node_leave = on_node_leave self._mutex = threading.Lock() - self.handlers = {'task': self.task_event, - 'worker': self.worker_event} - self._get_handler = self.handlers.__getitem__ + self.handlers = {} + self._seen_types = set() + self.rebuild_taskheap() + + @cached_property + def _event(self): + return self._create_dispatcher() def freeze_while(self, fun, *args, **kwargs): clear_after = kwargs.pop('clear_after', False) @@ -327,11 +450,12 @@ class State(object): """ try: worker = self.workers[hostname] - worker.update(kwargs) + if kwargs: + worker.update(kwargs) return worker, False except KeyError: - worker = self.workers[hostname] = Worker( - hostname=hostname, **kwargs) + worker = self.workers[hostname] = self.Worker( + hostname, **kwargs) return worker, True def get_or_create_task(self, uuid): @@ -339,61 +463,112 @@ class State(object): try: return self.tasks[uuid], False except KeyError: - task = self.tasks[uuid] = Task(uuid=uuid) + task = self.tasks[uuid] = self.Task(uuid) return task, True - def worker_event(self, type, fields): - """Process worker event.""" - try: - hostname = fields['hostname'] - except KeyError: - pass - else: - worker, created = self.get_or_create_worker(hostname) - handler = getattr(worker, 'on_' + type, None) - if handler: - handler(**fields) - return worker, created - - def task_event(self, type, fields, timetuple=timetuple): - """Process task event.""" - uuid = fields['uuid'] - hostname = fields['hostname'] - worker, _ = self.get_or_create_worker(hostname) - task, created = self.get_or_create_task(uuid) - task.worker = worker - maxtasks = self.max_tasks_in_memory * 2 - - taskheap = self._taskheap - timestamp = fields.get('timestamp') or 0 - clock = 0 if type == 'sent' else fields.get('clock') - heappush(taskheap, timetuple(clock, timestamp, worker.id, task)) - if len(taskheap) > maxtasks: - heappop(taskheap) - - handler = getattr(task, 'on_' + type, None) - if type == 'received': - self.task_count += 1 - if handler: - handler(**fields) - else: - task.on_unknown_event(type, **fields) - return created - def event(self, event): with self._mutex: - return self._dispatch_event(event) + return self._event(event) - def _dispatch_event(self, event, kwdict=kwdict): - self.event_count += 1 - event = kwdict(event) - group, _, subject = event['type'].partition('-') - try: - self._get_handler(group)(subject, event) - except KeyError: - pass - if self.event_callback: - self.event_callback(self, event) + def task_event(self, type_, fields): + """Deprecated, use :meth:`event`.""" + return self._event(dict(fields, type='-'.join(['task', type_])))[0] + + def worker_event(self, type_, fields): + """Deprecated, use :meth:`event`.""" + return self._event(dict(fields, type='-'.join(['worker', type_])))[0] + + def _create_dispatcher(self): + get_handler = self.handlers.__getitem__ + event_callback = self.event_callback + wfields = itemgetter('hostname', 'timestamp', 'local_received') + tfields = itemgetter('uuid', 'hostname', 'timestamp', + 'local_received', 'clock') + taskheap = self._taskheap + # Removing events from task heap is an O(n) operation, + # so easier to just account for the common number of events + # for each task (PENDING->RECEIVED->STARTED->final) + #: an O(n) operation + max_events_in_heap = self.max_tasks_in_memory * self.heap_multiplier + add_type = self._seen_types.add + on_node_join, on_node_leave = self.on_node_join, self.on_node_leave + tasks, Task = self.tasks, self.Task + workers, Worker = self.workers, self.Worker + # avoid updating LRU entry at getitem + get_worker, get_task = workers.data.__getitem__, tasks.data.__getitem__ + + def _event(event, + timetuple=timetuple, KeyError=KeyError, created=True): + self.event_count += 1 + if event_callback: + event_callback(self, event) + group, _, subject = event['type'].partition('-') + try: + handler = get_handler(group) + except KeyError: + pass + else: + return handler(subject, event), subject + + if group == 'worker': + try: + hostname, timestamp, local_received = wfields(event) + except KeyError: + pass + else: + try: + worker, created = get_worker(hostname), False + except KeyError: + if subject == 'offline': + worker, created = None, False + else: + worker = workers[hostname] = Worker(hostname) + if worker: + worker.event(subject, timestamp, local_received, event) + if on_node_join and (created or subject == 'online'): + on_node_join(worker) + if on_node_leave and subject == 'offline': + on_node_leave(worker) + return (worker, created), subject + elif group == 'task': + (uuid, hostname, timestamp, + local_received, clock) = tfields(event) + # task-sent event is sent by client, not worker + is_client_event = subject == 'sent' + try: + task, created = get_task(uuid), False + except KeyError: + task = tasks[uuid] = Task(uuid) + if is_client_event: + task.client = hostname + else: + try: + worker, created = get_worker(hostname), False + except KeyError: + worker = workers[hostname] = Worker(hostname) + task.worker = worker + if worker is not None and local_received: + worker.event(None, local_received, timestamp) + origin = hostname if is_client_event else worker.id + heappush(taskheap, + timetuple(clock, timestamp, origin, ref(task))) + if len(taskheap) > max_events_in_heap: + heappop(taskheap) + if subject == 'received': + self.task_count += 1 + task.event(subject, timestamp, local_received, event) + task_name = task.name + if task_name is not None: + add_type(task_name) + return (task, created), subject + return _event + + def rebuild_taskheap(self, timetuple=timetuple, heapify=heapify): + heap = self._taskheap[:] = [ + timetuple(t.clock, t.timestamp, t.origin, ref(t)) + for t in values(self.tasks) + ] + heapify(heap) def itertasks(self, limit=None): for index, row in enumerate(items(self.tasks)): @@ -406,10 +581,12 @@ class State(object): in ``(uuid, Task)`` tuples.""" seen = set() for evtup in islice(reversed(self._taskheap), 0, limit): - uuid = evtup[3].uuid - if uuid not in seen: - yield uuid, evtup[3] - seen.add(uuid) + task = evtup[3]() + if task is not None: + uuid = task.uuid + if uuid not in seen: + yield uuid, task + seen.add(uuid) tasks_by_timestamp = tasks_by_time def tasks_by_type(self, name, limit=None): @@ -436,7 +613,7 @@ class State(object): def task_types(self): """Return a list of all seen task types.""" - return list(sorted(set(task.name for task in values(self.tasks)))) + return sorted(self._seen_types) def alive_workers(self): """Return a list of (seemingly) alive workers.""" @@ -447,6 +624,7 @@ class State(object): def __reduce__(self): return self.__class__, ( - self.event_callback, self.workers, self.tasks, self._taskheap, + self.event_callback, self.workers, self.tasks, None, self.max_workers_in_memory, self.max_tasks_in_memory, + self.on_node_join, self.on_node_leave, ) diff --git a/awx/lib/site-packages/celery/five.py b/awx/lib/site-packages/celery/five.py index 23df8458a1..dfee614e4b 100644 --- a/awx/lib/site-packages/celery/five.py +++ b/awx/lib/site-packages/celery/five.py @@ -11,13 +11,15 @@ from __future__ import absolute_import __all__ = ['Counter', 'reload', 'UserList', 'UserDict', 'Queue', 'Empty', - 'zip_longest', 'StringIO', 'BytesIO', 'map', 'string', 'string_t', + 'zip_longest', 'map', 'string', 'string_t', 'long_t', 'text_t', 'range', 'int_types', 'items', 'keys', 'values', 'nextfun', 'reraise', 'WhateverIO', 'with_metaclass', 'OrderedDict', 'THREAD_TIMEOUT_MAX', 'format_d', 'class_property', 'reclassmethod', 'create_module', 'recreate_module', 'monotonic'] +import io + try: from collections import Counter except ImportError: # pragma: no cover @@ -53,7 +55,6 @@ if PY3: # pragma: no cover from queue import Queue, Empty from itertools import zip_longest - from io import StringIO, BytesIO map = map string = str @@ -62,6 +63,7 @@ if PY3: # pragma: no cover text_t = str range = range int_types = (int, ) + _byte_t = bytes open_fqdn = 'builtins.open' @@ -84,24 +86,17 @@ if PY3: # pragma: no cover raise value.with_traceback(tb) raise value - class WhateverIO(StringIO): - - def write(self, data): - if isinstance(data, bytes): - data = data.encode() - StringIO.write(self, data) - else: import __builtin__ as builtins # noqa from Queue import Queue, Empty # noqa from itertools import imap as map, izip_longest as zip_longest # noqa - from StringIO import StringIO # noqa string = unicode # noqa string_t = basestring # noqa - text_t = unicode + text_t = unicode # noqa long_t = long # noqa - range = xrange - int_types = (int, long) + range = xrange # noqa + int_types = (int, long) # noqa + _byte_t = (str, bytes) # noqa open_fqdn = '__builtin__.open' @@ -131,8 +126,6 @@ else: exec_("""def reraise(tp, value, tb=None): raise tp, value, tb""") - BytesIO = WhateverIO = StringIO # noqa - def with_metaclass(Type, skip_attrs=set(['__dict__', '__weakref__'])): """Class decorator to set metaclass. @@ -385,3 +378,16 @@ def get_origins(defs): for module, attrs in items(defs): origins.update(dict((attr, module) for attr in attrs)) return origins + + +_SIO_write = io.StringIO.write +_SIO_init = io.StringIO.__init__ + + +class WhateverIO(io.StringIO): + + def __init__(self, v=None, *a, **kw): + _SIO_init(self, v.decode() if isinstance(v, _byte_t) else v, *a, **kw) + + def write(self, data): + _SIO_write(self, data.decode() if isinstance(data, _byte_t) else data) diff --git a/awx/lib/site-packages/celery/fixups/django.py b/awx/lib/site-packages/celery/fixups/django.py index a71b329d75..cbf43941ae 100644 --- a/awx/lib/site-packages/celery/fixups/django.py +++ b/awx/lib/site-packages/celery/fixups/django.py @@ -1,10 +1,11 @@ from __future__ import absolute_import +import io import os import sys import warnings -from kombu.utils import symbol_by_name +from kombu.utils import cached_property, symbol_by_name from datetime import datetime from importlib import import_module @@ -40,6 +41,44 @@ def fixup(app, env='DJANGO_SETTINGS_MODULE'): class DjangoFixup(object): + + def __init__(self, app): + self.app = app + self.app.set_default() + + def install(self): + # Need to add project directory to path + sys.path.append(os.getcwd()) + + self.app.loader.now = self.now + self.app.loader.mail_admins = self.mail_admins + + signals.worker_init.connect(self.on_worker_init) + return self + + def on_worker_init(self, **kwargs): + # keep reference + self._worker_fixup = DjangoWorkerFixup(self.app).install() + + def now(self, utc=False): + return datetime.utcnow() if utc else self._now() + + def mail_admins(self, subject, body, fail_silently=False, **kwargs): + return self._mail_admins(subject, body, fail_silently=fail_silently) + + @cached_property + def _mail_admins(self): + return symbol_by_name('django.core.mail:mail_admins') + + @cached_property + def _now(self): + try: + return symbol_by_name('django.utils.timezone:now') + except (AttributeError, ImportError): # pre django-1.4 + return datetime.now + + +class DjangoWorkerFixup(object): _db_recycles = 0 def __init__(self, app): @@ -48,13 +87,6 @@ class DjangoFixup(object): self._db = import_module('django.db') self._cache = import_module('django.core.cache') self._settings = symbol_by_name('django.conf:settings') - self._mail_admins = symbol_by_name('django.core.mail:mail_admins') - - # Current time and date - try: - self._now = symbol_by_name('django.utils.timezone:now') - except ImportError: # pre django-1.4 - self._now = datetime.now # noqa # Database-related exceptions. DatabaseError = symbol_by_name('django.db:DatabaseError') @@ -101,36 +133,25 @@ class DjangoFixup(object): _oracle_database_errors ) + def validate_models(self): + from django.core.management.validation import get_validation_errors + s = io.StringIO() + num_errors = get_validation_errors(s, None) + if num_errors: + raise RuntimeError( + 'One or more Django models did not validate:\n{0}'.format( + s.getvalue())) + def install(self): - # Need to add project directory to path - sys.path.append(os.getcwd()) signals.beat_embedded_init.connect(self.close_database) signals.worker_ready.connect(self.on_worker_ready) signals.task_prerun.connect(self.on_task_prerun) signals.task_postrun.connect(self.on_task_postrun) - signals.worker_init.connect(self.on_worker_init) signals.worker_process_init.connect(self.on_worker_process_init) - - self.app.loader.now = self.now - self.app.loader.mail_admins = self.mail_admins - - return self - - def now(self, utc=False): - return datetime.utcnow() if utc else self._now() - - def mail_admins(self, subject, body, fail_silently=False, **kwargs): - return self._mail_admins(subject, body, fail_silently=fail_silently) - - def on_worker_init(self, **kwargs): - """Called when the worker starts. - - Automatically discovers any ``tasks.py`` files in the applications - listed in ``INSTALLED_APPS``. - - """ + self.validate_models() self.close_database() self.close_cache() + return self def on_worker_process_init(self, **kwargs): # the parent process may have established these, diff --git a/awx/lib/site-packages/celery/loaders/__init__.py b/awx/lib/site-packages/celery/loaders/__init__.py index 0ff5a6f747..2a39ba2ab7 100644 --- a/awx/lib/site-packages/celery/loaders/__init__.py +++ b/awx/lib/site-packages/celery/loaders/__init__.py @@ -25,13 +25,13 @@ def get_loader_cls(loader): return symbol_by_name(loader, LOADER_ALIASES, imp=import_from_cwd) -@deprecated(deprecation='2.5', removal='4.0', +@deprecated(deprecation=2.5, removal=4.0, alternative='celery.current_app.loader') def current_loader(): return current_app.loader -@deprecated(deprecation='2.5', removal='4.0', +@deprecated(deprecation=2.5, removal=4.0, alternative='celery.current_app.conf') def load_settings(): return current_app.conf diff --git a/awx/lib/site-packages/celery/loaders/base.py b/awx/lib/site-packages/celery/loaders/base.py index 4caed2f318..1062b1bacb 100644 --- a/awx/lib/site-packages/celery/loaders/base.py +++ b/awx/lib/site-packages/celery/loaders/base.py @@ -20,6 +20,7 @@ from datetime import datetime from kombu.utils import cached_property from kombu.utils.encoding import safe_str +from celery import signals from celery.datastructures import DictAttribute, force_mapping from celery.five import reraise, string_t from celery.utils.functional import maybe_list @@ -112,6 +113,7 @@ class BaseLoader(object): ) def import_default_modules(self): + signals.import_modules.send(sender=self.app) return [ self.import_task_module(m) for m in ( tuple(self.builtin_modules) + diff --git a/awx/lib/site-packages/celery/local.py b/awx/lib/site-packages/celery/local.py index db4afd0b63..55fd6d164d 100644 --- a/awx/lib/site-packages/celery/local.py +++ b/awx/lib/site-packages/celery/local.py @@ -13,13 +13,16 @@ from __future__ import absolute_import import importlib +import sys -from .five import long_t, string +from .five import string __all__ = ['Proxy', 'PromiseProxy', 'try_import', 'maybe_evaluate'] __module__ = __name__ # used by Proxy class body +PY3 = sys.version_info[0] == 3 + def _default_cls_attr(name, type_, cls_value): # Proxy uses properties to forward the standard @@ -160,7 +163,6 @@ class Proxy(object): __ne__ = lambda x, o: x._get_current_object() != o __gt__ = lambda x, o: x._get_current_object() > o __ge__ = lambda x, o: x._get_current_object() >= o - __cmp__ = lambda x, o: cmp(x._get_current_object(), o) __hash__ = lambda x: hash(x._get_current_object()) __call__ = lambda x, *a, **kw: x._get_current_object()(*a, **kw) __len__ = lambda x: len(x._get_current_object()) @@ -188,7 +190,6 @@ class Proxy(object): __invert__ = lambda x: ~(x._get_current_object()) __complex__ = lambda x: complex(x._get_current_object()) __int__ = lambda x: int(x._get_current_object()) - __long__ = lambda x: long_t(x._get_current_object()) __float__ = lambda x: float(x._get_current_object()) __oct__ = lambda x: oct(x._get_current_object()) __hex__ = lambda x: hex(x._get_current_object()) @@ -198,6 +199,10 @@ class Proxy(object): __exit__ = lambda x, *a, **kw: x._get_current_object().__exit__(*a, **kw) __reduce__ = lambda x: x._get_current_object().__reduce__() + if not PY3: + __cmp__ = lambda x, o: cmp(x._get_current_object(), o) # noqa + __long__ = lambda x: long(x._get_current_object()) # noqa + class PromiseProxy(Proxy): """This is a proxy to an object that has not yet been evaulated. diff --git a/awx/lib/site-packages/celery/platforms.py b/awx/lib/site-packages/celery/platforms.py index 6163a66844..2689126ead 100644 --- a/awx/lib/site-packages/celery/platforms.py +++ b/awx/lib/site-packages/celery/platforms.py @@ -16,6 +16,7 @@ import os import platform as _platform import signal as _signal import sys +import warnings from collections import namedtuple @@ -64,6 +65,27 @@ Seems we're already running? (pid: {1})""" _range = namedtuple('_range', ('start', 'stop')) +C_FORCE_ROOT = os.environ.get('C_FORCE_ROOT', False) + +ROOT_DISALLOWED = """\ +Running a worker with superuser privileges when the +worker accepts messages serialized with pickle is a very bad idea! + +If you really want to continue then you have to set the C_FORCE_ROOT +environment variable (but please think about this before you do). + +User information: uid={uid} euid={euid} gid={gid} egid={egid} +""" + +ROOT_DISCOURAGED = """\ +You are running the worker with superuser privileges, which is +absolutely not recommended! + +Please specify a different user using the -u option. + +User information: uid={uid} euid={euid} gid={gid} egid={egid} +""" + def pyimplementation(): """Return string identifying the current Python implementation.""" @@ -244,9 +266,9 @@ def _create_pidlock(pidfile): if hasattr(os, 'closerange'): def close_open_fds(keep=None): - keep = [maybe_fileno(f) - for f in uniq(sorted(keep or [])) - if maybe_fileno(f) is not None] + keep = list(uniq(sorted(filter(None, ( + maybe_fileno(f) for f in keep or [] + ))))) maxfd = get_fdmax(default=2048) kL, kH = iter([-1] + keep), iter(keep + [maxfd]) for low, high in zip_longest(kL, kH): @@ -354,9 +376,7 @@ def detached(logfile=None, pidfile=None, uid=None, gid=None, umask=0, workdir = os.getcwd() if workdir is None else workdir signals.reset('SIGCLD') # Make sure SIGCLD is using the default handler. - if not os.geteuid(): - # no point trying to setuid unless we're root. - maybe_drop_privileges(uid=uid, gid=gid) + maybe_drop_privileges(uid=uid, gid=gid) def after_chdir_do(): # Since without stderr any errors will be silently suppressed, @@ -473,6 +493,12 @@ def maybe_drop_privileges(uid=None, gid=None): If only GID is specified, only the group is changed. """ + if sys.platform == 'win32': + return + if os.geteuid(): + # no point trying to setuid unless we're root. + if not os.getuid(): + raise AssertionError('contact support') uid = uid and parse_uid(uid) gid = gid and parse_gid(gid) @@ -501,10 +527,14 @@ def maybe_drop_privileges(uid=None, gid=None): else: raise RuntimeError( 'non-root user able to restore privileges after setuid.') - else: gid and setgid(gid) + if uid and (not os.getuid()) and not (os.geteuid()): + raise AssertionError('Still root uid after drop privileges!') + if gid and (not os.getgid()) and not (os.getegid()): + raise AssertionError('Still root gid after drop privileges!') + class Signals(object): """Convenience interface to :mod:`signals`. @@ -701,3 +731,29 @@ def ignore_errno(*errnos, **kwargs): raise if exc.errno not in errnos: raise + + +def check_privileges(accept_content): + uid = os.getuid() if hasattr(os, 'getuid') else 65535 + gid = os.getgid() if hasattr(os, 'getgid') else 65535 + euid = os.geteuid() if hasattr(os, 'geteuid') else 65535 + egid = os.getegid() if hasattr(os, 'getegid') else 65535 + + if hasattr(os, 'fchown'): + if not all(hasattr(os, attr) + for attr in ['getuid', 'getgid', 'geteuid', 'getegid']): + raise AssertionError('suspicious platform, contact support') + + if not uid or not gid or not euid or not egid: + if ('pickle' in accept_content or + 'application/x-python-serialize' in accept_content): + if not C_FORCE_ROOT: + try: + print(ROOT_DISALLOWED.format( + uid=uid, euid=euid, gid=gid, egid=egid, + ), file=sys.stderr) + finally: + os._exit(1) + warnings.warn(RuntimeWarning(ROOT_DISCOURAGED.format( + uid=uid, euid=euid, gid=gid, egid=egid, + ))) diff --git a/awx/lib/site-packages/celery/result.py b/awx/lib/site-packages/celery/result.py index 44ef0522bb..eef9558285 100644 --- a/awx/lib/site-packages/celery/result.py +++ b/awx/lib/site-packages/celery/result.py @@ -9,8 +9,10 @@ from __future__ import absolute_import import time +import warnings from collections import deque +from contextlib import contextmanager from copy import copy from kombu.utils import cached_property @@ -18,7 +20,7 @@ from kombu.utils.compat import OrderedDict from . import current_app from . import states -from ._state import task_join_will_block +from ._state import _set_task_join_will_block, task_join_will_block from .app import app_or_default from .datastructures import DependencyGraph, GraphFormatter from .exceptions import IncompleteStream, TimeoutError @@ -31,12 +33,25 @@ E_WOULDBLOCK = """\ Never call result.get() within a task! See http://docs.celeryq.org/en/latest/userguide/tasks.html\ #task-synchronous-subtasks + +In Celery 3.2 this will result in an exception being +raised instead of just being a warning. """ def assert_will_not_block(): if task_join_will_block(): - pass # TODO future version: raise + warnings.warn(RuntimeWarning(E_WOULDBLOCK)) + + +@contextmanager +def allow_join_result(): + reset_value = task_join_will_block() + _set_task_join_will_block(False) + try: + yield + finally: + _set_task_join_will_block(reset_value) class ResultBase(object): diff --git a/awx/lib/site-packages/celery/schedules.py b/awx/lib/site-packages/celery/schedules.py index b511955b5a..f437bde45a 100644 --- a/awx/lib/site-packages/celery/schedules.py +++ b/awx/lib/site-packages/celery/schedules.py @@ -84,25 +84,27 @@ class schedule(object): ) def is_due(self, last_run_at): - """Returns tuple of two items `(is_due, next_time_to_run)`, - where next time to run is in seconds. + """Returns tuple of two items `(is_due, next_time_to_check)`, + where next time to check is in seconds. e.g. * `(True, 20)`, means the task should be run now, and the next - time to run is in 20 seconds. + time to check is in 20 seconds. - * `(False, 12)`, means the task should be run in 12 seconds. + * `(False, 12.3)`, means the task is not due, but that the scheduler + should check again in 12.3 seconds. - You can override this to decide the interval at runtime, - but keep in mind the value of :setting:`CELERYBEAT_MAX_LOOP_INTERVAL`, - which decides the maximum number of seconds the Beat scheduler can + The next time to check is used to save energy/cpu cycles, + it does not need to be accurate but will influence the precision + of your schedule. You must also keep in mind + the value of :setting:`CELERYBEAT_MAX_LOOP_INTERVAL`, + which decides the maximum number of seconds the scheduler can sleep between re-checking the periodic task intervals. So if you - dynamically change the next run at value, and the max interval is - set to 5 minutes, it will take 5 minutes for the change to take - effect, so you may consider lowering the value of - :setting:`CELERYBEAT_MAX_LOOP_INTERVAL` if responsiveness is of - importance to you. + have a task that changes schedule at runtime then your next_run_at + check will decide how long it will take before a change to the + schedule takes effect. The max loop interval takes precendence + over the next check at value returned. .. admonition:: Scheduler max interval variance diff --git a/awx/lib/site-packages/celery/signals.py b/awx/lib/site-packages/celery/signals.py index 6eae2febff..2091830cb2 100644 --- a/awx/lib/site-packages/celery/signals.py +++ b/awx/lib/site-packages/celery/signals.py @@ -52,6 +52,7 @@ task_revoked = Signal(providing_args=[ ]) celeryd_init = Signal(providing_args=['instance', 'conf', 'options']) celeryd_after_setup = Signal(providing_args=['instance', 'conf']) +import_modules = Signal(providing_args=[]) worker_init = Signal(providing_args=[]) worker_process_init = Signal(providing_args=[]) worker_process_shutdown = Signal(providing_args=[]) diff --git a/awx/lib/site-packages/celery/states.py b/awx/lib/site-packages/celery/states.py index 1665cefa53..665a57baf1 100644 --- a/awx/lib/site-packages/celery/states.py +++ b/awx/lib/site-packages/celery/states.py @@ -116,16 +116,16 @@ class state(str): return fun(precedence(self), precedence(other)) def __gt__(self, other): - return self.compare(other, lambda a, b: a < b) + return precedence(self) < precedence(other) def __ge__(self, other): - return self.compare(other, lambda a, b: a <= b) + return precedence(self) <= precedence(other) def __lt__(self, other): - return self.compare(other, lambda a, b: a > b) + return precedence(self) > precedence(other) def __le__(self, other): - return self.compare(other, lambda a, b: a >= b) + return precedence(self) >= precedence(other) #: Task state is unknown (assumed pending since you know the id). PENDING = 'PENDING' diff --git a/awx/lib/site-packages/celery/task/http.py b/awx/lib/site-packages/celery/task/http.py index 152bfff1cb..e170ec3a59 100644 --- a/awx/lib/site-packages/celery/task/http.py +++ b/awx/lib/site-packages/celery/task/http.py @@ -46,7 +46,7 @@ else: keys/values encoded.""" return dict( (k.encode('utf-8'), - v.encode('utf-8') if isinstance(v, unicode) else v) + v.encode('utf-8') if isinstance(v, unicode) else v) # noqa for k, v in tup) diff --git a/awx/lib/site-packages/celery/tests/app/test_amqp.py b/awx/lib/site-packages/celery/tests/app/test_amqp.py index 2bbd376301..efb398ac6b 100644 --- a/awx/lib/site-packages/celery/tests/app/test_amqp.py +++ b/awx/lib/site-packages/celery/tests/app/test_amqp.py @@ -1,5 +1,9 @@ from __future__ import absolute_import +import datetime + +import pytz + from kombu import Exchange, Queue from celery.app.amqp import Queues, TaskPublisher @@ -47,6 +51,32 @@ class test_TaskProducer(AppCase): self.assertEqual(prod.publish.call_args[1]['exchange'], 'yyy') self.assertEqual(prod.publish.call_args[1]['routing_key'], 'zzz') + def test_publish_with_countdown(self): + prod = self.app.amqp.TaskProducer(Mock()) + prod.channel.connection.client.declared_entities = set() + prod.publish = Mock() + now = datetime.datetime(2013, 11, 26, 16, 48, 46) + prod.publish_task('tasks.add', (1, 1), {}, retry=False, + countdown=10, now=now) + self.assertEqual( + prod.publish.call_args[0][0]['eta'], + '2013-11-26T16:48:56+00:00', + ) + + def test_publish_with_countdown_and_timezone(self): + # use timezone with fixed offset to be sure it won't be changed + self.app.conf.CELERY_TIMEZONE = pytz.FixedOffset(120) + prod = self.app.amqp.TaskProducer(Mock()) + prod.channel.connection.client.declared_entities = set() + prod.publish = Mock() + now = datetime.datetime(2013, 11, 26, 16, 48, 46) + prod.publish_task('tasks.add', (2, 2), {}, retry=False, + countdown=20, now=now) + self.assertEqual( + prod.publish.call_args[0][0]['eta'], + '2013-11-26T18:49:06+02:00', + ) + def test_event_dispatcher(self): prod = self.app.amqp.TaskProducer(Mock()) self.assertTrue(prod.event_dispatcher) diff --git a/awx/lib/site-packages/celery/tests/app/test_app.py b/awx/lib/site-packages/celery/tests/app/test_app.py index 93857c7974..7d209d57de 100644 --- a/awx/lib/site-packages/celery/tests/app/test_app.py +++ b/awx/lib/site-packages/celery/tests/app/test_app.py @@ -1,11 +1,13 @@ from __future__ import absolute_import +import gc import os import itertools from copy import deepcopy from pickle import loads, dumps +from amqp import promise from kombu import Exchange from celery import shared_task, current_app @@ -45,6 +47,14 @@ object_config = ObjectConfig() dict_config = dict(FOO=10, BAR=20) +class ObjectConfig2(object): + LEAVE_FOR_WORK = True + MOMENT_TO_STOP = True + CALL_ME_BACK = 123456789 + WANT_ME_TO = False + UNDERSTAND_ME = True + + class Object(object): def __init__(self, **kwargs): @@ -71,6 +81,30 @@ class test_App(AppCase): def setup(self): self.app.add_defaults(test_config) + def test_task_autofinalize_disabled(self): + with self.Celery('xyzibari', autofinalize=False) as app: + @app.task + def ttafd(): + return 42 + + with self.assertRaises(RuntimeError): + ttafd() + + with self.Celery('xyzibari', autofinalize=False) as app: + @app.task + def ttafd2(): + return 42 + + app.finalize() + self.assertEqual(ttafd2(), 42) + + def test_registry_autofinalize_disabled(self): + with self.Celery('xyzibari', autofinalize=False) as app: + with self.assertRaises(RuntimeError): + app.tasks['celery.chain'] + app.finalize() + self.assertTrue(app.tasks['celery.chain']) + def test_task(self): with self.Celery('foozibari') as app: @@ -140,12 +174,13 @@ class test_App(AppCase): def test_maybe_close_pool(self): cpool = self.app._pool = Mock() - ppool = self.app.amqp._producer_pool = Mock() + amqp = self.app.__dict__['amqp'] = Mock() + ppool = amqp._producer_pool self.app._maybe_close_pool() cpool.force_close_all.assert_called_with() ppool.force_close_all.assert_called_with() self.assertIsNone(self.app._pool) - self.assertIsNone(self.app.amqp._producer_pool) + self.assertIsNone(self.app.__dict__['amqp']._producer_pool) self.app._pool = Mock() self.app._maybe_close_pool() @@ -155,19 +190,31 @@ class test_App(AppCase): self.app._using_v1_reduce = True self.assertTrue(loads(dumps(self.app))) - def test_autodiscover_tasks(self): - self.app.conf.CELERY_FORCE_BILLIARD_LOGGING = True - with patch('celery.app.base.ensure_process_aware_logger') as ep: - self.app.loader.autodiscover_tasks = Mock() - self.app.autodiscover_tasks(['proj.A', 'proj.B']) - ep.assert_called_with() - self.app.loader.autodiscover_tasks.assert_called_with( - ['proj.A', 'proj.B'], 'tasks', - ) - with patch('celery.app.base.ensure_process_aware_logger') as ep: - self.app.conf.CELERY_FORCE_BILLIARD_LOGGING = False - self.app.autodiscover_tasks(['proj.A', 'proj.B']) - self.assertFalse(ep.called) + def test_autodiscover_tasks_force(self): + self.app.loader.autodiscover_tasks = Mock() + self.app.autodiscover_tasks(['proj.A', 'proj.B'], force=True) + self.app.loader.autodiscover_tasks.assert_called_with( + ['proj.A', 'proj.B'], 'tasks', + ) + self.app.loader.autodiscover_tasks = Mock() + self.app.autodiscover_tasks( + lambda: ['proj.A', 'proj.B'], + related_name='george', + force=True, + ) + self.app.loader.autodiscover_tasks.assert_called_with( + ['proj.A', 'proj.B'], 'george', + ) + + def test_autodiscover_tasks_lazy(self): + with patch('celery.signals.import_modules') as import_modules: + packages = lambda: [1, 2, 3] + self.app.autodiscover_tasks(packages) + self.assertTrue(import_modules.connect.called) + prom = import_modules.connect.call_args[0][0] + self.assertIsInstance(prom, promise) + self.assertEqual(prom.fun, self.app._autodiscover_tasks) + self.assertEqual(prom.args[0](), [1, 2, 3]) @with_environ('CELERY_BROKER_URL', '') def test_with_broker(self): @@ -345,23 +392,27 @@ class test_App(AppCase): self.app.config_from_envvar('CELERYTEST_CONFIG_OBJECT') self.assertEqual(self.app.conf.THIS_IS_A_KEY, 'this is a value') - def test_config_from_object(self): - - class Object(object): - LEAVE_FOR_WORK = True - MOMENT_TO_STOP = True - CALL_ME_BACK = 123456789 - WANT_ME_TO = False - UNDERSTAND_ME = True - - self.app.config_from_object(Object()) - + def assert_config2(self): self.assertTrue(self.app.conf.LEAVE_FOR_WORK) self.assertTrue(self.app.conf.MOMENT_TO_STOP) self.assertEqual(self.app.conf.CALL_ME_BACK, 123456789) self.assertFalse(self.app.conf.WANT_ME_TO) self.assertTrue(self.app.conf.UNDERSTAND_ME) + def test_config_from_object__lazy(self): + conf = ObjectConfig2() + self.app.config_from_object(conf) + self.assertFalse(self.app.loader._conf) + self.assertIs(self.app._config_source, conf) + + self.assert_config2() + + def test_config_from_object__force(self): + self.app.config_from_object(ObjectConfig2(), force=True) + self.assertTrue(self.app.loader._conf) + + self.assert_config2() + def test_config_from_cmdline(self): cmdline = ['.always_eager=no', '.result_backend=/dev/null', @@ -426,27 +477,35 @@ class test_App(AppCase): app1.close() del(app1) + gc.collect() + # weakref removed from list when app goes out of scope. with self.assertRaises(StopIteration): next(app for app in _state._get_active_apps() if id(app) == appid) def test_config_from_envvar_more(self, key='CELERY_HARNESS_CFG1'): - self.assertFalse(self.app.config_from_envvar('HDSAJIHWIQHEWQU', - silent=True)) + self.assertFalse( + self.app.config_from_envvar( + 'HDSAJIHWIQHEWQU', force=True, silent=True), + ) with self.assertRaises(ImproperlyConfigured): - self.app.config_from_envvar('HDSAJIHWIQHEWQU', silent=False) + self.app.config_from_envvar( + 'HDSAJIHWIQHEWQU', force=True, silent=False, + ) os.environ[key] = __name__ + '.object_config' - self.assertTrue(self.app.config_from_envvar(key)) + self.assertTrue(self.app.config_from_envvar(key, force=True)) self.assertEqual(self.app.conf['FOO'], 1) self.assertEqual(self.app.conf['BAR'], 2) os.environ[key] = 'unknown_asdwqe.asdwqewqe' with self.assertRaises(ImportError): self.app.config_from_envvar(key, silent=False) - self.assertFalse(self.app.config_from_envvar(key, silent=True)) + self.assertFalse( + self.app.config_from_envvar(key, force=True, silent=True), + ) os.environ[key] = __name__ + '.dict_config' - self.assertTrue(self.app.config_from_envvar(key)) + self.assertTrue(self.app.config_from_envvar(key, force=True)) self.assertEqual(self.app.conf['FOO'], 10) self.assertEqual(self.app.conf['BAR'], 20) diff --git a/awx/lib/site-packages/celery/tests/app/test_log.py b/awx/lib/site-packages/celery/tests/app/test_log.py index 8b6823b1fc..c6f90f783b 100644 --- a/awx/lib/site-packages/celery/tests/app/test_log.py +++ b/awx/lib/site-packages/celery/tests/app/test_log.py @@ -16,7 +16,7 @@ from celery.utils.log import ( task_logger, in_sighandler, logger_isa, - _patch_logger_class, + ensure_process_aware_logger, ) from celery.tests.case import ( AppCase, Mock, SkipTest, @@ -342,11 +342,7 @@ class test_task_logger(test_default_logger): class test_patch_logger_cls(AppCase): def test_patches(self): - _patch_logger_class() - self.assertTrue(logging.getLoggerClass()._signal_safe) - _patch_logger_class() - self.assertTrue(logging.getLoggerClass()._signal_safe) - + ensure_process_aware_logger() with in_sighandler(): logging.getLoggerClass().log(get_logger('test')) diff --git a/awx/lib/site-packages/celery/tests/backends/test_base.py b/awx/lib/site-packages/celery/tests/backends/test_base.py index b86ea68b5e..17b569c33e 100644 --- a/awx/lib/site-packages/celery/tests/backends/test_base.py +++ b/awx/lib/site-packages/celery/tests/backends/test_base.py @@ -14,6 +14,7 @@ from celery.utils.serialization import UnpickleableExceptionWrapper from celery.utils.serialization import get_pickleable_exception as gpe from celery import states +from celery import group from celery.backends.base import ( BaseBackend, KeyValueStoreBackend, @@ -29,7 +30,7 @@ class wrapobject(object): def __init__(self, *args, **kwargs): self.args = args -if sys.version_info >= (3, 0): +if sys.version_info[0] == 3 or getattr(sys, 'pypy_version_info', None): Oldstyle = None else: Oldstyle = types.ClassType('Oldstyle', (), {}) @@ -62,10 +63,10 @@ class test_BaseBackend_interface(AppCase): def test_on_chord_part_return(self): self.b.on_chord_part_return(None) - def test_on_chord_apply(self, unlock='celery.chord_unlock'): + def test_apply_chord(self, unlock='celery.chord_unlock'): self.app.tasks[unlock] = Mock() - self.b.on_chord_apply( - 'dakj221', 'sdokqweok', + self.b.apply_chord( + group(app=self.app), (), 'dakj221', None, result=[self.app.AsyncResult(x) for x in [1, 2, 3]], ) self.assertTrue(self.app.tasks[unlock].apply_async.call_count) @@ -306,7 +307,7 @@ class test_KeyValueStoreBackend(AppCase): self.b.on_chord_part_return(task, propagate=True) self.assertFalse(self.b.expire.called) deps.delete.assert_called_with() - deps.join_native.assert_called_with(propagate=True) + deps.join_native.assert_called_with(propagate=True, timeout=3.0) def test_chord_part_return_propagate_default(self): with self._chord_part_context(self.b) as (task, deps, _): @@ -315,6 +316,7 @@ class test_KeyValueStoreBackend(AppCase): deps.delete.assert_called_with() deps.join_native.assert_called_with( propagate=self.b.app.conf.CELERY_CHORD_PROPAGATES, + timeout=3.0, ) def test_chord_part_return_join_raises_internal(self): @@ -364,9 +366,12 @@ class test_KeyValueStoreBackend(AppCase): def test_chord_apply_fallback(self): self.b.implements_incr = False self.b.fallback_chord_unlock = Mock() - self.b.on_chord_apply('group_id', 'body', 'result', foo=1) + self.b.apply_chord( + group(app=self.app), (), 'group_id', 'body', + result='result', foo=1, + ) self.b.fallback_chord_unlock.assert_called_with( - 'group_id', 'body', 'result', foo=1, + 'group_id', 'body', result='result', foo=1, ) def test_get_missing_meta(self): diff --git a/awx/lib/site-packages/celery/tests/backends/test_cache.py b/awx/lib/site-packages/celery/tests/backends/test_cache.py index 61eacd4b24..08165b5d36 100644 --- a/awx/lib/site-packages/celery/tests/backends/test_cache.py +++ b/awx/lib/site-packages/celery/tests/backends/test_cache.py @@ -9,6 +9,7 @@ from kombu.utils.encoding import str_to_bytes from celery import signature from celery import states +from celery import group from celery.backends.cache import CacheBackend, DummyClient from celery.exceptions import ImproperlyConfigured from celery.five import items, string, text_t @@ -18,6 +19,8 @@ from celery.tests.case import ( AppCase, Mock, mask_modules, patch, reset_modules, ) +PY3 = sys.version_info[0] == 3 + class SomeClass(object): @@ -60,10 +63,10 @@ class test_CacheBackend(AppCase): self.assertEqual(self.tb.get_status(self.tid), states.FAILURE) self.assertIsInstance(self.tb.get_result(self.tid), KeyError) - def test_on_chord_apply(self): + def test_apply_chord(self): tb = CacheBackend(backend='memory://', app=self.app) gid, res = uuid(), [self.app.AsyncResult(uuid()) for _ in range(3)] - tb.on_chord_apply(gid, {}, result=res) + tb.apply_chord(group(app=self.app), (), gid, {}, result=res) @patch('celery.result.GroupResult.restore') def test_on_chord_part_return(self, restore): @@ -80,14 +83,14 @@ class test_CacheBackend(AppCase): gid, res = uuid(), [self.app.AsyncResult(uuid()) for _ in range(3)] task.request.group = gid - tb.on_chord_apply(gid, {}, result=res) + tb.apply_chord(group(app=self.app), (), gid, {}, result=res) self.assertFalse(deps.join_native.called) tb.on_chord_part_return(task) self.assertFalse(deps.join_native.called) tb.on_chord_part_return(task) - deps.join_native.assert_called_with(propagate=True) + deps.join_native.assert_called_with(propagate=True, timeout=3.0) deps.delete.assert_called_with() def test_mget(self): @@ -122,10 +125,15 @@ class MyMemcachedStringEncodingError(Exception): class MemcachedClient(DummyClient): def set(self, key, value, *args, **kwargs): - if isinstance(key, text_t): + if PY3: + key_t, must_be, not_be, cod = bytes, 'string', 'bytes', 'decode' + else: + key_t, must_be, not_be, cod = text_t, 'bytes', 'string', 'encode' + if isinstance(key, key_t): raise MyMemcachedStringEncodingError( - 'Keys must be bytes, not string. Convert your ' - 'strings using mystring.encode(charset)!') + 'Keys must be {0}, not {1}. Convert your ' + 'strings using mystring.{2}(charset)!'.format( + must_be, not_be, cod)) return super(MemcachedClient, self).set(key, value, *args, **kwargs) @@ -164,7 +172,7 @@ class test_get_best_memcache(AppCase, MockCacheMixin): with reset_modules('celery.backends.cache'): from celery.backends import cache cache._imp = [None] - self.assertEqual(cache.get_best_memcache().__module__, + self.assertEqual(cache.get_best_memcache()[0].__module__, 'pylibmc') def test_memcache(self): @@ -173,7 +181,7 @@ class test_get_best_memcache(AppCase, MockCacheMixin): with mask_modules('pylibmc'): from celery.backends import cache cache._imp = [None] - self.assertEqual(cache.get_best_memcache().__module__, + self.assertEqual(cache.get_best_memcache()[0]().__module__, 'memcache') def test_no_implementations(self): @@ -189,14 +197,15 @@ class test_get_best_memcache(AppCase, MockCacheMixin): with reset_modules('celery.backends.cache'): from celery.backends import cache cache._imp = [None] - cache.get_best_memcache(behaviors={'foo': 'bar'}) + cache.get_best_memcache()[0](behaviors={'foo': 'bar'}) self.assertTrue(cache._imp[0]) - cache.get_best_memcache() + cache.get_best_memcache()[0]() def test_backends(self): from celery.backends.cache import backends - for name, fun in items(backends): - self.assertTrue(fun()) + with self.mock_memcache(): + for name, fun in items(backends): + self.assertTrue(fun()) class test_memcache_key(AppCase, MockCacheMixin): diff --git a/awx/lib/site-packages/celery/tests/backends/test_redis.py b/awx/lib/site-packages/celery/tests/backends/test_redis.py index e87df94acf..25b0c5750b 100644 --- a/awx/lib/site-packages/celery/tests/backends/test_redis.py +++ b/awx/lib/site-packages/celery/tests/backends/test_redis.py @@ -8,8 +8,9 @@ from kombu.utils import cached_property, uuid from celery import signature from celery import states +from celery import group from celery.datastructures import AttributeDict -from celery.exceptions import ImproperlyConfigured +from celery.exceptions import CPendingDeprecationWarning, ImproperlyConfigured from celery.utils.timeutils import timedelta_seconds from celery.tests.case import ( @@ -62,6 +63,11 @@ class redis(object): def __init__(self, **kwargs): pass + class UnixDomainSocketConnection(object): + + def __init__(self, **kwargs): + pass + class test_RedisBackend(AppCase): @@ -99,9 +105,45 @@ class test_RedisBackend(AppCase): self.MockBackend(app=self.app) def test_url(self): - x = self.MockBackend('redis://foobar//1', app=self.app) - self.assertEqual(x.host, 'foobar') - self.assertEqual(x.db, '1') + x = self.MockBackend( + 'redis://:bosco@vandelay.com:123//1', app=self.app, + ) + self.assertTrue(x.connparams) + self.assertEqual(x.connparams['host'], 'vandelay.com') + self.assertEqual(x.connparams['db'], 1) + self.assertEqual(x.connparams['port'], 123) + self.assertEqual(x.connparams['password'], 'bosco') + + def test_socket_url(self): + x = self.MockBackend( + 'socket:///tmp/redis.sock?virtual_host=/3', app=self.app, + ) + self.assertTrue(x.connparams) + self.assertEqual(x.connparams['path'], '/tmp/redis.sock') + self.assertIs( + x.connparams['connection_class'], + redis.UnixDomainSocketConnection, + ) + self.assertNotIn('host', x.connparams) + self.assertNotIn('port', x.connparams) + self.assertEqual(x.connparams['db'], 3) + + def test_compat_propertie(self): + x = self.MockBackend( + 'redis://:bosco@vandelay.com:123//1', app=self.app, + ) + with self.assertWarnsRegex(CPendingDeprecationWarning, + r'scheduled for deprecation'): + self.assertEqual(x.host, 'vandelay.com') + with self.assertWarnsRegex(CPendingDeprecationWarning, + r'scheduled for deprecation'): + self.assertEqual(x.db, 1) + with self.assertWarnsRegex(CPendingDeprecationWarning, + r'scheduled for deprecation'): + self.assertEqual(x.port, 123) + with self.assertWarnsRegex(CPendingDeprecationWarning, + r'scheduled for deprecation'): + self.assertEqual(x.password, 'bosco') def test_conf_raises_KeyError(self): self.app.conf = AttributeDict({ @@ -130,9 +172,9 @@ class test_RedisBackend(AppCase): b = self.Backend(expires=timedelta(minutes=1), app=self.app) self.assertEqual(b.expires, 60) - def test_on_chord_apply(self): - self.Backend(app=self.app).on_chord_apply( - 'group_id', {}, + def test_apply_chord(self): + self.Backend(app=self.app).apply_chord( + group(app=self.app), (), 'group_id', {}, result=[self.app.AsyncResult(x) for x in [1, 2, 3]], ) @@ -165,7 +207,7 @@ class test_RedisBackend(AppCase): b.client.incr.return_value = len(deps) b.on_chord_part_return(task) - deps.join_native.assert_called_with(propagate=True) + deps.join_native.assert_called_with(propagate=True, timeout=3.0) deps.delete.assert_called_with() self.assertTrue(b.client.expire.call_count) diff --git a/awx/lib/site-packages/celery/tests/bin/test_base.py b/awx/lib/site-packages/celery/tests/bin/test_base.py index fc38d50ad5..907817d194 100644 --- a/awx/lib/site-packages/celery/tests/bin/test_base.py +++ b/awx/lib/site-packages/celery/tests/bin/test_base.py @@ -300,7 +300,7 @@ class test_Command(AppCase): def on_sbn(*args, **kwargs): def after(*args, **kwargs): - x.celery = 'quick brown fox' + x.app = 'quick brown fox' x.__path__ = None return x sbn.side_effect = after diff --git a/awx/lib/site-packages/celery/tests/bin/test_celery.py b/awx/lib/site-packages/celery/tests/bin/test_celery.py index a89d3f036c..6864831b6a 100644 --- a/awx/lib/site-packages/celery/tests/bin/test_celery.py +++ b/awx/lib/site-packages/celery/tests/bin/test_celery.py @@ -62,7 +62,7 @@ class test__main__(AppCase): with patch('celery.__main__._warn_deprecated') as depr: with patch('celery.bin.multi.main') as main: __main__._compat_multi() - mpc.assert_called_with() + self.assertFalse(mpc.called) depr.assert_called_with('celery multi') main.assert_called_with() @@ -330,13 +330,25 @@ class test_CeleryCommand(AppCase): self.assertEqual(determine_exit_status('true'), EX_OK) self.assertEqual(determine_exit_status(''), EX_FAILURE) - def test_remove_options_at_beginning(self): + def test_relocate_args_from_start(self): x = CeleryCommand(app=self.app) - self.assertEqual(x.remove_options_at_beginning(None), []) - self.assertEqual(x.remove_options_at_beginning(['-c 3', '--foo']), []) - self.assertEqual(x.remove_options_at_beginning(['--foo', '-c 3']), []) - self.assertEqual(x.remove_options_at_beginning( - ['foo', '--foo=1']), ['foo', '--foo=1']) + self.assertEqual(x._relocate_args_from_start(None), []) + self.assertEqual( + x._relocate_args_from_start( + ['-l', 'debug', 'worker', '-c', '3', '--foo'], + ), + ['worker', '-c', '3', '--foo', '-l', 'debug'], + ) + self.assertEqual( + x._relocate_args_from_start( + ['--pool=gevent', '-l', 'debug', 'worker', '--foo', '-c', '3'], + ), + ['worker', '--foo', '-c', '3', '--pool=gevent', '-l', 'debug'], + ) + self.assertEqual( + x._relocate_args_from_start(['foo', '--foo=1']), + ['foo', '--foo=1'], + ) def test_handle_argv(self): x = CeleryCommand(app=self.app) @@ -359,9 +371,13 @@ class test_CeleryCommand(AppCase): Dummy = x.commands['dummy'] = Mock() dummy = Dummy.return_value = Mock() - dummy.run_from_argv.side_effect = Error('foo', status='EX_FAILURE') + exc = dummy.run_from_argv.side_effect = Error( + 'foo', status='EX_FAILURE', + ) + x.on_error = Mock(name='on_error') help.reset() x.execute('dummy', ['dummy']) + x.on_error.assert_called_with(exc) dummy.run_from_argv.assert_called_with( x.prog_name, [], command='dummy', ) @@ -508,12 +524,12 @@ class test_control(AppCase): def test_rate_limit(self): i = self.control(True) i.rate_limit('rate_limit', 'proj.add', '1/s') - i.call.assert_called_with('rate_limit', 'proj.add', '1/s', reply=True) + i.call.assert_called_with('rate_limit', 'proj.add', '1/s') def test_time_limit(self): i = self.control(True) i.time_limit('time_limit', 'proj.add', 10, 30) - i.call.assert_called_with('time_limit', 'proj.add', 10, 30, reply=True) + i.call.assert_called_with('time_limit', 'proj.add', 10, 30) def test_add_consumer(self): i = self.control(True) @@ -523,13 +539,13 @@ class test_control(AppCase): ) i.call.assert_called_with( 'add_consumer', 'queue', 'exchange', 'topic', 'rkey', - durable=True, reply=True, + durable=True, ) def test_cancel_consumer(self): i = self.control(True) i.cancel_consumer('cancel_consumer', 'queue') - i.call.assert_called_with('cancel_consumer', 'queue', reply=True) + i.call.assert_called_with('cancel_consumer', 'queue') class test_multi(AppCase): diff --git a/awx/lib/site-packages/celery/tests/bin/test_worker.py b/awx/lib/site-packages/celery/tests/bin/test_worker.py index 7d4dba3be4..8a8f6ef6a2 100644 --- a/awx/lib/site-packages/celery/tests/bin/test_worker.py +++ b/awx/lib/site-packages/celery/tests/bin/test_worker.py @@ -272,7 +272,8 @@ class test_Worker(WorkerAppCase): self.assertEqual(worker1.loglevel, 0xFFFF) @disable_stdouts - def test_warns_if_running_as_privileged_user(self): + @patch('os._exit') + def test_warns_if_running_as_privileged_user(self, _exit): app = self.app if app.IS_WINDOWS: raise SkipTest('Not applicable on Windows') @@ -280,10 +281,11 @@ class test_Worker(WorkerAppCase): with patch('os.getuid') as getuid: getuid.return_value = 0 self.app.conf.CELERY_ACCEPT_CONTENT = ['pickle'] - with self.assertRaises(RuntimeError): - worker = self.Worker(app=self.app) - worker.on_start() - cd.C_FORCE_ROOT = True + worker = self.Worker(app=self.app) + worker.on_start() + _exit.assert_called_with(1) + from celery import platforms + platforms.C_FORCE_ROOT = True try: with self.assertWarnsRegex( RuntimeWarning, @@ -291,7 +293,7 @@ class test_Worker(WorkerAppCase): worker = self.Worker(app=self.app) worker.on_start() finally: - cd.C_FORCE_ROOT = False + platforms.C_FORCE_ROOT = False self.app.conf.CELERY_ACCEPT_CONTENT = ['json'] with self.assertWarnsRegex( RuntimeWarning, diff --git a/awx/lib/site-packages/celery/tests/case.py b/awx/lib/site-packages/celery/tests/case.py index c453721f10..465d2b080e 100644 --- a/awx/lib/site-packages/celery/tests/case.py +++ b/awx/lib/site-packages/celery/tests/case.py @@ -139,6 +139,29 @@ class Mock(mock.Mock): setattr(self, attr_name, attr_value) +class _ContextMock(Mock): + """Dummy class implementing __enter__ and __exit__ + as the with statement requires these to be implemented + in the class, not just the instance.""" + + def __enter__(self): + pass + + def __exit__(self, *exc_info): + pass + + +def ContextMock(*args, **kwargs): + obj = _ContextMock(*args, **kwargs) + obj.attach_mock(_ContextMock(), '__enter__') + obj.attach_mock(_ContextMock(), '__exit__') + obj.__enter__.return_value = obj + # if __exit__ return a value the exception is ignored, + # so it must return None here. + obj.__exit__.return_value = None + return obj + + def skip_unless_module(module): def _inner(fun): @@ -511,7 +534,7 @@ def mask_modules(*modnames): ... try: ... import sys ... except ImportError: - ... print 'sys not found' + ... print('sys not found') sys not found >>> import sys # noqa diff --git a/awx/lib/site-packages/celery/tests/compat_modules/test_http.py b/awx/lib/site-packages/celery/tests/compat_modules/test_http.py index 993142fad0..08505f87e5 100644 --- a/awx/lib/site-packages/celery/tests/compat_modules/test_http.py +++ b/awx/lib/site-packages/celery/tests/compat_modules/test_http.py @@ -11,7 +11,7 @@ except ImportError: # py3k from anyjson import dumps from kombu.utils.encoding import from_utf8 -from celery.five import StringIO, items +from celery.five import WhateverIO, items from celery.task import http from celery.tests.case import AppCase, Case @@ -24,7 +24,7 @@ def mock_urlopen(response_method): @wraps(urlopen) def _mocked(url, *args, **kwargs): response_data, headers = response_method(url) - return addinfourl(StringIO(response_data), headers, url) + return addinfourl(WhateverIO(response_data), headers, url) http.urlopen = _mocked diff --git a/awx/lib/site-packages/celery/tests/events/test_state.py b/awx/lib/site-packages/celery/tests/events/test_state.py index a1b3c1a605..d7387966f1 100644 --- a/awx/lib/site-packages/celery/tests/events/test_state.py +++ b/awx/lib/site-packages/celery/tests/events/test_state.py @@ -2,6 +2,7 @@ from __future__ import absolute_import import pickle +from decimal import Decimal from random import shuffle from time import time from itertools import count @@ -19,6 +20,14 @@ from celery.five import range from celery.utils import uuid from celery.tests.case import AppCase, patch +try: + Decimal(2.6) +except TypeError: # pragma: no cover + # Py2.6: Must first convert float to str + _float_to_decimal = str +else: + _float_to_decimal = lambda f: f # noqa + class replay(object): @@ -34,7 +43,10 @@ class replay(object): def next_event(self): ev = self.events[next(self.position)] ev['local_received'] = ev['timestamp'] - self.current_clock = ev.get('clock') or self.current_clock + 1 + try: + self.current_clock = ev['clock'] + except KeyError: + ev['clock'] = self.current_clock = self.current_clock + 1 return ev def __iter__(self): @@ -94,10 +106,10 @@ class ev_task_states(replay): ] -def QTEV(type, uuid, hostname, clock, timestamp=None): +def QTEV(type, uuid, hostname, clock, name=None, timestamp=None): """Quick task event.""" return Event('task-{0}'.format(type), uuid=uuid, hostname=hostname, - clock=clock, timestamp=timestamp or time()) + clock=clock, name=name, timestamp=timestamp or time()) class ev_logical_clock_ordering(replay): @@ -115,18 +127,18 @@ class ev_logical_clock_ordering(replay): offset = self.offset tA, tB, tC = self.uids self.events = [ - QTEV('received', tA, 'w1', clock=offset + 1), - QTEV('received', tB, 'w2', clock=offset + 1), - QTEV('started', tA, 'w1', clock=offset + 3), - QTEV('received', tC, 'w2', clock=offset + 3), - QTEV('started', tB, 'w2', clock=offset + 5), - QTEV('retried', tA, 'w1', clock=offset + 7), - QTEV('succeeded', tB, 'w2', clock=offset + 9), - QTEV('started', tC, 'w2', clock=offset + 10), - QTEV('received', tA, 'w3', clock=offset + 13), - QTEV('succeded', tC, 'w2', clock=offset + 12), - QTEV('started', tA, 'w3', clock=offset + 14), - QTEV('succeeded', tA, 'w3', clock=offset + 16), + QTEV('received', tA, 'w1', name='tA', clock=offset + 1), + QTEV('received', tB, 'w2', name='tB', clock=offset + 1), + QTEV('started', tA, 'w1', name='tA', clock=offset + 3), + QTEV('received', tC, 'w2', name='tC', clock=offset + 3), + QTEV('started', tB, 'w2', name='tB', clock=offset + 5), + QTEV('retried', tA, 'w1', name='tA', clock=offset + 7), + QTEV('succeeded', tB, 'w2', name='tB', clock=offset + 9), + QTEV('started', tC, 'w2', name='tC', clock=offset + 10), + QTEV('received', tA, 'w3', name='tA', clock=offset + 13), + QTEV('succeded', tC, 'w2', name='tC', clock=offset + 12), + QTEV('started', tA, 'w3', name='tA', clock=offset + 14), + QTEV('succeeded', tA, 'w3', name='TA', clock=offset + 16), ] def rewind_with_offset(self, offset, uids=None): @@ -168,9 +180,20 @@ class test_Worker(AppCase): hash(Worker(hostname='foo')), hash(Worker(hostname='bar')), ) + def test_compatible_with_Decimal(self): + w = Worker('george@vandelay.com') + timestamp, local_received = Decimal(_float_to_decimal(time())), time() + w.event('worker-online', timestamp, local_received, fields={ + 'hostname': 'george@vandelay.com', + 'timestamp': timestamp, + 'local_received': local_received, + 'freq': Decimal(_float_to_decimal(5.6335431)), + }) + self.assertTrue(w.alive) + def test_survives_missing_timestamp(self): worker = Worker(hostname='foo') - worker.on_heartbeat(timestamp=None) + worker.event('heartbeat') self.assertEqual(worker.heartbeats, []) def test_repr(self): @@ -179,15 +202,15 @@ class test_Worker(AppCase): def test_drift_warning(self): worker = Worker(hostname='foo') with patch('celery.events.state.warn') as warn: - worker.update_heartbeat(time(), time() + (HEARTBEAT_DRIFT_MAX * 2)) + worker.event(None, time() + (HEARTBEAT_DRIFT_MAX * 2), time()) self.assertTrue(warn.called) self.assertIn('Substantial drift', warn.call_args[0][0]) - def test_update_heartbeat(self): + def test_updates_heartbeat(self): worker = Worker(hostname='foo') - worker.update_heartbeat(time(), time()) + worker.event(None, time(), time()) self.assertEqual(len(worker.heartbeats), 1) - worker.update_heartbeat(time() - 10, time()) + worker.event(None, time(), time() - 10) self.assertEqual(len(worker.heartbeats), 1) @@ -238,26 +261,28 @@ class test_Task(AppCase): def test_ready(self): task = Task(uuid='abcdefg', name='tasks.add') - task.on_received(timestamp=time()) + task.event('received', time(), time()) self.assertFalse(task.ready) - task.on_succeeded(timestamp=time()) + task.event('succeeded', time(), time()) self.assertTrue(task.ready) def test_sent(self): task = Task(uuid='abcdefg', name='tasks.add') - task.on_sent(timestamp=time()) + task.event('sent', time(), time()) self.assertEqual(task.state, states.PENDING) def test_merge(self): task = Task() - task.on_failed(timestamp=time()) - task.on_started(timestamp=time()) - task.on_received(timestamp=time(), name='tasks.add', args=(2, 2)) + task.event('failed', time(), time()) + task.event('started', time(), time()) + task.event('received', time(), time(), { + 'name': 'tasks.add', 'args': (2, 2), + }) self.assertEqual(task.state, states.FAILURE) self.assertEqual(task.name, 'tasks.add') self.assertTupleEqual(task.args, (2, 2)) - task.on_retried(timestamp=time()) + task.event('retried', time(), time()) self.assertEqual(task.state, states.RETRY) def test_repr(self): @@ -452,32 +477,60 @@ class test_State(AppCase): def test_survives_unknown_worker_event(self): s = State() - s.worker_event('worker-unknown-event-xxx', {'foo': 'bar'}) - s.worker_event('worker-unknown-event-xxx', {'hostname': 'xxx', - 'foo': 'bar'}) + s.event({ + 'type': 'worker-unknown-event-xxx', + 'foo': 'bar', + }) + s.event({ + 'type': 'worker-unknown-event-xxx', + 'hostname': 'xxx', + 'foo': 'bar', + }) def test_survives_unknown_task_event(self): s = State() - s.task_event('task-unknown-event-xxx', {'foo': 'bar', - 'uuid': 'x', - 'hostname': 'y'}) + s.event( + { + 'type': 'task-unknown-event-xxx', + 'foo': 'bar', + 'uuid': 'x', + 'hostname': 'y', + 'timestamp': time(), + 'local_received': time(), + 'clock': 0, + }, + ) def test_limits_maxtasks(self): - s = State() - s.max_tasks_in_memory = 1 - s.task_event('task-unknown-event-xxx', {'foo': 'bar', - 'uuid': 'x', - 'hostname': 'y', - 'clock': 3}) - s.task_event('task-unknown-event-xxx', {'foo': 'bar', - 'uuid': 'y', - 'hostname': 'y', - 'clock': 4}) - - s.task_event('task-unknown-event-xxx', {'foo': 'bar', - 'uuid': 'z', - 'hostname': 'y', - 'clock': 5}) + s = State(max_tasks_in_memory=1) + s.heap_multiplier = 2 + s.event({ + 'type': 'task-unknown-event-xxx', + 'foo': 'bar', + 'uuid': 'x', + 'hostname': 'y', + 'clock': 3, + 'timestamp': time(), + 'local_received': time(), + }) + s.event({ + 'type': 'task-unknown-event-xxx', + 'foo': 'bar', + 'uuid': 'y', + 'hostname': 'y', + 'clock': 4, + 'timestamp': time(), + 'local_received': time(), + }) + s.event({ + 'type': 'task-unknown-event-xxx', + 'foo': 'bar', + 'uuid': 'z', + 'hostname': 'y', + 'clock': 5, + 'timestamp': time(), + 'local_received': time(), + }) self.assertEqual(len(s._taskheap), 2) self.assertEqual(s._taskheap[0].clock, 4) self.assertEqual(s._taskheap[1].clock, 5) diff --git a/awx/lib/site-packages/celery/tests/fixups/test_django.py b/awx/lib/site-packages/celery/tests/fixups/test_django.py index 1a995fe076..1d4ec5ceaa 100644 --- a/awx/lib/site-packages/celery/tests/fixups/test_django.py +++ b/awx/lib/site-packages/celery/tests/fixups/test_django.py @@ -8,6 +8,7 @@ from celery.fixups.django import ( _maybe_close_fd, fixup, DjangoFixup, + DjangoWorkerFixup, ) from celery.tests.case import ( @@ -15,7 +16,20 @@ from celery.tests.case import ( ) -class test_DjangoFixup(AppCase): +class FixupCase(AppCase): + Fixup = None + + @contextmanager + def fixup_context(self, app): + with patch('celery.fixups.django.DjangoWorkerFixup.validate_models'): + with patch('celery.fixups.django.symbol_by_name') as symbyname: + with patch('celery.fixups.django.import_module') as impmod: + f = self.Fixup(app) + yield f, impmod, symbyname + + +class test_DjangoFixup(FixupCase): + Fixup = DjangoFixup def test_fixup(self): with patch('celery.fixups.django.DjangoFixup') as Fixup: @@ -31,13 +45,6 @@ class test_DjangoFixup(AppCase): fixup(self.app) self.assertTrue(Fixup.called) - @contextmanager - def fixup_context(self, app): - with patch('celery.fixups.django.import_module') as import_module: - with patch('celery.fixups.django.symbol_by_name') as symbyname: - f = DjangoFixup(app) - yield f, import_module, symbyname - def test_maybe_close_fd(self): with patch('os.close'): _maybe_close_fd(Mock()) @@ -52,33 +59,16 @@ class test_DjangoFixup(AppCase): raise ImportError() return Mock() sym.side_effect = se - self.assertTrue(DjangoFixup(self.app)._now) - - def se2(name): - if name == 'django.db:close_old_connections': - raise ImportError() - return Mock() - sym.side_effect = se2 - self.assertIsNone(DjangoFixup(self.app)._close_old_connections) + self.assertTrue(self.Fixup(self.app)._now) def test_install(self): - self.app.conf = {'CELERY_DB_REUSE_MAX': None} self.app.loader = Mock() with self.fixup_context(self.app) as (f, _, _): with patch_many('os.getcwd', 'sys.path', 'celery.fixups.django.signals') as (cw, p, sigs): cw.return_value = '/opt/vandelay' f.install() - sigs.beat_embedded_init.connect.assert_called_with( - f.close_database, - ) - sigs.worker_ready.connect.assert_called_with(f.on_worker_ready) - sigs.task_prerun.connect.assert_called_with(f.on_task_prerun) - sigs.task_postrun.connect.assert_called_with(f.on_task_postrun) sigs.worker_init.connect.assert_called_with(f.on_worker_init) - sigs.worker_process_init.connect.assert_called_with( - f.on_worker_process_init, - ) self.assertEqual(self.app.loader.now, f.now) self.assertEqual(self.app.loader.mail_admins, f.mail_admins) p.append.assert_called_with('/opt/vandelay') @@ -99,11 +89,44 @@ class test_DjangoFixup(AppCase): def test_on_worker_init(self): with self.fixup_context(self.app) as (f, _, _): - f.close_database = Mock() - f.close_cache = Mock() - f.on_worker_init() - f.close_database.assert_called_with() - f.close_cache.assert_called_with() + with patch('celery.fixups.django.DjangoWorkerFixup') as DWF: + f.on_worker_init() + DWF.assert_called_with(f.app) + DWF.return_value.install.assert_called_with() + self.assertIs( + f._worker_fixup, DWF.return_value.install.return_value, + ) + + +class test_DjangoWorkerFixup(FixupCase): + Fixup = DjangoWorkerFixup + + def test_init(self): + with self.fixup_context(self.app) as (f, importmod, sym): + self.assertTrue(f) + + def se(name): + if name == 'django.db:close_old_connections': + raise ImportError() + return Mock() + sym.side_effect = se + self.assertIsNone(self.Fixup(self.app)._close_old_connections) + + def test_install(self): + self.app.conf = {'CELERY_DB_REUSE_MAX': None} + self.app.loader = Mock() + with self.fixup_context(self.app) as (f, _, _): + with patch_many('celery.fixups.django.signals') as (sigs, ): + f.install() + sigs.beat_embedded_init.connect.assert_called_with( + f.close_database, + ) + sigs.worker_ready.connect.assert_called_with(f.on_worker_ready) + sigs.task_prerun.connect.assert_called_with(f.on_task_prerun) + sigs.task_postrun.connect.assert_called_with(f.on_task_postrun) + sigs.worker_process_init.connect.assert_called_with( + f.on_worker_process_init, + ) def test_on_worker_process_init(self): with self.fixup_context(self.app) as (f, _, _): diff --git a/awx/lib/site-packages/celery/tests/tasks/test_canvas.py b/awx/lib/site-packages/celery/tests/tasks/test_canvas.py index ac2509a261..8ecbbbbc95 100644 --- a/awx/lib/site-packages/celery/tests/tasks/test_canvas.py +++ b/awx/lib/site-packages/celery/tests/tasks/test_canvas.py @@ -220,6 +220,10 @@ class test_chain(CanvasCase): self.assertEqual(res.parent.parent.get(), 8) self.assertIsNone(res.parent.parent.parent) + def test_empty_chain_returns_none(self): + self.assertIsNone(chain(app=self.app)()) + self.assertIsNone(chain(app=self.app).apply_async()) + def test_call_no_tasks(self): x = chain() self.assertFalse(x()) diff --git a/awx/lib/site-packages/celery/tests/tasks/test_chord.py b/awx/lib/site-packages/celery/tests/tasks/test_chord.py index ff4d9cd068..47e7718419 100644 --- a/awx/lib/site-packages/celery/tests/tasks/test_chord.py +++ b/awx/lib/site-packages/celery/tests/tasks/test_chord.py @@ -5,7 +5,7 @@ from contextlib import contextmanager from celery import group from celery import canvas from celery import result -from celery.exceptions import ChordError +from celery.exceptions import ChordError, Retry from celery.five import range from celery.result import AsyncResult, GroupResult, EagerResult from celery.tests.case import AppCase, Mock @@ -54,6 +54,7 @@ class TSRNoReport(TSR): def patch_unlock_retry(app): unlock = app.tasks['celery.chord_unlock'] retry = Mock() + retry.return_value = Retry() prev, unlock.retry = unlock.retry, retry try: yield unlock, retry @@ -148,11 +149,16 @@ class test_unlock_chord_task(ChordCase): setup(callback) try: assert self.app.tasks['celery.chord_unlock'] is unlock - unlock( - 'group_id', callback_s, - result=[self.app.AsyncResult(r) for r in ['1', 2, 3]], - GroupResult=ResultCls, **kwargs - ) + try: + unlock( + 'group_id', callback_s, + result=[ + self.app.AsyncResult(r) for r in ['1', 2, 3] + ], + GroupResult=ResultCls, **kwargs + ) + except Retry: + pass finally: canvas.maybe_signature = subtask yield callback_s, retry, fail_current @@ -224,4 +230,4 @@ class test_Chord_task(ChordCase): body = dict() Chord(group(self.add.subtask((i, i)) for i in range(5)), body) Chord([self.add.subtask((j, j)) for j in range(5)], body) - self.assertEqual(self.app.backend.on_chord_apply.call_count, 2) + self.assertEqual(self.app.backend.apply_chord.call_count, 2) diff --git a/awx/lib/site-packages/celery/tests/tasks/test_context.py b/awx/lib/site-packages/celery/tests/tasks/test_context.py index 5486982053..ecad3f840d 100644 --- a/awx/lib/site-packages/celery/tests/tasks/test_context.py +++ b/awx/lib/site-packages/celery/tests/tasks/test_context.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*-' from __future__ import absolute_import -from collections import Callable - from celery.app.task import Context from celery.tests.case import AppCase @@ -15,7 +13,7 @@ def get_context_as_dict(ctx, getter=getattr): if attr_name.startswith('_'): continue # Ignore pseudo-private attributes attr = getter(ctx, attr_name) - if isinstance(attr, Callable): + if callable(attr): continue # Ignore methods and other non-trivial types defaults[attr_name] = attr return defaults diff --git a/awx/lib/site-packages/celery/tests/tasks/test_tasks.py b/awx/lib/site-packages/celery/tests/tasks/test_tasks.py index 7269794f37..93a782ecc9 100644 --- a/awx/lib/site-packages/celery/tests/tasks/test_tasks.py +++ b/awx/lib/site-packages/celery/tests/tasks/test_tasks.py @@ -1,6 +1,5 @@ from __future__ import absolute_import -from collections import Callable from datetime import datetime, timedelta from kombu import Queue @@ -267,8 +266,9 @@ class test_tasks(TasksCase): def test_regular_task(self): self.assertIsInstance(self.mytask, Task) self.assertTrue(self.mytask.run()) - self.assertTrue(isinstance(self.mytask, Callable), - 'Task class is callable()') + self.assertTrue( + callable(self.mytask), 'Task class is callable()', + ) self.assertTrue(self.mytask(), 'Task class runs run() when called') with self.app.connection_or_acquire() as conn: diff --git a/awx/lib/site-packages/celery/tests/utils/test_local.py b/awx/lib/site-packages/celery/tests/utils/test_local.py index 9778922473..324a207b6b 100644 --- a/awx/lib/site-packages/celery/tests/utils/test_local.py +++ b/awx/lib/site-packages/celery/tests/utils/test_local.py @@ -11,6 +11,8 @@ from celery.local import ( ) from celery.tests.case import Case, Mock +PY3 = sys.version_info[0] == 3 + class test_try_import(Case): @@ -258,7 +260,8 @@ class test_Proxy(Case): x = Proxy(lambda: 10) self.assertEqual(type(x.__float__()), float) self.assertEqual(type(x.__int__()), int) - self.assertEqual(type(x.__long__()), long_t) + if not PY3: + self.assertEqual(type(x.__long__()), long_t) self.assertTrue(hex(x)) self.assertTrue(oct(x)) diff --git a/awx/lib/site-packages/celery/tests/worker/test_autoreload.py b/awx/lib/site-packages/celery/tests/worker/test_autoreload.py index aa550d930f..e61b330ca3 100644 --- a/awx/lib/site-packages/celery/tests/worker/test_autoreload.py +++ b/awx/lib/site-packages/celery/tests/worker/test_autoreload.py @@ -18,7 +18,7 @@ from celery.worker.autoreload import ( Autoreloader, ) -from celery.tests.case import AppCase, Case, Mock, patch, mock_open +from celery.tests.case import AppCase, Case, Mock, SkipTest, patch, mock_open class test_WorkerComponent(AppCase): @@ -34,7 +34,8 @@ class test_WorkerComponent(AppCase): @patch('select.kevent', create=True) @patch('select.kqueue', create=True) - def test_create_ev(self, kqueue, kevent): + @patch('kombu.utils.eventio.kqueue') + def test_create_ev(self, kq, kqueue, kevent): w = Mock() w.use_eventloop = True x = WorkerComponent(w) @@ -122,22 +123,25 @@ class test_KQueueMonitor(Case): x.stop() def test_register_with_event_loop(self): + from kombu.utils import eventio + if eventio.kqueue is None: + raise SkipTest('version of kombu does not work with pypy') x = KQueueMonitor(['a', 'b']) - hub = Mock() - x.add_events = Mock() + hub = Mock(name='hub') + x.add_events = Mock(name='add_events()') x.register_with_event_loop(hub) - x.add_events.assert_called_with(hub.poller) + x.add_events.assert_called_with(x._kq) self.assertEqual( - hub.poller.on_file_change, + x._kq.on_file_change, x.handle_event, ) def test_on_event_loop_close(self): x = KQueueMonitor(['a', 'b']) x.close = Mock() - hub = Mock() - x.on_event_loop_close(hub) - x.close.assert_called_with(hub.poller) + x._kq = Mock(name='_kq') + x.on_event_loop_close(Mock(name='hub')) + x.close.assert_called_with(x._kq) def test_handle_event(self): x = KQueueMonitor(['a', 'b']) @@ -217,7 +221,8 @@ class test_InotifyMonitor(Case): class test_default_implementation(Case): @patch('select.kqueue', create=True) - def test_kqueue(self, kqueue): + @patch('kombu.utils.eventio.kqueue', create=True) + def test_kqueue(self, kq, kqueue): self.assertEqual(default_implementation(), 'kqueue') @patch('celery.worker.autoreload.pyinotify') diff --git a/awx/lib/site-packages/celery/tests/worker/test_consumer.py b/awx/lib/site-packages/celery/tests/worker/test_consumer.py index f287ce417e..d5dea26d75 100644 --- a/awx/lib/site-packages/celery/tests/worker/test_consumer.py +++ b/awx/lib/site-packages/celery/tests/worker/test_consumer.py @@ -18,7 +18,7 @@ from celery.worker.consumer import ( CLOSE, ) -from celery.tests.case import AppCase, Mock, SkipTest, call, patch +from celery.tests.case import AppCase, ContextMock, Mock, SkipTest, call, patch class test_Consumer(AppCase): @@ -36,7 +36,7 @@ class test_Consumer(AppCase): ) consumer.blueprint = Mock() consumer._restart_state = Mock() - consumer.connection = Mock() + consumer.connection = _amqp_connection() consumer.connection_errors = (socket.error, OSError, ) return consumer @@ -144,8 +144,8 @@ class test_Consumer(AppCase): c.on_close() def test_connect_error_handler(self): - self.app.connection = Mock() - conn = self.app.connection.return_value = Mock() + self.app.connection = _amqp_connection() + conn = self.app.connection.return_value c = self.get_consumer() self.assertTrue(c.connect()) self.assertTrue(conn.ensure_connection.called) @@ -204,6 +204,7 @@ class test_Mingle(AppCase): def test_start_no_replies(self): c = Mock() + c.app.connection = _amqp_connection() mingle = Mingle(c) I = c.app.control.inspect.return_value = Mock() I.hello.return_value = {} @@ -212,6 +213,7 @@ class test_Mingle(AppCase): def test_start(self): try: c = Mock() + c.app.connection = _amqp_connection() mingle = Mingle(c) self.assertTrue(mingle.enabled) @@ -248,16 +250,25 @@ class test_Mingle(AppCase): worker_state.revoked.clear() +def _amqp_connection(): + connection = ContextMock() + connection.return_value = ContextMock() + connection.return_value.transport.driver_type = 'amqp' + return connection + + class test_Gossip(AppCase): def test_init(self): c = self.Consumer() + c.app.connection = _amqp_connection() g = Gossip(c) self.assertTrue(g.enabled) self.assertIs(c.gossip, g) def test_election(self): c = self.Consumer() + c.app.connection = _amqp_connection() g = Gossip(c) g.start(c) g.election('id', 'topic', 'action') @@ -268,6 +279,7 @@ class test_Gossip(AppCase): def test_call_task(self): c = self.Consumer() + c.app.connection = _amqp_connection() g = Gossip(c) g.start(c) @@ -298,6 +310,7 @@ class test_Gossip(AppCase): def test_on_elect(self): c = self.Consumer() + c.app.connection = _amqp_connection() g = Gossip(c) g.start(c) @@ -314,6 +327,7 @@ class test_Gossip(AppCase): def Consumer(self, hostname='foo@x.com', pid=4312): c = Mock() + c.app.connection = _amqp_connection() c.hostname = hostname c.pid = pid return c @@ -355,6 +369,7 @@ class test_Gossip(AppCase): def test_on_elect_ack_lose(self): c = self.Consumer(hostname='bar@x.com') # I will lose + c.app.connection = _amqp_connection() g = Gossip(c) handler = g.election_handlers['topic'] = Mock() self.setup_election(g, c) @@ -371,23 +386,23 @@ class test_Gossip(AppCase): def test_on_node_join(self): c = self.Consumer() g = Gossip(c) - with patch('celery.worker.consumer.info') as info: + with patch('celery.worker.consumer.debug') as debug: g.on_node_join(c) - info.assert_called_with('%s joined the party', 'foo@x.com') + debug.assert_called_with('%s joined the party', 'foo@x.com') def test_on_node_leave(self): c = self.Consumer() g = Gossip(c) - with patch('celery.worker.consumer.info') as info: + with patch('celery.worker.consumer.debug') as debug: g.on_node_leave(c) - info.assert_called_with('%s left', 'foo@x.com') + debug.assert_called_with('%s left', 'foo@x.com') def test_on_node_lost(self): c = self.Consumer() g = Gossip(c) - with patch('celery.worker.consumer.warn') as warn: + with patch('celery.worker.consumer.info') as info: g.on_node_lost(c) - warn.assert_called_with('%s went missing!', 'foo@x.com') + info.assert_called_with('missed heartbeat from %s', 'foo@x.com') def test_register_timer(self): c = self.Consumer() @@ -418,8 +433,13 @@ class test_Gossip(AppCase): def test_on_message(self): c = self.Consumer() g = Gossip(c) + self.assertTrue(g.enabled) prepare = Mock() prepare.return_value = 'worker-online', {} + c.app.events.State.assert_called_with( + on_node_join=g.on_node_join, + on_node_leave=g.on_node_leave, + ) g.update_state = Mock() worker = Mock() g.on_node_join = Mock() @@ -435,20 +455,16 @@ class test_Gossip(AppCase): g.event_handlers = {} g.on_message(prepare, message) - g.on_node_join.assert_called_with(worker) message.delivery_info = {'routing_key': 'worker-offline'} prepare.return_value = 'worker-offline', {} g.on_message(prepare, message) - g.on_node_leave.assert_called_with(worker) message.delivery_info = {'routing_key': 'worker-baz'} prepare.return_value = 'worker-baz', {} g.update_state.return_value = worker, 0 g.on_message(prepare, message) - g.on_node_leave.reset_mock() message.headers = {'hostname': g.hostname} g.on_message(prepare, message) - self.assertFalse(g.on_node_leave.called) g.clock.forward.assert_called_with() diff --git a/awx/lib/site-packages/celery/tests/worker/test_control.py b/awx/lib/site-packages/celery/tests/worker/test_control.py index c47be9103d..e613440ff3 100644 --- a/awx/lib/site-packages/celery/tests/worker/test_control.py +++ b/awx/lib/site-packages/celery/tests/worker/test_control.py @@ -515,8 +515,13 @@ class test_ControlPanel(AppCase): def test_pool_restart(self): consumer = Consumer(self.app) consumer.controller = _WC(app=self.app) + consumer.controller.consumer = consumer consumer.controller.pool.restart = Mock() + consumer.reset_rate_limits = Mock(name='reset_rate_limits()') + consumer.update_strategies = Mock(name='update_strategies()') + consumer.event_dispatcher = Mock(name='evd') panel = self.create_panel(consumer=consumer) + assert panel.state.consumer.controller.consumer is consumer panel.app = self.app _import = panel.app.loader.import_from_cwd = Mock() _reload = Mock() @@ -527,15 +532,21 @@ class test_ControlPanel(AppCase): self.app.conf.CELERYD_POOL_RESTARTS = True panel.handle('pool_restart', {'reloader': _reload}) self.assertTrue(consumer.controller.pool.restart.called) + consumer.reset_rate_limits.assert_called_with() + consumer.update_strategies.assert_called_with() self.assertFalse(_reload.called) self.assertFalse(_import.called) def test_pool_restart_import_modules(self): consumer = Consumer(self.app) consumer.controller = _WC(app=self.app) + consumer.controller.consumer = consumer consumer.controller.pool.restart = Mock() + consumer.reset_rate_limits = Mock(name='reset_rate_limits()') + consumer.update_strategies = Mock(name='update_strategies()') panel = self.create_panel(consumer=consumer) panel.app = self.app + assert panel.state.consumer.controller.consumer is consumer _import = consumer.controller.app.loader.import_from_cwd = Mock() _reload = Mock() @@ -544,6 +555,8 @@ class test_ControlPanel(AppCase): 'reloader': _reload}) self.assertTrue(consumer.controller.pool.restart.called) + consumer.reset_rate_limits.assert_called_with() + consumer.update_strategies.assert_called_with() self.assertFalse(_reload.called) self.assertItemsEqual( [call('bar'), call('foo')], @@ -553,7 +566,10 @@ class test_ControlPanel(AppCase): def test_pool_restart_reload_modules(self): consumer = Consumer(self.app) consumer.controller = _WC(app=self.app) + consumer.controller.consumer = consumer consumer.controller.pool.restart = Mock() + consumer.reset_rate_limits = Mock(name='reset_rate_limits()') + consumer.update_strategies = Mock(name='update_strategies()') panel = self.create_panel(consumer=consumer) panel.app = self.app _import = panel.app.loader.import_from_cwd = Mock() diff --git a/awx/lib/site-packages/celery/tests/worker/test_request.py b/awx/lib/site-packages/celery/tests/worker/test_request.py index 9b46a27ea7..488ea72f4d 100644 --- a/awx/lib/site-packages/celery/tests/worker/test_request.py +++ b/awx/lib/site-packages/celery/tests/worker/test_request.py @@ -762,6 +762,7 @@ class test_Request(AppCase): 'name': job.name, 'id': job.id, 'exc': 'FOOBARBAZ', + 'description': 'raised unexpected', 'traceback': 'foobarbaz', } self.assertTrue(x) diff --git a/awx/lib/site-packages/celery/tests/worker/test_worker.py b/awx/lib/site-packages/celery/tests/worker/test_worker.py index db773d71fc..3bd7cd3d34 100644 --- a/awx/lib/site-packages/celery/tests/worker/test_worker.py +++ b/awx/lib/site-packages/celery/tests/worker/test_worker.py @@ -27,7 +27,7 @@ from celery.utils import worker_direct from celery.utils.serialization import pickle from celery.utils.timer2 import Timer -from celery.tests.case import AppCase, Mock, patch, restore_logging +from celery.tests.case import AppCase, Mock, SkipTest, patch, restore_logging def MockStep(step=None): @@ -38,6 +38,13 @@ def MockStep(step=None): return step +def mock_event_dispatcher(): + evd = Mock(name='event_dispatcher') + evd.groups = ['worker'] + evd._outbound_buffer = deque() + return evd + + class PlaceHolder(object): pass @@ -182,7 +189,7 @@ class test_Consumer(AppCase): self.assertIsNone(l.connection) l = MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - eventer = l.event_dispatcher = Mock() + eventer = l.event_dispatcher = mock_event_dispatcher() eventer.enabled = True heart = l.heart = MockHeart() l.blueprint.state = RUN @@ -200,7 +207,7 @@ class test_Consumer(AppCase): l.steps.pop() backend = Mock() m = create_message(backend, unknown={'baz': '!!!'}) - l.event_dispatcher = Mock() + l.event_dispatcher = mock_event_dispatcher() l.node = MockNode() callback = self._get_on_message(l) @@ -217,7 +224,7 @@ class test_Consumer(AppCase): args=('2, 2'), kwargs={}, eta=datetime.now().isoformat()) - l.event_dispatcher = Mock() + l.event_dispatcher = mock_event_dispatcher() l.node = MockNode() l.update_strategies() l.qos = Mock() @@ -230,12 +237,12 @@ class test_Consumer(AppCase): def test_receive_message_InvalidTaskError(self, error): l = _MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) l.blueprint.state = RUN - l.event_dispatcher = Mock() + l.event_dispatcher = mock_event_dispatcher() l.steps.pop() m = create_message(Mock(), task=self.foo_task.name, args=(1, 2), kwargs='foobarbaz', id=1) l.update_strategies() - l.event_dispatcher = Mock() + l.event_dispatcher = mock_event_dispatcher() callback = self._get_on_message(l) callback(m.decode(), m) @@ -258,7 +265,7 @@ class test_Consumer(AppCase): def _get_on_message(self, l): if l.qos is None: l.qos = Mock() - l.event_dispatcher = Mock() + l.event_dispatcher = mock_event_dispatcher() l.task_consumer = Mock() l.connection = Mock() l.connection.drain_events.side_effect = SystemExit() @@ -271,7 +278,7 @@ class test_Consumer(AppCase): def test_receieve_message(self): l = Consumer(self.buffer.put, timer=self.timer, app=self.app) l.blueprint.state = RUN - l.event_dispatcher = Mock() + l.event_dispatcher = mock_event_dispatcher() m = create_message(Mock(), task=self.foo_task.name, args=[2, 4, 8], kwargs={}) l.update_strategies() @@ -419,7 +426,7 @@ class test_Consumer(AppCase): l.task_consumer = Mock() l.qos = QoS(l.task_consumer.qos, 1) current_pcount = l.qos.value - l.event_dispatcher = Mock() + l.event_dispatcher = mock_event_dispatcher() l.enabled = False l.update_strategies() callback = self._get_on_message(l) @@ -478,7 +485,7 @@ class test_Consumer(AppCase): backend = Mock() m = create_message(backend, task='x.X.31x', args=[2, 4, 8], kwargs={}) - l.event_dispatcher = Mock() + l.event_dispatcher = mock_event_dispatcher() callback = self._get_on_message(l) self.assertFalse(callback(m.decode(), m)) with self.assertRaises(Empty): @@ -493,7 +500,7 @@ class test_Consumer(AppCase): backend = Mock() m = create_message(backend, args=[2, 4, 8], kwargs={}) - l.event_dispatcher = Mock() + l.event_dispatcher = mock_event_dispatcher() l.connection_errors = (socket.error, ) m.reject = Mock() m.reject.side_effect = socket.error('foo') @@ -509,8 +516,7 @@ class test_Consumer(AppCase): def test_receive_message_eta(self): l = _MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) l.steps.pop() - l.event_dispatcher = Mock() - l.event_dispatcher._outbound_buffer = deque() + l.event_dispatcher = mock_event_dispatcher() backend = Mock() m = create_message( backend, task=self.foo_task.name, @@ -525,12 +531,15 @@ class test_Consumer(AppCase): l.blueprint.start(l) l.app.conf.BROKER_CONNECTION_RETRY = p l.blueprint.restart(l) - l.event_dispatcher = Mock() + l.event_dispatcher = mock_event_dispatcher() callback = self._get_on_message(l) callback(m.decode(), m) finally: l.timer.stop() - l.timer.join() + try: + l.timer.join() + except RuntimeError: + pass in_hold = l.timer.queue[0] self.assertEqual(len(in_hold), 3) @@ -751,6 +760,7 @@ class test_WorkController(AppCase): ws.send.assert_called_with(sender=self.worker) def test_process_shutdown_on_worker_shutdown(self): + raise SkipTest('unstable test') from celery.concurrency.prefork import process_destructor from celery.concurrency.asynpool import Worker with patch('celery.signals.worker_process_shutdown') as ws: diff --git a/awx/lib/site-packages/celery/utils/__init__.py b/awx/lib/site-packages/celery/utils/__init__.py index c884028b03..5f3266353a 100644 --- a/awx/lib/site-packages/celery/utils/__init__.py +++ b/awx/lib/site-packages/celery/utils/__init__.py @@ -9,6 +9,7 @@ from __future__ import absolute_import, print_function import os +import socket import sys import traceback import warnings @@ -21,7 +22,7 @@ from pprint import pprint from kombu.entity import Exchange, Queue from celery.exceptions import CPendingDeprecationWarning, CDeprecationWarning -from celery.five import StringIO, items, reraise, string_t +from celery.five import WhateverIO, items, reraise, string_t __all__ = ['worker_direct', 'warn_deprecated', 'deprecated', 'lpmerge', 'is_iterable', 'isatty', 'cry', 'maybe_reraise', 'strtobool', @@ -55,6 +56,8 @@ WORKER_DIRECT_QUEUE_FORMAT = '{hostname}.dq' #: Separator for worker node name and hostname. NODENAME_SEP = '@' +NODENAME_DEFAULT = 'celery' + def worker_direct(hostname): """Return :class:`kombu.Queue` that is a direct route to @@ -73,7 +76,7 @@ def worker_direct(hostname): def warn_deprecated(description=None, deprecation=None, - removal=None, alternative=None): + removal=None, alternative=None, stacklevel=2): ctx = {'description': description, 'deprecation': deprecation, 'removal': removal, 'alternative': alternative} @@ -81,21 +84,21 @@ def warn_deprecated(description=None, deprecation=None, w = CPendingDeprecationWarning(PENDING_DEPRECATION_FMT.format(**ctx)) else: w = CDeprecationWarning(DEPRECATION_FMT.format(**ctx)) - warnings.warn(w) + warnings.warn(w, stacklevel=stacklevel) -def deprecated(description=None, deprecation=None, - removal=None, alternative=None): +def deprecated(deprecation=None, removal=None, + alternative=None, description=None): """Decorator for deprecated functions. A deprecation warning will be emitted when the function is called. - :keyword description: Description of what is being deprecated. :keyword deprecation: Version that marks first deprecation, if this argument is not set a ``PendingDeprecationWarning`` will be emitted instead. :keyword removed: Future version when this feature will be removed. :keyword alternative: Instructions for an alternative solution (if any). + :keyword description: Description of what is being deprecated. """ def _inner(fun): @@ -106,12 +109,63 @@ def deprecated(description=None, deprecation=None, warn_deprecated(description=description or qualname(fun), deprecation=deprecation, removal=removal, - alternative=alternative) + alternative=alternative, + stacklevel=3) return fun(*args, **kwargs) return __inner return _inner +def deprecated_property(deprecation=None, removal=None, + alternative=None, description=None): + def _inner(fun): + return _deprecated_property( + fun, deprecation=deprecation, removal=removal, + alternative=alternative, description=description or fun.__name__) + return _inner + + +class _deprecated_property(object): + + def __init__(self, fget=None, fset=None, fdel=None, doc=None, **depreinfo): + self.__get = fget + self.__set = fset + self.__del = fdel + self.__name__, self.__module__, self.__doc__ = ( + fget.__name__, fget.__module__, fget.__doc__, + ) + self.depreinfo = depreinfo + self.depreinfo.setdefault('stacklevel', 3) + + def __get__(self, obj, type=None): + if obj is None: + return self + warn_deprecated(**self.depreinfo) + return self.__get(obj) + + def __set__(self, obj, value): + if obj is None: + return self + if self.__set is None: + raise AttributeError('cannot set attribute') + warn_deprecated(**self.depreinfo) + self.__set(obj, value) + + def __delete__(self, obj): + if obj is None: + return self + if self.__del is None: + raise AttributeError('cannot delete attribute') + warn_deprecated(**self.depreinfo) + self.__del(obj) + + def setter(self, fset): + return self.__class__(self.__get, fset, self.__del, **self.depreinfo) + + def deleter(self, fdel): + return self.__class__(self.__get, self.__set, fdel, **self.depreinfo) + + def lpmerge(L, R): """In place left precedent dictionary merge. @@ -149,7 +203,7 @@ def cry(out=None, sepchr='=', seplen=49): # pragma: no cover taken from https://gist.github.com/737056.""" import threading - out = StringIO() if out is None else out + out = WhateverIO() if out is None else out P = partial(print, file=out) # get a map of threads by their ID so we can print their names @@ -270,6 +324,11 @@ def nodename(name, hostname): return NODENAME_SEP.join((name, hostname)) +def anon_nodename(hostname=None, prefix='gen'): + return nodename(''.join([prefix, str(os.getpid())]), + hostname or socket.gethostname()) + + def nodesplit(nodename): """Split node name into tuple of name/hostname.""" parts = nodename.split(NODENAME_SEP, 1) @@ -278,6 +337,10 @@ def nodesplit(nodename): return parts +def default_nodename(hostname): + name, host = nodesplit(hostname or '') + return nodename(name or NODENAME_DEFAULT, host or socket.gethostname()) + # ------------------------------------------------------------------------ # # > XXX Compat from .log import LOG_LEVELS # noqa diff --git a/awx/lib/site-packages/celery/utils/dispatch/saferef.py b/awx/lib/site-packages/celery/utils/dispatch/saferef.py index d11fdc3084..cd818bb2d4 100644 --- a/awx/lib/site-packages/celery/utils/dispatch/saferef.py +++ b/awx/lib/site-packages/celery/utils/dispatch/saferef.py @@ -7,13 +7,14 @@ aren't handled by the core weakref module). """ from __future__ import absolute_import -import weakref +import sys import traceback - -from collections import Callable +import weakref __all__ = ['safe_ref'] +PY3 = sys.version_info[0] == 3 + def safe_ref(target, on_delete=None): # pragma: no cover """Return a *safe* weak reference to a callable target @@ -35,7 +36,7 @@ def safe_ref(target, on_delete=None): # pragma: no cover don't know how to create reference""".format(target) return get_bound_method_weakref(target=target, on_delete=on_delete) - if isinstance(on_delete, Callable): + if callable(on_delete): return weakref.ref(target, on_delete) else: return weakref.ref(target) @@ -140,7 +141,7 @@ class BoundMethodWeakref(object): # pragma: no cover pass for function in methods: try: - if isinstance(function, Callable): + if callable(function): function(self) except Exception as exc: try: @@ -180,11 +181,12 @@ class BoundMethodWeakref(object): # pragma: no cover return self() is not None __nonzero__ = __bool__ # py2 - def __cmp__(self, other): - """Compare with another reference""" - if not isinstance(other, self.__class__): - return cmp(self.__class__, type(other)) - return cmp(self.key, other.key) + if not PY3: + def __cmp__(self, other): + """Compare with another reference""" + if not isinstance(other, self.__class__): + return cmp(self.__class__, type(other)) # noqa + return cmp(self.key, other.key) # noqa def __call__(self): """Return a strong reference to the bound method diff --git a/awx/lib/site-packages/celery/utils/dispatch/signal.py b/awx/lib/site-packages/celery/utils/dispatch/signal.py index fe81e0bcce..a2423d9788 100644 --- a/awx/lib/site-packages/celery/utils/dispatch/signal.py +++ b/awx/lib/site-packages/celery/utils/dispatch/signal.py @@ -3,7 +3,6 @@ from __future__ import absolute_import import weakref -from collections import Callable from . import saferef from celery.five import range @@ -95,7 +94,7 @@ class Signal(object): # pragma: no cover return _connect_signal - if args and isinstance(args[0], Callable): + if args and callable(args[0]): return _handle_options(*args[1:], **kwargs)(args[0]) return _handle_options(*args, **kwargs) diff --git a/awx/lib/site-packages/celery/utils/functional.py b/awx/lib/site-packages/celery/utils/functional.py index d2d597194c..be8aa14fe0 100644 --- a/awx/lib/site-packages/celery/utils/functional.py +++ b/awx/lib/site-packages/celery/utils/functional.py @@ -289,6 +289,9 @@ class _regen(UserList, list): def __reduce__(self): return list, (self.data, ) + def __length_hint__(self): + return self.__it.__length_hint__() + @cached_property def data(self): return list(self.__it) diff --git a/awx/lib/site-packages/celery/utils/log.py b/awx/lib/site-packages/celery/utils/log.py index 80b25476d9..e20a9503bb 100644 --- a/awx/lib/site-packages/celery/utils/log.py +++ b/awx/lib/site-packages/celery/utils/log.py @@ -245,10 +245,10 @@ class LoggingProxy(object): return False -def ensure_process_aware_logger(): +def ensure_process_aware_logger(force=False): """Make sure process name is recorded when loggers are used.""" global _process_aware - if not _process_aware: + if force or not _process_aware: logging._acquireLock() try: _process_aware = True @@ -257,12 +257,18 @@ def ensure_process_aware_logger(): return class ProcessAwareLogger(Logger): + _signal_safe = True _process_aware = True def makeRecord(self, *args, **kwds): record = Logger.makeRecord(self, *args, **kwds) record.processName = current_process()._name return record + + def log(self, *args, **kwargs): + if _in_sighandler: + return + return Logger.log(self, *args, **kwargs) logging.setLoggerClass(ProcessAwareLogger) finally: logging._releaseLock() @@ -275,24 +281,4 @@ def get_multiprocessing_logger(): def reset_multiprocessing_logger(): if mputil and hasattr(mputil, '_logger'): mputil._logger = None - - -def _patch_logger_class(): - """Make sure loggers don't log while in a signal handler.""" - - logging._acquireLock() - try: - OldLoggerClass = logging.getLoggerClass() - if not getattr(OldLoggerClass, '_signal_safe', False): - - class SigSafeLogger(OldLoggerClass): - _signal_safe = True - - def log(self, *args, **kwargs): - if _in_sighandler: - return - return OldLoggerClass.log(self, *args, **kwargs) - logging.setLoggerClass(SigSafeLogger) - finally: - logging._releaseLock() -_patch_logger_class() +ensure_process_aware_logger() diff --git a/awx/lib/site-packages/celery/utils/term.py b/awx/lib/site-packages/celery/utils/term.py index cec2ab25f6..f6f08d44cb 100644 --- a/awx/lib/site-packages/celery/utils/term.py +++ b/awx/lib/site-packages/celery/utils/term.py @@ -64,24 +64,24 @@ class colored(object): except AttributeError: B = string(b) - return safe_str(safe_str(A) + safe_str(B)) + return ''.join((string(A), string(B))) def no_color(self): if self.s: - return safe_str(reduce(self._fold_no_color, self.s)) + return string(reduce(self._fold_no_color, self.s)) return '' def embed(self): prefix = '' if self.enabled: prefix = self.op - return safe_str(prefix) + safe_str(reduce(self._add, self.s)) + return ''.join((string(prefix), string(reduce(self._add, self.s)))) def __unicode__(self): suffix = '' if self.enabled: suffix = RESET_SEQ - return safe_str(self.embed() + safe_str(suffix)) + return string(''.join((self.embed(), string(suffix)))) def __str__(self): return safe_str(self.__unicode__()) diff --git a/awx/lib/site-packages/celery/utils/timeutils.py b/awx/lib/site-packages/celery/utils/timeutils.py index adfac3bc37..785b86f31d 100644 --- a/awx/lib/site-packages/celery/utils/timeutils.py +++ b/awx/lib/site-packages/celery/utils/timeutils.py @@ -335,7 +335,7 @@ class ffwd(object): def utcoffset(): if _time.daylight: - return (__timezone__ + __altzone__) // 3600 + return __altzone__ // 3600 return __timezone__ // 3600 diff --git a/awx/lib/site-packages/celery/worker/__init__.py b/awx/lib/site-packages/celery/worker/__init__.py index f34f986b01..44da42bc9c 100644 --- a/awx/lib/site-packages/celery/worker/__init__.py +++ b/awx/lib/site-packages/celery/worker/__init__.py @@ -12,7 +12,6 @@ from __future__ import absolute_import import os -import socket import sys import traceback try: @@ -33,14 +32,18 @@ from celery.exceptions import ( ImproperlyConfigured, SystemTerminate, TaskRevokedError, ) from celery.five import string_t, values -from celery.utils import nodename, nodesplit, worker_direct +from celery.utils import default_nodename, worker_direct from celery.utils.imports import reload_from_cwd from celery.utils.log import mlevel, worker_logger as logger +from celery.utils.threads import default_socket_timeout from . import state __all__ = ['WorkController', 'default_nodename'] +#: Default socket timeout at shutdown. +SHUTDOWN_SOCKET_TIMEOUT = 5.0 + SELECT_UNKNOWN_QUEUE = """\ Trying to select queue subset of {0!r}, but queue {1} is not defined in the CELERY_QUEUES setting. @@ -61,11 +64,6 @@ def str_to_list(s): return s -def default_nodename(hostname): - name, host = nodesplit(hostname or '') - return nodename(name or 'celery', host or socket.gethostname()) - - class WorkController(object): """Unmanaged worker instance.""" app = None @@ -215,7 +213,10 @@ class WorkController(object): self.stop() def register_with_event_loop(self, hub): - self.blueprint.send_all(self, 'register_with_event_loop', args=(hub, )) + self.blueprint.send_all( + self, 'register_with_event_loop', args=(hub, ), + description='hub.register', + ) def _process_task_sem(self, req): return self._quick_acquire(self._process_task, req) @@ -261,8 +262,9 @@ class WorkController(object): # if blueprint does not exist it means that we had an # error before the bootsteps could be initialized. if self.blueprint is not None: - self.blueprint.stop(self, terminate=not warm) - self.blueprint.join() + with default_socket_timeout(SHUTDOWN_SOCKET_TIMEOUT): # Issue 975 + self.blueprint.stop(self, terminate=not warm) + self.blueprint.join() def reload(self, modules=None, reload=False, reloader=None): modules = self.app.loader.task_modules if modules is None else modules @@ -275,6 +277,10 @@ class WorkController(object): elif reload: logger.debug('reloading module %s', module) reload_from_cwd(sys.modules[module], reloader) + + if self.consumer: + self.consumer.update_strategies() + self.consumer.reset_rate_limits() self.pool.restart() def info(self): diff --git a/awx/lib/site-packages/celery/worker/autoreload.py b/awx/lib/site-packages/celery/worker/autoreload.py index c5483ee350..8ade32fb2d 100644 --- a/awx/lib/site-packages/celery/worker/autoreload.py +++ b/awx/lib/site-packages/celery/worker/autoreload.py @@ -57,9 +57,8 @@ class WorkerComponent(bootsteps.StartStopStep): return w.autoreloader if not w.use_eventloop else None def register_with_event_loop(self, w, hub): - if hasattr(select, 'kqueue'): - w.autoreloader.register_with_event_loop(hub) - hub.on_close.add(w.autoreloader.on_event_loop_close) + w.autoreloader.register_with_event_loop(hub) + hub.on_close.add(w.autoreloader.on_event_loop_close) def file_hash(filename, algorithm='md5'): @@ -90,6 +89,9 @@ class BaseMonitor(object): if self._on_change: return self._on_change(modified) + def on_event_loop_close(self, hub): + pass + class StatMonitor(BaseMonitor): """File change monitor based on the ``stat`` system call.""" @@ -100,13 +102,20 @@ class StatMonitor(BaseMonitor): def _maybe_modified(self, f, mt): return mt is not None and self.modify_times[f] != mt + def register_with_event_loop(self, hub): + hub.call_repeatedly(2.0, self.find_changes) + + def find_changes(self): + maybe_modified = self._maybe_modified + modified = dict((f, mt) for f, mt in self._mtimes() + if maybe_modified(f, mt)) + if modified: + self.on_change(modified) + self.modify_times.update(modified) + def start(self): while not self.shutdown_event.is_set(): - modified = dict((f, mt) for f, mt in self._mtimes() - if self._maybe_modified(f, mt)) - if modified: - self.on_change(modified) - self.modify_times.update(modified) + self.find_changes() time.sleep(self.interval) @staticmethod @@ -126,11 +135,14 @@ class KQueueMonitor(BaseMonitor): self.fdmap = {} def register_with_event_loop(self, hub): - self.add_events(hub.poller) - hub.poller.on_file_change = self.handle_event + if eventio.kqueue is not None: + self._kq = eventio._kqueue() + self.add_events(self._kq) + self._kq.on_file_change = self.handle_event + hub.add_reader(self._kq._kqueue, self._kq.poll, 0) def on_event_loop_close(self, hub): - self.close(hub.poller) + self.close(self._kq) def add_events(self, poller): for f in self.filemap: @@ -172,14 +184,28 @@ class InotifyMonitor(_ProcessEvent): self._wm = None self._notifier = None + def register_with_event_loop(self, hub): + self.create_notifier() + hub.add_reader(self._wm.get_fd(), self.on_readable) + + def on_event_loop_close(self, hub): + pass + + def on_readable(self): + self._notifier.read_events() + self._notifier.process_events() + + def create_notifier(self): + self._wm = pyinotify.WatchManager() + self._notifier = pyinotify.Notifier(self._wm, self) + add_watch = self._wm.add_watch + flags = pyinotify.IN_MODIFY | pyinotify.IN_ATTRIB + for m in self._modules: + add_watch(m, flags) + def start(self): try: - self._wm = pyinotify.WatchManager() - self._notifier = pyinotify.Notifier(self._wm, self) - add_watch = self._wm.add_watch - flags = pyinotify.IN_MODIFY | pyinotify.IN_ATTRIB - for m in self._modules: - add_watch(m, flags) + self.create_notifier() self._notifier.loop() finally: if self._wm: @@ -201,9 +227,9 @@ class InotifyMonitor(_ProcessEvent): def default_implementation(): - if hasattr(select, 'kqueue'): + if hasattr(select, 'kqueue') and eventio.kqueue is not None: return 'kqueue' - if sys.platform.startswith('linux') and pyinotify: + elif sys.platform.startswith('linux') and pyinotify: return 'inotify' else: return 'stat' diff --git a/awx/lib/site-packages/celery/worker/components.py b/awx/lib/site-packages/celery/worker/components.py index be355f0a46..d23a3b6b84 100644 --- a/awx/lib/site-packages/celery/worker/components.py +++ b/awx/lib/site-packages/celery/worker/components.py @@ -86,7 +86,7 @@ class Hub(bootsteps.StartStopStep): def _patch_thread_primitives(self, w): # make clock use dummy lock - w.app.clock.lock = DummyLock() + w.app.clock.mutex = DummyLock() # multiprocessing's ApplyResult uses this lock. try: from billiard import pool @@ -179,7 +179,7 @@ class Pool(bootsteps.StartStopStep): return pool def info(self, w): - return {'pool': w.pool.info} + return {'pool': w.pool.info if w.pool else 'N/A'} def register_with_event_loop(self, w, hub): w.pool.register_with_event_loop(hub) diff --git a/awx/lib/site-packages/celery/worker/consumer.py b/awx/lib/site-packages/celery/worker/consumer.py index 853b44ae45..3f156faae9 100644 --- a/awx/lib/site-packages/celery/worker/consumer.py +++ b/awx/lib/site-packages/celery/worker/consumer.py @@ -120,7 +120,7 @@ MINGLE_GET_FIELDS = itemgetter('clock', 'revoked') def dump_body(m, body): if isinstance(body, buffer_t): - body = bytes_t(buffer) + body = bytes_t(body) return '{0} ({1}b)'.format(truncate(safe_repr(body), 1024), len(m.body)) @@ -193,13 +193,12 @@ class Consumer(object): self.task_buckets = defaultdict(lambda: None) self.reset_rate_limits() - if hub: + self.hub = hub + if self.hub: self.amqheartbeat = amqheartbeat if self.amqheartbeat is None: self.amqheartbeat = self.app.conf.BROKER_HEARTBEAT - self.hub = hub else: - self.hub = None self.amqheartbeat = 0 if not hasattr(self, 'loop'): @@ -288,7 +287,10 @@ class Consumer(object): blueprint.restart(self) def register_with_event_loop(self, hub): - self.blueprint.send_all(self, 'register_with_event_loop', args=(hub, )) + self.blueprint.send_all( + self, 'register_with_event_loop', args=(hub, ), + description='Hub.register', + ) def shutdown(self): self.in_shutdown = True @@ -387,9 +389,10 @@ class Consumer(object): if not cset.consuming_from(queue): cset.add_queue(q) cset.consume() - info('Started consuming from %r', queue) + info('Started consuming from %s', queue) def cancel_task_queue(self, queue): + info('Cancelling queue %s', queue) self.app.amqp.queues.deselect(queue) self.task_consumer.cancel_by_queue(queue) @@ -472,10 +475,11 @@ class Connection(bootsteps.StartStopStep): if connection: ignore_errors(connection, connection.close) - def info(self, c): - info = c.connection.info() - info.pop('password', None) # don't send password. - return {'broker': info} + def info(self, c, params='N/A'): + if c.connection: + params = c.connection.info() + params.pop('password', None) # don't send password. + return {'broker': params} class Events(bootsteps.StartStopStep): @@ -488,7 +492,7 @@ class Events(bootsteps.StartStopStep): def start(self, c): # flush events sent while connection was down. - prev = c.event_dispatcher + prev = self._close(c) dis = c.event_dispatcher = c.app.events.Dispatcher( c.connect(), hostname=c.hostname, enabled=self.send_events, groups=self.groups, @@ -498,16 +502,23 @@ class Events(bootsteps.StartStopStep): dis.flush() def stop(self, c): + pass + + def _close(self, c): if c.event_dispatcher: + dispatcher = c.event_dispatcher # remember changes from remote control commands: - self.groups = c.event_dispatcher.groups + self.groups = dispatcher.groups # close custom connection - if c.event_dispatcher.connection: - ignore_errors(c, c.event_dispatcher.connection.close) - ignore_errors(c, c.event_dispatcher.close) + if dispatcher.connection: + ignore_errors(c, dispatcher.connection.close) + ignore_errors(c, dispatcher.close) c.event_dispatcher = None - shutdown = stop + return dispatcher + + def shutdown(self, c): + self._close(c) class Heart(bootsteps.StartStopStep): @@ -526,20 +537,6 @@ class Heart(bootsteps.StartStopStep): shutdown = stop -class Control(bootsteps.StartStopStep): - requires = (Events, ) - - def __init__(self, c, **kwargs): - self.is_green = c.pool is not None and c.pool.is_green - self.box = (pidbox.gPidbox if self.is_green else pidbox.Pidbox)(c) - self.start = self.box.start - self.stop = self.box.stop - self.shutdown = self.box.shutdown - - def include_if(self, c): - return c.app.conf.CELERY_ENABLE_REMOTE_CONTROL - - class Tasks(bootsteps.StartStopStep): requires = (Events, ) @@ -567,7 +564,7 @@ class Tasks(bootsteps.StartStopStep): c.task_consumer = None def info(self, c): - return {'prefetch_count': c.qos.value} + return {'prefetch_count': c.qos.value if c.qos else 'N/A'} class Agent(bootsteps.StartStopStep): @@ -582,15 +579,64 @@ class Agent(bootsteps.StartStopStep): return agent +class Mingle(bootsteps.StartStopStep): + label = 'Mingle' + requires = (Events, ) + compatible_transports = set(['amqp', 'redis']) + + def __init__(self, c, without_mingle=False, **kwargs): + self.enabled = not without_mingle and self.compatible_transport(c.app) + + def compatible_transport(self, app): + with app.connection() as conn: + return conn.transport.driver_type in self.compatible_transports + + def start(self, c): + info('mingle: searching for neighbors') + I = c.app.control.inspect(timeout=1.0, connection=c.connection) + replies = I.hello(c.hostname, revoked._data) or {} + replies.pop(c.hostname, None) + if replies: + info('mingle: sync with %s nodes', + len([reply for reply, value in items(replies) if value])) + for reply in values(replies): + if reply: + try: + other_clock, other_revoked = MINGLE_GET_FIELDS(reply) + except KeyError: # reply from pre-3.1 worker + pass + else: + c.app.clock.adjust(other_clock) + revoked.update(other_revoked) + info('mingle: sync complete') + else: + info('mingle: all alone') + + +class Control(bootsteps.StartStopStep): + requires = (Mingle, ) + + def __init__(self, c, **kwargs): + self.is_green = c.pool is not None and c.pool.is_green + self.box = (pidbox.gPidbox if self.is_green else pidbox.Pidbox)(c) + self.start = self.box.start + self.stop = self.box.stop + self.shutdown = self.box.shutdown + + def include_if(self, c): + return c.app.conf.CELERY_ENABLE_REMOTE_CONTROL + + class Gossip(bootsteps.ConsumerStep): label = 'Gossip' - requires = (Events, ) + requires = (Mingle, ) _cons_stamp_fields = itemgetter( 'id', 'clock', 'hostname', 'pid', 'topic', 'action', 'cver', ) + compatible_transports = set(['amqp', 'redis']) def __init__(self, c, without_gossip=False, interval=5.0, **kwargs): - self.enabled = not without_gossip + self.enabled = not without_gossip and self.compatible_transport(c.app) self.app = c.app c.gossip = self self.Receiver = c.app.events.Receiver @@ -598,12 +644,18 @@ class Gossip(bootsteps.ConsumerStep): self.full_hostname = '.'.join([self.hostname, str(c.pid)]) self.timer = c.timer - self.state = c.app.events.State() + if self.enabled: + self.state = c.app.events.State( + on_node_join=self.on_node_join, + on_node_leave=self.on_node_leave, + ) + if c.hub: + c._mutex = DummyLock() + self.update_state = self.state.event self.interval = interval self._tref = None self.consensus_requests = defaultdict(list) self.consensus_replies = {} - self.update_state = self.state.worker_event self.event_handlers = { 'worker.elect': self.on_elect, 'worker.elect.ack': self.on_elect_ack, @@ -614,6 +666,10 @@ class Gossip(bootsteps.ConsumerStep): 'task': self.call_task } + def compatible_transport(self, app): + with app.connection() as conn: + return conn.transport.driver_type in self.compatible_transports + def election(self, id, topic, action=None): self.consensus_replies[id] = [] self.dispatcher.send( @@ -670,13 +726,13 @@ class Gossip(bootsteps.ConsumerStep): self.consensus_replies.pop(id, None) def on_node_join(self, worker): - info('%s joined the party', worker.hostname) + debug('%s joined the party', worker.hostname) def on_node_leave(self, worker): - info('%s left', worker.hostname) + debug('%s left', worker.hostname) def on_node_lost(self, worker): - warn('%s went missing!', worker.hostname) + info('missed heartbeat from %s', worker.hostname) def register_timer(self): if self._tref is not None: @@ -716,47 +772,11 @@ class Gossip(bootsteps.ConsumerStep): message.payload['hostname']) if hostname != self.hostname: type, event = prepare(message.payload) - group, _, subject = type.partition('-') - worker, created = self.update_state(subject, event) - if subject == 'offline': - try: - self.on_node_leave(worker) - finally: - self.state.workers.pop(worker.hostname, None) - elif created or subject == 'online': - self.on_node_join(worker) + obj, subject = self.update_state(event) else: self.clock.forward() -class Mingle(bootsteps.StartStopStep): - label = 'Mingle' - requires = (Gossip, ) - - def __init__(self, c, without_mingle=False, **kwargs): - self.enabled = not without_mingle - - def start(self, c): - info('mingle: searching for neighbors') - I = c.app.control.inspect(timeout=1.0, connection=c.connection) - replies = I.hello(c.hostname, revoked._data) or {} - replies.pop(c.hostname, None) - if replies: - info('mingle: hello %s! sync with me', - ', '.join(reply for reply, value in items(replies) if value)) - for reply in values(replies): - if reply: - try: - other_clock, other_revoked = MINGLE_GET_FIELDS(reply) - except KeyError: # reply from pre-3.1 worker - pass - else: - c.app.clock.adjust(other_clock) - revoked.update(other_revoked) - else: - info('mingle: all alone') - - class Evloop(bootsteps.StartStopStep): label = 'event loop' last = True diff --git a/awx/lib/site-packages/celery/worker/control.py b/awx/lib/site-packages/celery/worker/control.py index c69254b79e..a1502525fe 100644 --- a/awx/lib/site-packages/celery/worker/control.py +++ b/awx/lib/site-packages/celery/worker/control.py @@ -8,11 +8,12 @@ """ from __future__ import absolute_import +import io import tempfile from kombu.utils.encoding import safe_repr -from celery.five import UserDict, items, StringIO +from celery.five import UserDict, items from celery.platforms import signals as _signals from celery.utils import timeutils from celery.utils.functional import maybe_list @@ -247,7 +248,7 @@ def memsample(state, **kwargs): # pragma: no cover @Panel.register def memdump(state, samples=10, **kwargs): # pragma: no cover from celery.utils.debug import memdump - out = StringIO() + out = io.StringIO() memdump(file=out) return out.getvalue() @@ -355,8 +356,10 @@ def cancel_consumer(state, queue=None, **_): @Panel.register def active_queues(state): """Return information about the queues a worker consumes from.""" - return [dict(queue.as_dict(recurse=True)) - for queue in state.consumer.task_consumer.queues] + if state.consumer.task_consumer: + return [dict(queue.as_dict(recurse=True)) + for queue in state.consumer.task_consumer.queues] + return [] def _wanted_config_key(key): @@ -372,4 +375,5 @@ def dump_conf(state, with_defaults=False, **kwargs): @Panel.register def election(state, id, topic, action=None, **kwargs): - state.consumer.gossip.election(id, topic, action) + if state.consumer.gossip: + state.consumer.gossip.election(id, topic, action) diff --git a/awx/lib/site-packages/celery/worker/heartbeat.py b/awx/lib/site-packages/celery/worker/heartbeat.py index d945239b12..297c6cad2c 100644 --- a/awx/lib/site-packages/celery/worker/heartbeat.py +++ b/awx/lib/site-packages/celery/worker/heartbeat.py @@ -9,10 +9,9 @@ """ from __future__ import absolute_import -from celery.five import values from celery.utils.sysinfo import load_average -from .state import SOFTWARE_INFO, active_requests, total_count +from .state import SOFTWARE_INFO, active_requests, all_total_count __all__ = ['Heart'] @@ -40,7 +39,7 @@ class Heart(object): def _send(self, event): return self.eventer.send(event, freq=self.interval, active=len(active_requests), - processed=sum(values(total_count)), + processed=all_total_count[0], loadavg=load_average(), **SOFTWARE_INFO) diff --git a/awx/lib/site-packages/celery/worker/job.py b/awx/lib/site-packages/celery/worker/job.py index f324ab3359..75c4a193e7 100644 --- a/awx/lib/site-packages/celery/worker/job.py +++ b/awx/lib/site-packages/celery/worker/job.py @@ -27,7 +27,7 @@ from celery.exceptions import ( SoftTimeLimitExceeded, TimeLimitExceeded, WorkerLostError, Terminated, Retry, Reject, ) -from celery.five import items, monotonic, string_t +from celery.five import items, monotonic, string, string_t from celery.platforms import signals as _signals from celery.utils import fun_takes_kwargs from celery.utils.functional import noop @@ -48,6 +48,9 @@ debug, info, warn, error = (logger.debug, logger.info, _does_info = False _does_debug = False +#: Max length of result representation +RESULT_MAXLEN = 128 + def __optimize__(): # this is also called by celery.app.trace.setup_worker_optimizations @@ -101,16 +104,16 @@ class Request(object): #: Format string used to log task failure. error_msg = """\ - Task %(name)s[%(id)s] raised exception: %(exc)s + Task %(name)s[%(id)s] %(description)s: %(exc)s """ #: Format string used to log internal error. internal_error_msg = """\ - Task %(name)s[%(id)s] INTERNAL ERROR: %(exc)s + Task %(name)s[%(id)s] %(description)s: %(exc)s """ ignored_msg = """\ - Task %(name)s[%(id)s] ignored + Task %(name)s[%(id)s] %(description)s """ rejected_msg = """\ @@ -427,7 +430,8 @@ class Request(object): self.id, exc, request=self, ) elif isinstance(exc, Terminated): - self._announce_revoked('terminated', True, str(exc), False) + self._announce_revoked( + 'terminated', True, string(exc), False) send_failed_event = False # already sent revoked event # (acks_late) acknowledge after result stored. if self.task.acks_late: @@ -436,17 +440,23 @@ class Request(object): def _log_error(self, einfo, send_failed_event=True): einfo.exception = get_pickled_exception(einfo.exception) + eobj = einfo.exception exception, traceback, exc_info, internal, sargs, skwargs = ( - safe_repr(einfo.exception), + safe_repr(eobj), safe_str(einfo.traceback), einfo.exc_info, einfo.internal, safe_repr(self.args), safe_repr(self.kwargs), ) + task = self.task + if task.throws and isinstance(eobj, task.throws): + severity, exc_info = logging.INFO, None + description = 'raised expected' + else: + severity = logging.ERROR + description = 'raised unexpected' format = self.error_msg - description = 'raised exception' - severity = logging.ERROR if send_failed_event: self.send_event( 'task-failed', exception=exception, traceback=traceback, @@ -492,7 +502,7 @@ class Request(object): 'hostname': self.hostname, 'internal': internal}}) - self.task.send_error_email(context, einfo.exception) + task.send_error_email(context, einfo.exception) def acknowledge(self): """Acknowledge task.""" @@ -505,7 +515,7 @@ class Request(object): self.on_reject(logger, self.connection_errors, requeue) self.acknowledged = True - def repr_result(self, result, maxlen=46): + def repr_result(self, result, maxlen=RESULT_MAXLEN): # 46 is the length needed to fit # 'the quick brown fox jumps over the lazy dog' :) if not isinstance(result, string_t): diff --git a/awx/lib/site-packages/celery/worker/state.py b/awx/lib/site-packages/celery/worker/state.py index 6642ecce53..68aac9df5a 100644 --- a/awx/lib/site-packages/celery/worker/state.py +++ b/awx/lib/site-packages/celery/worker/state.py @@ -51,6 +51,9 @@ active_requests = set() #: count of tasks accepted by the worker, sorted by type. total_count = Counter() +#: count of all tasks accepted by the worker +all_total_count = [0] + #: the list of currently revoked tasks. Persistent if statedb set. revoked = LimitedSet(maxlen=REVOKES_MAX, expires=REVOKE_EXPIRES) @@ -68,10 +71,11 @@ def maybe_shutdown(): raise SystemTerminate() -def task_accepted(request): +def task_accepted(request, _all_total_count=all_total_count): """Updates global state when a task has been accepted.""" active_requests.add(request) total_count[request.name] += 1 + all_total_count[0] += 1 def task_ready(request): diff --git a/awx/lib/site-packages/django_auth_ldap/__init__.py b/awx/lib/site-packages/django_auth_ldap/__init__.py index 38711b9b4b..7e7b1c57f1 100644 --- a/awx/lib/site-packages/django_auth_ldap/__init__.py +++ b/awx/lib/site-packages/django_auth_ldap/__init__.py @@ -1,2 +1,2 @@ -version = (1, 1, 6) -version_string = '1.1.6' +version = (1, 1, 7) +version_string = '.'.join(map(str, version)) diff --git a/awx/lib/site-packages/django_auth_ldap/backend.py b/awx/lib/site-packages/django_auth_ldap/backend.py index db6fe2ea8b..e0bcc64e6d 100644 --- a/awx/lib/site-packages/django_auth_ldap/backend.py +++ b/awx/lib/site-packages/django_auth_ldap/backend.py @@ -703,7 +703,7 @@ class _LDAPUser(object): if callable(uri): uri = uri() - self._connection = ldap.initialize(uri) + self._connection = self.backend.ldap.initialize(uri) for opt, value in self.settings.CONNECTION_OPTIONS.iteritems(): self._connection.set_option(opt, value) diff --git a/awx/lib/site-packages/jsonfield/VERSION b/awx/lib/site-packages/jsonfield/VERSION index 8225a4ba4f..583b27acca 100644 --- a/awx/lib/site-packages/jsonfield/VERSION +++ b/awx/lib/site-packages/jsonfield/VERSION @@ -1 +1 @@ -0.9.11 +0.9.12 diff --git a/awx/lib/site-packages/jsonfield/fields.py b/awx/lib/site-packages/jsonfield/fields.py index db3024f7aa..f6aab486c3 100644 --- a/awx/lib/site-packages/jsonfield/fields.py +++ b/awx/lib/site-packages/jsonfield/fields.py @@ -6,6 +6,7 @@ from django.conf import settings from django.db import models, DatabaseError, transaction from django.utils.translation import ugettext_lazy as _ from django.utils import six +from django.core.cache import cache from decimal import Decimal import datetime @@ -13,6 +14,12 @@ import datetime from .utils import default from .widgets import JSONWidget from .forms import JSONFormField +from jsonfield import __version__ + +DB_TYPE_CACHE_KEY = ( + 'django-jsonfield:db-type:%s' % __version__ + + '%(ENGINE)s:%(HOST)s:%(PORT)s:%(NAME)s' +) class JSONField(six.with_metaclass(models.SubfieldBase, models.Field)): """ @@ -62,17 +69,23 @@ class JSONField(six.with_metaclass(models.SubfieldBase, models.Field)): return 'TextField' def db_type(self, connection): - # Test to see if we support JSON querying. - # (Protip: nothing does, at this stage). - cursor = connection.cursor() - try: - sid = transaction.savepoint(using=connection.alias) - cursor.execute('SELECT \'{}\'::json = \'{}\'::json;') - except DatabaseError: - transaction.savepoint_rollback(sid, using=connection.alias) - return 'text' - else: - return 'json' + cache_key = DB_TYPE_CACHE_KEY % connection.settings_dict + db_type = cache.get(cache_key) + + if not db_type: + # Test to see if we support JSON querying. + cursor = connection.cursor() + try: + sid = transaction.savepoint(using=connection.alias) + cursor.execute('SELECT \'{}\'::json = \'{}\'::json;') + except DatabaseError: + transaction.savepoint_rollback(sid, using=connection.alias) + db_type = 'text' + else: + db_type = 'json' + cache.set(cache_key, db_type) + + return db_type def to_python(self, value): if isinstance(value, six.string_types): diff --git a/awx/lib/site-packages/jsonfield/forms.py b/awx/lib/site-packages/jsonfield/forms.py index 4b7025f8f6..60d17fe49b 100644 --- a/awx/lib/site-packages/jsonfield/forms.py +++ b/awx/lib/site-packages/jsonfield/forms.py @@ -7,25 +7,15 @@ from .widgets import JSONWidget class JSONFormField(forms.CharField): + empty_values = [None, ''] + def __init__(self, *args, **kwargs): if 'widget' not in kwargs: kwargs['widget'] = JSONWidget super(JSONFormField, self).__init__(*args, **kwargs) - def clean(self, value): - """ - The default is to have a TextField, and we will decode the string - that comes back from this. However, another use of this field is - to store a list of values, and use these in a MultipleSelect - widget. So, if we have an object that isn't a string, then for now - we will assume that is where it has come from. - """ - value = super(JSONFormField, self).clean(value) - - if not value: - return value - - if isinstance(value, six.string_types): + def to_python(self, value): + if isinstance(value, six.string_types) and value: try: return json.loads(value) except Exception as exc: @@ -34,3 +24,8 @@ class JSONFormField(forms.CharField): ) else: return value + + def validate(self, value): + # This is required in older django versions. + if value in self.empty_values and self.required: + raise forms.ValidationError(self.error_messages['required'], code='required') \ No newline at end of file diff --git a/awx/lib/site-packages/jsonfield/templatetags/jsonify.py b/awx/lib/site-packages/jsonfield/templatetags/jsonify.py index efc3e1b73d..da20e980f0 100644 --- a/awx/lib/site-packages/jsonfield/templatetags/jsonify.py +++ b/awx/lib/site-packages/jsonfield/templatetags/jsonify.py @@ -8,6 +8,7 @@ register = template.Library() @register.filter def jsonify(value): + # If we have a queryset, then convert it into a list. if getattr(value, 'all', False): value = list(value) return mark_safe(json.dumps(value, cls=TZAwareJSONEncoder)) diff --git a/awx/lib/site-packages/jsonfield/tests/test_fields.py b/awx/lib/site-packages/jsonfield/tests/test_fields.py index 8d80c4ac00..37b521ecbb 100644 --- a/awx/lib/site-packages/jsonfield/tests/test_fields.py +++ b/awx/lib/site-packages/jsonfield/tests/test_fields.py @@ -66,7 +66,7 @@ class JSONFieldTest(DjangoTestCase): def test_formfield_null_and_blank_clean_none(self): field = JSONField("test", null=True, blank=True) formfield = field.formfield() - self.assertEquals(formfield.clean(value=None), '') + self.assertEquals(formfield.clean(value=None), None) def test_formfield_blank_clean_blank(self): field = JSONField("test", null=False, blank=True) @@ -74,9 +74,11 @@ class JSONFieldTest(DjangoTestCase): self.assertEquals(formfield.clean(value=''), '') def test_formfield_blank_clean_none(self): + # Hmm, I'm not sure how to do this. What happens if we pass a + # None to a field that has null=False? field = JSONField("test", null=False, blank=True) formfield = field.formfield() - self.assertEquals(formfield.clean(value=None), '') + self.assertEquals(formfield.clean(value=None), None) def test_default_value(self): obj = JSONFieldWithDefaultTestModel.objects.create() @@ -142,4 +144,10 @@ class JSONFieldTest(DjangoTestCase): def test_invalid_json_default(self): with self.assertRaises(ValueError): - field = JSONField('test', default='{"foo"}') \ No newline at end of file + field = JSONField('test', default='{"foo"}') + +class SavingModelsTest(DjangoTestCase): + def test_saving_null(self): + obj = BlankJSONFieldTestModel.objects.create(blank_json='', null_json=None) + self.assertEquals('', obj.blank_json) + self.assertEquals(None, obj.null_json) \ No newline at end of file diff --git a/awx/lib/site-packages/jsonfield/tests/test_forms.py b/awx/lib/site-packages/jsonfield/tests/test_forms.py index 3e057bda86..3e7d53b40b 100644 --- a/awx/lib/site-packages/jsonfield/tests/test_forms.py +++ b/awx/lib/site-packages/jsonfield/tests/test_forms.py @@ -1,22 +1,56 @@ from django.test import TestCase as DjangoTestCase from django.utils import unittest +from django.forms import ValidationError from jsonfield.forms import JSONFormField from jsonfield.tests.jsonfield_test_app.forms import JSONTestForm, JSONTestModelForm class JSONFormFieldTest(DjangoTestCase): - def test_form_field_clean(self): + def test_form_field_clean_empty_object(self): field = JSONFormField(required=False) self.assertEquals({}, field.clean('{}')) + def test_form_field_clean_object(self): + field = JSONFormField(required=False) self.assertEquals( {'foo':'bar', 'baz':2}, field.clean('{"foo":"bar","baz":2}') ) - + + def test_form_field_clean_empty_array(self): + field = JSONFormField(required=False) self.assertEquals([],field.clean('[]')) + + def test_required_form_field_array(self): + field = JSONFormField(required=True) + self.assertEquals([], field.clean('[]')) + + def test_required_form_field_object(self): + field = JSONFormField(required=True) + self.assertEquals({}, field.clean('{}')) + + def test_required_form_field_empty(self): + field = JSONFormField(required=True) + with self.assertRaises(ValidationError): + field.clean('') + + def test_invalid_json(self): + field = JSONFormField(required=True) + + with self.assertRaises(ValidationError): + field.clean('{"foo"}') class JSONFormTest(DjangoTestCase): def test_form_clean(self): form = JSONTestForm({}) - self.assertFalse(form.is_valid()) \ No newline at end of file + self.assertFalse(form.is_valid()) + + +class JSONFormMultipleSelectFieldTest(DjangoTestCase): + def test_multiple_select_data(self): + form = JSONTestForm({'json_data': [u'SA', u'WA']}) + assert form.is_valid() + + self.assertEquals([u'SA', u'WA'], form.cleaned_data['json_data']) + + diff --git a/awx/lib/site-packages/jsonfield/widgets.py b/awx/lib/site-packages/jsonfield/widgets.py index 4a9e87e4a8..52d6116632 100644 --- a/awx/lib/site-packages/jsonfield/widgets.py +++ b/awx/lib/site-packages/jsonfield/widgets.py @@ -16,4 +16,3 @@ class JSONWidget(forms.Textarea): class JSONSelectWidget(forms.SelectMultiple): pass - diff --git a/awx/lib/site-packages/keyring/backends/SecretService.py b/awx/lib/site-packages/keyring/backends/SecretService.py index 8090f7094b..1fa97f5067 100644 --- a/awx/lib/site-packages/keyring/backends/SecretService.py +++ b/awx/lib/site-packages/keyring/backends/SecretService.py @@ -24,9 +24,10 @@ class Keyring(KeyringBackend): raise RuntimeError("SecretService required") try: bus = secretstorage.dbus_init() - secretstorage.Collection(bus) - except secretstorage.exceptions.SecretServiceNotAvailableException: - raise RuntimeError("Unable to get initialize SecretService") + list(secretstorage.get_all_collections(bus)) + except secretstorage.exceptions.SecretServiceNotAvailableException as e: + raise RuntimeError( + "Unable to initialize SecretService: %s" % e) return 5 def get_default_collection(self): diff --git a/awx/lib/site-packages/keyring/backends/kwallet.py b/awx/lib/site-packages/keyring/backends/kwallet.py index 19b3e7a056..b4e1e211ee 100644 --- a/awx/lib/site-packages/keyring/backends/kwallet.py +++ b/awx/lib/site-packages/keyring/backends/kwallet.py @@ -58,7 +58,13 @@ class Keyring(KeyringBackend): KWallet.__name__ if exc: raise RuntimeError("KDE libraries not available") - if 'KDE_SESSION_ID' not in os.environ: + # Infer if KDE environment is active based on environment vars. + # TODO: Does PyKDE provide a better indicator? + kde_session_keys = ( + 'KDE_SESSION_ID', # most environments + 'KDE_FULL_SESSION', # openSUSE + ) + if not set(os.environ).intersection(kde_session_keys): return 0 return 5 diff --git a/awx/lib/site-packages/keyring/tests/test_backend.py b/awx/lib/site-packages/keyring/tests/test_backend.py index 1efe42de6e..ffed807261 100644 --- a/awx/lib/site-packages/keyring/tests/test_backend.py +++ b/awx/lib/site-packages/keyring/tests/test_backend.py @@ -92,7 +92,7 @@ class BackendBasicTests(object): password = random_string(20, DIFFICULT_CHARS) service = random_string(20, DIFFICULT_CHARS) self.keyring.set_password(service, username1, password) - self.keyring.set_password(service, username2, password) + self.set_password(service, username2, password) self.keyring.delete_password(service, username1) self.assertEqual(self.keyring.get_password( service, username2), password) diff --git a/awx/lib/site-packages/kombu/__init__.py b/awx/lib/site-packages/kombu/__init__.py index 6f4c92fb58..f9aaa8aa10 100644 --- a/awx/lib/site-packages/kombu/__init__.py +++ b/awx/lib/site-packages/kombu/__init__.py @@ -1,8 +1,14 @@ """Messaging library for Python""" from __future__ import absolute_import -VERSION = (3, 0, 4) -__version__ = '.'.join(map(str, VERSION[0:3])) + ''.join(VERSION[3:]) +from collections import namedtuple + +version_info_t = namedtuple( + 'version_info_t', ('major', 'minor', 'micro', 'releaselevel', 'serial'), +) + +VERSION = version_info_t(3, 0, 8, '', '') +__version__ = '{0.major}.{0.minor}.{0.micro}{0.releaselevel}'.format(VERSION) __author__ = 'Ask Solem' __contact__ = 'ask@celeryproject.org' __homepage__ = 'http://kombu.readthedocs.org' diff --git a/awx/lib/site-packages/kombu/async/semaphore.py b/awx/lib/site-packages/kombu/async/semaphore.py index 631d9919a9..58b4ff72ec 100644 --- a/awx/lib/site-packages/kombu/async/semaphore.py +++ b/awx/lib/site-packages/kombu/async/semaphore.py @@ -21,15 +21,18 @@ class LaxBoundedSemaphore(object): Example: + >>> from future import print_statement as printf + # ^ ignore: just fooling stupid pyflakes + >>> x = LaxBoundedSemaphore(2) - >>> x.acquire(print, 'HELLO 1') + >>> x.acquire(printf, 'HELLO 1') HELLO 1 - >>> x.acquire(print, 'HELLO 2') + >>> x.acquire(printf, 'HELLO 2') HELLO 2 - >>> x.acquire(print, 'HELLO 3') + >>> x.acquire(printf, 'HELLO 3') >>> x._waiters # private, do not access directly [print, ('HELLO 3', )] @@ -94,7 +97,7 @@ class LaxBoundedSemaphore(object): def __repr__(self): return '<{0} at {1:#x} value:{2} waiting:{3}>'.format( - self.__class__.__name__, id(self), self.value, len(self.waiting), + self.__class__.__name__, id(self), self.value, len(self._waiting), ) diff --git a/awx/lib/site-packages/kombu/async/timer.py b/awx/lib/site-packages/kombu/async/timer.py index b4134bdfc0..4f95033201 100644 --- a/awx/lib/site-packages/kombu/async/timer.py +++ b/awx/lib/site-packages/kombu/async/timer.py @@ -74,7 +74,7 @@ class Entry(object): self.fun.__name__, self.args, self.kwargs) def __hash__(self): - return hash((self.fun, self.args, self.kwargs)) + return hash((self.fun, self.args)) if sys.version_info[0] == 3: # pragma: no cover diff --git a/awx/lib/site-packages/kombu/clocks.py b/awx/lib/site-packages/kombu/clocks.py index 612ddb49bb..a9862382df 100644 --- a/awx/lib/site-packages/kombu/clocks.py +++ b/awx/lib/site-packages/kombu/clocks.py @@ -107,8 +107,8 @@ class LamportClock(object): def adjust(self, other): with self.mutex: - self.value = max(self.value, other) + 1 - return self.value + value = self.value = max(self.value, other) + 1 + return value def forward(self): with self.mutex: diff --git a/awx/lib/site-packages/kombu/common.py b/awx/lib/site-packages/kombu/common.py index 37f242d20b..4c8f7b6d58 100644 --- a/awx/lib/site-packages/kombu/common.py +++ b/awx/lib/site-packages/kombu/common.py @@ -145,13 +145,14 @@ def eventloop(conn, limit=None, timeout=None, ignore_timeouts=False): ``eventloop`` is a generator:: - >>> from kombu.common import eventloop + from kombu.common import eventloop - >>> it = eventloop(connection, timeout=1, ignore_timeouts=True) - >>> next(it) # one event consumed, or timed out. + def run(connection): + it = eventloop(connection, timeout=1, ignore_timeouts=True) + next(it) # one event consumed, or timed out. - >>> for _ in eventloop(connection, timeout=1, ignore_timeouts=True): - ... pass # loop forever. + for _ in eventloop(connection, timeout=1, ignore_timeouts=True): + pass # loop forever. It also takes an optional limit parameter, and timeout errors are propagated by default:: @@ -235,14 +236,20 @@ def ignore_errors(conn, fun=None, *args, **kwargs): The first argument must be a connection object, or any other object with ``connection_error`` and ``channel_error`` attributes. - Can be used as a function:: + Can be used as a function: - >>> ignore_errors(conn, consumer.channel.close) + .. code-block:: python - or as a context manager:: + def example(connection): + ignore_errors(connection, consumer.channel.close) - >>> with ignore_errors(conn): - ... consumer.channel.close() + or as a context manager: + + .. code-block:: python + + def example(connection): + with ignore_errors(connection): + consumer.channel.close() .. note:: @@ -292,6 +299,8 @@ class QoS(object): .. code-block:: python + >>> from kombu import Consumer, Connection + >>> connection = Connection('amqp://') >>> consumer = Consumer(connection) >>> qos = QoS(consumer.qos, initial_prefetch_count=2) >>> qos.update() # set initial @@ -305,7 +314,7 @@ class QoS(object): >>> def in_some_other_thread(): ... qos.decrement_eventually() - >>> while some_loop: + >>> while 1: ... if qos.prev != qos.value: ... qos.update() # prefetch changed so update. @@ -317,7 +326,7 @@ class QoS(object): >>> def set_qos(prefetch_count): - ... some_object.change(prefetch=prefetch_count) + ... print('prefetch count now: %r' % (prefetch_count, )) >>> QoS(set_qos, 10) """ diff --git a/awx/lib/site-packages/kombu/connection.py b/awx/lib/site-packages/kombu/connection.py index bdfc38bc26..972dc58079 100644 --- a/awx/lib/site-packages/kombu/connection.py +++ b/awx/lib/site-packages/kombu/connection.py @@ -10,7 +10,6 @@ from __future__ import absolute_import import os import socket -from collections import Callable from contextlib import contextmanager from functools import partial from itertools import count, cycle @@ -100,6 +99,7 @@ class Connection(object): connection to be established, then force it by calling :meth:`connect`:: + >>> conn = Connection('amqp://') >>> conn.connect() and always remember to close the connection:: @@ -415,12 +415,17 @@ class Connection(object): This is an example ensuring a publish operation:: + >>> from kombu import Connection, Producer + >>> conn = Connection('amqp://') + >>> producer = Producer(conn) + >>> def errback(exc, interval): - ... print('Cannot publish message: {0!r}. ' - 'Retry in {1}s'.format(exc, interval)) + ... logger.error('Error: %r', exc, exc_info=1) + ... logger.info('Retry in %s seconds.', interval) + >>> publish = conn.ensure(producer, producer.publish, ... errback=errback, max_retries=3) - >>> publish(message, routing_key) + >>> publish({'hello': 'world'}, routing_key='dest') """ def _ensured(*args, **kwargs): @@ -604,6 +609,7 @@ class Connection(object): *Example usage*:: + >>> connection = Connection('amqp://') >>> pool = connection.Pool(2) >>> c1 = pool.acquire() >>> c2 = pool.acquire() @@ -631,6 +637,7 @@ class Connection(object): *Example usage*:: + >>> connection = Connection('amqp://') >>> pool = connection.ChannelPool(2) >>> c1 = pool.acquire() >>> c2 = pool.acquire() @@ -829,6 +836,7 @@ class Resource(object): def __init__(self, limit=None, preload=None): self.limit = limit self.preload = preload or 0 + self._closed = False self._resource = _LifoQueue() self._dirty = set() @@ -857,6 +865,8 @@ class Resource(object): and the limit has been exceeded. """ + if self._closed: + raise RuntimeError('Acquire on closed pool') if self.limit: while 1: try: @@ -926,6 +936,7 @@ class Resource(object): after fork (e.g. sockets/connections). """ + self._closed = True dirty = self._dirty resource = self._resource while 1: # - acquired @@ -1016,7 +1027,7 @@ class ConnectionPool(Resource): self._resource.put_nowait(conn) def prepare(self, resource): - if isinstance(resource, Callable): + if callable(resource): resource = resource() resource._debug('acquired') return resource @@ -1041,7 +1052,7 @@ class ChannelPool(Resource): i < self.preload and channel() or lazy(channel)) def prepare(self, channel): - if isinstance(channel, Callable): + if callable(channel): channel = channel() return channel diff --git a/awx/lib/site-packages/kombu/entity.py b/awx/lib/site-packages/kombu/entity.py index 254f2c621d..5bf1470b9c 100644 --- a/awx/lib/site-packages/kombu/entity.py +++ b/awx/lib/site-packages/kombu/entity.py @@ -661,11 +661,11 @@ class Queue(MaybeChannelBound): def __repr__(self): s = super(Queue, self).__repr__ if self.bindings: - return s('Queue {0.name!r} -> {bindings}'.format( + return s('Queue {0.name} -> {bindings}'.format( self, bindings=pretty_bindings(self.bindings), )) return s( - 'Queue {0.name!r} -> {0.exchange!r} -> {0.routing_key}'.format( + 'Queue {0.name} -> {0.exchange!r} -> {0.routing_key}'.format( self)) @property diff --git a/awx/lib/site-packages/kombu/exceptions.py b/awx/lib/site-packages/kombu/exceptions.py index 55dd3c2096..feb7e39da2 100644 --- a/awx/lib/site-packages/kombu/exceptions.py +++ b/awx/lib/site-packages/kombu/exceptions.py @@ -22,6 +22,20 @@ TimeoutError = socket.timeout class KombuError(Exception): """Common subclass for all Kombu exceptions.""" + pass + + +class SerializationError(KombuError): + """Failed to serialize/deserialize content.""" + + +class EncodeError(SerializationError): + """Cannot encode object.""" + pass + + +class DecodeError(SerializationError): + """Cannot decode object.""" class NotBoundError(KombuError): diff --git a/awx/lib/site-packages/kombu/five.py b/awx/lib/site-packages/kombu/five.py index 37633434ff..f2b5349f54 100644 --- a/awx/lib/site-packages/kombu/five.py +++ b/awx/lib/site-packages/kombu/five.py @@ -43,11 +43,10 @@ if sys.version_info < (3, 3): if SYSTEM == 'Darwin': import ctypes + from ctypes.util import find_library libSystem = ctypes.CDLL('libSystem.dylib') - CoreServices = ctypes.CDLL( - '/System/Library/Frameworks/CoreServices.framework/CoreServices', - use_errno=True, - ) + CoreServices = ctypes.CDLL(find_library('CoreServices'), + use_errno=True) mach_absolute_time = libSystem.mach_absolute_time mach_absolute_time.restype = ctypes.c_uint64 absolute_to_nanoseconds = CoreServices.AbsoluteToNanoseconds diff --git a/awx/lib/site-packages/kombu/pools.py b/awx/lib/site-packages/kombu/pools.py index b7804a62e9..4d075e6243 100644 --- a/awx/lib/site-packages/kombu/pools.py +++ b/awx/lib/site-packages/kombu/pools.py @@ -9,7 +9,6 @@ from __future__ import absolute_import import os -from collections import Callable from itertools import chain from .connection import Resource @@ -58,7 +57,7 @@ class ProducerPool(Resource): pass def prepare(self, p): - if isinstance(p, Callable): + if callable(p): p = p() if p._channel is None: conn = self._acquire_connection() diff --git a/awx/lib/site-packages/kombu/serialization.py b/awx/lib/site-packages/kombu/serialization.py index b726102b3e..5f71c0238c 100644 --- a/awx/lib/site-packages/kombu/serialization.py +++ b/awx/lib/site-packages/kombu/serialization.py @@ -18,9 +18,12 @@ except ImportError: # pragma: no cover cpickle = None # noqa from collections import namedtuple +from contextlib import contextmanager -from .exceptions import SerializerNotInstalled, ContentDisallowed -from .five import BytesIO, text_t +from .exceptions import ( + ContentDisallowed, DecodeError, EncodeError, SerializerNotInstalled +) +from .five import BytesIO, reraise, text_t from .utils import entrypoints from .utils.encoding import str_to_bytes, bytes_t @@ -44,6 +47,17 @@ pickle_protocol = int(os.environ.get('PICKLE_PROTOCOL', 2)) codec = namedtuple('codec', ('content_type', 'content_encoding', 'encoder')) +@contextmanager +def _reraise_errors(wrapper, + include=(Exception, ), exclude=(SerializerNotInstalled, )): + try: + yield + except exclude: + raise + except include as exc: + reraise(wrapper, wrapper(exc), sys.exc_info()[2]) + + def pickle_loads(s, load=pickle_load): # used to support buffer objects return load(BytesIO(s)) @@ -133,7 +147,8 @@ class SerializerRegistry(object): # For Unicode objects, force it into a string if not serializer and isinstance(data, text_t): - payload = data.encode('utf-8') + with _reraise_errors(EncodeError, exclude=()): + payload = data.encode('utf-8') return 'text/plain', 'utf-8', payload if serializer: @@ -144,7 +159,8 @@ class SerializerRegistry(object): content_type = self._default_content_type content_encoding = self._default_content_encoding - payload = encoder(data) + with _reraise_errors(EncodeError): + payload = encoder(data) return content_type, content_encoding, payload encode = dumps # XXX compat @@ -162,10 +178,12 @@ class SerializerRegistry(object): if data: decode = self._decoders.get(content_type) if decode: - return decode(data) + with _reraise_errors(DecodeError): + return decode(data) if content_encoding not in SKIP_DECODE and \ not isinstance(data, text_t): - return _decode(data, content_encoding) + with _reraise_errors(DecodeError): + return _decode(data, content_encoding) return data decode = loads # XXX compat @@ -278,7 +296,8 @@ def raw_encode(data): payload = data if isinstance(payload, text_t): content_encoding = 'utf-8' - payload = payload.encode(content_encoding) + with _reraise_errors(EncodeError, exclude=()): + payload = payload.encode(content_encoding) else: content_encoding = 'binary' return content_type, content_encoding, payload diff --git a/awx/lib/site-packages/kombu/tests/test_clocks.py b/awx/lib/site-packages/kombu/tests/test_clocks.py index 538ed0a5c0..fa39b6d1a7 100644 --- a/awx/lib/site-packages/kombu/tests/test_clocks.py +++ b/awx/lib/site-packages/kombu/tests/test_clocks.py @@ -70,6 +70,7 @@ class test_timetuple(Case): def test_order(self): t1 = time() + t2 = time() + 300 # windows clock not reliable a = timetuple(133, t1, 'A', 'obj') b = timetuple(140, t1, 'A', 'obj') self.assertTrue(a.__getnewargs__()) @@ -89,8 +90,8 @@ class test_timetuple(Case): NotImplemented, ) self.assertGreater( - timetuple(134, time(), 'A', 'obj'), - timetuple(133, time(), 'A', 'obj'), + timetuple(134, t2, 'A', 'obj'), + timetuple(133, t1, 'A', 'obj'), ) self.assertGreater( timetuple(134, t1, 'B', 'obj'), @@ -98,6 +99,6 @@ class test_timetuple(Case): ) self.assertGreater( - timetuple(None, time(), 'B', 'obj'), + timetuple(None, t2, 'B', 'obj'), timetuple(None, t1, 'A', 'obj'), ) diff --git a/awx/lib/site-packages/kombu/tests/test_serialization.py b/awx/lib/site-packages/kombu/tests/test_serialization.py index 8ce1a4258d..8c84d6d8c8 100644 --- a/awx/lib/site-packages/kombu/tests/test_serialization.py +++ b/awx/lib/site-packages/kombu/tests/test_serialization.py @@ -7,7 +7,7 @@ import sys from base64 import b64decode -from kombu.exceptions import ContentDisallowed +from kombu.exceptions import ContentDisallowed, EncodeError, DecodeError from kombu.five import text_t, bytes_t from kombu.serialization import ( registry, register, SerializerNotInstalled, @@ -186,6 +186,15 @@ class test_Serialization(Case): call('pickle'), call('yaml'), call('doomsday') ]) + def test_reraises_EncodeError(self): + with self.assertRaises(EncodeError): + dumps([object()], serializer='json') + + def test_reraises_DecodeError(self): + with self.assertRaises(DecodeError): + loads(object(), content_type='application/json', + content_encoding='utf-8') + def test_json_loads(self): self.assertEqual( py_data, diff --git a/awx/lib/site-packages/kombu/tests/transport/test_SQS.py b/awx/lib/site-packages/kombu/tests/transport/test_SQS.py new file mode 100644 index 0000000000..a655bca89c --- /dev/null +++ b/awx/lib/site-packages/kombu/tests/transport/test_SQS.py @@ -0,0 +1,293 @@ +"""Testing module for the kombu.transport.SQS package. + +NOTE: The SQSQueueMock and SQSConnectionMock classes originally come from +http://github.com/pcsforeducation/sqs-mock-python. They have been patched +slightly. +""" + +from __future__ import absolute_import + +from kombu import Connection +from kombu import messaging +from kombu import five +from kombu.tests.case import Case, SkipTest +import kombu + +try: + from kombu.transport import SQS +except ImportError: + # Boto must not be installed if the SQS transport fails to import, + # so we skip all unit tests. Set SQS to None here, and it will be + # checked during the setUp() phase later. + SQS = None + + +class SQSQueueMock(object): + + def __init__(self, name): + self.name = name + self.messages = [] + self._get_message_calls = 0 + + def clear(self, page_size=10, vtimeout=10): + empty, self.messages[:] = not self.messages, [] + return not empty + + def count(self, page_size=10, vtimeout=10): + return len(self.messages) + count_slow = count + + def delete(self): + self.messages[:] = [] + return True + + def delete_message(self, message): + try: + self.messages.remove(message) + except ValueError: + return False + return True + + def get_messages(self, num_messages=1, visibility_timeout=None, + attributes=None, *args, **kwargs): + self._get_message_calls += 1 + return self.messages[:num_messages] + + def read(self, visibility_timeout=None): + return self.messages.pop(0) + + def write(self, message): + self.messages.append(message) + return True + + +class SQSConnectionMock(object): + + def __init__(self): + self.queues = {} + + def get_queue(self, queue): + return self.queues.get(queue) + + def get_all_queues(self, prefix=""): + return self.queues.values() + + def delete_queue(self, queue, force_deletion=False): + q = self.get_queue(queue) + if q: + if q.count(): + return False + q.clear() + self.queues.pop(queue, None) + + def delete_message(self, queue, message): + return queue.delete_message(message) + + def create_queue(self, name, *args, **kwargs): + q = self.queues[name] = SQSQueueMock(name) + return q + + +class test_Channel(Case): + + def handleMessageCallback(self, message): + self.callback_message = message + + def setUp(self): + """Mock the back-end SQS classes""" + # Sanity check... if SQS is None, then it did not import and we + # cannot execute our tests. + if SQS is None: + raise SkipTest('Boto is not installed') + + SQS.Channel._queue_cache.clear() + + # Common variables used in the unit tests + self.queue_name = 'unittest' + + # Mock the sqs() method that returns an SQSConnection object and + # instead return an SQSConnectionMock() object. + self.sqs_conn_mock = SQSConnectionMock() + + def mock_sqs(): + return self.sqs_conn_mock + SQS.Channel.sqs = mock_sqs() + + # Set up a task exchange for passing tasks through the queue + self.exchange = kombu.Exchange('test_SQS', type='direct') + self.queue = kombu.Queue(self.queue_name, + self.exchange, + self.queue_name) + + # Mock up a test SQS Queue with the SQSQueueMock class (and always + # make sure its a clean empty queue) + self.sqs_queue_mock = SQSQueueMock(self.queue_name) + + # Now, create our Connection object with the SQS Transport and store + # the connection/channel objects as references for use in these tests. + self.connection = Connection(transport=SQS.Transport) + self.channel = self.connection.channel() + + self.queue(self.channel).declare() + self.producer = messaging.Producer(self.channel, + self.exchange, + routing_key=self.queue_name) + + # Lastly, make sure that we're set up to 'consume' this queue. + self.channel.basic_consume(self.queue_name, + no_ack=True, + callback=self.handleMessageCallback, + consumer_tag='unittest') + + def test_init(self): + """kombu.SQS.Channel instantiates correctly with mocked queues""" + self.assertIn(self.queue_name, self.channel._queue_cache) + + def test_new_queue(self): + queue_name = "new_unittest_queue" + self.channel._new_queue(queue_name) + self.assertIn(queue_name, self.sqs_conn_mock.queues) + # For cleanup purposes, delete the queue and the queue file + self.channel._delete(queue_name) + + def test_delete(self): + queue_name = "new_unittest_queue" + self.channel._new_queue(queue_name) + self.channel._delete(queue_name) + self.assertNotIn(queue_name, self.channel._queue_cache) + + def test_get_from_sqs(self): + # Test getting a single message + message = "my test message" + self.producer.publish(message) + results = self.channel._get_from_sqs(self.queue_name) + self.assertEquals(len(results), 1) + + # Now test getting many messages + for i in xrange(3): + message = "message: %s" % i + self.producer.publish(message) + + results = self.channel._get_from_sqs(self.queue_name, count=3) + self.assertEquals(len(results), 3) + + def test_get_with_empty_list(self): + self.assertRaises(five.Empty, self.channel._get, self.queue_name) + + def test_get_bulk_raises_empty(self): + self.assertRaises(five.Empty, self.channel._get_bulk, self.queue_name) + + def test_messages_to_python(self): + message_count = 3 + # Create several test messages and publish them + for i in range(message_count): + message = 'message: %s' % i + self.producer.publish(message) + + # Get the messages now + messages = self.channel._get_from_sqs( + self.queue_name, count=message_count, + ) + + # Now convert them to payloads + payloads = self.channel._messages_to_python( + messages, self.queue_name, + ) + + # We got the same number of payloads back, right? + self.assertEquals(len(payloads), message_count) + + # Make sure they're payload-style objects + for p in payloads: + self.assertTrue('properties' in p) + + def test_put_and_get(self): + message = 'my test message' + self.producer.publish(message) + results = self.queue(self.channel).get().payload + self.assertEquals(message, results) + + def test_puts_and_gets(self): + for i in xrange(3): + message = 'message: %s' % i + self.producer.publish(message) + + for i in xrange(3): + self.assertEquals('message: %s' % i, + self.queue(self.channel).get().payload) + + def test_put_and_get_bulk(self): + # With QoS.prefetch_count = 0 + message = 'my test message' + self.producer.publish(message) + results = self.channel._get_bulk(self.queue_name) + self.assertEquals(1, len(results)) + + def test_puts_and_get_bulk(self): + # Generate 8 messages + message_count = 8 + + # Set the prefetch_count to 5 + self.channel.qos.prefetch_count = 5 + + # Now, generate all the messages + for i in xrange(message_count): + message = 'message: %s' % i + self.producer.publish(message) + + # Count how many messages are retrieved the first time. Should + # be 5 (message_count). + results = self.channel._get_bulk(self.queue_name) + self.assertEquals(5, len(results)) + + # Now, do the get again, the number of messages returned should be 3. + results = self.channel._get_bulk(self.queue_name) + self.assertEquals(3, len(results)) + + def test_drain_events_with_empty_list(self): + def mock_can_consume(): + return False + self.channel.qos.can_consume = mock_can_consume + self.assertRaises(five.Empty, self.channel.drain_events) + + def test_drain_events_with_prefetch_5(self): + # Generate 20 messages + message_count = 20 + expected_get_message_count = 4 + + # Set the prefetch_count to 5 + self.channel.qos.prefetch_count = 5 + + # Now, generate all the messages + for i in xrange(message_count): + self.producer.publish('message: %s' % i) + + # Now drain all the events + for i in xrange(message_count): + self.channel.drain_events() + + # How many times was the SQSConnectionMock get_message method called? + self.assertEquals( + expected_get_message_count, + self.channel._queue_cache[self.queue_name]._get_message_calls) + + def test_drain_events_with_prefetch_none(self): + # Generate 20 messages + message_count = 20 + expected_get_message_count = 20 + + # Set the prefetch_count to None + self.channel.qos.prefetch_count = None + + # Now, generate all the messages + for i in xrange(message_count): + self.producer.publish('message: %s' % i) + + # Now drain all the events + for i in xrange(message_count): + self.channel.drain_events() + + # How many times was the SQSConnectionMock get_message method called? + self.assertEquals( + expected_get_message_count, + self.channel._queue_cache[self.queue_name]._get_message_calls) diff --git a/awx/lib/site-packages/kombu/tests/transport/test_filesystem.py b/awx/lib/site-packages/kombu/tests/transport/test_filesystem.py index 876c203fa7..0649a8d000 100644 --- a/awx/lib/site-packages/kombu/tests/transport/test_filesystem.py +++ b/awx/lib/site-packages/kombu/tests/transport/test_filesystem.py @@ -1,5 +1,6 @@ from __future__ import absolute_import +import sys import tempfile from kombu import Connection, Exchange, Queue, Consumer, Producer @@ -10,6 +11,8 @@ from kombu.tests.case import Case, SkipTest class test_FilesystemTransport(Case): def setUp(self): + if sys.platform == 'win32': + raise SkipTest('Needs win32con module') try: data_folder_in = tempfile.mkdtemp() data_folder_out = tempfile.mkdtemp() diff --git a/awx/lib/site-packages/kombu/tests/transport/test_redis.py b/awx/lib/site-packages/kombu/tests/transport/test_redis.py index 704b8a4e1c..37c1ad9c30 100644 --- a/awx/lib/site-packages/kombu/tests/transport/test_redis.py +++ b/awx/lib/site-packages/kombu/tests/transport/test_redis.py @@ -300,11 +300,11 @@ class test_Channel(Case): ]) client.rpush.side_effect = KeyError() - with patch('kombu.transport.redis.logger') as logger: + with patch('kombu.transport.redis.crit') as crit: self.channel._do_restore_message( pl2, 'ex', 'rkey', client, ) - self.assertTrue(logger.critical.called) + self.assertTrue(crit.called) def test_restore(self): message = Mock(name='message') @@ -496,10 +496,22 @@ class test_Channel(Case): c.parse_response = Mock() self.channel._poll_error('BRPOP') - c.parse_response.assert_called_with('BRPOP') + c.parse_response.assert_called_with(c.connection, 'BRPOP') c.parse_response.side_effect = KeyError('foo') - self.assertIsNone(self.channel._poll_error('BRPOP')) + with self.assertRaises(KeyError): + self.channel._poll_error('BRPOP') + + def test_poll_error_on_type_LISTEN(self): + c = self.channel.subclient = Mock() + c.parse_response = Mock() + self.channel._poll_error('LISTEN') + + c.parse_response.assert_called_with() + + c.parse_response.side_effect = KeyError('foo') + with self.assertRaises(KeyError): + self.channel._poll_error('LISTEN') def test_put_fanout(self): self.channel._in_poll = False diff --git a/awx/lib/site-packages/kombu/transport/SLMQ.py b/awx/lib/site-packages/kombu/transport/SLMQ.py index 0a79deec34..d6589f6610 100644 --- a/awx/lib/site-packages/kombu/transport/SLMQ.py +++ b/awx/lib/site-packages/kombu/transport/SLMQ.py @@ -16,7 +16,7 @@ import os from kombu.five import Empty, text_t from kombu.utils import cached_property # , uuid -from kombu.utils.encoding import safe_str +from kombu.utils.encoding import bytes_to_str, safe_str from . import virtual @@ -96,7 +96,7 @@ class Channel(virtual.Channel): rs = q.pop(1) if rs['items']: m = rs['items'][0] - payload = loads(m['body']) + payload = loads(bytes_to_str(m['body'])) if queue in self._noack_queues: q.message(m['id']).delete() else: diff --git a/awx/lib/site-packages/kombu/transport/SQS.py b/awx/lib/site-packages/kombu/transport/SQS.py index 7b4d360b1f..a19334d857 100644 --- a/awx/lib/site-packages/kombu/transport/SQS.py +++ b/awx/lib/site-packages/kombu/transport/SQS.py @@ -2,11 +2,44 @@ kombu.transport.SQS =================== -Amazon SQS transport. +Amazon SQS transport module for Kombu. This package implements an AMQP-like +interface on top of Amazons SQS service, with the goal of being optimized for +high performance and reliability. +The default settings for this module are focused now on high performance in +task queue situations where tasks are small, idempotent and run very fast. + +SQS Features supported by this transport: + Long Polling: + http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/ + sqs-long-polling.html + + Long polling is enabled by setting the `wait_time_seconds` transport + option to a number > 1. Amazon supports up to 20 seconds. This is + disabled for now, but will be enabled by default in the near future. + + Batch API Actions: + http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/ + sqs-batch-api.html + + The default behavior of the SQS Channel.drain_events() method is to + request up to the 'prefetch_count' messages on every request to SQS. + These messages are stored locally in a deque object and passed back + to the Transport until the deque is empty, before triggering a new + API call to Amazon. + + This behavior dramatically speeds up the rate that you can pull tasks + from SQS when you have short-running tasks (or a large number of workers). + + When a Celery worker has multiple queues to monitor, it will pull down + up to 'prefetch_count' messages from queueA and work on them all before + moving on to queueB. If queueB is empty, it will wait up until + 'polling_interval' expires before moving back and checking on queueA. """ + from __future__ import absolute_import +import collections import socket import string @@ -22,11 +55,15 @@ from boto.sqs.connection import SQSConnection from boto.sqs.message import Message from kombu.five import Empty, range, text_t +from kombu.log import get_logger from kombu.utils import cached_property, uuid -from kombu.utils.encoding import safe_str +from kombu.utils.encoding import bytes_to_str, safe_str +from kombu.transport.virtual import scheduling from . import virtual +logger = get_logger(__name__) + # dots are replaced by dash, all other punctuation # replaced by underscore. CHARS_REPLACE_TABLE = dict((ord(c), 0x5f) @@ -149,11 +186,18 @@ class Channel(virtual.Channel): self._queue_cache[queue.name] = queue self._fanout_queues = set() + # The drain_events() method stores extra messages in a local + # Deque object. This allows multiple messages to be requested from + # SQS at once for performance, but maintains the same external API + # to the caller of the drain_events() method. + self._queue_message_cache = collections.deque() + def basic_consume(self, queue, no_ack, *args, **kwargs): if no_ack: self._noack_queues.add(queue) - return super(Channel, self).basic_consume(queue, no_ack, - *args, **kwargs) + return super(Channel, self).basic_consume( + queue, no_ack, *args, **kwargs + ) def basic_cancel(self, consumer_tag): if consumer_tag in self._consumers: @@ -161,12 +205,53 @@ class Channel(virtual.Channel): self._noack_queues.discard(queue) return super(Channel, self).basic_cancel(consumer_tag) + def drain_events(self, timeout=None): + """Return a single payload message from one of our queues. + + :raises Empty: if no messages available. + + """ + # If we're not allowed to consume or have no consumers, raise Empty + if not self._consumers or not self.qos.can_consume(): + raise Empty() + message_cache = self._queue_message_cache + + # Check if there are any items in our buffer. If there are any, pop + # off that queue first. + try: + return message_cache.popleft() + except IndexError: + pass + + # At this point, go and get more messages from SQS + res, queue = self._poll(self.cycle, timeout=timeout) + message_cache.extend((r, queue) for r in res) + + # Now try to pop off the queue again. + try: + return message_cache.popleft() + except IndexError: + raise Empty() + + def _reset_cycle(self): + """Reset the consume cycle. + + :returns: a FairCycle object that points to our _get_bulk() method + rather than the standard _get() method. This allows for multiple + messages to be returned at once from SQS (based on the prefetch + limit). + + """ + self._cycle = scheduling.FairCycle( + self._get_bulk, self._active_queues, Empty, + ) + def entity_name(self, name, table=CHARS_REPLACE_TABLE): """Format AMQP queue name into a legal SQS queue name.""" return text_t(safe_str(name)).translate(table) def _new_queue(self, queue, **kwargs): - """Ensures a queue exists in SQS.""" + """Ensure a queue with given name exists in SQS.""" # Translate to SQS name for consistency with initial # _queue_cache population. queue = self.entity_name(self.queue_name_prefix + queue) @@ -212,10 +297,10 @@ class Channel(virtual.Channel): def _delete(self, queue, *args): """delete queue by name.""" - self._queue_cache.pop(queue, None) if self.supports_fanout: self.table.queue_delete(queue) super(Channel, self)._delete(queue) + self._queue_cache.pop(queue, None) def exchange_delete(self, exchange, **kwargs): """Delete exchange by name.""" @@ -241,23 +326,86 @@ class Channel(virtual.Channel): for route in self.table.routes_for(exchange): self._put(route['queue'], message, **kwargs) - def _get(self, queue): - """Try to retrieve a single message off ``queue``.""" + def _get_from_sqs(self, queue, count=1): + """Retrieve messages from SQS and returns the raw SQS message objects. + + :returns: List of SQS message objects + + """ q = self._new_queue(queue) if W_LONG_POLLING and queue not in self._fanout_queues: - rs = q.get_messages(1, wait_time_seconds=self.wait_time_seconds) + return q.get_messages( + count, wait_time_seconds=self.wait_time_seconds, + ) else: # boto < 2.8 - rs = q.get_messages(1) - if rs: - m = rs[0] - payload = loads(rs[0].get_body()) - if queue in self._noack_queues: - q.delete_message(m) - else: - payload['properties']['delivery_info'].update({ - 'sqs_message': m, 'sqs_queue': q, }) - return payload - raise Empty() + return q.get_messages(count) + + def _message_to_python(self, message, queue_name, queue): + payload = loads(bytes_to_str(message.get_body())) + if queue_name in self._noack_queues: + queue.delete_message(message) + else: + payload['properties']['delivery_info'].update({ + 'sqs_message': message, 'sqs_queue': queue, + }) + return payload + + def _messages_to_python(self, messages, queue): + """Convert a list of SQS Message objects into Payloads. + + This method handles converting SQS Message objects into + Payloads, and appropriately updating the queue depending on + the 'ack' settings for that queue. + + :param messages: A list of SQS Message objects. + :param queue: String name representing the queue they came from + + :returns: A list of Payload objects + + """ + q = self._new_queue(queue) + return [self._message_to_python(m, queue, q) for m in messages] + + def _get_bulk(self, queue, max_if_unlimited=10): + """Try to retrieve multiple messages off ``queue``. + + Where _get() returns a single Payload object, this method returns a + list of Payload objects. The number of objects returned is determined + by the total number of messages available in the queue and the + number of messages that the QoS object allows (based on the + prefetch_count). + + .. note:: + Ignores QoS limits so caller is responsible for checking + that we are allowed to consume at least one message from the + queue. get_bulk will then ask QoS for an estimate of + the number of extra messages that we can consume. + + args: + queue: The queue name (string) to pull from + + returns: + payloads: A list of payload objects returned + """ + # drain_events calls `can_consume` first, consuming + # a token, so we know that we are allowed to consume at least + # one message. + maxcount = self.qos.can_consume_max_estimate() + maxcount = max_if_unlimited if maxcount is None else max(maxcount, 1) + messages = self._get_from_sqs(queue, count=maxcount) + + if not messages: + raise Empty() + return self._messages_to_python(messages, queue) + + def _get(self, queue): + """Try to retrieve a single message off ``queue``.""" + messages = self._get_from_sqs(queue, count=1) + + if not messages: + raise Empty() + + return self._messages_to_python(messages, queue)[0] def _restore(self, message, unwanted_delivery_info=('sqs_message', 'sqs_queue')): diff --git a/awx/lib/site-packages/kombu/transport/__init__.py b/awx/lib/site-packages/kombu/transport/__init__.py index 5df75b0660..10d62e9506 100644 --- a/awx/lib/site-packages/kombu/transport/__init__.py +++ b/awx/lib/site-packages/kombu/transport/__init__.py @@ -7,8 +7,6 @@ Built-in transports. """ from __future__ import absolute_import -from collections import Callable - from kombu.five import string_t from kombu.syn import _detect_environment from kombu.utils import symbol_by_name @@ -29,7 +27,7 @@ def _ghettoq(name, new, alias=None): def __inner(): import warnings - _new = isinstance(xxx, Callable) and xxx() or xxx + _new = callable(xxx) and xxx() or xxx gtransport = 'ghettoq.taproot.{0}'.format(name) ktransport = 'kombu.transport.{0}.Transport'.format(_new) this = alias or name @@ -89,7 +87,7 @@ def resolve_transport(transport=None): transport, alt)) raise KeyError('No such transport: {0}'.format(transport)) else: - if isinstance(transport, Callable): + if callable(transport): transport = transport() return symbol_by_name(transport) return transport diff --git a/awx/lib/site-packages/kombu/transport/beanstalk.py b/awx/lib/site-packages/kombu/transport/beanstalk.py index f583899efa..9dff8b4923 100644 --- a/awx/lib/site-packages/kombu/transport/beanstalk.py +++ b/awx/lib/site-packages/kombu/transport/beanstalk.py @@ -16,6 +16,7 @@ import socket from anyjson import loads, dumps from kombu.five import Empty +from kombu.utils.encoding import bytes_to_str from . import virtual @@ -31,7 +32,7 @@ class Channel(virtual.Channel): item, dest = None, None if job: try: - item = loads(job.body) + item = loads(bytes_to_str(job.body)) dest = job.stats()['tube'] except Exception: job.bury() diff --git a/awx/lib/site-packages/kombu/transport/couchdb.py b/awx/lib/site-packages/kombu/transport/couchdb.py index 42864cfdc0..009dbbdcb4 100644 --- a/awx/lib/site-packages/kombu/transport/couchdb.py +++ b/awx/lib/site-packages/kombu/transport/couchdb.py @@ -17,6 +17,7 @@ from anyjson import loads, dumps from kombu.five import Empty from kombu.utils import uuid4 +from kombu.utils.encoding import bytes_to_str from . import virtual @@ -56,7 +57,7 @@ class Channel(virtual.Channel): item = result.rows[0].value self.client.delete(item) - return loads(item['payload']) + return loads(bytes_to_str(item['payload'])) def _purge(self, queue): result = self._query(queue) diff --git a/awx/lib/site-packages/kombu/transport/django/__init__.py b/awx/lib/site-packages/kombu/transport/django/__init__.py index 7c4ec6a45f..67bfa57683 100644 --- a/awx/lib/site-packages/kombu/transport/django/__init__.py +++ b/awx/lib/site-packages/kombu/transport/django/__init__.py @@ -8,6 +8,7 @@ from django.core import exceptions as errors from kombu.five import Empty from kombu.transport import virtual +from kombu.utils.encoding import bytes_to_str from .models import Queue @@ -37,7 +38,7 @@ class Channel(virtual.Channel): #self.refresh_connection() m = Queue.objects.fetch(queue) if m: - return loads(m) + return loads(bytes_to_str(m)) raise Empty() def _size(self, queue): diff --git a/awx/lib/site-packages/kombu/transport/mongodb.py b/awx/lib/site-packages/kombu/transport/mongodb.py index 9b063236fc..9d6fe45d09 100644 --- a/awx/lib/site-packages/kombu/transport/mongodb.py +++ b/awx/lib/site-packages/kombu/transport/mongodb.py @@ -18,6 +18,7 @@ from pymongo import MongoClient from kombu.five import Empty from kombu.syn import _detect_environment +from kombu.utils.encoding import bytes_to_str from . import virtual @@ -50,7 +51,7 @@ class Channel(virtual.Channel): if queue in self._fanout_queues: msg = next(self._queue_cursors[queue]) self._queue_readcounts[queue] += 1 - return loads(msg['payload']) + return loads(bytes_to_str(msg['payload'])) else: msg = self.client.command( 'findandmodify', 'messages', @@ -67,7 +68,7 @@ class Channel(virtual.Channel): # as of mongo 2.0 empty results won't raise an error if msg['value'] is None: raise Empty() - return loads(msg['value']['payload']) + return loads(bytes_to_str(msg['value']['payload'])) def _size(self, queue): if queue in self._fanout_queues: @@ -96,13 +97,11 @@ class Channel(virtual.Channel): client = self.connection.client options = client.transport_options hostname = client.hostname or DEFAULT_HOST - authdb = dbname = client.virtual_host + dbname = client.virtual_host if dbname in ['/', None]: dbname = "kombu_default" - authdb = "admin" if not hostname.startswith(scheme): - hostname = scheme + hostname if not hostname[len(scheme):]: @@ -113,10 +112,7 @@ class Channel(virtual.Channel): if '/' in urest: if not client.userid: urest = urest.replace('/' + client.virtual_host, '/') - else: - urest = hostname.replace('/' + client.virtual_host, - '/' + authdb) - hostname = ''.join([scheme, urest]) + hostname = ''.join([scheme, urest]) # At this point we expect the hostname to be something like # (considering replica set form too): diff --git a/awx/lib/site-packages/kombu/transport/pyamqp.py b/awx/lib/site-packages/kombu/transport/pyamqp.py index 2958a05d5f..8ecdec28b4 100644 --- a/awx/lib/site-packages/kombu/transport/pyamqp.py +++ b/awx/lib/site-packages/kombu/transport/pyamqp.py @@ -46,7 +46,7 @@ class Channel(amqp.Channel, base.StdChannel): content_type=content_type, content_encoding=content_encoding, application_headers=headers, - **properties + **properties or {} ) def message_to_python(self, raw_message): diff --git a/awx/lib/site-packages/kombu/transport/redis.py b/awx/lib/site-packages/kombu/transport/redis.py index df39cb464c..ede424f16d 100644 --- a/awx/lib/site-packages/kombu/transport/redis.py +++ b/awx/lib/site-packages/kombu/transport/redis.py @@ -21,6 +21,7 @@ from kombu.log import get_logger from kombu.utils import cached_property, uuid from kombu.utils.eventio import poll, READ, ERR from kombu.utils.encoding import bytes_to_str +from kombu.utils.url import _parse_url NO_ROUTE_ERROR = """ Cannot route message for exchange {0!r}: Table empty or key no longer exists. @@ -45,6 +46,7 @@ except ImportError: # pragma: no cover from . import virtual logger = get_logger('kombu.transport.redis') +crit, warn = logger.critical, logger.warn DEFAULT_PORT = 6379 DEFAULT_DB = 0 @@ -162,7 +164,7 @@ class QoS(virtual.QoS): p, _, _ = self._remove_from_indices( tag, client.pipeline().hget(self.unacked_key, tag)).execute() if p: - M, EX, RK = loads(p) + M, EX, RK = loads(bytes_to_str(p)) # json is unicode self.channel._do_restore_message(M, EX, RK, client, leftmost) @cached_property @@ -408,8 +410,7 @@ class Channel(virtual.Channel): queue, dumps(payload), ) except Exception: - logger.critical('Could not restore message: %r', payload, - exc_info=True) + crit('Could not restore message: %r', payload, exc_info=True) def _restore(self, message, leftmost=False): tag = message.delivery_tag @@ -419,7 +420,7 @@ class Channel(virtual.Channel): .hdel(self.unacked_key, tag) \ .execute() if P: - M, EX, RK = loads(P) + M, EX, RK = loads(bytes_to_str(P)) # json is unicode self._do_restore_message(M, EX, RK, client, leftmost) def _restore_at_beginning(self, message): @@ -480,16 +481,20 @@ class Channel(virtual.Channel): response = c.parse_response() except self.connection_errors: self._in_listen = False + raise Empty() if response is not None: payload = self._handle_message(c, response) if bytes_to_str(payload['type']) == 'message': channel = bytes_to_str(payload['channel']) - if channel[0] == '/': - _, _, channel = channel.partition('.') - return ( - loads(bytes_to_str(payload['data'])), - self._fanout_to_queue[channel], - ) + if payload['data']: + if channel[0] == '/': + _, _, channel = channel.partition('.') + try: + message = loads(bytes_to_str(payload['data'])) + except (TypeError, ValueError): + warn('Cannot process event on channel %r: %r', + channel, payload, exc_info=1) + return message, self._fanout_to_queue[channel] raise Empty() def _brpop_start(self, timeout=1): @@ -523,17 +528,17 @@ class Channel(virtual.Channel): self._in_poll = False def _poll_error(self, type, **options): - try: - self.client.parse_response(type) - except self.connection_errors: - pass + if type == 'LISTEN': + self.subclient.parse_response() + else: + self.client.parse_response(self.client.connection, type) def _get(self, queue): with self.conn_or_acquire() as client: for pri in PRIORITY_STEPS: item = client.rpop(self._q_for_pri(queue, pri)) if item: - return loads(item) + return loads(bytes_to_str(item)) raise Empty() def _size(self, queue): @@ -631,41 +636,52 @@ class Channel(virtual.Channel): if queue in self.auto_delete_queues: self.queue_delete(queue) - # Close connections - for attr in 'client', 'subclient': - try: - self.__dict__[attr].connection.disconnect() - except (KeyError, AttributeError, self.ResponseError): - pass + self._close_clients() + super(Channel, self).close() + def _close_clients(self): + # Close connections + for attr in 'client', 'subclient': + try: + self.__dict__[attr].connection.disconnect() + except (KeyError, AttributeError, self.ResponseError): + pass + + def _prepare_virtual_host(self, vhost): + if not isinstance(vhost, int): + if not vhost or vhost == '/': + vhost = DEFAULT_DB + elif vhost.startswith('/'): + vhost = vhost[1:] + try: + vhost = int(vhost) + except ValueError: + raise ValueError( + 'Database is int between 0 and limit - 1, not {0}'.format( + vhost, + )) + return vhost + def _connparams(self): conninfo = self.connection.client - database = conninfo.virtual_host - if not isinstance(database, int): - if not database or database == '/': - database = DEFAULT_DB - elif database.startswith('/'): - database = database[1:] - try: - database = int(database) - except ValueError: - raise ValueError( - 'Database name must be int between 0 and limit - 1') - host = conninfo.hostname or '127.0.0.1' - connparams = {'host': host, + connparams = {'host': conninfo.hostname or '127.0.0.1', 'port': conninfo.port or DEFAULT_PORT, - 'db': database, + 'virtual_host': conninfo.virtual_host, 'password': conninfo.password, 'max_connections': self.max_connections, 'socket_timeout': self.socket_timeout} - if host.split('://')[0] == 'socket': - connparams.update({ - 'connection_class': redis.UnixDomainSocketConnection, - 'path': host.split('://')[1]}) + host = connparams['host'] + if '://' in host: + scheme, _, _, _, _, path, query = _parse_url(host) + if scheme == 'socket': + connparams.update({ + 'connection_class': redis.UnixDomainSocketConnection, + 'path': '/' + path}, **query) connparams.pop('host', None) connparams.pop('port', None) - + connparams['db'] = self._prepare_virtual_host( + connparams.pop('virtual_host', None)) return connparams def _create_client(self): @@ -821,7 +837,9 @@ class Transport(virtual.Transport): return ( (virtual.Transport.connection_errors + ( InconsistencyError, - socket.timeout, + socket.error, + IOError, + OSError, exceptions.ConnectionError, exceptions.AuthenticationError)), (virtual.Transport.channel_errors + ( diff --git a/awx/lib/site-packages/kombu/transport/sqlalchemy/__init__.py b/awx/lib/site-packages/kombu/transport/sqlalchemy/__init__.py index 90f6ac571d..c085b46931 100644 --- a/awx/lib/site-packages/kombu/transport/sqlalchemy/__init__.py +++ b/awx/lib/site-packages/kombu/transport/sqlalchemy/__init__.py @@ -12,6 +12,7 @@ from sqlalchemy.orm import sessionmaker from kombu.five import Empty from kombu.transport import virtual from kombu.utils import cached_property +from kombu.utils.encoding import bytes_to_str from .models import (ModelBase, Queue as QueueBase, Message as MessageBase, class_registry, metadata) @@ -102,7 +103,7 @@ class Channel(virtual.Channel): .first() if msg: msg.visible = False - return loads(msg.payload) + return loads(bytes_to_str(msg.payload)) raise Empty() finally: self.session.commit() diff --git a/awx/lib/site-packages/kombu/transport/virtual/__init__.py b/awx/lib/site-packages/kombu/transport/virtual/__init__.py index 5ee0a47071..19a356a2e8 100644 --- a/awx/lib/site-packages/kombu/transport/virtual/__init__.py +++ b/awx/lib/site-packages/kombu/transport/virtual/__init__.py @@ -23,7 +23,7 @@ from amqp.protocol import queue_declare_ok_t from kombu.exceptions import ResourceError, ChannelError from kombu.five import Empty, items, monotonic -from kombu.utils import emergency_dump_state, say, uuid +from kombu.utils import emergency_dump_state, kwdict, say, uuid from kombu.utils.compat import OrderedDict from kombu.utils.encoding import str_to_bytes, bytes_to_str @@ -130,6 +130,27 @@ class QoS(object): pcount = self.prefetch_count return not pcount or len(self._delivered) - len(self._dirty) < pcount + def can_consume_max_estimate(self): + """Returns the maximum number of messages allowed to be returned. + + Returns an estimated number of messages that a consumer may be allowed + to consume at once from the broker. This is used for services where + bulk 'get message' calls are preferred to many individual 'get message' + calls - like SQS. + + returns: + An integer > 0 + """ + pcount = self.prefetch_count + count = None + if pcount: + count = pcount - (len(self._delivered) - len(self._dirty)) + + if count < 1: + return 1 + + return count + def append(self, message, delivery_tag): """Append message to transactional state.""" if self._dirty: @@ -210,6 +231,15 @@ class QoS(object): finally: state.restored = True + def restore_visible(self, *args, **kwargs): + """Restore any pending unackwnowledged messages for visibility_timeout + style implementations. + + Optional: Currently only used by the Redis transport. + + """ + pass + class Message(base.Message): @@ -219,7 +249,7 @@ class Message(base.Message): body = payload.get('body') if body: body = channel.decode_body(body, properties.get('body_encoding')) - fields = { + kwargs.update({ 'body': body, 'delivery_tag': properties['delivery_tag'], 'content_type': payload.get('content-type'), @@ -228,8 +258,8 @@ class Message(base.Message): 'properties': properties, 'delivery_info': properties.get('delivery_info'), 'postencode': 'utf-8', - } - super(Message, self).__init__(channel, **dict(kwargs, **fields)) + }) + super(Message, self).__init__(channel, **kwdict(kwargs)) def serializable(self): props = self.properties diff --git a/awx/lib/site-packages/kombu/transport/zookeeper.py b/awx/lib/site-packages/kombu/transport/zookeeper.py index 0d524e254f..2d1c8abcea 100644 --- a/awx/lib/site-packages/kombu/transport/zookeeper.py +++ b/awx/lib/site-packages/kombu/transport/zookeeper.py @@ -33,6 +33,7 @@ import socket from anyjson import loads, dumps from kombu.five import Empty +from kombu.utils.encoding import bytes_to_str from . import virtual @@ -117,7 +118,7 @@ class Channel(virtual.Channel): if msg is None: raise Empty() - return loads(msg) + return loads(bytes_to_str(msg)) def _purge(self, queue): count = 0 diff --git a/awx/lib/site-packages/kombu/utils/__init__.py b/awx/lib/site-packages/kombu/utils/__init__.py index 3a5e35b613..32cb18b81f 100644 --- a/awx/lib/site-packages/kombu/utils/__init__.py +++ b/awx/lib/site-packages/kombu/utils/__init__.py @@ -13,6 +13,7 @@ import sys from contextlib import contextmanager from itertools import count, repeat +from functools import wraps from time import sleep from uuid import UUID, uuid4 as _uuid4, _uuid_generate_random diff --git a/awx/lib/site-packages/kombu/utils/debug.py b/awx/lib/site-packages/kombu/utils/debug.py index 553eee06bb..8d08115b06 100644 --- a/awx/lib/site-packages/kombu/utils/debug.py +++ b/awx/lib/site-packages/kombu/utils/debug.py @@ -9,7 +9,6 @@ from __future__ import absolute_import import logging -from collections import Callable from functools import wraps from kombu.five import items @@ -37,7 +36,7 @@ class Logwrapped(object): def __getattr__(self, key): meth = getattr(self.instance, key) - if not isinstance(meth, Callable) or key in self.__ignore: + if not callable(meth) or key in self.__ignore: return meth @wraps(meth) diff --git a/awx/lib/site-packages/kombu/utils/eventio.py b/awx/lib/site-packages/kombu/utils/eventio.py index de9951ba0d..ae6b18877e 100644 --- a/awx/lib/site-packages/kombu/utils/eventio.py +++ b/awx/lib/site-packages/kombu/utils/eventio.py @@ -8,40 +8,38 @@ Evented IO support for multiple platforms. from __future__ import absolute_import import errno +import select as __select__ import socket -from select import select as _selectf, error as _selecterr +from kombu.five import int_types -try: - from select import epoll -except ImportError: - epoll = None # noqa +_selectf = __select__.select +_selecterr = __select__.error +epoll = getattr(__select__, 'epoll', None) +kqueue = getattr(__select__, 'kqueue', None) +kevent = getattr(__select__, 'kevent', None) +KQ_EV_ADD = getattr(__select__, 'KQ_EV_ADD', 1) +KQ_EV_DELETE = getattr(__select__, 'KQ_EV_DELETE', 2) +KQ_EV_ENABLE = getattr(__select__, 'KQ_EV_ENABLE', 4) +KQ_EV_CLEAR = getattr(__select__, 'KQ_EV_CLEAR', 32) +KQ_EV_ERROR = getattr(__select__, 'KQ_EV_ERROR', 16384) +KQ_EV_EOF = getattr(__select__, 'KQ_EV_EOF', 32768) +KQ_FILTER_READ = getattr(__select__, 'KQ_FILTER_READ', -1) +KQ_FILTER_WRITE = getattr(__select__, 'KQ_FILTER_WRITE', -2) +KQ_FILTER_AIO = getattr(__select__, 'KQ_FILTER_AIO', -3) +KQ_FILTER_VNODE = getattr(__select__, 'KQ_FILTER_VNODE', -4) +KQ_FILTER_PROC = getattr(__select__, 'KQ_FILTER_PROC', -5) +KQ_FILTER_SIGNAL = getattr(__select__, 'KQ_FILTER_SIGNAL', -6) +KQ_FILTER_TIMER = getattr(__select__, 'KQ_FILTER_TIMER', -7) +KQ_NOTE_LOWAT = getattr(__select__, 'KQ_NOTE_LOWAT', 1) +KQ_NOTE_DELETE = getattr(__select__, 'KQ_NOTE_DELETE', 1) +KQ_NOTE_WRITE = getattr(__select__, 'KQ_NOTE_WRITE', 2) +KQ_NOTE_EXTEND = getattr(__select__, 'KQ_NOTE_EXTEND', 4) +KQ_NOTE_ATTRIB = getattr(__select__, 'KQ_NOTE_ATTRIB', 8) +KQ_NOTE_LINK = getattr(__select__, 'KQ_NOTE_LINK', 16) +KQ_NOTE_RENAME = getattr(__select__, 'KQ_NOTE_RENAME', 32) +KQ_NOTE_REVOKE = getattr(__select__, 'kQ_NOTE_REVOKE', 64) -try: - from select import ( - kqueue, - kevent, - KQ_EV_ADD, - KQ_EV_DELETE, - KQ_EV_EOF, - KQ_EV_ERROR, - KQ_EV_ENABLE, - KQ_EV_CLEAR, - KQ_FILTER_WRITE, - KQ_FILTER_READ, - KQ_FILTER_VNODE, - KQ_NOTE_WRITE, - KQ_NOTE_EXTEND, - KQ_NOTE_DELETE, - KQ_NOTE_ATTRIB, - ) -except ImportError: - kqueue = kevent = None # noqa - KQ_EV_ADD = KQ_EV_DELETE = KQ_EV_EOF = KQ_EV_ERROR = 0 # noqa - KQ_EV_ENABLE = KQ_EV_CLEAR = KQ_EV_VNODE = 0 # noqa - KQ_FILTER_WRITE = KQ_FILTER_READ = 0 # noqa - KQ_NOTE_WRITE = KQ_NOTE_EXTEND = 0 # noqa - KQ_NOTE_ATTRIB = KQ_NOTE_DELETE = 0 # noqa from kombu.syn import detect_environment @@ -223,15 +221,15 @@ class _select(Poller): events = {} for fd in read: - if not isinstance(fd, int): + if not isinstance(fd, int_types): fd = fd.fileno() events[fd] = events.get(fd, 0) | READ for fd in write: - if not isinstance(fd, int): + if not isinstance(fd, int_types): fd = fd.fileno() events[fd] = events.get(fd, 0) | WRITE for fd in error: - if not isinstance(fd, int): + if not isinstance(fd, int_types): fd = fd.fileno() events[fd] = events.get(fd, 0) | ERR return list(events.items()) diff --git a/awx/lib/site-packages/os_virtual_interfacesv2_python_novaclient_ext.py b/awx/lib/site-packages/os_virtual_interfacesv2_python_novaclient_ext.py new file mode 100644 index 0000000000..712d8d315e --- /dev/null +++ b/awx/lib/site-packages/os_virtual_interfacesv2_python_novaclient_ext.py @@ -0,0 +1,96 @@ +# Copyright 2011 OpenStack, LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from novaclient import base +from novaclient import utils + + +class VirtualInterface(base.Resource): + def create(self): + self.manager.create() + + +class VirtualInterfaceManager(base.ManagerWithFind): + resource_class = base.Resource + + def list(self, instance_id): + return self._list("/servers/%s/os-virtual-interfacesv2" % instance_id, + "virtual_interfaces") + + def create(self, network_id, instance_id): + body = {'virtual_interface': {'network_id': network_id}} + return self._create('/servers/%s/os-virtual-interfacesv2' % + instance_id, + body, 'virtual_interfaces', return_raw=True) + + def delete(self, instance_id, interface_id): + return self._delete('/servers/%s/os-virtual-interfacesv2/%s' % + (instance_id, interface_id)) + + +def ip_dict_formatter(ip_dict): + net_id = ip_dict["network_id"] + ip_addr = ip_dict["address"] + label = ip_dict["network_label"] + return "label=%s, network_id=%s, ip_address=%s" % (label, + net_id, ip_addr) + + +def ip_address_formatter(field): + addresses = [ip_dict_formatter(addr) for addr in field.ip_addresses] + return ",".join(addresses) + + +@utils.arg('instance_id', metavar='', + help="ID of the instance you want to display virtual" + "interfaces for") +def do_virtual_interface_list(cs, args): + """ + Lists the virtual interfaces for a specified server instance + """ + vifs = cs.os_virtual_interfacesv2_python_novaclient_ext.list( + args.instance_id) + utils.print_list(vifs, ["id", "mac_address", "ip_addresses"], + formatters={"ip_addresses": ip_address_formatter}) + + +@utils.arg('network_id', metavar='', + help='Network ID to connect the new virtual interface to') +@utils.arg('instance_id', metavar='', + help="Instance to attach the new virtual interface to") +def do_virtual_interface_create(cs, args): + """ + Add a new virtual interface to an instance + """ + addresses = cs.os_virtual_interfacesv2_python_novaclient_ext.create( + args.network_id, + args.instance_id) + for address in addresses: + addr_list = [ip_dict_formatter(a) for a in address["ip_addresses"]] + addr_dict = {"id": address["id"], + "mac_address": address["mac_address"], + "ip_addresses": ','.join(addr_list)} + utils.print_dict(addr_dict) + + +@utils.arg('instance_id', metavar='', + help="Instance to remove the virtual interface from") +@utils.arg('interface_id', metavar='', + help='ID of the virtual interface to delete') +def do_virtual_interface_delete(cs, args): + """ + Removes the specified virtual interface from an instance + """ + cs.os_virtual_interfacesv2_python_novaclient_ext.delete(args.instance_id, + args.interface_id) diff --git a/awx/lib/site-packages/pip/__init__.py b/awx/lib/site-packages/pip/__init__.py index 8bc68aaca2..8437136c88 100644 --- a/awx/lib/site-packages/pip/__init__.py +++ b/awx/lib/site-packages/pip/__init__.py @@ -9,12 +9,18 @@ from pip.exceptions import InstallationError, CommandError, PipError from pip.log import logger from pip.util import get_installed_distributions, get_prog from pip.vcs import git, mercurial, subversion, bazaar # noqa -from pip.baseparser import create_main_parser -from pip.commands import commands, get_similar_commands, get_summaries +from pip.baseparser import ConfigOptionParser, UpdatingDefaultsHelpFormatter +from pip.commands import commands, get_summaries, get_similar_commands +# This fixes a peculiarity when importing via __import__ - as we are +# initialising the pip module, "from pip import cmdoptions" is recursive +# and appears not to work properly in that situation. +import pip.cmdoptions +cmdoptions = pip.cmdoptions # The version as used in the setup.py and the docs conf.py -__version__ = "1.4.1" +__version__ = "1.5" + def autocomplete(): """Command and option completion for the main option parser (and options) @@ -59,7 +65,7 @@ def autocomplete(): print(dist) sys.exit(1) - subcommand = commands[subcommand_name](parser) + subcommand = commands[subcommand_name]() options += [(opt.get_opt_string(), opt.nargs) for opt in subcommand.parser.option_list_all if opt.help != optparse.SUPPRESS_HELP] @@ -89,45 +95,76 @@ def autocomplete(): sys.exit(1) -def parseopts(args): - parser = create_main_parser() +def create_main_parser(): + parser_kw = { + 'usage': '\n%prog [options]', + 'add_help_option': False, + 'formatter': UpdatingDefaultsHelpFormatter(), + 'name': 'global', + 'prog': get_prog(), + } + + parser = ConfigOptionParser(**parser_kw) + parser.disable_interspersed_args() + + pip_pkg_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + parser.version = 'pip %s from %s (python %s)' % ( + __version__, pip_pkg_dir, sys.version[:3]) + + # add the general options + gen_opts = cmdoptions.make_option_group(cmdoptions.general_group, parser) + parser.add_option_group(gen_opts) + parser.main = True # so the help formatter knows - # create command listing + # create command listing for description command_summaries = get_summaries() - description = [''] + ['%-27s %s' % (i, j) for i, j in command_summaries] parser.description = '\n'.join(description) - options, args = parser.parse_args(args) + return parser - if options.version: + +def parseopts(args): + parser = create_main_parser() + + # Note: parser calls disable_interspersed_args(), so the result of this call + # is to split the initial args into the general options before the + # subcommand and everything else. + # For example: + # args: ['--timeout=5', 'install', '--user', 'INITools'] + # general_options: ['--timeout==5'] + # args_else: ['install', '--user', 'INITools'] + general_options, args_else = parser.parse_args(args) + + # --version + if general_options.version: sys.stdout.write(parser.version) sys.stdout.write(os.linesep) sys.exit() - # pip || pip help || pip --help -> print_help() - if not args or (args[0] == 'help' and len(args) == 1): + # pip || pip help -> print_help() + if not args_else or (args_else[0] == 'help' and len(args_else) == 1): parser.print_help() sys.exit() - if not args: - msg = ('You must give a command ' - '(use "pip --help" to see a list of commands)') - raise CommandError(msg) + # the subcommand name + cmd_name = args_else[0].lower() - command = args[0].lower() + #all the args without the subcommand + cmd_args = args[:] + cmd_args.remove(args_else[0].lower()) - if command not in commands: - guess = get_similar_commands(command) + if cmd_name not in commands: + guess = get_similar_commands(cmd_name) - msg = ['unknown command "%s"' % command] + msg = ['unknown command "%s"' % cmd_name] if guess: msg.append('maybe you meant "%s"' % guess) raise CommandError(' - '.join(msg)) - return command, options, args, parser + return cmd_name, cmd_args def main(initial_args=None): @@ -137,15 +174,15 @@ def main(initial_args=None): autocomplete() try: - cmd_name, options, args, parser = parseopts(initial_args) + cmd_name, cmd_args = parseopts(initial_args) except PipError: e = sys.exc_info()[1] sys.stderr.write("ERROR: %s" % e) sys.stderr.write(os.linesep) sys.exit(1) - command = commands[cmd_name](parser) # see baseparser.Command - return command.main(args[1:], options) + command = commands[cmd_name]() + return command.main(cmd_args) def bootstrap(): diff --git a/awx/lib/site-packages/pip/_vendor/__init__.py b/awx/lib/site-packages/pip/_vendor/__init__.py new file mode 100644 index 0000000000..f233ca0d3a --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/__init__.py @@ -0,0 +1,8 @@ +""" +pip._vendor is for vendoring dependencies of pip to prevent needing pip to +depend on something external. + +Files inside of pip._vendor should be considered immutable and should only be +updated to versions from upstream. +""" +from __future__ import absolute_import diff --git a/awx/lib/site-packages/pip/_vendor/colorama/__init__.py b/awx/lib/site-packages/pip/_vendor/colorama/__init__.py new file mode 100644 index 0000000000..2d127fa8e2 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/colorama/__init__.py @@ -0,0 +1,7 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from .initialise import init, deinit, reinit +from .ansi import Fore, Back, Style +from .ansitowin32 import AnsiToWin32 + +VERSION = '0.2.7' + diff --git a/awx/lib/site-packages/pip/_vendor/colorama/ansi.py b/awx/lib/site-packages/pip/_vendor/colorama/ansi.py new file mode 100644 index 0000000000..fef40571dd --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/colorama/ansi.py @@ -0,0 +1,50 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +''' +This module generates ANSI character codes to printing colors to terminals. +See: http://en.wikipedia.org/wiki/ANSI_escape_code +''' + +CSI = '\033[' + +def code_to_chars(code): + return CSI + str(code) + 'm' + +class AnsiCodes(object): + def __init__(self, codes): + for name in dir(codes): + if not name.startswith('_'): + value = getattr(codes, name) + setattr(self, name, code_to_chars(value)) + +class AnsiFore: + BLACK = 30 + RED = 31 + GREEN = 32 + YELLOW = 33 + BLUE = 34 + MAGENTA = 35 + CYAN = 36 + WHITE = 37 + RESET = 39 + +class AnsiBack: + BLACK = 40 + RED = 41 + GREEN = 42 + YELLOW = 43 + BLUE = 44 + MAGENTA = 45 + CYAN = 46 + WHITE = 47 + RESET = 49 + +class AnsiStyle: + BRIGHT = 1 + DIM = 2 + NORMAL = 22 + RESET_ALL = 0 + +Fore = AnsiCodes( AnsiFore ) +Back = AnsiCodes( AnsiBack ) +Style = AnsiCodes( AnsiStyle ) + diff --git a/awx/lib/site-packages/pip/_vendor/colorama/ansitowin32.py b/awx/lib/site-packages/pip/_vendor/colorama/ansitowin32.py new file mode 100644 index 0000000000..d29060187c --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/colorama/ansitowin32.py @@ -0,0 +1,189 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import re +import sys + +from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style +from .winterm import WinTerm, WinColor, WinStyle +from .win32 import windll + + +if windll is not None: + winterm = WinTerm() + + +def is_a_tty(stream): + return hasattr(stream, 'isatty') and stream.isatty() + + +class StreamWrapper(object): + ''' + Wraps a stream (such as stdout), acting as a transparent proxy for all + attribute access apart from method 'write()', which is delegated to our + Converter instance. + ''' + def __init__(self, wrapped, converter): + # double-underscore everything to prevent clashes with names of + # attributes on the wrapped stream object. + self.__wrapped = wrapped + self.__convertor = converter + + def __getattr__(self, name): + return getattr(self.__wrapped, name) + + def write(self, text): + self.__convertor.write(text) + + +class AnsiToWin32(object): + ''' + Implements a 'write()' method which, on Windows, will strip ANSI character + sequences from the text, and if outputting to a tty, will convert them into + win32 function calls. + ''' + ANSI_RE = re.compile('\033\[((?:\d|;)*)([a-zA-Z])') + + def __init__(self, wrapped, convert=None, strip=None, autoreset=False): + # The wrapped stream (normally sys.stdout or sys.stderr) + self.wrapped = wrapped + + # should we reset colors to defaults after every .write() + self.autoreset = autoreset + + # create the proxy wrapping our output stream + self.stream = StreamWrapper(wrapped, self) + + on_windows = sys.platform.startswith('win') + + # should we strip ANSI sequences from our output? + if strip is None: + strip = on_windows + self.strip = strip + + # should we should convert ANSI sequences into win32 calls? + if convert is None: + convert = on_windows and is_a_tty(wrapped) + self.convert = convert + + # dict of ansi codes to win32 functions and parameters + self.win32_calls = self.get_win32_calls() + + # are we wrapping stderr? + self.on_stderr = self.wrapped is sys.stderr + + + def should_wrap(self): + ''' + True if this class is actually needed. If false, then the output + stream will not be affected, nor will win32 calls be issued, so + wrapping stdout is not actually required. This will generally be + False on non-Windows platforms, unless optional functionality like + autoreset has been requested using kwargs to init() + ''' + return self.convert or self.strip or self.autoreset + + + def get_win32_calls(self): + if self.convert and winterm: + return { + AnsiStyle.RESET_ALL: (winterm.reset_all, ), + AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), + AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), + AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), + AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), + AnsiFore.RED: (winterm.fore, WinColor.RED), + AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), + AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), + AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), + AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), + AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), + AnsiFore.WHITE: (winterm.fore, WinColor.GREY), + AnsiFore.RESET: (winterm.fore, ), + AnsiBack.BLACK: (winterm.back, WinColor.BLACK), + AnsiBack.RED: (winterm.back, WinColor.RED), + AnsiBack.GREEN: (winterm.back, WinColor.GREEN), + AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), + AnsiBack.BLUE: (winterm.back, WinColor.BLUE), + AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), + AnsiBack.CYAN: (winterm.back, WinColor.CYAN), + AnsiBack.WHITE: (winterm.back, WinColor.GREY), + AnsiBack.RESET: (winterm.back, ), + } + + + def write(self, text): + if self.strip or self.convert: + self.write_and_convert(text) + else: + self.wrapped.write(text) + self.wrapped.flush() + if self.autoreset: + self.reset_all() + + + def reset_all(self): + if self.convert: + self.call_win32('m', (0,)) + elif is_a_tty(self.wrapped): + self.wrapped.write(Style.RESET_ALL) + + + def write_and_convert(self, text): + ''' + Write the given text to our wrapped stream, stripping any ANSI + sequences from the text, and optionally converting them into win32 + calls. + ''' + cursor = 0 + for match in self.ANSI_RE.finditer(text): + start, end = match.span() + self.write_plain_text(text, cursor, start) + self.convert_ansi(*match.groups()) + cursor = end + self.write_plain_text(text, cursor, len(text)) + + + def write_plain_text(self, text, start, end): + if start < end: + self.wrapped.write(text[start:end]) + self.wrapped.flush() + + + def convert_ansi(self, paramstring, command): + if self.convert: + params = self.extract_params(paramstring) + self.call_win32(command, params) + + + def extract_params(self, paramstring): + def split(paramstring): + for p in paramstring.split(';'): + if p != '': + yield int(p) + return tuple(split(paramstring)) + + + def call_win32(self, command, params): + if params == []: + params = [0] + if command == 'm': + for param in params: + if param in self.win32_calls: + func_args = self.win32_calls[param] + func = func_args[0] + args = func_args[1:] + kwargs = dict(on_stderr=self.on_stderr) + func(*args, **kwargs) + elif command in ('H', 'f'): # set cursor position + func = winterm.set_cursor_position + func(params, on_stderr=self.on_stderr) + elif command in ('J'): + func = winterm.erase_data + func(params, on_stderr=self.on_stderr) + elif command == 'A': + if params == () or params == None: + num_rows = 1 + else: + num_rows = params[0] + func = winterm.cursor_up + func(num_rows, on_stderr=self.on_stderr) + diff --git a/awx/lib/site-packages/pip/_vendor/colorama/initialise.py b/awx/lib/site-packages/pip/_vendor/colorama/initialise.py new file mode 100644 index 0000000000..7c8e77611b --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/colorama/initialise.py @@ -0,0 +1,56 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import atexit +import sys + +from .ansitowin32 import AnsiToWin32 + + +orig_stdout = sys.stdout +orig_stderr = sys.stderr + +wrapped_stdout = sys.stdout +wrapped_stderr = sys.stderr + +atexit_done = False + + +def reset_all(): + AnsiToWin32(orig_stdout).reset_all() + + +def init(autoreset=False, convert=None, strip=None, wrap=True): + + if not wrap and any([autoreset, convert, strip]): + raise ValueError('wrap=False conflicts with any other arg=True') + + global wrapped_stdout, wrapped_stderr + sys.stdout = wrapped_stdout = \ + wrap_stream(orig_stdout, convert, strip, autoreset, wrap) + sys.stderr = wrapped_stderr = \ + wrap_stream(orig_stderr, convert, strip, autoreset, wrap) + + global atexit_done + if not atexit_done: + atexit.register(reset_all) + atexit_done = True + + +def deinit(): + sys.stdout = orig_stdout + sys.stderr = orig_stderr + + +def reinit(): + sys.stdout = wrapped_stdout + sys.stderr = wrapped_stdout + + +def wrap_stream(stream, convert, strip, autoreset, wrap): + if wrap: + wrapper = AnsiToWin32(stream, + convert=convert, strip=strip, autoreset=autoreset) + if wrapper.should_wrap(): + stream = wrapper.stream + return stream + + diff --git a/awx/lib/site-packages/pip/_vendor/colorama/win32.py b/awx/lib/site-packages/pip/_vendor/colorama/win32.py new file mode 100644 index 0000000000..f4024f95ee --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/colorama/win32.py @@ -0,0 +1,134 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. + +# from winbase.h +STDOUT = -11 +STDERR = -12 + +try: + from ctypes import windll + from ctypes import wintypes +except ImportError: + windll = None + SetConsoleTextAttribute = lambda *_: None +else: + from ctypes import ( + byref, Structure, c_char, c_short, c_uint32, c_ushort, POINTER + ) + + class CONSOLE_SCREEN_BUFFER_INFO(Structure): + """struct in wincon.h.""" + _fields_ = [ + ("dwSize", wintypes._COORD), + ("dwCursorPosition", wintypes._COORD), + ("wAttributes", wintypes.WORD), + ("srWindow", wintypes.SMALL_RECT), + ("dwMaximumWindowSize", wintypes._COORD), + ] + def __str__(self): + return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( + self.dwSize.Y, self.dwSize.X + , self.dwCursorPosition.Y, self.dwCursorPosition.X + , self.wAttributes + , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right + , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X + ) + + _GetStdHandle = windll.kernel32.GetStdHandle + _GetStdHandle.argtypes = [ + wintypes.DWORD, + ] + _GetStdHandle.restype = wintypes.HANDLE + + _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo + _GetConsoleScreenBufferInfo.argtypes = [ + wintypes.HANDLE, + POINTER(CONSOLE_SCREEN_BUFFER_INFO), + ] + _GetConsoleScreenBufferInfo.restype = wintypes.BOOL + + _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute + _SetConsoleTextAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + ] + _SetConsoleTextAttribute.restype = wintypes.BOOL + + _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition + _SetConsoleCursorPosition.argtypes = [ + wintypes.HANDLE, + wintypes._COORD, + ] + _SetConsoleCursorPosition.restype = wintypes.BOOL + + _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA + _FillConsoleOutputCharacterA.argtypes = [ + wintypes.HANDLE, + c_char, + wintypes.DWORD, + wintypes._COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputCharacterA.restype = wintypes.BOOL + + _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute + _FillConsoleOutputAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + wintypes.DWORD, + wintypes._COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputAttribute.restype = wintypes.BOOL + + handles = { + STDOUT: _GetStdHandle(STDOUT), + STDERR: _GetStdHandle(STDERR), + } + + def GetConsoleScreenBufferInfo(stream_id=STDOUT): + handle = handles[stream_id] + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return csbi + + def SetConsoleTextAttribute(stream_id, attrs): + handle = handles[stream_id] + return _SetConsoleTextAttribute(handle, attrs) + + def SetConsoleCursorPosition(stream_id, position): + position = wintypes._COORD(*position) + # If the position is out of range, do nothing. + if position.Y <= 0 or position.X <= 0: + return + # Adjust for Windows' SetConsoleCursorPosition: + # 1. being 0-based, while ANSI is 1-based. + # 2. expecting (x,y), while ANSI uses (y,x). + adjusted_position = wintypes._COORD(position.Y - 1, position.X - 1) + # Adjust for viewport's scroll position + sr = GetConsoleScreenBufferInfo(STDOUT).srWindow + adjusted_position.Y += sr.Top + adjusted_position.X += sr.Left + # Resume normal processing + handle = handles[stream_id] + return _SetConsoleCursorPosition(handle, adjusted_position) + + def FillConsoleOutputCharacter(stream_id, char, length, start): + handle = handles[stream_id] + char = c_char(char) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + success = _FillConsoleOutputCharacterA( + handle, char, length, start, byref(num_written)) + return num_written.value + + def FillConsoleOutputAttribute(stream_id, attr, length, start): + ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' + handle = handles[stream_id] + attribute = wintypes.WORD(attr) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + return _FillConsoleOutputAttribute( + handle, attribute, length, start, byref(num_written)) diff --git a/awx/lib/site-packages/pip/_vendor/colorama/winterm.py b/awx/lib/site-packages/pip/_vendor/colorama/winterm.py new file mode 100644 index 0000000000..4a711fde95 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/colorama/winterm.py @@ -0,0 +1,120 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from . import win32 + + +# from wincon.h +class WinColor(object): + BLACK = 0 + BLUE = 1 + GREEN = 2 + CYAN = 3 + RED = 4 + MAGENTA = 5 + YELLOW = 6 + GREY = 7 + +# from wincon.h +class WinStyle(object): + NORMAL = 0x00 # dim text, dim background + BRIGHT = 0x08 # bright text, dim background + + +class WinTerm(object): + + def __init__(self): + self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes + self.set_attrs(self._default) + self._default_fore = self._fore + self._default_back = self._back + self._default_style = self._style + + def get_attrs(self): + return self._fore + self._back * 16 + self._style + + def set_attrs(self, value): + self._fore = value & 7 + self._back = (value >> 4) & 7 + self._style = value & WinStyle.BRIGHT + + def reset_all(self, on_stderr=None): + self.set_attrs(self._default) + self.set_console(attrs=self._default) + + def fore(self, fore=None, on_stderr=False): + if fore is None: + fore = self._default_fore + self._fore = fore + self.set_console(on_stderr=on_stderr) + + def back(self, back=None, on_stderr=False): + if back is None: + back = self._default_back + self._back = back + self.set_console(on_stderr=on_stderr) + + def style(self, style=None, on_stderr=False): + if style is None: + style = self._default_style + self._style = style + self.set_console(on_stderr=on_stderr) + + def set_console(self, attrs=None, on_stderr=False): + if attrs is None: + attrs = self.get_attrs() + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleTextAttribute(handle, attrs) + + def get_position(self, handle): + position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition + # Because Windows coordinates are 0-based, + # and win32.SetConsoleCursorPosition expects 1-based. + position.X += 1 + position.Y += 1 + return position + + def set_cursor_position(self, position=None, on_stderr=False): + if position is None: + #I'm not currently tracking the position, so there is no default. + #position = self.get_position() + return + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleCursorPosition(handle, position) + + def cursor_up(self, num_rows=0, on_stderr=False): + if num_rows == 0: + return + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + position = self.get_position(handle) + adjusted_position = (position.Y - num_rows, position.X) + self.set_cursor_position(adjusted_position, on_stderr) + + def erase_data(self, mode=0, on_stderr=False): + # 0 (or None) should clear from the cursor to the end of the screen. + # 1 should clear from the cursor to the beginning of the screen. + # 2 should clear the entire screen. (And maybe move cursor to (1,1)?) + # + # At the moment, I only support mode 2. From looking at the API, it + # should be possible to calculate a different number of bytes to clear, + # and to do so relative to the cursor position. + if mode[0] not in (2,): + return + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + # here's where we'll home the cursor + coord_screen = win32.COORD(0,0) + csbi = win32.GetConsoleScreenBufferInfo(handle) + # get the number of character cells in the current buffer + dw_con_size = csbi.dwSize.X * csbi.dwSize.Y + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', dw_con_size, coord_screen) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), dw_con_size, coord_screen ); + # put the cursor at (0, 0) + win32.SetConsoleCursorPosition(handle, (coord_screen.X, coord_screen.Y)) diff --git a/awx/lib/site-packages/pip/vendor/distlib/__init__.py b/awx/lib/site-packages/pip/_vendor/distlib/__init__.py similarity index 95% rename from awx/lib/site-packages/pip/vendor/distlib/__init__.py rename to awx/lib/site-packages/pip/_vendor/distlib/__init__.py index d6ae0f2954..ed465f7e4a 100644 --- a/awx/lib/site-packages/pip/vendor/distlib/__init__.py +++ b/awx/lib/site-packages/pip/_vendor/distlib/__init__.py @@ -6,7 +6,7 @@ # import logging -__version__ = '0.1.1' +__version__ = '0.1.6' class DistlibException(Exception): pass diff --git a/awx/lib/site-packages/pip/vendor/distlib/_backport/__init__.py b/awx/lib/site-packages/pip/_vendor/distlib/_backport/__init__.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/distlib/_backport/__init__.py rename to awx/lib/site-packages/pip/_vendor/distlib/_backport/__init__.py diff --git a/awx/lib/site-packages/pip/vendor/distlib/_backport/misc.py b/awx/lib/site-packages/pip/_vendor/distlib/_backport/misc.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/distlib/_backport/misc.py rename to awx/lib/site-packages/pip/_vendor/distlib/_backport/misc.py diff --git a/awx/lib/site-packages/pip/vendor/distlib/_backport/shutil.py b/awx/lib/site-packages/pip/_vendor/distlib/_backport/shutil.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/distlib/_backport/shutil.py rename to awx/lib/site-packages/pip/_vendor/distlib/_backport/shutil.py diff --git a/awx/lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg b/awx/lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg new file mode 100644 index 0000000000..1746bd01c1 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg @@ -0,0 +1,84 @@ +[posix_prefix] +# Configuration directories. Some of these come straight out of the +# configure script. They are for implementing the other variables, not to +# be used directly in [resource_locations]. +confdir = /etc +datadir = /usr/share +libdir = /usr/lib +statedir = /var +# User resource directory +local = ~/.local/{distribution.name} + +stdlib = {base}/lib/python{py_version_short} +platstdlib = {platbase}/lib/python{py_version_short} +purelib = {base}/lib/python{py_version_short}/site-packages +platlib = {platbase}/lib/python{py_version_short}/site-packages +include = {base}/include/python{py_version_short}{abiflags} +platinclude = {platbase}/include/python{py_version_short}{abiflags} +data = {base} + +[posix_home] +stdlib = {base}/lib/python +platstdlib = {base}/lib/python +purelib = {base}/lib/python +platlib = {base}/lib/python +include = {base}/include/python +platinclude = {base}/include/python +scripts = {base}/bin +data = {base} + +[nt] +stdlib = {base}/Lib +platstdlib = {base}/Lib +purelib = {base}/Lib/site-packages +platlib = {base}/Lib/site-packages +include = {base}/Include +platinclude = {base}/Include +scripts = {base}/Scripts +data = {base} + +[os2] +stdlib = {base}/Lib +platstdlib = {base}/Lib +purelib = {base}/Lib/site-packages +platlib = {base}/Lib/site-packages +include = {base}/Include +platinclude = {base}/Include +scripts = {base}/Scripts +data = {base} + +[os2_home] +stdlib = {userbase}/lib/python{py_version_short} +platstdlib = {userbase}/lib/python{py_version_short} +purelib = {userbase}/lib/python{py_version_short}/site-packages +platlib = {userbase}/lib/python{py_version_short}/site-packages +include = {userbase}/include/python{py_version_short} +scripts = {userbase}/bin +data = {userbase} + +[nt_user] +stdlib = {userbase}/Python{py_version_nodot} +platstdlib = {userbase}/Python{py_version_nodot} +purelib = {userbase}/Python{py_version_nodot}/site-packages +platlib = {userbase}/Python{py_version_nodot}/site-packages +include = {userbase}/Python{py_version_nodot}/Include +scripts = {userbase}/Scripts +data = {userbase} + +[posix_user] +stdlib = {userbase}/lib/python{py_version_short} +platstdlib = {userbase}/lib/python{py_version_short} +purelib = {userbase}/lib/python{py_version_short}/site-packages +platlib = {userbase}/lib/python{py_version_short}/site-packages +include = {userbase}/include/python{py_version_short} +scripts = {userbase}/bin +data = {userbase} + +[osx_framework_user] +stdlib = {userbase}/lib/python +platstdlib = {userbase}/lib/python +purelib = {userbase}/lib/python/site-packages +platlib = {userbase}/lib/python/site-packages +include = {userbase}/include +scripts = {userbase}/bin +data = {userbase} diff --git a/awx/lib/site-packages/pip/vendor/distlib/_backport/sysconfig.py b/awx/lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py similarity index 99% rename from awx/lib/site-packages/pip/vendor/distlib/_backport/sysconfig.py rename to awx/lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py index 34e2ef1976..a5b55feb4e 100644 --- a/awx/lib/site-packages/pip/vendor/distlib/_backport/sysconfig.py +++ b/awx/lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py @@ -69,7 +69,8 @@ def _ensure_cfg_read(): global _cfg_read if not _cfg_read: from distlib.resources import finder - _finder = finder('distlib._backport') + backport_package = __name__.rsplit('.', 1)[0] + _finder = finder(backport_package) _cfgfile = _finder.find('sysconfig.cfg') assert _cfgfile, 'sysconfig.cfg exists' with _cfgfile.as_stream() as s: diff --git a/awx/lib/site-packages/pip/vendor/distlib/_backport/tarfile.py b/awx/lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/distlib/_backport/tarfile.py rename to awx/lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py diff --git a/awx/lib/site-packages/pip/vendor/distlib/compat.py b/awx/lib/site-packages/pip/_vendor/distlib/compat.py similarity index 69% rename from awx/lib/site-packages/pip/vendor/distlib/compat.py rename to awx/lib/site-packages/pip/_vendor/distlib/compat.py index fd2c1cb8e2..63af3742de 100644 --- a/awx/lib/site-packages/pip/vendor/distlib/compat.py +++ b/awx/lib/site-packages/pip/_vendor/distlib/compat.py @@ -53,6 +53,35 @@ if sys.version_info[0] < 3: if match: return match.group(1, 2) return None, host +else: + from io import StringIO + string_types = str, + text_type = str + from io import TextIOWrapper as file_type + import builtins + import configparser + import shutil + from urllib.parse import (urlparse, urlunparse, urljoin, splituser, quote, + unquote, urlsplit, urlunsplit, splittype) + from urllib.request import (urlopen, urlretrieve, Request, url2pathname, + pathname2url, + HTTPBasicAuthHandler, HTTPPasswordMgr, + HTTPSHandler, HTTPHandler, HTTPRedirectHandler, + build_opener) + from urllib.error import HTTPError, URLError, ContentTooShortError + import http.client as httplib + import urllib.request as urllib2 + import xmlrpc.client as xmlrpclib + import queue + from html.parser import HTMLParser + import html.entities as htmlentitydefs + raw_input = input + from itertools import filterfalse + filter = filter + +try: + from ssl import match_hostname, CertificateError +except ImportError: class CertificateError(ValueError): pass @@ -111,33 +140,84 @@ if sys.version_info[0] < 3: raise CertificateError("no appropriate commonName or " "subjectAltName fields were found") -else: - from io import StringIO - string_types = str, - text_type = str - from io import TextIOWrapper as file_type - import builtins - import configparser - import shutil - from urllib.parse import (urlparse, urlunparse, urljoin, splituser, quote, - unquote, urlsplit, urlunsplit, splittype) - from urllib.request import (urlopen, urlretrieve, Request, url2pathname, - pathname2url, - HTTPBasicAuthHandler, HTTPPasswordMgr, - HTTPSHandler, HTTPHandler, HTTPRedirectHandler, - build_opener) - from urllib.error import HTTPError, URLError, ContentTooShortError - import http.client as httplib - import urllib.request as urllib2 - import xmlrpc.client as xmlrpclib - import queue - from html.parser import HTMLParser - import html.entities as htmlentitydefs - raw_input = input - from itertools import filterfalse - filter = filter - from ssl import match_hostname, CertificateError +try: + from types import SimpleNamespace as Container +except ImportError: + class Container(object): + """ + A generic container for when multiple values need to be returned + """ + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + +try: + from shutil import which +except ImportError: + # Implementation from Python 3.3 + def which(cmd, mode=os.F_OK | os.X_OK, path=None): + """Given a command, mode, and a PATH string, return the path which + conforms to the given mode on the PATH, or None if there is no such + file. + + `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result + of os.environ.get("PATH"), or can be overridden with a custom search + path. + + """ + # Check that a given file can be accessed with the correct mode. + # Additionally check that `file` is not a directory, as on Windows + # directories pass the os.access check. + def _access_check(fn, mode): + return (os.path.exists(fn) and os.access(fn, mode) + and not os.path.isdir(fn)) + + # If we're given a path with a directory part, look it up directly rather + # than referring to PATH directories. This includes checking relative to the + # current directory, e.g. ./script + if os.path.dirname(cmd): + if _access_check(cmd, mode): + return cmd + return None + + if path is None: + path = os.environ.get("PATH", os.defpath) + if not path: + return None + path = path.split(os.pathsep) + + if sys.platform == "win32": + # The current directory takes precedence on Windows. + if not os.curdir in path: + path.insert(0, os.curdir) + + # PATHEXT is necessary to check on Windows. + pathext = os.environ.get("PATHEXT", "").split(os.pathsep) + # See if the given file matches any of the expected path extensions. + # This will allow us to short circuit when given "python.exe". + # If it does match, only test that one, otherwise we have to try + # others. + if any(cmd.lower().endswith(ext.lower()) for ext in pathext): + files = [cmd] + else: + files = [cmd + ext for ext in pathext] + else: + # On other platforms you don't have things like PATHEXT to tell you + # what file suffixes are executable, so just pass on cmd as-is. + files = [cmd] + + seen = set() + for dir in path: + normdir = os.path.normcase(dir) + if not normdir in seen: + seen.add(normdir) + for thefile in files: + name = os.path.join(dir, thefile) + if _access_check(name, mode): + return name + return None + # ZipFile is a context manager in 2.7, but not in 2.6 @@ -340,7 +420,10 @@ try: from html import escape except ImportError: from cgi import escape -unescape = HTMLParser().unescape +if sys.version_info[:2] < (3, 4): + unescape = HTMLParser().unescape +else: + from html import unescape try: from collections import ChainMap @@ -752,3 +835,230 @@ except ImportError: # pragma: no cover def viewitems(self): "od.viewitems() -> a set-like object providing a view on od's items" return ItemsView(self) + +try: + from logging.config import BaseConfigurator, valid_ident +except ImportError: # pragma: no cover + IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) + + + def valid_ident(s): + m = IDENTIFIER.match(s) + if not m: + raise ValueError('Not a valid Python identifier: %r' % s) + return True + + + # The ConvertingXXX classes are wrappers around standard Python containers, + # and they serve to convert any suitable values in the container. The + # conversion converts base dicts, lists and tuples to their wrapped + # equivalents, whereas strings which match a conversion format are converted + # appropriately. + # + # Each wrapper should have a configurator attribute holding the actual + # configurator to use for conversion. + + class ConvertingDict(dict): + """A converting dictionary wrapper.""" + + def __getitem__(self, key): + value = dict.__getitem__(self, key) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def get(self, key, default=None): + value = dict.get(self, key, default) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def pop(self, key, default=None): + value = dict.pop(self, key, default) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + class ConvertingList(list): + """A converting list wrapper.""" + def __getitem__(self, key): + value = list.__getitem__(self, key) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def pop(self, idx=-1): + value = list.pop(self, idx) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + return result + + class ConvertingTuple(tuple): + """A converting tuple wrapper.""" + def __getitem__(self, key): + value = tuple.__getitem__(self, key) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + class BaseConfigurator(object): + """ + The configurator base class which defines some useful defaults. + """ + + CONVERT_PATTERN = re.compile(r'^(?P[a-z]+)://(?P.*)$') + + WORD_PATTERN = re.compile(r'^\s*(\w+)\s*') + DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*') + INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*') + DIGIT_PATTERN = re.compile(r'^\d+$') + + value_converters = { + 'ext' : 'ext_convert', + 'cfg' : 'cfg_convert', + } + + # We might want to use a different one, e.g. importlib + importer = staticmethod(__import__) + + def __init__(self, config): + self.config = ConvertingDict(config) + self.config.configurator = self + + def resolve(self, s): + """ + Resolve strings to objects using standard import and attribute + syntax. + """ + name = s.split('.') + used = name.pop(0) + try: + found = self.importer(used) + for frag in name: + used += '.' + frag + try: + found = getattr(found, frag) + except AttributeError: + self.importer(used) + found = getattr(found, frag) + return found + except ImportError: + e, tb = sys.exc_info()[1:] + v = ValueError('Cannot resolve %r: %s' % (s, e)) + v.__cause__, v.__traceback__ = e, tb + raise v + + def ext_convert(self, value): + """Default converter for the ext:// protocol.""" + return self.resolve(value) + + def cfg_convert(self, value): + """Default converter for the cfg:// protocol.""" + rest = value + m = self.WORD_PATTERN.match(rest) + if m is None: + raise ValueError("Unable to convert %r" % value) + else: + rest = rest[m.end():] + d = self.config[m.groups()[0]] + #print d, rest + while rest: + m = self.DOT_PATTERN.match(rest) + if m: + d = d[m.groups()[0]] + else: + m = self.INDEX_PATTERN.match(rest) + if m: + idx = m.groups()[0] + if not self.DIGIT_PATTERN.match(idx): + d = d[idx] + else: + try: + n = int(idx) # try as number first (most likely) + d = d[n] + except TypeError: + d = d[idx] + if m: + rest = rest[m.end():] + else: + raise ValueError('Unable to convert ' + '%r at %r' % (value, rest)) + #rest should be empty + return d + + def convert(self, value): + """ + Convert values to an appropriate type. dicts, lists and tuples are + replaced by their converting alternatives. Strings are checked to + see if they have a conversion format and are converted if they do. + """ + if not isinstance(value, ConvertingDict) and isinstance(value, dict): + value = ConvertingDict(value) + value.configurator = self + elif not isinstance(value, ConvertingList) and isinstance(value, list): + value = ConvertingList(value) + value.configurator = self + elif not isinstance(value, ConvertingTuple) and\ + isinstance(value, tuple): + value = ConvertingTuple(value) + value.configurator = self + elif isinstance(value, string_types): + m = self.CONVERT_PATTERN.match(value) + if m: + d = m.groupdict() + prefix = d['prefix'] + converter = self.value_converters.get(prefix, None) + if converter: + suffix = d['suffix'] + converter = getattr(self, converter) + value = converter(suffix) + return value + + def configure_custom(self, config): + """Configure an object with a user-supplied factory.""" + c = config.pop('()') + if not callable(c): + c = self.resolve(c) + props = config.pop('.', None) + # Check for valid identifiers + kwargs = dict([(k, config[k]) for k in config if valid_ident(k)]) + result = c(**kwargs) + if props: + for name, value in props.items(): + setattr(result, name, value) + return result + + def as_tuple(self, value): + """Utility function which converts lists to tuples.""" + if isinstance(value, list): + value = tuple(value) + return value diff --git a/awx/lib/site-packages/pip/vendor/distlib/database.py b/awx/lib/site-packages/pip/_vendor/distlib/database.py similarity index 81% rename from awx/lib/site-packages/pip/vendor/distlib/database.py rename to awx/lib/site-packages/pip/_vendor/distlib/database.py index eb6444a5ee..0f013ec549 100644 --- a/awx/lib/site-packages/pip/vendor/distlib/database.py +++ b/awx/lib/site-packages/pip/_vendor/distlib/database.py @@ -9,19 +9,20 @@ from __future__ import unicode_literals import base64 import codecs +import contextlib import hashlib import logging import os +import posixpath import sys import zipimport -from . import DistlibException -from .compat import StringIO, configparser, string_types +from . import DistlibException, resources +from .compat import StringIO from .version import get_scheme, UnsupportedVersionError -from .markers import interpret -from .metadata import Metadata -from .util import (parse_requirement, cached_property, get_export_entry, - CSVReader, CSVWriter) +from .metadata import Metadata, METADATA_FILENAME +from .util import (parse_requirement, cached_property, parse_name_and_version, + read_exports, write_exports, CSVReader, CSVWriter) __all__ = ['Distribution', 'BaseInstalledDistribution', @@ -31,8 +32,11 @@ __all__ = ['Distribution', 'BaseInstalledDistribution', logger = logging.getLogger(__name__) -DIST_FILES = ('INSTALLER', 'METADATA', 'RECORD', 'REQUESTED', 'RESOURCES', - 'EXPORTS', 'SHARED') +EXPORTS_FILENAME = 'pydist-exports.json' +COMMANDS_FILENAME = 'pydist-commands.json' + +DIST_FILES = ('INSTALLER', METADATA_FILENAME, 'RECORD', 'REQUESTED', + 'RESOURCES', EXPORTS_FILENAME, 'SHARED') DISTINFO_EXT = '.dist-info' @@ -66,6 +70,7 @@ class _Cache(object): self.path[dist.path] = dist self.name.setdefault(dist.key, []).append(dist) + class DistributionPath(object): """ Represents a set of distributions installed on a path (typically sys.path). @@ -110,17 +115,39 @@ class DistributionPath(object): """ Yield .dist-info and/or .egg(-info) distributions. """ + # We need to check if we've seen some resources already, because on + # some Linux systems (e.g. some Debian/Ubuntu variants) there are + # symlinks which alias other files in the environment. + seen = set() for path in self.path: - realpath = os.path.realpath(path) - if not os.path.isdir(realpath): + finder = resources.finder_for_path(path) + if finder is None: continue - for dir in os.listdir(realpath): - dist_path = os.path.join(realpath, dir) - if self._include_dist and dir.endswith(DISTINFO_EXT): - yield new_dist_class(dist_path, env=self) - elif self._include_egg and dir.endswith(('.egg-info', - '.egg')): - yield old_dist_class(dist_path, self) + r = finder.find('') + if not r or not r.is_container: + continue + rset = sorted(r.resources) + for entry in rset: + r = finder.find(entry) + if not r or r.path in seen: + continue + if self._include_dist and entry.endswith(DISTINFO_EXT): + metadata_path = posixpath.join(entry, METADATA_FILENAME) + pydist = finder.find(metadata_path) + if not pydist: + continue + + metadata = Metadata(fileobj=pydist.as_stream(), + scheme='legacy') + logger.debug('Found %s', r.path) + seen.add(r.path) + yield new_dist_class(r.path, metadata=metadata, + env=self) + elif self._include_egg and entry.endswith(('.egg-info', + '.egg')): + logger.debug('Found %s', r.path) + seen.add(r.path) + yield old_dist_class(r.path, self) def _generate_cache(self): """ @@ -163,7 +190,6 @@ class DistributionPath(object): name = name.replace('-', '_') return '-'.join([name, version]) + DISTINFO_EXT - def get_distributions(self): """ Provides an iterator that looks for distributions and returns @@ -186,7 +212,6 @@ class DistributionPath(object): for dist in self._cache_egg.path.values(): yield dist - def get_distribution(self, name): """ Looks for a named distribution on the path. @@ -239,18 +264,12 @@ class DistributionPath(object): provided = dist.provides for p in provided: - p_components = p.rsplit(' ', 1) - if len(p_components) == 1 or matcher is None: - if name == p_components[0]: + p_name, p_ver = parse_name_and_version(p) + if matcher is None: + if p_name == name: yield dist break else: - p_name, p_ver = p_components - if len(p_ver) < 2 or p_ver[0] != '(' or p_ver[-1] != ')': - raise DistlibException( - 'distribution %r has invalid Provides field: %r' % - (dist.name, p)) - p_ver = p_ver[1:-1] # trim off the parenthesis if p_name == name and matcher.match(p_ver): yield dist break @@ -282,6 +301,7 @@ class DistributionPath(object): for v in d.values(): yield v + class Distribution(object): """ A base class for distributions, whether installed or from indexes. @@ -311,15 +331,18 @@ class Distribution(object): self.key = self.name.lower() # for case-insensitive comparisons self.version = metadata.version self.locator = None - self.md5_digest = None - self.extras = None # additional features requested during installation + self.digest = None + self.extras = None # additional features requested + self.context = None # environment marker overrides @property - def download_url(self): + def source_url(self): """ - The download URL for this distribution. + The source archive download URL for this distribution. """ - return self.metadata.download_url + return self.metadata.source_url + + download_url = source_url # Backward compatibility @property def name_and_version(self): @@ -334,56 +357,36 @@ class Distribution(object): A set of distribution names and versions provided by this distribution. :return: A set of "name (version)" strings. """ - plist = self.metadata['Provides-Dist'] + plist = self.metadata.provides s = '%s (%s)' % (self.name, self.version) if s not in plist: plist.append(s) - return self.filter_requirements(plist) + return plist + + def _get_requirements(self, req_attr): + reqts = getattr(self.metadata, req_attr) + return set(self.metadata.get_requirements(reqts, extras=self.extras, + env=self.context)) @property - def requires(self): - rlist = self.metadata['Requires-Dist'] - return self.filter_requirements(rlist) + def run_requires(self): + return self._get_requirements('run_requires') @property - def setup_requires(self): - rlist = self.metadata['Setup-Requires-Dist'] - return self.filter_requirements(rlist) + def meta_requires(self): + return self._get_requirements('meta_requires') + + @property + def build_requires(self): + return self._get_requirements('build_requires') @property def test_requires(self): - rlist = self.metadata['Requires-Dist'] - return self.filter_requirements(rlist, extras=['test']) + return self._get_requirements('test_requires') @property - def doc_requires(self): - rlist = self.metadata['Requires-Dist'] - return self.filter_requirements(rlist, extras=['doc']) - - def filter_requirements(self, rlist, context=None, extras=None): - result = set() - marked = [] - for req in rlist: - if ';' not in req: - result.add(req) - else: - marked.append(req.split(';', 1)) - if marked: - if context is None: - context = {} - if extras is None: - extras = self.extras - if not extras: - extras = [None] - else: - extras = list(extras) # leave original alone - extras.append(None) - for extra in extras: - context['extra'] = extra - for r, marker in marked: - if interpret(marker, context): - result.add(r.strip()) - return result + def dev_requires(self): + return self._get_requirements('dev_requires') def matches_requirement(self, req): """ @@ -392,9 +395,12 @@ class Distribution(object): :rtype req: str :return: True if it matches, else False. """ + # Requirement may contain extras - parse to lose those + # from what's passed to the matcher + r = parse_requirement(req) scheme = get_scheme(self.metadata.scheme) try: - matcher = scheme.matcher(req) + matcher = scheme.matcher(r.requirement) except UnsupportedVersionError: # XXX compat-mode if cannot read the version logger.warning('could not read version %r - using name only', @@ -405,15 +411,12 @@ class Distribution(object): name = matcher.key # case-insensitive result = False - # Note this is similar to code in make_graph - to be refactored for p in self.provides: - vm = scheme.matcher(p) - if vm.key != name: + p_name, p_ver = parse_name_and_version(p) + if p_name != name: continue - version = vm.exact_version - assert version try: - result = matcher.match(version) + result = matcher.match(p_ver) break except UnsupportedVersionError: pass @@ -423,8 +426,8 @@ class Distribution(object): """ Return a textual representation of this instance, """ - if self.download_url: - suffix = ' [%s]' % self.download_url + if self.source_url: + suffix = ' [%s]' % self.source_url else: suffix = '' return '' % (self.name, self.version, suffix) @@ -434,7 +437,7 @@ class Distribution(object): See if this distribution is the same as another. :param other: The distribution to compare with. To be equal to one another. distributions must have the same type, name, - version and download_url. + version and source_url. :return: True if it is the same, else False. """ if type(other) is not type(self): @@ -442,14 +445,14 @@ class Distribution(object): else: result = (self.name == other.name and self.version == other.version and - self.download_url == other.download_url) + self.source_url == other.source_url) return result def __hash__(self): """ Compute hash in a way which matches the equality test. """ - return hash(self.name) + hash(self.version) + hash(self.download_url) + return hash(self.name) + hash(self.version) + hash(self.source_url) class BaseInstalledDistribution(Distribution): @@ -473,7 +476,7 @@ class BaseInstalledDistribution(Distribution): """ super(BaseInstalledDistribution, self).__init__(metadata) self.path = path - self.dist_path = env + self.dist_path = env def get_hash(self, data, hasher=None): """ @@ -506,28 +509,44 @@ class BaseInstalledDistribution(Distribution): digest = base64.urlsafe_b64encode(digest).rstrip(b'=').decode('ascii') return '%s%s' % (prefix, digest) + class InstalledDistribution(BaseInstalledDistribution): - """Created with the *path* of the ``.dist-info`` directory provided to the - constructor. It reads the metadata contained in ``METADATA`` when it is + """ + Created with the *path* of the ``.dist-info`` directory provided to the + constructor. It reads the metadata contained in ``pydist.json`` when it is instantiated., or uses a passed in Metadata instance (useful for when - dry-run mode is being used).""" + dry-run mode is being used). + """ hasher = 'sha256' def __init__(self, path, metadata=None, env=None): + self.finder = finder = resources.finder_for_path(path) + if finder is None: + import pdb; pdb.set_trace () if env and env._cache_enabled and path in env._cache.path: metadata = env._cache.path[path].metadata elif metadata is None: - metadata_path = os.path.join(path, 'METADATA') - metadata = Metadata(path=metadata_path, scheme='legacy') + r = finder.find(METADATA_FILENAME) + # Temporary - for legacy support + if r is None: + r = finder.find('METADATA') + if r is None: + raise ValueError('no %s found in %s' % (METADATA_FILENAME, + path)) + with contextlib.closing(r.as_stream()) as stream: + metadata = Metadata(fileobj=stream, scheme='legacy') super(InstalledDistribution, self).__init__(metadata, path, env) if env and env._cache_enabled: env._cache.add(self) - path = self.get_distinfo_file('REQUESTED') - self.requested = os.path.exists(path) + try: + r = finder.find('REQUESTED') + except AttributeError: + import pdb; pdb.set_trace () + self.requested = r is not None def __repr__(self): return '' % ( @@ -544,84 +563,60 @@ class InstalledDistribution(BaseInstalledDistribution): as stored in the file (which is as in PEP 376). """ results = [] - path = self.get_distinfo_file('RECORD') - with CSVReader(path) as record_reader: - # Base location is parent dir of .dist-info dir - #base_location = os.path.dirname(self.path) - #base_location = os.path.abspath(base_location) - for row in record_reader: - missing = [None for i in range(len(row), 3)] - path, checksum, size = row + missing - #if not os.path.isabs(path): - # path = path.replace('/', os.sep) - # path = os.path.join(base_location, path) - results.append((path, checksum, size)) + r = self.get_distinfo_resource('RECORD') + with contextlib.closing(r.as_stream()) as stream: + with CSVReader(stream=stream) as record_reader: + # Base location is parent dir of .dist-info dir + #base_location = os.path.dirname(self.path) + #base_location = os.path.abspath(base_location) + for row in record_reader: + missing = [None for i in range(len(row), 3)] + path, checksum, size = row + missing + #if not os.path.isabs(path): + # path = path.replace('/', os.sep) + # path = os.path.join(base_location, path) + results.append((path, checksum, size)) return results @cached_property def exports(self): """ Return the information exported by this distribution. - :return: A dictionary of exports, mapping an export category to a list + :return: A dictionary of exports, mapping an export category to a dict of :class:`ExportEntry` instances describing the individual - export entries. + export entries, and keyed by name. """ result = {} - rf = self.get_distinfo_file('EXPORTS') - if os.path.exists(rf): - result = self.read_exports(rf) + r = self.get_distinfo_resource(EXPORTS_FILENAME) + if r: + result = self.read_exports() return result - def read_exports(self, filename=None): + def read_exports(self): """ Read exports data from a file in .ini format. - :param filename: An absolute pathname of the file to read. If not - specified, the EXPORTS file in the .dist-info - directory of the distribution is read. + :return: A dictionary of exports, mapping an export category to a list of :class:`ExportEntry` instances describing the individual export entries. """ result = {} - rf = filename or self.get_distinfo_file('EXPORTS') - if os.path.exists(rf): - cp = configparser.ConfigParser() - cp.read(rf) - for key in cp.sections(): - result[key] = entries = {} - for name, value in cp.items(key): - s = '%s = %s' % (name, value) - entry = get_export_entry(s) - assert entry is not None - entry.dist = self - entries[name] = entry + r = self.get_distinfo_resource(EXPORTS_FILENAME) + if r: + with contextlib.closing(r.as_stream()) as stream: + result = read_exports(stream) return result - def write_exports(self, exports, filename=None): + def write_exports(self, exports): """ Write a dictionary of exports to a file in .ini format. :param exports: A dictionary of exports, mapping an export category to a list of :class:`ExportEntry` instances describing the individual export entries. - :param filename: The absolute pathname of the file to write to. If not - specified, the EXPORTS file in the .dist-info - directory is written to. """ - rf = filename or self.get_distinfo_file('EXPORTS') - cp = configparser.ConfigParser() - for k, v in exports.items(): - # TODO check k, v for valid values - cp.add_section(k) - for entry in v.values(): - if entry.suffix is None: - s = entry.prefix - else: - s = '%s:%s' % (entry.prefix, entry.suffix) - if entry.flags: - s = '%s [%s]' % (s, ', '.join(entry.flags)) - cp.set(k, entry.name, s) + rf = self.get_distinfo_file(EXPORTS_FILENAME) with open(rf, 'w') as f: - cp.write(f) + write_exports(exports, f) def get_resource_path(self, relative_path): """ @@ -634,11 +629,12 @@ class InstalledDistribution(BaseInstalledDistribution): of interest. :return: The absolute path where the resource is to be found. """ - path = self.get_distinfo_file('RESOURCES') - with CSVReader(path) as resources_reader: - for relative, destination in resources_reader: - if relative == relative_path: - return destination + r = self.get_distinfo_resource('RESOURCES') + with contextlib.closing(r.as_stream()) as stream: + with CSVReader(stream=stream) as resources_reader: + for relative, destination in resources_reader: + if relative == relative_path: + return destination raise KeyError('no resource file with relative path %r ' 'is installed' % relative_path) @@ -663,10 +659,10 @@ class InstalledDistribution(BaseInstalledDistribution): base = os.path.dirname(self.path) base_under_prefix = base.startswith(prefix) base = os.path.join(base, '') - record_path = os.path.join(self.path, 'RECORD') + record_path = self.get_distinfo_file('RECORD') logger.info('creating %s', record_path) if dry_run: - return + return None with CSVWriter(record_path) as writer: for path in paths: if os.path.isdir(path) or path.endswith(('.pyc', '.pyo')): @@ -677,7 +673,7 @@ class InstalledDistribution(BaseInstalledDistribution): with open(path, 'rb') as fp: hash_value = self.get_hash(fp.read()) if path.startswith(base) or (base_under_prefix and - path.startswith(prefix)): + path.startswith(prefix)): path = os.path.relpath(path, base) writer.writerow((path, hash_value, size)) @@ -685,6 +681,7 @@ class InstalledDistribution(BaseInstalledDistribution): if record_path.startswith(base): record_path = os.path.relpath(record_path, base) writer.writerow((record_path, '', '')) + return record_path def check_installed_files(self): """ @@ -697,7 +694,7 @@ class InstalledDistribution(BaseInstalledDistribution): """ mismatches = [] base = os.path.dirname(self.path) - record_path = os.path.join(self.path, 'RECORD') + record_path = self.get_distinfo_file('RECORD') for path, hash_value, size in self.list_installed_files(): if not os.path.isabs(path): path = os.path.join(base, path) @@ -760,7 +757,7 @@ class InstalledDistribution(BaseInstalledDistribution): shared_path = os.path.join(self.path, 'SHARED') logger.info('creating %s', shared_path) if dry_run: - return + return None lines = [] for key in ('prefix', 'lib', 'headers', 'scripts', 'data'): path = paths[key] @@ -773,6 +770,15 @@ class InstalledDistribution(BaseInstalledDistribution): f.write('\n'.join(lines)) return shared_path + def get_distinfo_resource(self, path): + if path not in DIST_FILES: + raise DistlibException('invalid path for a dist-info file: ' + '%r at %r' % (path, self.path)) + finder = resources.finder_for_path(self.path) + if finder is None: + raise DistlibException('Unable to get a finder for %s' % self.path) + return finder.find(path) + def get_distinfo_file(self, path): """ Returns a path located under the ``.dist-info`` directory. Returns a @@ -783,7 +789,7 @@ class InstalledDistribution(BaseInstalledDistribution): If *path* is an absolute path and doesn't start with the ``.dist-info`` directory path, a :class:`DistlibException` is raised - :type path: string + :type path: str :rtype: str """ # Check if it is an absolute path # XXX use relpath, add tests @@ -797,8 +803,8 @@ class InstalledDistribution(BaseInstalledDistribution): # The file must be relative if path not in DIST_FILES: - raise DistlibException('invalid path for a dist-info file: %r' % - path) + raise DistlibException('invalid path for a dist-info file: ' + '%r at %r' % (path, self.path)) return os.path.join(self.path, path) @@ -842,15 +848,15 @@ class EggInfoDistribution(BaseInstalledDistribution): s.version = v self.path = path - self.dist_path = env + self.dist_path = env if env and env._cache_enabled and path in env._cache_egg.path: metadata = env._cache_egg.path[path].metadata - set_name_and_version(self, metadata['Name'], metadata['Version']) + set_name_and_version(self, metadata.name, metadata.version) else: metadata = self._get_metadata(path) # Need to be set before caching - set_name_and_version(self, metadata['Name'], metadata['Version']) + set_name_and_version(self, metadata.name, metadata.version) if env and env._cache_enabled: env._cache_egg.add(self) @@ -859,19 +865,13 @@ class EggInfoDistribution(BaseInstalledDistribution): def _get_metadata(self, path): requires = None - def parse_requires(req_path): + def parse_requires_data(data): """Create a list of dependencies from a requires.txt file. - *req_path* must be the path to a setuptools-produced requires.txt file. + *data*: the contents of a setuptools-produced requires.txt file. """ - reqs = [] - try: - with open(req_path, 'r') as fp: - lines = fp.read().splitlines() - except IOError: - return reqs - + lines = data.splitlines() for line in lines: line = line.strip() if line.startswith('['): @@ -892,12 +892,26 @@ class EggInfoDistribution(BaseInstalledDistribution): reqs.append('%s (%s)' % (r.name, cons)) return reqs + def parse_requires_path(req_path): + """Create a list of dependencies from a requires.txt file. + + *req_path*: the path to a setuptools-produced requires.txt file. + """ + + reqs = [] + try: + with codecs.open(req_path, 'r', 'utf-8') as fp: + reqs = parse_requires_data(fp.read()) + except IOError: + pass + return reqs + if path.endswith('.egg'): if os.path.isdir(path): meta_path = os.path.join(path, 'EGG-INFO', 'PKG-INFO') metadata = Metadata(path=meta_path, scheme='legacy') req_path = os.path.join(path, 'EGG-INFO', 'requires.txt') - requires = parse_requires(req_path) + requires = parse_requires_path(req_path) else: # FIXME handle the case where zipfile is not available zipf = zipimport.zipimporter(path) @@ -905,26 +919,22 @@ class EggInfoDistribution(BaseInstalledDistribution): zipf.get_data('EGG-INFO/PKG-INFO').decode('utf8')) metadata = Metadata(fileobj=fileobj, scheme='legacy') try: - requires = zipf.get_data('EGG-INFO/requires.txt') + data = zipf.get_data('EGG-INFO/requires.txt') + requires = parse_requires_data(data.decode('utf-8')) except IOError: requires = None elif path.endswith('.egg-info'): if os.path.isdir(path): path = os.path.join(path, 'PKG-INFO') req_path = os.path.join(path, 'requires.txt') - requires = parse_requires(req_path) + requires = parse_requires_path(req_path) metadata = Metadata(path=path, scheme='legacy') else: raise DistlibException('path must end with .egg-info or .egg, ' 'got %r' % path) if requires: - if metadata['Metadata-Version'] == '1.1': - # we can't have 1.1 metadata *and* Setuptools requires - for field in ('Obsoletes', 'Requires', 'Provides'): - if field in metadata: - del metadata[field] - metadata['Requires-Dist'] += requires + metadata.add_requirements(requires) return metadata def __repr__(self): @@ -946,14 +956,14 @@ class EggInfoDistribution(BaseInstalledDistribution): mismatches = [] record_path = os.path.join(self.path, 'installed-files.txt') if os.path.exists(record_path): - for path, hash, size in self.list_installed_files(): + for path, _, _ in self.list_installed_files(): if path == record_path: continue if not os.path.exists(path): mismatches.append((path, 'exists', True, False)) return mismatches - def list_installed_files(self, local=False): + def list_installed_files(self): """ Iterates over the ``installed-files.txt`` entries and returns a tuple ``(path, hash, size)`` for each line. @@ -991,16 +1001,16 @@ class EggInfoDistribution(BaseInstalledDistribution): result.append((record_path, None, None)) return result - def list_distinfo_files(self, local=False): + def list_distinfo_files(self, absolute=False): """ Iterates over the ``installed-files.txt`` entries and returns paths for each line if the path is pointing to a file located in the ``.egg-info`` directory or one of its subdirectories. - :parameter local: If *local* is ``True``, each returned path is + :parameter absolute: If *absolute* is ``True``, each returned path is transformed into a local absolute path. Otherwise the raw value from ``installed-files.txt`` is returned. - :type local: boolean + :type absolute: boolean :returns: iterator of paths """ record_path = os.path.join(self.path, 'installed-files.txt') @@ -1014,7 +1024,7 @@ class EggInfoDistribution(BaseInstalledDistribution): if not skip: p = os.path.normpath(os.path.join(self.path, line)) if p.startswith(self.path): - if local: + if absolute: yield p else: yield line @@ -1121,7 +1131,7 @@ class DependencyGraph(object): for other, label in adjs: if not label is None: f.write('"%s" -> "%s" [label="%s"]\n' % - (dist.name, other.name, label)) + (dist.name, other.name, label)) else: f.write('"%s" -> "%s"\n' % (dist.name, other.name)) if not skip_disconnected and len(disconnected) > 0: @@ -1162,7 +1172,7 @@ class DependencyGraph(object): for k, v in alist.items(): alist[k] = [(d, r) for d, r in v if d not in to_remove] logger.debug('Moving to result: %s', - ['%s (%s)' % (d.name, d.version) for d in to_remove]) + ['%s (%s)' % (d.name, d.version) for d in to_remove]) result.extend(to_remove) return result, list(alist.keys()) @@ -1191,28 +1201,14 @@ def make_graph(dists, scheme='default'): graph.add_distribution(dist) for p in dist.provides: - comps = p.strip().rsplit(" ", 1) - name = comps[0] - version = None - if len(comps) == 2: - version = comps[1] - if len(version) < 3 or version[0] != '(' or version[-1] != ')': - logger.warning('distribution %r has ill-formed ' - 'provides field: %r', dist.name, p) - continue - # don't raise an exception. Legacy installed distributions - # could have all manner of metadata - #raise DistlibException('distribution %r has ill-formed ' - # 'provides field: %r' % (dist.name, p)) - version = version[1:-1] # trim off parenthesis - # Add name in lower case for case-insensitivity - name = name.lower() + name, version = parse_name_and_version(p) logger.debug('Add to provided: %s, %s, %s', name, version, dist) provided.setdefault(name, []).append((version, dist)) # now make the edges for dist in dists: - requires = (dist.requires | dist.setup_requires) + requires = (dist.run_requires | dist.meta_requires | + dist.build_requires | dist.dev_requires) for req in requires: try: matcher = scheme.matcher(req) @@ -1267,6 +1263,7 @@ def get_dependent_dists(dists, dist): dep.pop(0) # remove dist from dep, was there to prevent infinite loops return dep + def get_required_dists(dists, dist): """Recursively generate a list of distributions from *dists* that are required by *dist*. @@ -1291,11 +1288,14 @@ def get_required_dists(dists, dist): return req + def make_dist(name, version, **kwargs): """ A convenience method for making a dist given just a name and version. """ + summary = kwargs.pop('summary', 'Placeholder for summary') md = Metadata(**kwargs) - md['Name'] = name - md['Version'] = version + md.name = name + md.version = version + md.summary = summary or 'Plaeholder for summary' return Distribution(md) diff --git a/awx/lib/site-packages/pip/vendor/distlib/index.py b/awx/lib/site-packages/pip/_vendor/distlib/index.py similarity index 87% rename from awx/lib/site-packages/pip/vendor/distlib/index.py rename to awx/lib/site-packages/pip/_vendor/distlib/index.py index 282f6b7455..30b2aa5a50 100644 --- a/awx/lib/site-packages/pip/vendor/distlib/index.py +++ b/awx/lib/site-packages/pip/_vendor/distlib/index.py @@ -5,15 +5,15 @@ # See LICENSE.txt and CONTRIBUTORS.txt. # import hashlib -import itertools import logging import os import shutil -import socket -from string import ascii_lowercase import subprocess import tempfile -from threading import Thread +try: + from threading import Thread +except ImportError: + from dummy_threading import Thread from distlib import DistlibException from distlib.compat import (HTTPBasicAuthHandler, Request, HTTPPasswordMgr, @@ -22,8 +22,7 @@ from distlib.util import cached_property, zip_dir logger = logging.getLogger(__name__) -DEFAULT_MIRROR_HOST = 'last.pypi.python.org' -DEFAULT_INDEX = 'http://pypi.python.org/pypi' +DEFAULT_INDEX = 'https://pypi.python.org/pypi' DEFAULT_REALM = 'pypi' class PackageIndex(object): @@ -34,23 +33,14 @@ class PackageIndex(object): boundary = b'----------ThIs_Is_tHe_distlib_index_bouNdaRY_$' - def __init__(self, url=None, mirror_host=None): + def __init__(self, url=None): """ Initialise an instance. :param url: The URL of the index. If not specified, the URL for PyPI is used. - :param mirror_host: If not specified, ``last.pypi.python.org`` is used. - This is expected to have a canonial name which - allows all mirror hostnames to be divined (e.g. if - the canonical hostname for ``last.pypi.python.org`` - is ``g.pypi.python.org``, then the mirrors that are - available would be assumed to be - ``a.pypi.python.org``, ``b.pypi.python.org``, ... - up to and including ``g.pypi.python.org``. """ self.url = url or DEFAULT_INDEX - self.mirror_host = mirror_host or DEFAULT_MIRROR_HOST self.read_configuration() scheme, netloc, path, params, query, frag = urlparse(self.url) if params or query or frag or scheme not in ('http', 'https'): @@ -130,10 +120,8 @@ class PackageIndex(object): request. """ self.check_credentials() - missing, warnings = metadata.check(True) # strict check - logger.debug('result of check: missing: %s, warnings: %s', - missing, warnings) - d = metadata.todict(True) + metadata.validate() + d = metadata.todict() d[':action'] = 'verify' request = self.encode_request(d.items(), []) response = self.send_request(request) @@ -259,10 +247,8 @@ class PackageIndex(object): self.check_credentials() if not os.path.exists(filename): raise DistlibException('not found: %s' % filename) - missing, warnings = metadata.check(True) # strict check - logger.debug('result of check: missing: %s, warnings: %s', - missing, warnings) - d = metadata.todict(True) + metadata.validate() + d = metadata.todict() sig_file = None if signer: if not self.gpg: @@ -271,13 +257,15 @@ class PackageIndex(object): sig_file = self.sign_file(filename, signer, sign_password) with open(filename, 'rb') as f: file_data = f.read() - digest = hashlib.md5(file_data).hexdigest() + md5_digest = hashlib.md5(file_data).hexdigest() + sha256_digest = hashlib.sha256(file_data).hexdigest() d.update({ ':action': 'file_upload', 'protcol_version': '1', 'filetype': filetype, 'pyversion': pyversion, - 'md5_digest': digest, + 'md5_digest': md5_digest, + 'sha256_digest': sha256_digest, }) files = [('content', os.path.basename(filename), file_data)] if sig_file: @@ -286,7 +274,6 @@ class PackageIndex(object): files.append(('gpg_signature', os.path.basename(sig_file), sig_data)) shutil.rmtree(os.path.dirname(sig_file)) - logger.debug('files: %s', files) request = self.encode_request(d.items(), files) return self.send_request(request) @@ -309,9 +296,7 @@ class PackageIndex(object): fn = os.path.join(doc_dir, 'index.html') if not os.path.exists(fn): raise DistlibException('not found: %r' % fn) - missing, warnings = metadata.check(True) # strict check - logger.debug('result of check: missing: %s, warnings: %s', - missing, warnings) + metadata.validate() name, version = metadata.name, metadata.version zip_data = zip_dir(doc_dir).getvalue() fields = [(':action', 'doc_upload'), @@ -382,12 +367,14 @@ class PackageIndex(object): """ if digest is None: digester = None + logger.debug('No digest specified') else: if isinstance(digest, (list, tuple)): hasher, digest = digest else: hasher = 'md5' digester = getattr(hashlib, hasher)() + logger.debug('Digest specified: %s' % digest) # The following code is equivalent to urlretrieve. # We need to do it this way so that we can compute the # digest of the file as we go. @@ -428,9 +415,10 @@ class PackageIndex(object): if digester: actual = digester.hexdigest() if digest != actual: - raise DistlibException('MD5 digest mismatch for %s: expected ' - '%s, got %s' % (destfile, digest, - actual)) + raise DistlibException('%s digest mismatch for %s: expected ' + '%s, got %s' % (hasher, destfile, + digest, actual)) + logger.debug('Digest verified: %s', digest) def send_request(self, req): """ @@ -490,26 +478,3 @@ class PackageIndex(object): 'Content-length': str(len(body)) } return Request(self.url, body, headers) - - @cached_property - def mirrors(self): - """ - Return the list of hostnames which are mirrors for this index. - :return: A (possibly empty) list of hostnames of mirrors. - """ - result = [] - try: - host = socket.gethostbyname_ex(self.mirror_host)[0] - except socket.gaierror: # pragma: no cover - host = None - if host: - last, rest = host.split('.', 1) - n = len(last) - host_list = (''.join(w) for w in itertools.chain.from_iterable( - itertools.product(ascii_lowercase, repeat=i) - for i in range(1, n + 1))) - for s in host_list: - result.append('.'.join((s, rest))) - if s == last: - break - return result diff --git a/awx/lib/site-packages/pip/vendor/distlib/locators.py b/awx/lib/site-packages/pip/_vendor/distlib/locators.py similarity index 86% rename from awx/lib/site-packages/pip/vendor/distlib/locators.py rename to awx/lib/site-packages/pip/_vendor/distlib/locators.py index 3dab8a2fcb..ffe99310f6 100644 --- a/awx/lib/site-packages/pip/vendor/distlib/locators.py +++ b/awx/lib/site-packages/pip/_vendor/distlib/locators.py @@ -12,7 +12,10 @@ import logging import os import posixpath import re -import threading +try: + import threading +except ImportError: + import dummy_threading as threading import zlib from . import DistlibException @@ -24,13 +27,13 @@ from .database import Distribution, DistributionPath, make_dist from .metadata import Metadata from .util import (cached_property, parse_credentials, ensure_slash, split_filename, get_project_data, parse_requirement, - ServerProxy) + parse_name_and_version, ServerProxy) from .version import get_scheme, UnsupportedVersionError from .wheel import Wheel, is_compatible logger = logging.getLogger(__name__) -MD5_HASH = re.compile('^md5=([a-f0-9]+)$') +HASHER_HASH = re.compile('^(\w+)=([a-f0-9]+)') CHARSET = re.compile(r';\s*charset\s*=\s*(.*)\s*$', re.I) HTML_CONTENT_TYPE = re.compile('text/html|application/x(ht)?ml') DEFAULT_INDEX = 'http://python.org/pypi' @@ -106,6 +109,10 @@ class Locator(object): # Because of bugs in some of the handlers on some of the platforms, # we use our own opener rather than just using urlopen. self.opener = build_opener(RedirectHandler()) + # If get_project() is called from locate(), the matcher instance + # is set from the requirement passed to locate(). See issue #18 for + # why this can be useful to know. + self.matcher = None def clear_cache(self): self._cache.clear() @@ -124,6 +131,9 @@ class Locator(object): instances. This should be implemented in subclasses. + + If called from a locate() request, self.matcher will be set to a + matcher for the requirement to satisfy, otherwise it will be None. """ raise NotImplementedError('Please implement in the subclass') @@ -167,10 +177,8 @@ class Locator(object): The current implement favours http:// URLs over https://, archives from PyPI over those from other locations and then the archive name. """ - if url1 == 'UNKNOWN': - result = url2 - else: - result = url2 + result = url2 + if url1: s1 = self.score_url(url1) s2 = self.score_url(url2) if s1 > s2: @@ -210,6 +218,11 @@ class Locator(object): if frag.lower().startswith('egg='): logger.debug('%s: version hint in fragment: %r', project_name, frag) + m = HASHER_HASH.match(frag) + if m: + algo, digest = m.groups() + else: + algo, digest = None, None origpath = path if path and path[-1] == '/': path = path[:-1] @@ -231,9 +244,6 @@ class Locator(object): 'python-version': ', '.join( ['.'.join(list(v[2:])) for v in wheel.pyver]), } - m = MD5_HASH.match(frag) - if m: - result['md5_digest'] = m.group(1) except Exception as e: logger.warning('invalid path for wheel: %s', path) elif path.endswith(self.downloadable_extensions): @@ -257,10 +267,25 @@ class Locator(object): } if pyver: result['python-version'] = pyver - m = MD5_HASH.match(frag) - if m: - result['md5_digest'] = m.group(1) break + if result and algo: + result['%s_digest' % algo] = digest + return result + + def _get_digest(self, info): + """ + Get a digest from a dictionary by looking at keys of the form + 'algo_digest'. + + Returns a 2-tuple (algo, digest) if found, else None. Currently + looks only for SHA256, then MD5. + """ + result = None + for algo in ('sha256', 'md5'): + key = '%s_digest' % algo + if key in info: + result = (algo, info[key]) + break return result def _update_version_data(self, result, info): @@ -277,12 +302,9 @@ class Locator(object): else: dist = make_dist(name, version, scheme=self.scheme) md = dist.metadata - dist.md5_digest = info.get('md5_digest') - if 'python-version' in info: - md['Requires-Python'] = info['python-version'] - if md['Download-URL'] != info['url']: - md['Download-URL'] = self.prefer_url(md['Download-URL'], - info['url']) + dist.digest = self._get_digest(info) + if md.source_url != info['url']: + md.source_url = self.prefer_url(md.source_url, info['url']) dist.locator = self result[version] = dist @@ -300,20 +322,17 @@ class Locator(object): distribution could be located. """ result = None - scheme = get_scheme(self.scheme) r = parse_requirement(requirement) if r is None: raise DistlibException('Not a valid requirement: %r' % requirement) - if r.extras: - # lose the extras part of the requirement - requirement = r.requirement - matcher = scheme.matcher(requirement) - vcls = matcher.version_class + scheme = get_scheme(self.scheme) + self.matcher = matcher = scheme.matcher(r.requirement) logger.debug('matcher: %s (%s)', matcher, type(matcher).__name__) - versions = self.get_project(matcher.name) + versions = self.get_project(r.name) if versions: # sometimes, versions are invalid slist = [] + vcls = matcher.version_class for k in versions: try: if not matcher.match(k): @@ -322,7 +341,8 @@ class Locator(object): if prereleases or not vcls(k).is_prerelease: slist.append(k) else: - logger.debug('skipping pre-release version %s', k) + logger.debug('skipping pre-release ' + 'version %s of %s', k, matcher.name) except Exception: logger.warning('error matching %s with %r', matcher, k) pass # slist.append(k) @@ -333,13 +353,14 @@ class Locator(object): result = versions[slist[-1]] if result and r.extras: result.extras = r.extras + self.matcher = None return result class PyPIRPCLocator(Locator): """ - This locator uses XML-RPC to locate distributions. It therefore cannot be - used with simple mirrors (that only mirror file content). + This locator uses XML-RPC to locate distributions. It therefore + cannot be used with simple mirrors (that only mirror file content). """ def __init__(self, url, **kwargs): """ @@ -365,12 +386,16 @@ class PyPIRPCLocator(Locator): urls = self.client.release_urls(name, v) data = self.client.release_data(name, v) metadata = Metadata(scheme=self.scheme) - metadata.update(data) + metadata.name = data['name'] + metadata.version = data['version'] + metadata.license = data.get('license') + metadata.keywords = data.get('keywords', []) + metadata.summary = data.get('summary') dist = Distribution(metadata) if urls: info = urls[0] - metadata['Download-URL'] = info['url'] - dist.md5_digest = info.get('md5_digest') + metadata.source_url = info['url'] + dist.digest = self._get_digest(info) dist.locator = self result[v] = dist return result @@ -398,13 +423,18 @@ class PyPIJSONLocator(Locator): data = resp.read().decode() # for now d = json.loads(data) md = Metadata(scheme=self.scheme) - md.update(d['info']) + data = d['info'] + md.name = data['name'] + md.version = data['version'] + md.license = data.get('license') + md.keywords = data.get('keywords', []) + md.summary = data.get('summary') dist = Distribution(md) urls = d['urls'] if urls: info = urls[0] - md['Download-URL'] = info['url'] - dist.md5_digest = info.get('md5_digest') + md.source_url = info['url'] + dist.digest = self._get_digest(info) dist.locator = self result[md.version] = dist except Exception as e: @@ -791,11 +821,18 @@ class JSONLocator(Locator): for info in data.get('files', []): if info['ptype'] != 'sdist' or info['pyversion'] != 'source': continue + # We don't store summary in project metadata as it makes + # the data bigger for no benefit during dependency + # resolution dist = make_dist(data['name'], info['version'], + summary=data.get('summary', + 'Placeholder for summary'), scheme=self.scheme) md = dist.metadata - md['Download-URL'] = info['url'] - dist.md5_digest = info.get('digest') + md.source_url = info['url'] + # TODO SHA256 digest + if 'digest' in info and info['digest']: + dist.digest = ('md5', info['digest']) md.dependencies = info.get('requirements', {}) dist.exports = info.get('exports', {}) result[dist.version] = dist @@ -860,13 +897,32 @@ class AggregatingLocator(Locator): def _get_project(self, name): result = {} for locator in self.locators: - r = locator.get_project(name) - if r: + d = locator.get_project(name) + if d: if self.merge: - result.update(r) + result.update(d) else: - result = r - break + # See issue #18. If any dists are found and we're looking + # for specific constraints, we only return something if + # a match is found. For example, if a DirectoryLocator + # returns just foo (1.0) while we're looking for + # foo (>= 2.0), we'll pretend there was nothing there so + # that subsequent locators can be queried. Otherwise we + # would just return foo (1.0) which would then lead to a + # failure to find foo (>= 2.0), because other locators + # weren't searched. Note that this only matters when + # merge=False. + if self.matcher is None: + found = True + else: + found = False + for k in d: + if self.matcher.match(k): + found = True + break + if found: + result = d + break return result def get_distribution_names(self): @@ -882,13 +938,19 @@ class AggregatingLocator(Locator): return result +# We use a legacy scheme simply because most of the dists on PyPI use legacy +# versions which don't conform to PEP 426 / PEP 440. default_locator = AggregatingLocator( JSONLocator(), SimpleScrapingLocator('https://pypi.python.org/simple/', - timeout=3.0)) + timeout=3.0), + scheme='legacy') locate = default_locator.locate +NAME_VERSION_RE = re.compile(r'(?P[\w-]+)\s*' + r'\(\s*(==\s*)?(?P[^)]+)\)$') + class DependencyFinder(object): """ Locate dependencies for distributions. @@ -902,25 +964,6 @@ class DependencyFinder(object): self.locator = locator or default_locator self.scheme = get_scheme(self.locator.scheme) - def _get_name_and_version(self, p): - """ - A utility method used to get name and version from e.g. a Provides-Dist - value. - - :param p: A value in a form foo (1.0) - :return: The name and version as a tuple. - """ - comps = p.strip().rsplit(' ', 1) - name = comps[0] - version = None - if len(comps) == 2: - version = comps[1] - if len(version) < 3 or version[0] != '(' or version[-1] != ')': - raise DistlibException('Ill-formed provides field: %r' % p) - version = version[1:-1] # trim off parentheses - # Name in lower case for case-insensitivity - return name.lower(), version - def add_distribution(self, dist): """ Add a distribution to the finder. This will update internal information @@ -932,7 +975,7 @@ class DependencyFinder(object): self.dists_by_name[name] = dist self.dists[(name, dist.version)] = dist for p in dist.provides: - name, version = self._get_name_and_version(p) + name, version = parse_name_and_version(p) logger.debug('Add to provided: %s, %s, %s', name, version, dist) self.provided.setdefault(name, set()).add((version, dist)) @@ -947,7 +990,7 @@ class DependencyFinder(object): del self.dists_by_name[name] del self.dists[(name, dist.version)] for p in dist.provides: - name, version = self._get_name_and_version(p) + name, version = parse_name_and_version(p) logger.debug('Remove from provided: %s, %s, %s', name, version, dist) s = self.provided[name] s.remove((version, dist)) @@ -1033,15 +1076,17 @@ class DependencyFinder(object): result = True return result - def find(self, requirement, tests=False, prereleases=False): + def find(self, requirement, meta_extras=None, prereleases=False): """ - Find a distribution matching requirement and all distributions - it depends on. Use the ``tests`` argument to determine whether - distributions used only for testing should be included in the - results. Allow ``requirement`` to be either a :class:`Distribution` - instance or a string expressing a requirement. If ``prereleases`` - is True, allow pre-release versions to be returned - otherwise, - don't. + Find a distribution and all distributions it depends on. + + :param requirement: The requirement specifying the distribution to + find, or a Distribution instance. + :param meta_extras: A list of meta extras such as :test:, :build: and + so on. + :param prereleases: If ``True``, allow pre-release versions to be + returned - otherwise, don't return prereleases + unless they're all that's available. Return a set of :class:`Distribution` instances and a set of problems. @@ -1062,6 +1107,12 @@ class DependencyFinder(object): self.dists_by_name = {} self.reqts = {} + meta_extras = set(meta_extras or []) + if ':*:' in meta_extras: + meta_extras.remove(':*:') + # :meta: and :run: are implicitly included + meta_extras |= set([':test:', ':build:', ':dev:']) + if isinstance(requirement, Distribution): dist = odist = requirement logger.debug('passed %s as requirement', odist) @@ -1077,7 +1128,7 @@ class DependencyFinder(object): install_dists = set([odist]) while todo: dist = todo.pop() - name = dist.key # case-insensitive + name = dist.key # case-insensitive if name not in self.dists_by_name: self.add_distribution(dist) else: @@ -1086,19 +1137,24 @@ class DependencyFinder(object): if other != dist: self.try_to_replace(dist, other, problems) - ireqts = dist.requires - sreqts = dist.setup_requires + ireqts = dist.run_requires | dist.meta_requires + sreqts = dist.build_requires ereqts = set() - if not tests or dist not in install_dists: - treqts = set() - else: - treqts = dist.test_requires - all_reqts = ireqts | sreqts | treqts | ereqts + if dist in install_dists: + for key in ('test', 'build', 'dev'): + e = ':%s:' % key + if e in meta_extras: + ereqts |= getattr(dist, '%s_requires' % key) + all_reqts = ireqts | sreqts | ereqts for r in all_reqts: providers = self.find_providers(r) if not providers: logger.debug('No providers found for %r', r) provider = self.locator.locate(r, prereleases=prereleases) + # If no provider is found and we didn't consider + # prereleases, consider them now. + if provider is None and not prereleases: + provider = self.locator.locate(r, prereleases=True) if provider is None: logger.debug('Cannot satisfy %r', r) problems.add(('unsatisfied', r)) diff --git a/awx/lib/site-packages/pip/vendor/distlib/manifest.py b/awx/lib/site-packages/pip/_vendor/distlib/manifest.py similarity index 95% rename from awx/lib/site-packages/pip/vendor/distlib/manifest.py rename to awx/lib/site-packages/pip/_vendor/distlib/manifest.py index ae2c3ea607..c6b98c59a3 100644 --- a/awx/lib/site-packages/pip/vendor/distlib/manifest.py +++ b/awx/lib/site-packages/pip/_vendor/distlib/manifest.py @@ -97,6 +97,7 @@ class Manifest(object): """ Return sorted files in directory order """ + def add_dir(dirs, d): dirs.add(d) logger.debug('add_dir added %s', d) @@ -185,7 +186,7 @@ class Manifest(object): if not self._exclude_pattern(None, prefix=dirpattern): logger.warning('no previously-included directories found ' 'matching %r', dirpattern) - else: #pragma: no cover + else: # pragma: no cover # This should never happen, as it should be caught in # _parse_template_line raise DistlibException( @@ -202,9 +203,12 @@ class Manifest(object): :return: A tuple of action, patterns, thedir, dir_patterns """ words = directive.split() - if len(words) == 1 and words[0] not in ( - 'include', 'exclude', 'global-include', 'global-exclude', - 'recursive-include', 'recursive-exclude', 'graft', 'prune'): + if len(words) == 1 and words[0] not in ('include', 'exclude', + 'global-include', + 'global-exclude', + 'recursive-include', + 'recursive-exclude', + 'graft', 'prune'): # no action given, let's use the default 'include' words.insert(0, 'include') @@ -281,7 +285,7 @@ class Manifest(object): return found def _exclude_pattern(self, pattern, anchor=True, prefix=None, - is_regex=False): + is_regex=False): """Remove strings (presumably filenames) from 'files' that match 'pattern'. @@ -300,7 +304,6 @@ class Manifest(object): found = True return found - def _translate_pattern(self, pattern, anchor=True, prefix=None, is_regex=False): """Translate a shell-like wildcard pattern to a compiled regular @@ -330,7 +333,7 @@ class Manifest(object): if os.sep == '\\': sep = r'\\' pattern_re = '^' + base + sep.join((prefix_re, - '.*' + pattern_re)) + '.*' + pattern_re)) else: # no prefix -- respect anchor flag if anchor: pattern_re = '^' + base + pattern_re diff --git a/awx/lib/site-packages/pip/vendor/distlib/markers.py b/awx/lib/site-packages/pip/_vendor/distlib/markers.py similarity index 90% rename from awx/lib/site-packages/pip/vendor/distlib/markers.py rename to awx/lib/site-packages/pip/_vendor/distlib/markers.py index 182474008a..afb19c62e0 100644 --- a/awx/lib/site-packages/pip/vendor/distlib/markers.py +++ b/awx/lib/site-packages/pip/_vendor/distlib/markers.py @@ -16,6 +16,7 @@ from .util import in_venv __all__ = ['interpret'] + class Evaluator(object): """ A limited evaluator for Python expressions. @@ -34,16 +35,17 @@ class Evaluator(object): } allowed_values = { - 'sys.platform': sys.platform, + 'sys_platform': sys.platform, 'python_version': '%s.%s' % sys.version_info[:2], # parsing sys.platform is not reliable, but there is no other # way to get e.g. 2.7.2+, and the PEP is defined with sys.version 'python_full_version': sys.version.split(' ', 1)[0], - 'os.name': os.name, - 'platform.in_venv': str(in_venv()), - 'platform.version': platform.version(), - 'platform.machine': platform.machine(), - 'platform.python_implementation': platform.python_implementation(), + 'os_name': os.name, + 'platform_in_venv': str(in_venv()), + 'platform_release': platform.release(), + 'platform_version': platform.version(), + 'platform_machine': platform.machine(), + 'platform_python_implementation': python_implementation(), } def __init__(self, context=None): @@ -102,7 +104,6 @@ class Evaluator(object): return '%s.%s' % (node.value.id, node.attr) def do_attribute(self, node): - valid = True if not isinstance(node.value, ast.Name): valid = False else: @@ -133,11 +134,11 @@ class Evaluator(object): valid = True if isinstance(lhsnode, ast.Str) and isinstance(rhsnode, ast.Str): valid = False - elif (isinstance(lhsnode, ast.Attribute) - and isinstance(rhsnode, ast.Attribute)): - klhs = self.get_attr_key(lhsnode) - krhs = self.get_attr_key(rhsnode) - valid = klhs != krhs + #elif (isinstance(lhsnode, ast.Attribute) + # and isinstance(rhsnode, ast.Attribute)): + # klhs = self.get_attr_key(lhsnode) + # krhs = self.get_attr_key(rhsnode) + # valid = klhs != krhs if not valid: s = self.get_fragment(node.col_offset) raise SyntaxError('Invalid comparison: %s' % s) diff --git a/awx/lib/site-packages/pip/vendor/distlib/metadata.py b/awx/lib/site-packages/pip/_vendor/distlib/metadata.py similarity index 54% rename from awx/lib/site-packages/pip/vendor/distlib/metadata.py rename to awx/lib/site-packages/pip/_vendor/distlib/metadata.py index 51dbe853f6..a8f79071ea 100644 --- a/awx/lib/site-packages/pip/vendor/distlib/metadata.py +++ b/awx/lib/site-packages/pip/_vendor/distlib/metadata.py @@ -11,17 +11,20 @@ from __future__ import unicode_literals import codecs from email import message_from_file +import json import logging import re -from . import DistlibException -from .compat import StringIO, string_types +from . import DistlibException, __version__ +from .compat import StringIO, string_types, text_type from .markers import interpret -from .version import get_scheme +from .util import extract_by_key, get_extras +from .version import get_scheme, PEP426_VERSION_RE logger = logging.getLogger(__name__) + class MetadataMissingError(DistlibException): """A required metadata is missing""" @@ -34,31 +37,8 @@ class MetadataUnrecognizedVersionError(DistlibException): """Unknown metadata version number.""" -try: - # docutils is installed - from docutils.utils import Reporter - from docutils.parsers.rst import Parser - from docutils import frontend - from docutils import nodes - - class SilentReporter(Reporter, object): - - def __init__(self, source, report_level, halt_level, stream=None, - debug=0, encoding='ascii', error_handler='replace'): - self.messages = [] - super(SilentReporter, self).__init__( - source, report_level, halt_level, stream, - debug, encoding, error_handler) - - def system_message(self, level, message, *children, **kwargs): - self.messages.append((level, message, children, kwargs)) - return nodes.system_message(message, level=level, type=self. - levels[level], *children, **kwargs) - - _HAS_DOCUTILS = True -except ImportError: - # docutils is not installed - _HAS_DOCUTILS = False +class MetadataInvalidError(DistlibException): + """A metadata value is invalid""" # public API of this module __all__ = ['Metadata', 'PKG_INFO_ENCODING', 'PKG_INFO_PREFERRED_VERSION'] @@ -118,6 +98,7 @@ _ALL_FIELDS.update(_426_FIELDS) EXTRA_RE = re.compile(r'''extra\s*==\s*("([^"]+)"|'([^']+)')''') + def _version2fieldlist(version): if version == '1.0': return _241_FIELDS @@ -238,32 +219,39 @@ _MISSING = object() _FILESAFE = re.compile('[^A-Za-z0-9.]+') -class Metadata(object): - """The metadata of a release. +def _get_name_and_version(name, version, for_filename=False): + """Return the distribution name with version. + + If for_filename is true, return a filename-escaped form.""" + if for_filename: + # For both name and version any runs of non-alphanumeric or '.' + # characters are replaced with a single '-'. Additionally any + # spaces in the version string become '.' + name = _FILESAFE.sub('-', name) + version = _FILESAFE.sub('-', version.replace(' ', '.')) + return '%s-%s' % (name, version) + + +class LegacyMetadata(object): + """The legacy metadata of a release. Supports versions 1.0, 1.1 and 1.2 (auto-detected). You can instantiate the class with one of these arguments (or none): - - *path*, the path to a METADATA file - - *fileobj* give a file-like object with METADATA as content + - *path*, the path to a metadata file + - *fileobj* give a file-like object with metadata as content - *mapping* is a dict-like object - *scheme* is a version scheme name """ - # TODO document that execution_context and platform_dependent are used - # to filter on query, not when setting a key - # also document the mapping API and UNKNOWN default key + # TODO document the mapping API and UNKNOWN default key - def __init__(self, path=None, platform_dependent=False, - execution_context=None, fileobj=None, mapping=None, + def __init__(self, path=None, fileobj=None, mapping=None, scheme='default'): - self._fields = {} - self.requires_files = [] - self.docutils_support = _HAS_DOCUTILS - self.platform_dependent = platform_dependent - self.execution_context = execution_context - self._dependencies = None - self.scheme = scheme if [path, fileobj, mapping].count(None) < 2: raise TypeError('path, fileobj and mapping are exclusive') + self._fields = {} + self.requires_files = [] + self._dependencies = None + self.scheme = scheme if path is not None: self.read(path) elif fileobj is not None: @@ -275,8 +263,8 @@ class Metadata(object): def set_metadata_version(self): self._fields['Metadata-Version'] = _best_version(self._fields) - def _write_field(self, file, name, value): - file.write('%s: %s\n' % (name, value)) + def _write_field(self, fileobj, name, value): + fileobj.write('%s: %s\n' % (name, value)) def __getitem__(self, name): return self.get(name) @@ -306,38 +294,6 @@ class Metadata(object): return [] return 'UNKNOWN' - def _check_rst_data(self, data): - """Return warnings when the provided data has syntax errors.""" - source_path = StringIO() - parser = Parser() - settings = frontend.OptionParser().get_default_values() - settings.tab_width = 4 - settings.pep_references = None - settings.rfc_references = None - reporter = SilentReporter(source_path, - settings.report_level, - settings.halt_level, - stream=settings.warning_stream, - debug=settings.debug, - encoding=settings.error_encoding, - error_handler=settings.error_encoding_error_handler) - - document = nodes.document(settings, reporter, source=source_path) - document.note_source(source_path, -1) - try: - parser.parse(data, document) - except AttributeError: - reporter.messages.append((-1, 'Could not finish the parsing.', - '', {})) - - return reporter.messages - - def _platform(self, value): - if not self.platform_dependent or ';' not in value: - return True, value - value, marker = value.split(';') - return interpret(marker, self.execution_context), value - def _remove_line_prefix(self, value): return _LINE_PREFIX.sub('\n', value) @@ -346,69 +302,17 @@ class Metadata(object): return self[name] raise AttributeError(name) - def _get_dependencies(self): - def handle_req(req, rlist, extras): - if ';' not in req: - rlist.append(req) - else: - r, marker = req.split(';') - m = EXTRA_RE.search(marker) - if m: - extra = m.groups()[0][1:-1] - extras.setdefault(extra, []).append(r) - - result = self._dependencies - if result is None: - self._dependencies = result = {} - extras = {} - setup_reqs = self['Setup-Requires-Dist'] - if setup_reqs: - result['setup'] = setup_reqs - install_reqs = [] - for req in self['Requires-Dist']: - handle_req(req, install_reqs, extras) - if install_reqs: - result['install'] = install_reqs - if extras: - result['extras'] = extras - return result - - def _set_dependencies(self, value): - if 'test' in value: - value = dict(value) # don't change value passed in - value.setdefault('extras', {})['test'] = value.pop('test') - self._dependencies = value - setup_reqs = value.get('setup', []) - install_reqs = value.get('install', []) - klist = [] - for k, rlist in value.get('extras', {}).items(): - klist.append(k) - for r in rlist: - install_reqs.append('%s; extra == "%s"' % (r, k)) - if setup_reqs: - self['Setup-Requires-Dist'] = setup_reqs - if install_reqs: - self['Requires-Dist'] = install_reqs - if klist: - self['Provides-Extra'] = klist # # Public API # - dependencies = property(_get_dependencies, _set_dependencies) +# dependencies = property(_get_dependencies, _set_dependencies) def get_fullname(self, filesafe=False): """Return the distribution name with version. If filesafe is true, return a filename-escaped form.""" - name, version = self['Name'], self['Version'] - if filesafe: - # For both name and version any runs of non-alphanumeric or '.' - # characters are replaced with a single '-'. Additionally any - # spaces in the version string become '.' - name = _FILESAFE.sub('-', name) - version = _FILESAFE.sub('-', version.replace(' ', '.')) - return '%s-%s' % (name, version) + return _get_name_and_version(self['Name'], self['Version'], filesafe) def is_field(self, name): """return True if name is a valid metadata key""" @@ -432,7 +336,10 @@ class Metadata(object): msg = message_from_file(fileob) self._fields['Metadata-Version'] = msg['metadata-version'] - for field in _version2fieldlist(self['Metadata-Version']): + # When reading, get all the fields we can + for field in _ALL_FIELDS: + if field not in msg: + continue if field in _LISTFIELDS: # we can have multiple lines values = msg.get_all(field) @@ -564,9 +471,6 @@ class Metadata(object): return [] res = [] for val in value: - valid, val = self._platform(val) - if not valid: - continue if name not in _LISTTUPLEFIELDS: res.append(val) else: @@ -575,17 +479,12 @@ class Metadata(object): return res elif name in _ELEMENTSFIELD: - valid, value = self._platform(self._fields[name]) - if not valid: - return [] + value = self._fields[name] if isinstance(value, string_types): return value.split(',') - valid, value = self._platform(self._fields[name]) - if not valid: - return None - return value + return self._fields[name] - def check(self, strict=False, restructuredtext=False): + def check(self, strict=False): """Check if the metadata is compliant. If strict is True then raise if no Name or Version are provided""" self.set_metadata_version() @@ -605,9 +504,6 @@ class Metadata(object): if attr not in self: missing.append(attr) - if _HAS_DOCUTILS and restructuredtext: - warnings.extend(self._check_rst_data(self['Description'])) - # checking metadata 1.2 (XXX needs to check 1.1, 1.0) if self['Metadata-Version'] != '1.2': return missing, warnings @@ -669,6 +565,8 @@ class Metadata(object): ('provides_dist', 'Provides-Dist'), ('obsoletes_dist', 'Obsoletes-Dist'), ('project_url', 'Project-URL'), + ('maintainer', 'Maintainer'), + ('maintainer_email', 'Maintainer-email'), ) for key, field_name in mapping_1_2: if not skip_missing or field_name in self._fields: @@ -683,11 +581,20 @@ class Metadata(object): ('requires', 'Requires'), ('obsoletes', 'Obsoletes'), ) - if not skip_missing or field_name in self._fields: - data[key] = self[field_name] + for key, field_name in mapping_1_1: + if not skip_missing or field_name in self._fields: + data[key] = self[field_name] return data + def add_requirements(self, requirements): + if self['Metadata-Version'] == '1.1': + # we can't have 1.1 metadata *and* Setuptools requires + for field in ('Obsoletes', 'Requires', 'Provides'): + if field in self: + del self[field] + self['Requires-Dist'] += requirements + # Mapping API # TODO could add iter* variants @@ -705,4 +612,402 @@ class Metadata(object): return [(key, self[key]) for key in self.keys()] def __repr__(self): - return '' % (self.name, self.version) + return '<%s %s %s>' % (self.__class__.__name__, self.name, + self.version) + + +METADATA_FILENAME = 'pydist.json' + + +class Metadata(object): + """ + The metadata of a release. This implementation uses 2.0 (JSON) + metadata where possible. If not possible, it wraps a LegacyMetadata + instance which handles the key-value metadata format. + """ + + METADATA_VERSION_MATCHER = re.compile('^\d+(\.\d+)*$') + + NAME_MATCHER = re.compile('^[0-9A-Z]([0-9A-Z_.-]*[0-9A-Z])?$', re.I) + + VERSION_MATCHER = PEP426_VERSION_RE + + SUMMARY_MATCHER = re.compile('.{1,2047}') + + METADATA_VERSION = '2.0' + + GENERATOR = 'distlib (%s)' % __version__ + + MANDATORY_KEYS = { + 'name': (), + 'version': (), + 'summary': ('legacy',), + } + + INDEX_KEYS = 'name version license summary description' + + DEPENDENCY_KEYS = ('extras run_requires test_requires build_requires ' + 'dev_requires provides meta_requires obsoleted_by ' + 'supports_environments') + + SYNTAX_VALIDATORS = { + 'metadata_version': (METADATA_VERSION_MATCHER, ()), + 'name': (NAME_MATCHER, ('legacy',)), + 'version': (VERSION_MATCHER, ('legacy',)), + 'summary': (SUMMARY_MATCHER, ('legacy',)), + } + + __slots__ = ('_legacy', '_data', 'scheme') + + def __init__(self, path=None, fileobj=None, mapping=None, + scheme='default'): + if [path, fileobj, mapping].count(None) < 2: + raise TypeError('path, fileobj and mapping are exclusive') + self._legacy = None + self._data = None + self.scheme = scheme + #import pdb; pdb.set_trace() + if mapping is not None: + try: + self._validate_mapping(mapping, scheme) + self._data = mapping + except MetadataUnrecognizedVersionError: + self._legacy = LegacyMetadata(mapping=mapping, scheme=scheme) + self.validate() + else: + data = None + if path: + with open(path, 'rb') as f: + data = f.read() + elif fileobj: + data = fileobj.read() + if data is None: + # Initialised with no args - to be added + self._data = { + 'metadata_version': self.METADATA_VERSION, + 'generator': self.GENERATOR, + } + else: + if not isinstance(data, text_type): + data = data.decode('utf-8') + try: + self._data = json.loads(data) + self._validate_mapping(self._data, scheme) + except ValueError: + # Note: MetadataUnrecognizedVersionError does not + # inherit from ValueError (it's a DistlibException, + # which should not inherit from ValueError). + # The ValueError comes from the json.load - if that + # succeeds and we get a validation error, we want + # that to propagate + self._legacy = LegacyMetadata(fileobj=StringIO(data), + scheme=scheme) + self.validate() + + common_keys = set(('name', 'version', 'license', 'keywords', 'summary')) + + none_list = (None, list) + none_dict = (None, dict) + + mapped_keys = { + 'run_requires': ('Requires-Dist', list), + 'build_requires': ('Setup-Requires-Dist', list), + 'dev_requires': none_list, + 'test_requires': none_list, + 'meta_requires': none_list, + 'extras': ('Provides-Extra', list), + 'modules': none_list, + 'namespaces': none_list, + 'exports': none_dict, + 'commands': none_dict, + 'classifiers': ('Classifier', list), + 'source_url': ('Download-URL', None), + 'metadata_version': ('Metadata-Version', None), + } + + del none_list, none_dict + + def __getattribute__(self, key): + common = object.__getattribute__(self, 'common_keys') + mapped = object.__getattribute__(self, 'mapped_keys') + if key in mapped: + lk, maker = mapped[key] + if self._legacy: + if lk is None: + result = None if maker is None else maker() + else: + result = self._legacy.get(lk) + else: + value = None if maker is None else maker() + result = self._data.get(key, value) + elif key not in common: + result = object.__getattribute__(self, key) + elif self._legacy: + result = self._legacy.get(key) + else: + result = self._data.get(key) + return result + + def _validate_value(self, key, value, scheme=None): + if key in self.SYNTAX_VALIDATORS: + pattern, exclusions = self.SYNTAX_VALIDATORS[key] + if (scheme or self.scheme) not in exclusions: + m = pattern.match(value) + if not m: + raise MetadataInvalidError('%r is an invalid value for ' + 'the %r property' % (value, + key)) + + def __setattr__(self, key, value): + self._validate_value(key, value) + common = object.__getattribute__(self, 'common_keys') + mapped = object.__getattribute__(self, 'mapped_keys') + if key in mapped: + lk, _ = mapped[key] + if self._legacy: + if lk is None: + raise NotImplementedError + self._legacy[lk] = value + else: + self._data[key] = value + elif key not in common: + object.__setattr__(self, key, value) + else: + if key == 'keywords': + if isinstance(value, string_types): + value = value.strip() + if value: + value = value.split() + else: + value = [] + if self._legacy: + self._legacy[key] = value + else: + self._data[key] = value + + @property + def name_and_version(self): + return _get_name_and_version(self.name, self.version, True) + + @property + def provides(self): + if self._legacy: + result = self._legacy['Provides-Dist'] + else: + result = self._data.setdefault('provides', []) + s = '%s (%s)' % (self.name, self.version) + if s not in result: + result.append(s) + return result + + @provides.setter + def provides(self, value): + if self._legacy: + self._legacy['Provides-Dist'] = value + else: + self._data['provides'] = value + + def get_requirements(self, reqts, extras=None, env=None): + """ + Base method to get dependencies, given a set of extras + to satisfy and an optional environment context. + :param reqts: A list of sometimes-wanted dependencies, + perhaps dependent on extras and environment. + :param extras: A list of optional components being requested. + :param env: An optional environment for marker evaluation. + """ + if self._legacy: + result = reqts + else: + result = [] + extras = get_extras(extras or [], self.extras) + for d in reqts: + if 'extra' not in d and 'environment' not in d: + # unconditional + include = True + else: + if 'extra' not in d: + # Not extra-dependent - only environment-dependent + include = True + else: + include = d.get('extra') in extras + if include: + # Not excluded because of extras, check environment + marker = d.get('environment') + if marker: + include = interpret(marker, env) + if include: + result.extend(d['requires']) + for key in ('build', 'dev', 'test'): + e = ':%s:' % key + if e in extras: + extras.remove(e) + # A recursive call, but it should terminate since 'test' + # has been removed from the extras + reqts = self._data.get('%s_requires' % key, []) + result.extend(self.get_requirements(reqts, extras=extras, + env=env)) + return result + + @property + def dictionary(self): + if self._legacy: + return self._from_legacy() + return self._data + + @property + def dependencies(self): + if self._legacy: + raise NotImplementedError + else: + return extract_by_key(self._data, self.DEPENDENCY_KEYS) + + @dependencies.setter + def dependencies(self, value): + if self._legacy: + raise NotImplementedError + else: + self._data.update(value) + + def _validate_mapping(self, mapping, scheme): + if mapping.get('metadata_version') != self.METADATA_VERSION: + raise MetadataUnrecognizedVersionError() + missing = [] + for key, exclusions in self.MANDATORY_KEYS.items(): + if key not in mapping: + if scheme not in exclusions: + missing.append(key) + if missing: + msg = 'Missing metadata items: %s' % ', '.join(missing) + raise MetadataMissingError(msg) + for k, v in mapping.items(): + self._validate_value(k, v, scheme) + + def validate(self): + if self._legacy: + missing, warnings = self._legacy.check(True) + if missing or warnings: + logger.warning('Metadata: missing: %s, warnings: %s', + missing, warnings) + else: + self._validate_mapping(self._data, self.scheme) + + def todict(self): + if self._legacy: + return self._legacy.todict(True) + else: + result = extract_by_key(self._data, self.INDEX_KEYS) + return result + + def _from_legacy(self): + assert self._legacy and not self._data + result = { + 'metadata_version': self.METADATA_VERSION, + 'generator': self.GENERATOR, + } + lmd = self._legacy.todict(True) # skip missing ones + for k in ('name', 'version', 'license', 'summary', 'description', + 'classifier'): + if k in lmd: + if k == 'classifier': + nk = 'classifiers' + else: + nk = k + result[nk] = lmd[k] + kw = lmd.get('Keywords', []) + if kw == ['']: + kw = [] + result['keywords'] = kw + keys = (('requires_dist', 'run_requires'), + ('setup_requires_dist', 'build_requires')) + for ok, nk in keys: + if ok in lmd and lmd[ok]: + result[nk] = [{'requires': lmd[ok]}] + result['provides'] = self.provides + author = {} + maintainer = {} + return result + + LEGACY_MAPPING = { + 'name': 'Name', + 'version': 'Version', + 'license': 'License', + 'summary': 'Summary', + 'description': 'Description', + 'classifiers': 'Classifier', + } + + def _to_legacy(self): + def process_entries(entries): + reqts = set() + for e in entries: + extra = e.get('extra') + env = e.get('environment') + rlist = e['requires'] + for r in rlist: + if not env and not extra: + reqts.add(r) + else: + marker = '' + if extra: + marker = 'extra == "%s"' % extra + if env: + if marker: + marker = '(%s) and %s' % (env, marker) + else: + marker = env + reqts.add(';'.join((r, marker))) + return reqts + + assert self._data and not self._legacy + result = LegacyMetadata() + nmd = self._data + for nk, ok in self.LEGACY_MAPPING.items(): + if nk in nmd: + result[ok] = nmd[nk] + r1 = process_entries(self.run_requires + self.meta_requires) + r2 = process_entries(self.build_requires + self.dev_requires) + if self.extras: + result['Provides-Extra'] = sorted(self.extras) + result['Requires-Dist'] = sorted(r1) + result['Setup-Requires-Dist'] = sorted(r2) + # TODO: other fields such as contacts + return result + + def write(self, path=None, fileobj=None, legacy=False, skip_unknown=True): + if [path, fileobj].count(None) != 1: + raise ValueError('Exactly one of path and fileobj is needed') + self.validate() + if legacy: + if self._legacy: + legacy_md = self._legacy + else: + legacy_md = self._to_legacy() + if path: + legacy_md.write(path, skip_unknown=skip_unknown) + else: + legacy_md.write_file(fileobj, skip_unknown=skip_unknown) + else: + if self._legacy: + d = self._from_legacy() + else: + d = self._data + if fileobj: + json.dump(d, fileobj, ensure_ascii=True, indent=2, + sort_keys=True) + else: + with codecs.open(path, 'w', 'utf-8') as f: + json.dump(d, f, ensure_ascii=True, indent=2, + sort_keys=True) + + def add_requirements(self, requirements): + if self._legacy: + self._legacy.add_requirements(requirements) + else: + self._data.setdefault('run_requires', []).extend(requirements) + + def __repr__(self): + name = self.name or '(no name)' + version = self.version or 'no version' + return '<%s %s %s (%s)>' % (self.__class__.__name__, + self.metadata_version, name, version) diff --git a/awx/lib/site-packages/pip/vendor/distlib/resources.py b/awx/lib/site-packages/pip/_vendor/distlib/resources.py similarity index 88% rename from awx/lib/site-packages/pip/vendor/distlib/resources.py rename to awx/lib/site-packages/pip/_vendor/distlib/resources.py index 5f2d212b17..d58b25a92e 100644 --- a/awx/lib/site-packages/pip/vendor/distlib/resources.py +++ b/awx/lib/site-packages/pip/_vendor/distlib/resources.py @@ -10,8 +10,10 @@ import bisect import io import logging import os +import pkgutil import shutil import sys +import types import zipimport from . import DistlibException @@ -19,6 +21,7 @@ from .util import cached_property, get_cache_base, path_to_cache_dir logger = logging.getLogger(__name__) + class Cache(object): """ A class implementing a cache for resources that need to live in the file system @@ -101,42 +104,51 @@ class Cache(object): cache = Cache() + class ResourceBase(object): def __init__(self, finder, name): self.finder = finder self.name = name + class Resource(ResourceBase): """ A class representing an in-package resource, such as a data file. This is not normally instantiated by user code, but rather by a :class:`ResourceFinder` which manages the resource. """ - is_container = False # Backwards compatibility - + is_container = False # Backwards compatibility + def as_stream(self): - "Get the resource as a stream. Not a property, as not idempotent." + """ + Get the resource as a stream. + + This is not a property to make it obvious that it returns a new stream + each time. + """ return self.finder.get_stream(self) - + @cached_property def file_path(self): return cache.get(self) - + @cached_property def bytes(self): return self.finder.get_bytes(self) - + @cached_property def size(self): return self.finder.get_size(self) - + + class ResourceContainer(ResourceBase): - is_container = True # Backwards compatibility - + is_container = True # Backwards compatibility + @cached_property def resources(self): return self.finder.get_resources(self) + class ResourceFinder(object): """ Resource finder for file system resources. @@ -149,7 +161,7 @@ class ResourceFinder(object): def _make_path(self, resource_name): parts = resource_name.split('/') parts.insert(0, self.base) - return os.path.join(*parts) + return os.path.realpath(os.path.join(*parts)) def _find(self, path): return os.path.exists(path) @@ -186,9 +198,10 @@ class ResourceFinder(object): def is_container(self, resource): return self._is_directory(resource.path) - + _is_directory = staticmethod(os.path.isdir) + class ZipResourceFinder(ResourceFinder): """ Resource finder for resources in .zip files. @@ -209,7 +222,7 @@ class ZipResourceFinder(ResourceFinder): if path in self._files: result = True else: - if path[-1] != os.sep: + if path and path[-1] != os.sep: path = path + os.sep i = bisect.bisect(self.index, path) try: @@ -239,7 +252,7 @@ class ZipResourceFinder(ResourceFinder): def get_resources(self, resource): path = resource.path[self.prefix_len:] - if path[-1] != os.sep: + if path and path[-1] != os.sep: path += os.sep plen = len(path) result = set() @@ -254,7 +267,7 @@ class ZipResourceFinder(ResourceFinder): def _is_directory(self, path): path = path[self.prefix_len:] - if path[-1] != os.sep: + if path and path[-1] != os.sep: path += os.sep i = bisect.bisect(self.index, path) try: @@ -271,14 +284,17 @@ _finder_registry = { try: import _frozen_importlib _finder_registry[_frozen_importlib.SourceFileLoader] = ResourceFinder + _finder_registry[_frozen_importlib.FileFinder] = ResourceFinder except (ImportError, AttributeError): pass + def register_finder(loader, finder_maker): _finder_registry[type(loader)] = finder_maker _finder_cache = {} + def finder(package): """ Return a resource finder for a package. @@ -302,3 +318,26 @@ def finder(package): result = finder_maker(module) _finder_cache[package] = result return result + + +_dummy_module = types.ModuleType(str('__dummy__')) + + +def finder_for_path(path): + """ + Return a resource finder for a path, which should represent a container. + + :param path: The path. + :return: A :class:`ResourceFinder` instance for the path. + """ + result = None + # calls any path hooks, gets importer into cache + pkgutil.get_importer(path) + loader = sys.path_importer_cache.get(path) + finder = _finder_registry.get(type(loader)) + if finder: + module = _dummy_module + module.__file__ = os.path.join(path, '') + module.__loader__ = loader + result = finder(module) + return result diff --git a/awx/lib/site-packages/pip/vendor/distlib/scripts.py b/awx/lib/site-packages/pip/_vendor/distlib/scripts.py similarity index 54% rename from awx/lib/site-packages/pip/vendor/distlib/scripts.py rename to awx/lib/site-packages/pip/_vendor/distlib/scripts.py index be923f61b4..c7c3c1d4c9 100644 --- a/awx/lib/site-packages/pip/vendor/distlib/scripts.py +++ b/awx/lib/site-packages/pip/_vendor/distlib/scripts.py @@ -4,22 +4,40 @@ # Licensed to the Python Software Foundation under a contributor agreement. # See LICENSE.txt and CONTRIBUTORS.txt. # +from io import BytesIO import logging import os import re import struct import sys -from . import DistlibException -from .compat import sysconfig, fsencode, detect_encoding +from .compat import sysconfig, fsencode, detect_encoding, ZipFile from .resources import finder from .util import FileOperator, get_export_entry, convert_path, get_executable logger = logging.getLogger(__name__) +_DEFAULT_MANIFEST = ''' + + + + + + + + + + + + +'''.strip() + # check if Python is called on the first line with this expression FIRST_LINE_RE = re.compile(b'^#!.*pythonw?[0-9.]*([ \t].*)?$') -SCRIPT_TEMPLATE = '''%(shebang)s +SCRIPT_TEMPLATE = '''# -*- coding: utf-8 -*- if __name__ == '__main__': import sys, re @@ -33,7 +51,7 @@ if __name__ == '__main__': return result try: - sys.argv[0] = re.sub('-script.pyw?$', '', sys.argv[0]) + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) func = _resolve('%(module)s', '%(func)s') rc = func() # None interpreted as 0 @@ -59,32 +77,34 @@ class ScriptMaker(object): self.target_dir = target_dir self.add_launchers = add_launchers self.force = False - self.set_mode = False + self.clobber = False + # It only makes sense to set mode bits on POSIX. + self.set_mode = (os.name == 'posix') + self.variants = set(('', 'X.Y')) self._fileop = fileop or FileOperator(dry_run) - def _get_alternate_executable(self, executable, flags): - if 'gui' in flags and os.name == 'nt': + def _get_alternate_executable(self, executable, options): + if options.get('gui', False) and os.name == 'nt': dn, fn = os.path.split(executable) fn = fn.replace('python', 'pythonw') executable = os.path.join(dn, fn) return executable - def _get_shebang(self, encoding, post_interp=b'', flags=None): + def _get_shebang(self, encoding, post_interp=b'', options=None): if self.executable: executable = self.executable elif not sysconfig.is_python_build(): executable = get_executable() elif hasattr(sys, 'base_prefix') and sys.prefix != sys.base_prefix: - executable = os.path.join( - sysconfig.get_path('scripts'), - 'python%s' % sysconfig.get_config_var('EXE')) + executable = os.path.join(sysconfig.get_path('scripts'), + 'python%s' % sysconfig.get_config_var('EXE')) else: executable = os.path.join( sysconfig.get_config_var('BINDIR'), 'python%s%s' % (sysconfig.get_config_var('VERSION'), sysconfig.get_config_var('EXE'))) - if flags: - executable = self._get_alternate_executable(executable, flags) + if options: + executable = self._get_alternate_executable(executable, options) executable = fsencode(executable) shebang = b'#!' + executable + post_interp + b'\n' @@ -110,39 +130,87 @@ class ScriptMaker(object): 'from the script encoding (%r)' % (shebang, encoding)) return shebang - def _get_script_text(self, shebang, entry): - return self.script_template % dict(shebang=shebang, - module=entry.prefix, + def _get_script_text(self, entry): + return self.script_template % dict(module=entry.prefix, func=entry.suffix) - def _make_script(self, entry, filenames): - shebang = self._get_shebang('utf-8', flags=entry.flags).decode('utf-8') - script = self._get_script_text(shebang, entry) - outname = os.path.join(self.target_dir, entry.name) + manifest = _DEFAULT_MANIFEST + + def get_manifest(self, exename): + base = os.path.basename(exename) + return self.manifest % base + + def _write_script(self, names, shebang, script_bytes, filenames, ext): use_launcher = self.add_launchers and os.name == 'nt' - if use_launcher: - exename = '%s.exe' % outname - if 'gui' in entry.flags: - ext = 'pyw' - launcher = self._get_launcher('w') - else: - ext = 'py' + linesep = os.linesep.encode('utf-8') + if not use_launcher: + script_bytes = shebang + linesep + script_bytes + else: + if ext == 'py': launcher = self._get_launcher('t') - outname = '%s-script.%s' % (outname, ext) - self._fileop.write_text_file(outname, script, 'utf-8') - if self.set_mode: - self._fileop.set_executable_mode([outname]) - filenames.append(outname) - if use_launcher: - self._fileop.write_binary_file(exename, launcher) - filenames.append(exename) + else: + launcher = self._get_launcher('w') + stream = BytesIO() + with ZipFile(stream, 'w') as zf: + zf.writestr('__main__.py', script_bytes) + zip_data = stream.getvalue() + script_bytes = launcher + shebang + linesep + zip_data + for name in names: + outname = os.path.join(self.target_dir, name) + if use_launcher: + n, e = os.path.splitext(outname) + if e.startswith('.py'): + outname = n + outname = '%s.exe' % outname + try: + self._fileop.write_binary_file(outname, script_bytes) + except Exception: + # Failed writing an executable - it might be in use. + logger.warning('Failed to write executable - trying to ' + 'use .deleteme logic') + dfname = '%s.deleteme' % outname + if os.path.exists(dfname): + os.remove(dfname) # Not allowed to fail here + os.rename(outname, dfname) # nor here + self._fileop.write_binary_file(outname, script_bytes) + logger.debug('Able to replace executable using ' + '.deleteme logic') + try: + os.remove(dfname) + except Exception: + pass # still in use - ignore error + else: + if os.name == 'nt' and not outname.endswith('.' + ext): + outname = '%s.%s' % (outname, ext) + if os.path.exists(outname) and not self.clobber: + logger.warning('Skipping existing file %s', outname) + continue + self._fileop.write_binary_file(outname, script_bytes) + if self.set_mode: + self._fileop.set_executable_mode([outname]) + filenames.append(outname) + + def _make_script(self, entry, filenames, options=None): + shebang = self._get_shebang('utf-8', options=options) + script = self._get_script_text(entry).encode('utf-8') + name = entry.name + scriptnames = set() + if '' in self.variants: + scriptnames.add(name) + if 'X' in self.variants: + scriptnames.add('%s%s' % (name, sys.version[0])) + if 'X.Y' in self.variants: + scriptnames.add('%s-%s' % (name, sys.version[:3])) + if options and options.get('gui', False): + ext = 'pyw' + else: + ext = 'py' + self._write_script(scriptnames, shebang, script, filenames, ext) def _copy_script(self, script, filenames): adjust = False - script = convert_path(script) + script = os.path.join(self.source_dir, convert_path(script)) outname = os.path.join(self.target_dir, os.path.basename(script)) - filenames.append(outname) - script = os.path.join(self.source_dir, script) if not self.force and not self._fileop.newer(script, outname): logger.debug('not copying %s (up-to-date)', script) return @@ -174,31 +242,22 @@ class ScriptMaker(object): if f: f.close() self._fileop.copy_file(script, outname) + if self.set_mode: + self._fileop.set_executable_mode([outname]) + filenames.append(outname) else: logger.info('copying and adjusting %s -> %s', script, self.target_dir) if not self._fileop.dry_run: shebang = self._get_shebang(encoding, post_interp) - use_launcher = self.add_launchers and os.name == 'nt' - if use_launcher: - n, e = os.path.splitext(outname) - exename = n + '.exe' - if b'pythonw' in first_line: - launcher = self._get_launcher('w') - suffix = '-script.pyw' - else: - launcher = self._get_launcher('t') - suffix = '-script.py' - outname = n + suffix - filenames[-1] = outname - self._fileop.write_binary_file(outname, shebang + f.read()) - if use_launcher: - self._fileop.write_binary_file(exename, launcher) - filenames.append(exename) + if b'pythonw' in first_line: + ext = 'pyw' + else: + ext = 'py' + n = os.path.basename(outname) + self._write_script([n], shebang, f.read(), filenames, ext) if f: f.close() - if self.set_mode: - self._fileop.set_executable_mode([outname]) @property def dry_run(self): @@ -218,12 +277,15 @@ class ScriptMaker(object): else: bits = '32' name = '%s%s.exe' % (kind, bits) - result = finder('distlib').find(name).bytes + # Issue 31: don't hardcode an absolute package name, but + # determine it relative to the current package + distlib_package = __name__.rsplit('.', 1)[0] + result = finder(distlib_package).find(name).bytes return result # Public API follows - def make(self, specification): + def make(self, specification, options=None): """ Make a script. @@ -231,17 +293,18 @@ class ScriptMaker(object): entry specification (to make a script from a callable) or a filename (to make a script by copying from a source location). - :return: A list of all absolute pathnames written to, + :param options: A dictionary of options controlling script generation. + :return: A list of all absolute pathnames written to. """ filenames = [] entry = get_export_entry(specification) if entry is None: self._copy_script(specification, filenames) else: - self._make_script(entry, filenames) + self._make_script(entry, filenames, options=options) return filenames - def make_multiple(self, specifications): + def make_multiple(self, specifications, options=None): """ Take a list of specifications and make scripts from them, :param specifications: A list of specifications. @@ -249,5 +312,5 @@ class ScriptMaker(object): """ filenames = [] for specification in specifications: - filenames.extend(self.make(specification)) + filenames.extend(self.make(specification, options)) return filenames diff --git a/awx/lib/site-packages/pip/_vendor/distlib/t32.exe b/awx/lib/site-packages/pip/_vendor/distlib/t32.exe new file mode 100644 index 0000000000000000000000000000000000000000..43f39f31e980ee403577a508fb64dddadf24477f GIT binary patch literal 91136 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∈;+_`Yk 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 MlkRZf|BD0v1$34UW&i*H literal 0 HcmV?d00001 diff --git a/awx/lib/site-packages/pip/vendor/distlib/util.py b/awx/lib/site-packages/pip/_vendor/distlib/util.py similarity index 80% rename from awx/lib/site-packages/pip/vendor/distlib/util.py rename to awx/lib/site-packages/pip/_vendor/distlib/util.py index f44e8c3528..63cd3132a3 100644 --- a/awx/lib/site-packages/pip/vendor/distlib/util.py +++ b/awx/lib/site-packages/pip/_vendor/distlib/util.py @@ -16,27 +16,25 @@ import re import shutil import socket import ssl +import subprocess import sys import tarfile import tempfile +try: + import threading +except ImportError: + import dummy_threading as threading import time -import zipfile from . import DistlibException -from .compat import (string_types, text_type, shutil, raw_input, +from .compat import (string_types, text_type, shutil, raw_input, StringIO, cache_from_source, urlopen, httplib, xmlrpclib, splittype, HTTPHandler, HTTPSHandler as BaseHTTPSHandler, - URLError, match_hostname, CertificateError) + BaseConfigurator, valid_ident, Container, configparser, + URLError, match_hostname, CertificateError, ZipFile) logger = logging.getLogger(__name__) -class Container(object): - """ - A generic container for when multiple values need to be returned - """ - def __init__(self, **kwargs): - self.__dict__.update(kwargs) - # # Requirement parsing code for name + optional constraints + optional extras # @@ -50,21 +48,26 @@ COMMA = r'\s*,\s*' COMMA_RE = re.compile(COMMA) IDENT = r'(\w|[.-])+' -RELOP = '([<>=!]=)|[<>]' +EXTRA_IDENT = r'(\*|:(\*|\w+):|' + IDENT + ')' +VERSPEC = IDENT + r'\*?' + +RELOP = '([<>=!~]=)|[<>]' # -# The first relop is optional - if absent, will be taken as '==' +# The first relop is optional - if absent, will be taken as '~=' # -BARE_CONSTRAINTS = ('(' + RELOP + r')?\s*(' + IDENT + ')(' + COMMA + '(' + - RELOP + r')\s*(' + IDENT + '))*') +BARE_CONSTRAINTS = ('(' + RELOP + r')?\s*(' + VERSPEC + ')(' + COMMA + '(' + + RELOP + r')\s*(' + VERSPEC + '))*') + +DIRECT_REF = '(from\s+(?P.*))' # # Either the bare constraints or the bare constraints in parentheses # -CONSTRAINTS = (r'\(\s*(?P' + BARE_CONSTRAINTS + r')\s*\)|(?P' + - BARE_CONSTRAINTS + '\s*)') +CONSTRAINTS = (r'\(\s*(?P' + BARE_CONSTRAINTS + '|' + DIRECT_REF + + r')\s*\)|(?P' + BARE_CONSTRAINTS + '\s*)') -EXTRA_LIST = IDENT + '(' + COMMA + IDENT + ')*' +EXTRA_LIST = EXTRA_IDENT + '(' + COMMA + EXTRA_IDENT + ')*' EXTRAS = r'\[\s*(?P' + EXTRA_LIST + r')?\s*\]' REQUIREMENT = ('(?P' + IDENT + r')\s*(' + EXTRAS + r'\s*)?(\s*' + CONSTRAINTS + ')?$') @@ -73,7 +76,7 @@ REQUIREMENT_RE = re.compile(REQUIREMENT) # # Used to scan through the constraints # -RELOP_IDENT = '(?P' + RELOP + r')\s*(?P' + IDENT + ')' +RELOP_IDENT = '(?P' + RELOP + r')\s*(?P' + VERSPEC + ')' RELOP_IDENT_RE = re.compile(RELOP_IDENT) def parse_requirement(s): @@ -88,13 +91,19 @@ def parse_requirement(s): d = m.groupdict() name = d['dn'] cons = d['c1'] or d['c2'] + if not d['diref']: + url = None + else: + # direct reference + cons = None + url = d['diref'].strip() if not cons: cons = None constr = '' rs = d['dn'] else: if cons[0] not in '<>!=': - cons = '==' + cons + cons = '~=' + cons iterator = RELOP_IDENT_RE.finditer(cons) cons = [get_constraint(m) for m in iterator] rs = '%s (%s)' % (name, ', '.join(['%s %s' % con for con in cons])) @@ -103,7 +112,7 @@ def parse_requirement(s): else: extras = COMMA_RE.split(d['ex']) result = Container(name=name, constraints=cons, extras=extras, - requirement=rs, source=s) + requirement=rs, source=s, url=url) return result @@ -168,6 +177,71 @@ def proceed(prompt, allowed_chars, error_prompt=None, default=None): p = '%c: %s\n%s' % (c, error_prompt, prompt) return c + +def extract_by_key(d, keys): + if isinstance(keys, string_types): + keys = keys.split() + result = {} + for key in keys: + if key in d: + result[key] = d[key] + return result + +def read_exports(stream): + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getreader('utf-8')(stream) + # Try to load as JSON, falling back on legacy format + data = stream.read() + stream = StringIO(data) + try: + data = json.load(stream) + result = data['exports'] + for group, entries in result.items(): + for k, v in entries.items(): + s = '%s = %s' % (k, v) + entry = get_export_entry(s) + assert entry is not None + entries[k] = entry + return result + except Exception: + stream.seek(0, 0) + cp = configparser.ConfigParser() + if hasattr(cp, 'read_file'): + cp.read_file(stream) + else: + cp.readfp(stream) + result = {} + for key in cp.sections(): + result[key] = entries = {} + for name, value in cp.items(key): + s = '%s = %s' % (name, value) + entry = get_export_entry(s) + assert entry is not None + #entry.dist = self + entries[name] = entry + return result + + +def write_exports(exports, stream): + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getwriter('utf-8')(stream) + cp = configparser.ConfigParser() + for k, v in exports.items(): + # TODO check k, v for valid values + cp.add_section(k) + for entry in v.values(): + if entry.suffix is None: + s = entry.prefix + else: + s = '%s:%s' % (entry.prefix, entry.suffix) + if entry.flags: + s = '%s [%s]' % (s, ', '.join(entry.flags)) + cp.set(k, entry.name, s) + cp.write(stream) + + @contextlib.contextmanager def tempdir(): td = tempfile.mkdtemp() @@ -202,7 +276,7 @@ class cached_property(object): #for attr in ('__name__', '__module__', '__doc__'): # setattr(self, attr, getattr(func, attr, None)) - def __get__(self, obj, type=None): + def __get__(self, obj, cls=None): if obj is None: return self value = self.func(obj) @@ -272,16 +346,22 @@ class FileOperator(object): return os.stat(source).st_mtime > os.stat(target).st_mtime - def copy_file(self, infile, outfile): + def copy_file(self, infile, outfile, check=True): """Copy a file respecting dry-run and force flags. """ - assert not os.path.isdir(outfile) self.ensure_dir(os.path.dirname(outfile)) logger.info('Copying %s to %s', infile, outfile) if not self.dry_run: + msg = None + if check: + if os.path.islink(outfile): + msg = '%s is a symlink' % outfile + elif os.path.exists(outfile) and not os.path.isfile(outfile): + msg = '%s is a non-regular file' % outfile + if msg: + raise ValueError(msg + ' which would be overwritten') shutil.copyfile(infile, outfile) - if self.record: - self.files_written.add(outfile) + self.record_as_written(outfile) def copy_stream(self, instream, outfile, encoding=None): assert not os.path.isdir(outfile) @@ -296,24 +376,21 @@ class FileOperator(object): shutil.copyfileobj(instream, outstream) finally: outstream.close() - if self.record: - self.files_written.add(outfile) + self.record_as_written(outfile) def write_binary_file(self, path, data): self.ensure_dir(os.path.dirname(path)) if not self.dry_run: with open(path, 'wb') as f: f.write(data) - if self.record: - self.files_written.add(path) + self.record_as_written(path) def write_text_file(self, path, data, encoding): self.ensure_dir(os.path.dirname(path)) if not self.dry_run: with open(path, 'wb') as f: f.write(data.encode(encoding)) - if self.record: - self.files_written.add(path) + self.record_as_written(path) def set_mode(self, bits, mask, files): if os.name == 'posix': @@ -351,9 +428,8 @@ class FileOperator(object): else: assert path.startswith(prefix) diagpath = path[len(prefix):] - py_compile.compile(path, dpath, diagpath, True) # raise on error - if self.record: - self.files_written.add(dpath) + py_compile.compile(path, dpath, diagpath, True) # raise error + self.record_as_written(dpath) return dpath def ensure_removed(self, path): @@ -414,7 +490,7 @@ class FileOperator(object): assert flist == ['__pycache__'] sd = os.path.join(d, flist[0]) os.rmdir(sd) - os.rmdir(d) # should fail if non-empty + os.rmdir(d) # should fail if non-empty self._init_record() def resolve(module_name, dotted_path): @@ -577,8 +653,8 @@ def is_string_sequence(seq): return result PROJECT_NAME_AND_VERSION = re.compile('([a-z0-9_]+([.-][a-z_][a-z0-9_]*)*)-' - '([0-9][a-z0-9_.+-]*)', re.I) -PYTHON_VERSION = re.compile(r'-py(\d\.?\d?)$') + '([a-z0-9_.+-]+)', re.I) +PYTHON_VERSION = re.compile(r'-py(\d\.?\d?)') def split_filename(filename, project_name=None): @@ -604,6 +680,46 @@ def split_filename(filename, project_name=None): result = m.group(1), m.group(3), pyver return result +# Allow spaces in name because of legacy dists like "Twisted Core" +NAME_VERSION_RE = re.compile(r'(?P[\w .-]+)\s*' + r'\(\s*(?P[^\s)]+)\)$') + +def parse_name_and_version(p): + """ + A utility method used to get name and version from a string. + + From e.g. a Provides-Dist value. + + :param p: A value in a form 'foo (1.0)' + :return: The name and version as a tuple. + """ + m = NAME_VERSION_RE.match(p) + if not m: + raise DistlibException('Ill-formed name/version string: \'%s\'' % p) + d = m.groupdict() + return d['name'].strip().lower(), d['ver'] + +def get_extras(requested, available): + result = set() + requested = set(requested or []) + available = set(available or []) + if '*' in requested: + requested.remove('*') + result |= available + for r in requested: + if r == '-': + result.add(r) + elif r.startswith('-'): + unwanted = r[1:] + if unwanted not in available: + logger.warning('undeclared extra: %s' % unwanted) + if unwanted in result: + result.remove(unwanted) + else: + if r not in available: + logger.warning('undeclared extra: %s' % r) + result.add(r) + return result # # Extended metadata functionality # @@ -634,39 +750,11 @@ def get_project_data(name): result = _get_external_data(url) return result -def get_package_data(dist): - name, version = dist.name, dist.version +def get_package_data(name, version): url = ('https://www.red-dove.com/pypi/projects/' '%s/%s/package-%s.json' % (name[0].upper(), name, version)) - result = _get_external_data(url) - if 'metadata' in result and dist.metadata: - update_metadata(dist.metadata, result) - return result + return _get_external_data(url) -RENAMES = { # Temporary - 'classifiers': 'Classifier', - 'use_2to3': None, - 'use_2to3_fixers': None, - 'test_suite': None, -} - -def update_metadata(metadata, pkginfo): - # update dist's metadata from received package data - assert metadata - assert 'metadata' in pkginfo - for k, v in pkginfo['metadata'].items(): - k = k.replace('-', '_') - k = RENAMES.get(k, k) - if k is not None: - metadata[k] = v - metadata.set_metadata_version() - if 'requirements' in pkginfo: - metadata.dependencies = pkginfo['requirements'] - - -# -# Simple event pub/sub -# class EventMixin(object): """ @@ -744,13 +832,26 @@ class Sequencer(object): def __init__(self): self._preds = {} self._succs = {} - self._nodes = set() # nodes with no preds/succs + self._nodes = set() # nodes with no preds/succs def add_node(self, node): self._nodes.add(node) - def remove_node(self, node): - self._nodes.remove(node) + def remove_node(self, node, edges=False): + if node in self._nodes: + self._nodes.remove(node) + if edges: + for p in set(self._preds.get(node, ())): + self.remove(p, node) + for s in set(self._succs.get(node, ())): + self.remove(node, s) + # Remove empties + for k, v in list(self._preds.items()): + if not v: + del self._preds[k] + for k, v in list(self._succs.items()): + if not v: + del self._succs[k] def add(self, pred, succ): assert pred != succ @@ -897,7 +998,7 @@ def unarchive(archive_filename, dest_dir, format=None, check=True): raise ValueError('Unknown format for %r' % archive_filename) try: if format == 'zip': - archive = zipfile.ZipFile(archive_filename, 'r') + archive = ZipFile(archive_filename, 'r') if check: names = archive.namelist() for name in names: @@ -927,7 +1028,7 @@ def zip_dir(directory): """zip a directory tree into a BytesIO object""" result = io.BytesIO() dlen = len(directory) - with zipfile.ZipFile(result, "w") as zf: + with ZipFile(result, "w") as zf: for root, dirs, files in os.walk(directory): for name in files: full = os.path.join(root, name) @@ -942,6 +1043,7 @@ def zip_dir(directory): UNITS = ('', 'K', 'M', 'G','T','P') + class Progress(object): unknown = 'UNKNOWN' @@ -1075,8 +1177,8 @@ def _iglob(path_glob): radical = radical.lstrip('\\') for path, dir, files in os.walk(prefix): path = os.path.normpath(path) - for file in _iglob(os.path.join(path, radical)): - yield file + for fn in _iglob(os.path.join(path, radical)): + yield fn @@ -1120,6 +1222,7 @@ class HTTPSConnection(httplib.HTTPSConnection): if self.ca_certs and self.check_domain: try: match_hostname(self.sock.getpeercert(), self.host) + logger.debug('Host verified: %s', self.host) except CertificateError: self.sock.shutdown(socket.SHUT_RDWR) self.sock.close() @@ -1273,7 +1376,7 @@ class CSVBase(object): class CSVReader(CSVBase): - def __init__(self, fn, **kwargs): + def __init__(self, **kwargs): if 'stream' in kwargs: stream = kwargs['stream'] if sys.version_info[0] >= 3: @@ -1281,7 +1384,7 @@ class CSVReader(CSVBase): stream = codecs.getreader('utf-8')(stream) self.stream = stream else: - self.stream = _csv_open(fn, 'r') + self.stream = _csv_open(kwargs['path'], 'r') self.reader = csv.reader(self.stream, **self.defaults) def __iter__(self): @@ -1311,3 +1414,107 @@ class CSVWriter(CSVBase): r.append(item) row = r self.writer.writerow(row) + +# +# Configurator functionality +# + +class Configurator(BaseConfigurator): + + value_converters = dict(BaseConfigurator.value_converters) + value_converters['inc'] = 'inc_convert' + + def __init__(self, config, base=None): + super(Configurator, self).__init__(config) + self.base = base or os.getcwd() + + def configure_custom(self, config): + def convert(o): + if isinstance(o, (list, tuple)): + result = type(o)([convert(i) for i in o]) + elif isinstance(o, dict): + if '()' in o: + result = self.configure_custom(o) + else: + result = {} + for k in o: + result[k] = convert(o[k]) + else: + result = self.convert(o) + return result + + c = config.pop('()') + if not callable(c): + c = self.resolve(c) + props = config.pop('.', None) + # Check for valid identifiers + args = config.pop('[]', ()) + if args: + args = tuple([convert(o) for o in args]) + items = [(k, convert(config[k])) for k in config if valid_ident(k)] + kwargs = dict(items) + result = c(*args, **kwargs) + if props: + for n, v in props.items(): + setattr(result, n, convert(v)) + return result + + def __getitem__(self, key): + result = self.config[key] + if isinstance(result, dict) and '()' in result: + self.config[key] = result = self.configure_custom(result) + return result + + def inc_convert(self, value): + """Default converter for the inc:// protocol.""" + if not os.path.isabs(value): + value = os.path.join(self.base, value) + with codecs.open(value, 'r', encoding='utf-8') as f: + result = json.load(f) + return result + +# +# Mixin for running subprocesses and capturing their output +# + +class SubprocessMixin(object): + def __init__(self, verbose=False, progress=None): + self.verbose = verbose + self.progress = progress + + def reader(self, stream, context): + """ + Read lines from a subprocess' output stream and either pass to a progress + callable (if specified) or write progress information to sys.stderr. + """ + progress = self.progress + verbose = self.verbose + while True: + s = stream.readline() + if not s: + break + if progress is not None: + progress(s, context) + else: + if not verbose: + sys.stderr.write('.') + else: + sys.stderr.write(s.decode('utf-8')) + sys.stderr.flush() + stream.close() + + def run_command(self, cmd, **kwargs): + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, **kwargs) + t1 = threading.Thread(target=self.reader, args=(p.stdout, 'stdout')) + t1.start() + t2 = threading.Thread(target=self.reader, args=(p.stderr, 'stderr')) + t2.start() + p.wait() + t1.join() + t2.join() + if self.progress is not None: + self.progress('done.', 'main') + elif self.verbose: + sys.stderr.write('done.\n') + return p diff --git a/awx/lib/site-packages/pip/vendor/distlib/version.py b/awx/lib/site-packages/pip/_vendor/distlib/version.py similarity index 64% rename from awx/lib/site-packages/pip/vendor/distlib/version.py rename to awx/lib/site-packages/pip/_vendor/distlib/version.py index 1e45e31182..a2192274ca 100644 --- a/awx/lib/site-packages/pip/vendor/distlib/version.py +++ b/awx/lib/site-packages/pip/_vendor/distlib/version.py @@ -8,6 +8,7 @@ Implementation of a flexible versioning scheme providing support for PEP-386, distribute-compatible and semantic versioning. """ +import logging import re from .compat import string_types @@ -15,37 +16,17 @@ from .compat import string_types __all__ = ['NormalizedVersion', 'NormalizedMatcher', 'LegacyVersion', 'LegacyMatcher', 'SemanticVersion', 'SemanticMatcher', - 'AdaptiveVersion', 'AdaptiveMatcher', - 'UnsupportedVersionError', 'HugeMajorVersionError', - 'suggest_normalized_version', 'suggest_semantic_version', - 'suggest_adaptive_version', - 'normalized_key', 'legacy_key', 'semantic_key', 'adaptive_key', - 'get_scheme'] + 'UnsupportedVersionError', 'get_scheme'] -class UnsupportedVersionError(Exception): +logger = logging.getLogger(__name__) + + +class UnsupportedVersionError(ValueError): """This is an unsupported version.""" pass -class HugeMajorVersionError(UnsupportedVersionError): - """An irrational version because the major version number is huge - (often because a year or date was used). - - See `error_on_huge_major_num` option in `NormalizedVersion` for details. - This guard can be disabled by setting that option False. - """ - pass - - -class _Common(object): - def __repr__(self): - return "%s(%r)" % (self.__class__.__name__, self._string) - - def __str__(self): - return self._string - - -class Version(_Common): +class Version(object): def __init__(self, s): self._string = s = s.strip() self._parts = parts = self.parse(s) @@ -83,30 +64,41 @@ class Version(_Common): def __hash__(self): return hash(self._parts) + def __repr__(self): + return "%s('%s')" % (self.__class__.__name__, self._string) + + def __str__(self): + return self._string + @property def is_prerelease(self): raise NotImplementedError('Please implement in subclasses.') -class Matcher(_Common): + +class Matcher(object): version_class = None - predicate_re = re.compile(r"^(\w[\s\w'.-]*)(\((.*)\))?") - constraint_re = re.compile(r'^(<=|>=|<|>|!=|==)?\s*([^\s,]+)$') + dist_re = re.compile(r"^(\w[\s\w'.-]*)(\((.*)\))?") + comp_re = re.compile(r'^(<=|>=|<|>|!=|==|~=)?\s*([^\s,]+)$') + num_re = re.compile(r'^\d+(\.\d+)*$') + # value is either a callable or the name of a method _operators = { - "<": lambda x, y: x < y, - ">": lambda x, y: x > y, - "<=": lambda x, y: x == y or x < y, - ">=": lambda x, y: x == y or x > y, - "==": lambda x, y: x == y, - "!=": lambda x, y: x != y, + '<': lambda v, c, p: v < c, + '>': lambda v, c, p: v > c, + '<=': lambda v, c, p: v == c or v < c, + '>=': lambda v, c, p: v == c or v > c, + '==': lambda v, c, p: v == c, + # by default, compatible => >=. + '~=': lambda v, c, p: v == c or v > c, + '!=': lambda v, c, p: v != c, } def __init__(self, s): if self.version_class is None: raise ValueError('Please specify a version class') self._string = s = s.strip() - m = self.predicate_re.match(s) + m = self.dist_re.match(s) if not m: raise ValueError('Not valid: %r' % s) groups = m.groups('') @@ -116,19 +108,47 @@ class Matcher(_Common): if groups[2]: constraints = [c.strip() for c in groups[2].split(',')] for c in constraints: - m = self.constraint_re.match(c) + m = self.comp_re.match(c) if not m: raise ValueError('Invalid %r in %r' % (c, s)) - groups = m.groups('==') - clist.append((groups[0], self.version_class(groups[1]))) + groups = m.groups() + op = groups[0] or '~=' + s = groups[1] + if s.endswith('.*'): + if op not in ('==', '!='): + raise ValueError('\'.*\' not allowed for ' + '%r constraints' % op) + # Could be a partial version (e.g. for '2.*') which + # won't parse as a version, so keep it as a string + vn, prefix = s[:-2], True + if not self.num_re.match(vn): + # Just to check that vn is a valid version + self.version_class(vn) + else: + # Should parse as a version, so we can create an + # instance for the comparison + vn, prefix = self.version_class(s), False + clist.append((op, vn, prefix)) self._parts = tuple(clist) def match(self, version): - """Check if the provided version matches the constraints.""" + """ + Check if the provided version matches the constraints. + + :param version: The version to match against this instance. + :type version: Strring or :class:`Version` instance. + """ if isinstance(version, string_types): version = self.version_class(version) - for operator, constraint in self._parts: - if not self._operators[operator](version, constraint): + for operator, constraint, prefix in self._parts: + f = self._operators.get(operator) + if isinstance(f, string_types): + f = getattr(self, f) + if not f: + msg = ('%r not implemented ' + 'for %s' % (operator, self.__class__.__name__)) + raise NotImplementedError(msg) + if not f(version, constraint, prefix): return False return True @@ -145,7 +165,7 @@ class Matcher(_Common): def __eq__(self, other): self._check_compatible(other) - return (self.key == other.key and self._parts == other._parts) + return self.key == other.key and self._parts == other._parts def __ne__(self, other): return not self.__eq__(other) @@ -154,104 +174,19 @@ class Matcher(_Common): def __hash__(self): return hash(self.key) + hash(self._parts) -# A marker used in the second and third parts of the `parts` tuple, for -# versions that don't have those segments, to sort properly. An example -# of versions in sort order ('highest' last): -# 1.0b1 ((1,0), ('b',1), ('z',)) -# 1.0.dev345 ((1,0), ('z',), ('dev', 345)) -# 1.0 ((1,0), ('z',), ('z',)) -# 1.0.post256.dev345 ((1,0), ('z',), ('z', 'post', 256, 'dev', 345)) -# 1.0.post345 ((1,0), ('z',), ('z', 'post', 345, 'z')) -# ^ ^ ^ -# 'b' < 'z' ---------------------/ | | -# | | -# 'dev' < 'z' ----------------------------/ | -# | -# 'dev' < 'z' ----------------------------------------------/ -# 'f' for 'final' would be kind of nice, but due to bugs in the support of -# 'rc' we must use 'z' -_FINAL_MARKER = ('z',) + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self._string) -_VERSION_RE = re.compile(r''' - ^ - (?P\d+\.\d+(\.\d+)*) # minimum 'N.N' - (?: - (?P[abc]|rc) # 'a'=alpha, 'b'=beta, 'c'=release candidate - # 'rc'= alias for release candidate - (?P\d+(?:\.\d+)*) - )? - (?P(\.post(?P\d+))?(\.dev(?P\d+))?)? - $''', re.VERBOSE) + def __str__(self): + return self._string -def _parse_numdots(s, full_ver, drop_zeroes=False, min_length=0): - """Parse 'N.N.N' sequences, return a list of ints. - - @param s {str} 'N.N.N...' sequence to be parsed - @param full_ver_str {str} The full version string from which this - comes. Used for error strings. - @param min_length {int} The length to which to pad the - returned list with zeros, if necessary. Default 0. - """ - result = [] - for n in s.split("."): - #if len(n) > 1 and n[0] == '0': - # raise UnsupportedVersionError("cannot have leading zero in " - # "version number segment: '%s' in %r" % (n, full_ver)) - result.append(int(n)) - if drop_zeroes: - while (result and result[-1] == 0 and - (1 + len(result)) > min_length): - result.pop() - return result - -def pep386_key(s, fail_on_huge_major_ver=True): - """Parses a string version into parts using PEP-386 logic.""" - - match = _VERSION_RE.search(s) - if not match: - raise UnsupportedVersionError(s) - - groups = match.groupdict() - parts = [] - - # main version - block = _parse_numdots(groups['version'], s, min_length=2) - parts.append(tuple(block)) - - # prerelease - prerel = groups.get('prerel') - if prerel is not None: - block = [prerel] - block += _parse_numdots(groups.get('prerelversion'), s, min_length=1) - parts.append(tuple(block)) - else: - parts.append(_FINAL_MARKER) - - # postdev - if groups.get('postdev'): - post = groups.get('post') - dev = groups.get('dev') - postdev = [] - if post is not None: - postdev.extend((_FINAL_MARKER[0], 'post', int(post))) - if dev is None: - postdev.append(_FINAL_MARKER[0]) - if dev is not None: - postdev.extend(('dev', int(dev))) - parts.append(tuple(postdev)) - else: - parts.append(_FINAL_MARKER) - if fail_on_huge_major_ver and parts[0][0] > 1980: - raise HugeMajorVersionError("huge major version number, %r, " - "which might cause future problems: %r" % (parts[0][0], s)) - return tuple(parts) +PEP426_VERSION_RE = re.compile(r'^(\d+\.\d+(\.\d+)*)((a|b|c|rc)(\d+))?' + r'(\.(post)(\d+))?(\.(dev)(\d+))?' + r'(-(\d+(\.\d+)?))?$') -PEP426_VERSION_RE = re.compile('^(\d+\.\d+(\.\d+)*)((a|b|c|rc)(\d+))?' - '(\.(post)(\d+))?(\.(dev)(\d+))?$') - -def pep426_key(s, _=None): +def _pep426_key(s): s = s.strip() m = PEP426_VERSION_RE.match(s) if not m: @@ -264,6 +199,7 @@ def pep426_key(s, _=None): pre = groups[3:5] post = groups[6:8] dev = groups[9:11] + local = groups[12] if pre == (None, None): pre = () else: @@ -276,13 +212,17 @@ def pep426_key(s, _=None): dev = () else: dev = dev[0], int(dev[1]) + if local is None: + local = () + else: + local = tuple([int(s) for s in local.split('.')]) if not pre: # either before pre-release, or final release and after if not post and dev: # before pre-release - pre = ('a', -1) # to sort before a0 + pre = ('a', -1) # to sort before a0 else: - pre = ('z',) # to sort after all pre-releases + pre = ('z',) # to sort after all pre-releases # now look at the state of post and dev. if not post: post = ('_',) # sort before 'a' @@ -290,10 +230,11 @@ def pep426_key(s, _=None): dev = ('final',) #print('%s -> %s' % (s, m.groups())) - return nums, pre, post, dev + return nums, pre, post, dev, local -normalized_key = pep426_key +_normalized_key = _pep426_key + class NormalizedVersion(Version): """A rational version. @@ -313,39 +254,93 @@ class NormalizedVersion(Version): 1.2a # release level must have a release serial 1.2.3b """ - def parse(self, s): return normalized_key(s) + def parse(self, s): + result = _normalized_key(s) + # _normalized_key loses trailing zeroes in the release + # clause, since that's needed to ensure that X.Y == X.Y.0 == X.Y.0.0 + # However, PEP 440 prefix matching needs it: for example, + # (~= 1.4.5.0) matches differently to (~= 1.4.5.0.0). + m = PEP426_VERSION_RE.match(s) # must succeed + groups = m.groups() + self._release_clause = tuple(int(v) for v in groups[0].split('.')) + return result PREREL_TAGS = set(['a', 'b', 'c', 'rc', 'dev']) @property def is_prerelease(self): - return any(t[0] in self.PREREL_TAGS for t in self._parts) + return any(t[0] in self.PREREL_TAGS for t in self._parts if t) -class UnlimitedMajorVersion(Version): - def parse(self, s): return normalized_key(s, False) -# We want '2.5' to match '2.5.4' but not '2.50'. - -def _match_at_front(x, y): - if x == y: - return True +def _match_prefix(x, y): x = str(x) y = str(y) + if x == y: + return True if not x.startswith(y): return False n = len(y) return x[n] == '.' + class NormalizedMatcher(Matcher): version_class = NormalizedVersion - _operators = dict(Matcher._operators) - _operators.update({ - "<=": lambda x, y: _match_at_front(x, y) or x < y, - ">=": lambda x, y: _match_at_front(x, y) or x > y, - "==": lambda x, y: _match_at_front(x, y), - "!=": lambda x, y: not _match_at_front(x, y), - }) + # value is either a callable or the name of a method + _operators = { + '~=': '_match_compatible', + '<': '_match_lt', + '>': '_match_gt', + '<=': '_match_le', + '>=': '_match_ge', + '==': '_match_eq', + '!=': '_match_ne', + } + + def _match_lt(self, version, constraint, prefix): + if version >= constraint: + return False + release_clause = constraint._release_clause + pfx = '.'.join([str(i) for i in release_clause]) + return not _match_prefix(version, pfx) + + def _match_gt(self, version, constraint, prefix): + if version <= constraint: + return False + release_clause = constraint._release_clause + pfx = '.'.join([str(i) for i in release_clause]) + return not _match_prefix(version, pfx) + + def _match_le(self, version, constraint, prefix): + return version <= constraint + + def _match_ge(self, version, constraint, prefix): + return version >= constraint + + def _match_eq(self, version, constraint, prefix): + if not prefix: + result = (version == constraint) + else: + result = _match_prefix(version, constraint) + return result + + def _match_ne(self, version, constraint, prefix): + if not prefix: + result = (version != constraint) + else: + result = not _match_prefix(version, constraint) + return result + + def _match_compatible(self, version, constraint, prefix): + if version == constraint: + return True + if version < constraint: + return False + release_clause = constraint._release_clause + if len(release_clause) > 1: + release_clause = release_clause[:-1] + pfx = '.'.join([str(i) for i in release_clause]) + return _match_prefix(version, pfx) _REPLACEMENTS = ( (re.compile('[.+-]$'), ''), # remove trailing puncts @@ -363,7 +358,7 @@ _REPLACEMENTS = ( _SUFFIX_REPLACEMENTS = ( (re.compile('^[:~._+-]+'), ''), # remove leading puncts - (re.compile('[,*")([\]]'), ''), # remove unwanted chars + (re.compile('[,*")([\]]'), ''), # remove unwanted chars (re.compile('[~:+_ -]'), '.'), # replace illegal chars (re.compile('[.]{2,}'), '.'), # multiple runs of '.' (re.compile(r'\.$'), ''), # trailing '.' @@ -371,10 +366,11 @@ _SUFFIX_REPLACEMENTS = ( _NUMERIC_PREFIX = re.compile(r'(\d+(\.\d+)*)') -def suggest_semantic_version(s): + +def _suggest_semantic_version(s): """ Try to suggest a semantic form for a version for which - suggest_normalized_version couldn't come up with anything. + _suggest_normalized_version couldn't come up with anything. """ result = s.strip().lower() for pat, repl in _REPLACEMENTS: @@ -417,7 +413,7 @@ def suggest_semantic_version(s): return result -def suggest_normalized_version(s): +def _suggest_normalized_version(s): """Suggest a normalized version close to the given version string. If you have a version string that isn't rational (i.e. NormalizedVersion @@ -435,7 +431,7 @@ def suggest_normalized_version(s): @returns A rational version string, or None, if couldn't determine one. """ try: - normalized_key(s) + _normalized_key(s) return s # already rational except UnsupportedVersionError: pass @@ -522,37 +518,34 @@ def suggest_normalized_version(s): rs = re.sub(r"p(\d+)$", r".post\1", rs) try: - normalized_key(rs) + _normalized_key(rs) except UnsupportedVersionError: rs = None return rs -def suggest_adaptive_version(s): - return suggest_normalized_version(s) or suggest_semantic_version(s) - # # Legacy version processing (distribute-compatible) # _VERSION_PART = re.compile(r'([a-z]+|\d+|[\.-])', re.I) _VERSION_REPLACE = { - 'pre':'c', - 'preview':'c', - '-':'final-', - 'rc':'c', - 'dev':'@', + 'pre': 'c', + 'preview': 'c', + '-': 'final-', + 'rc': 'c', + 'dev': '@', '': None, '.': None, } -def legacy_key(s): +def _legacy_key(s): def get_parts(s): result = [] for p in _VERSION_PART.split(s.lower()): p = _VERSION_REPLACE.get(p, p) if p: - if '0' <= p[:1] <= '9': + if '0' <= p[:1] <= '9': p = p.zfill(8) else: p = '*' + p @@ -571,8 +564,10 @@ def legacy_key(s): result.append(p) return tuple(result) + class LegacyVersion(Version): - def parse(self, s): return legacy_key(s) + def parse(self, s): + return _legacy_key(s) PREREL_TAGS = set( ['*a', '*alpha', '*b', '*beta', '*c', '*rc', '*r', '*@', '*pre'] @@ -582,9 +577,28 @@ class LegacyVersion(Version): def is_prerelease(self): return any(x in self.PREREL_TAGS for x in self._parts) + class LegacyMatcher(Matcher): version_class = LegacyVersion + _operators = dict(Matcher._operators) + _operators['~='] = '_match_compatible' + + numeric_re = re.compile('^(\d+(\.\d+)*)') + + def _match_compatible(self, version, constraint, prefix): + if version < constraint: + return False + m = self.numeric_re.match(str(constraint)) + if not m: + logger.warning('Cannot compute compatible match for version %s ' + ' and constraint %s', version, constraint) + return True + s = m.groups()[0] + if '.' in s: + s = s.rsplit('.', 1)[0] + return _match_prefix(version, s) + # # Semantic versioning # @@ -593,10 +607,12 @@ _SEMVER_RE = re.compile(r'^(\d+)\.(\d+)\.(\d+)' r'(-[a-z0-9]+(\.[a-z0-9-]+)*)?' r'(\+[a-z0-9]+(\.[a-z0-9-]+)*)?$', re.I) + def is_semver(s): return _SEMVER_RE.match(s) -def semantic_key(s): + +def _semantic_key(s): def make_tuple(s, absent): if s is None: result = (absent,) @@ -607,7 +623,6 @@ def semantic_key(s): result = tuple([p.zfill(8) if p.isdigit() else p for p in parts]) return result - result = None m = is_semver(s) if not m: raise UnsupportedVersionError(s) @@ -615,11 +630,12 @@ def semantic_key(s): major, minor, patch = [int(i) for i in groups[:3]] # choose the '|' and '*' so that versions sort correctly pre, build = make_tuple(groups[3], '|'), make_tuple(groups[5], '*') - return ((major, minor, patch), pre, build) + return (major, minor, patch), pre, build class SemanticVersion(Version): - def parse(self, s): return semantic_key(s) + def parse(self, s): + return _semantic_key(s) @property def is_prerelease(self): @@ -629,42 +645,6 @@ class SemanticVersion(Version): class SemanticMatcher(Matcher): version_class = SemanticVersion -# -# Adaptive versioning. When handed a legacy version string, tries to -# determine a suggested normalized version, and work with that. -# - -def adaptive_key(s): - try: - result = normalized_key(s, False) - except UnsupportedVersionError: - ss = suggest_normalized_version(s) - if ss is not None: - result = normalized_key(ss) # "guaranteed" to work - else: - ss = s # suggest_semantic_version(s) or s - result = semantic_key(ss) # let's hope ... - return result - - -class AdaptiveVersion(NormalizedVersion): - def parse(self, s): return adaptive_key(s) - - @property - def is_prerelease(self): - try: - normalized_key(self._string) - not_sem = True - except UnsupportedVersionError: - ss = suggest_normalized_version(self._string) - not_sem = ss is not None - if not_sem: - return any(t[0] in self.PREREL_TAGS for t in self._parts) - return self._parts[1][0] != '|' - -class AdaptiveMatcher(NormalizedMatcher): - version_class = AdaptiveVersion - class VersionScheme(object): def __init__(self, key, matcher, suggester=None): @@ -702,16 +682,15 @@ class VersionScheme(object): return result _SCHEMES = { - 'normalized': VersionScheme(normalized_key, NormalizedMatcher, - suggest_normalized_version), - 'legacy': VersionScheme(legacy_key, LegacyMatcher, lambda self, s: s), - 'semantic': VersionScheme(semantic_key, SemanticMatcher, - suggest_semantic_version), - 'adaptive': VersionScheme(adaptive_key, AdaptiveMatcher, - suggest_adaptive_version), + 'normalized': VersionScheme(_normalized_key, NormalizedMatcher, + _suggest_normalized_version), + 'legacy': VersionScheme(_legacy_key, LegacyMatcher, lambda self, s: s), + 'semantic': VersionScheme(_semantic_key, SemanticMatcher, + _suggest_semantic_version), } -_SCHEMES['default'] = _SCHEMES['adaptive'] +_SCHEMES['default'] = _SCHEMES['normalized'] + def get_scheme(name): if name not in _SCHEMES: diff --git a/awx/lib/site-packages/pip/_vendor/distlib/w32.exe b/awx/lib/site-packages/pip/_vendor/distlib/w32.exe new file mode 100644 index 0000000000000000000000000000000000000000..09e76354f7b45b4a90272ed578ff14bbbf5ab540 GIT binary patch literal 87040 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 literal 0 HcmV?d00001 diff --git a/awx/lib/site-packages/pip/_vendor/distlib/w64.exe b/awx/lib/site-packages/pip/_vendor/distlib/w64.exe new file mode 100644 index 0000000000000000000000000000000000000000..29e44e1f8a4215238d7af0f5ee8a9a6dabaaf18d GIT binary patch literal 91648 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

S7V%iUn;9oxpVta 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 literal 0 HcmV?d00001 diff --git a/awx/lib/site-packages/pip/vendor/distlib/wheel.py b/awx/lib/site-packages/pip/_vendor/distlib/wheel.py similarity index 77% rename from awx/lib/site-packages/pip/vendor/distlib/wheel.py rename to awx/lib/site-packages/pip/_vendor/distlib/wheel.py index 8274732adc..a2bca6ed96 100644 --- a/awx/lib/site-packages/pip/vendor/distlib/wheel.py +++ b/awx/lib/site-packages/pip/_vendor/distlib/wheel.py @@ -23,13 +23,12 @@ import sys import tempfile import zipfile -from . import DistlibException +from . import __version__, DistlibException from .compat import sysconfig, ZipFile, fsdecode, text_type, filter -from .database import DistributionPath, InstalledDistribution -from .metadata import Metadata -from .scripts import ScriptMaker +from .database import InstalledDistribution +from .metadata import Metadata, METADATA_FILENAME from .util import (FileOperator, convert_path, CSVReader, CSVWriter, - cached_property, get_cache_base) + cached_property, get_cache_base, read_exports) logger = logging.getLogger(__name__) @@ -112,7 +111,9 @@ class Mounter(object): raise ImportError('unable to find extension for %s' % fullname) result = imp.load_dynamic(fullname, self.libs[fullname]) result.__loader__ = self - result.__package__, _ = fullname.rsplit('.', 1) + parts = fullname.rsplit('.', 1) + if len(parts) > 1: + result.__package__ = parts[0] return result _hook = Mounter() @@ -123,7 +124,7 @@ class Wheel(object): Class to build and install from Wheel files (PEP 427). """ - wheel_version = (1, 0) + wheel_version = (1, 1) hash_kind = 'sha256' def __init__(self, filename=None, sign=False, verify=False): @@ -193,13 +194,16 @@ class Wheel(object): pathname = os.path.join(self.dirname, self.filename) name_ver = '%s-%s' % (self.name, self.version) info_dir = '%s.dist-info' % name_ver - metadata_filename = posixpath.join(info_dir, 'METADATA') wrapper = codecs.getreader('utf-8') + metadata_filename = posixpath.join(info_dir, METADATA_FILENAME) with ZipFile(pathname, 'r') as zf: - with zf.open(metadata_filename) as bf: - wf = wrapper(bf) - result = Metadata() - result.read_file(wf) + try: + with zf.open(metadata_filename) as bf: + wf = wrapper(bf) + result = Metadata(fileobj=wf) + except KeyError: + raise ValueError('Invalid wheel, because %s is ' + 'missing' % METADATA_FILENAME) return result @cached_property @@ -251,7 +255,7 @@ class Wheel(object): p = to_posix(os.path.relpath(record_path, base)) writer.writerow((p, '', '')) - def build(self, paths, tags=None): + def build(self, paths, tags=None, wheel_version=None): """ Build a wheel from files in specified paths, and use any specified tags when determining the name of the wheel. @@ -334,11 +338,9 @@ class Wheel(object): ap = to_posix(os.path.join(info_dir, fn)) archive_paths.append((ap, p)) - import distlib - wheel_metadata = [ - 'Wheel-Version: %d.%d' % self.wheel_version, - 'Generator: distlib %s' % distlib.__version__, + 'Wheel-Version: %d.%d' % (wheel_version or self.wheel_version), + 'Generator: distlib %s' % __version__, 'Root-Is-Purelib: %s' % is_pure, ] for pyver, abi, arch in self.tags: @@ -372,21 +374,31 @@ class Wheel(object): zf.write(p, ap) return pathname - def install(self, paths, dry_run=False, executable=None, warner=None): + def install(self, paths, maker, **kwargs): """ - Install a wheel to the specified paths. If ``executable`` is specified, - it should be the Unicode absolute path the to the executable written - into the shebang lines of any scripts installed. If ``warner`` is + Install a wheel to the specified paths. If kwarg ``warner`` is specified, it should be a callable, which will be called with two tuples indicating the wheel version of this software and the wheel version in the file, if there is a discrepancy in the versions. This can be used to issue any warnings to raise any exceptions. + If kwarg ``lib_only`` is True, only the purelib/platlib files are + installed, and the headers, scripts, data and dist-info metadata are + not written. + + The return value is a :class:`InstalledDistribution` instance unless + ``options.lib_only`` is True, in which case the return value is ``None``. """ + + dry_run = maker.dry_run + warner = kwargs.get('warner') + lib_only = kwargs.get('lib_only', False) + pathname = os.path.join(self.dirname, self.filename) name_ver = '%s-%s' % (self.name, self.version) data_dir = '%s.data' % name_ver info_dir = '%s.dist-info' % name_ver + metadata_name = posixpath.join(info_dir, METADATA_FILENAME) wheel_metadata_name = posixpath.join(info_dir, 'WHEEL') record_name = posixpath.join(info_dir, 'RECORD') @@ -405,16 +417,20 @@ class Wheel(object): libdir = paths['purelib'] else: libdir = paths['platlib'] + records = {} with zf.open(record_name) as bf: - with CSVReader(record_name, stream=bf) as reader: + with CSVReader(stream=bf) as reader: for row in reader: p = row[0] records[p] = row data_pfx = posixpath.join(data_dir, '') + info_pfx = posixpath.join(info_dir, '') script_pfx = posixpath.join(data_dir, 'scripts', '') + # make a new instance rather than a copy of maker's, + # as we mutate it fileop = FileOperator(dry_run=dry_run) fileop.record = True # so we can rollback if needed @@ -427,9 +443,8 @@ class Wheel(object): # set target dir later # we default add_launchers to False, as the # Python Launcher should be used instead - maker = ScriptMaker(workdir, None, fileop=fileop, - add_launchers=False) - maker.executable = executable + maker.source_dir = workdir + maker.target_dir = None try: for zinfo in zf.infolist(): arcname = zinfo.filename @@ -437,6 +452,10 @@ class Wheel(object): u_arcname = arcname else: u_arcname = arcname.decode('utf-8') + # The signature file won't be in RECORD, + # and we don't currently don't do anything with it + if u_arcname.endswith('/RECORD.jws'): + continue row = records[u_arcname] if row[2] and str(zinfo.file_size) != row[2]: raise DistlibException('size mismatch for ' @@ -450,6 +469,9 @@ class Wheel(object): raise DistlibException('digest mismatch for ' '%s' % arcname) + if lib_only and u_arcname.startswith((info_pfx, data_pfx)): + logger.debug('lib_only: skipping %s', u_arcname) + continue is_script = (u_arcname.startswith(script_pfx) and not u_arcname.endswith('.exe')) @@ -495,22 +517,83 @@ class Wheel(object): fileop.set_executable_mode(filenames) outfiles.extend(filenames) - p = os.path.join(libdir, info_dir) - dist = InstalledDistribution(p) + if lib_only: + logger.debug('lib_only: returning None') + dist = None + else: + # Generate scripts - # Write SHARED - paths = dict(paths) # don't change passed in dict - del paths['purelib'] - del paths['platlib'] - paths['lib'] = libdir - p = dist.write_shared_locations(paths, dry_run) - outfiles.append(p) + # Try to get pydist.json so we can see if there are + # any commands to generate. If this fails (e.g. because + # of a legacy wheel), log a warning but don't give up. + commands = None + file_version = self.info['Wheel-Version'] + if file_version == '1.0': + # Use legacy info + ep = posixpath.join(info_dir, 'entry_points.txt') + try: + with zf.open(ep) as bwf: + epdata = read_exports(bwf) + commands = {} + for key in ('console', 'gui'): + k = '%s_scripts' % key + if k in epdata: + commands['wrap_%s' % key] = d = {} + for v in epdata[k].values(): + s = '%s:%s' % (v.prefix, v.suffix) + if v.flags: + s += ' %s' % v.flags + d[v.name] = s + except Exception: + logger.warning('Unable to read legacy script ' + 'metadata, so cannot generate ' + 'scripts') + else: + try: + with zf.open(metadata_name) as bwf: + wf = wrapper(bwf) + commands = json.load(wf).get('commands') + except Exception: + logger.warning('Unable to read JSON metadata, so ' + 'cannot generate scripts') + if commands: + console_scripts = commands.get('wrap_console', {}) + gui_scripts = commands.get('wrap_gui', {}) + if console_scripts or gui_scripts: + script_dir = paths.get('scripts', '') + if not os.path.isdir(script_dir): + raise ValueError('Valid script path not ' + 'specified') + maker.target_dir = script_dir + for k, v in console_scripts.items(): + script = '%s = %s' % (k, v) + filenames = maker.make(script) + fileop.set_executable_mode(filenames) - # Write RECORD - dist.write_installed_files(outfiles, paths['prefix'], - dry_run) + if gui_scripts: + options = {'gui': True } + for k, v in gui_scripts.items(): + script = '%s = %s' % (k, v) + filenames = maker.make(script, options) + fileop.set_executable_mode(filenames) + + p = os.path.join(libdir, info_dir) + dist = InstalledDistribution(p) + + # Write SHARED + paths = dict(paths) # don't change passed in dict + del paths['purelib'] + del paths['platlib'] + paths['lib'] = libdir + p = dist.write_shared_locations(paths, dry_run) + if p: + outfiles.append(p) + + # Write RECORD + dist.write_installed_files(outfiles, paths['prefix'], + dry_run) return dist - except Exception as e: # pragma: no cover + except Exception: # pragma: no cover logger.exception('installation failed.') fileop.rollback() raise @@ -518,7 +601,7 @@ class Wheel(object): shutil.rmtree(workdir) def _get_dylib_cache(self): - result = os.path.join(get_cache_base(), 'dylib-cache') + result = os.path.join(get_cache_base(), 'dylib-cache', sys.version[:3]) if not os.path.isdir(result): os.makedirs(result) return result @@ -625,6 +708,7 @@ COMPATIBLE_TAGS = compatible_tags() del compatible_tags + def is_compatible(wheel, tags=None): if not isinstance(wheel, Wheel): wheel = Wheel(wheel) # assume it's a filename diff --git a/awx/lib/site-packages/pip/vendor/html5lib/__init__.py b/awx/lib/site-packages/pip/_vendor/html5lib/__init__.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/__init__.py rename to awx/lib/site-packages/pip/_vendor/html5lib/__init__.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/constants.py b/awx/lib/site-packages/pip/_vendor/html5lib/constants.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/constants.py rename to awx/lib/site-packages/pip/_vendor/html5lib/constants.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/filters/__init__.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/__init__.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/filters/__init__.py rename to awx/lib/site-packages/pip/_vendor/html5lib/filters/__init__.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/filters/_base.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/_base.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/filters/_base.py rename to awx/lib/site-packages/pip/_vendor/html5lib/filters/_base.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/filters/alphabeticalattributes.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/filters/alphabeticalattributes.py rename to awx/lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/filters/inject_meta_charset.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/filters/inject_meta_charset.py rename to awx/lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/filters/lint.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/lint.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/filters/lint.py rename to awx/lib/site-packages/pip/_vendor/html5lib/filters/lint.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/filters/optionaltags.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/filters/optionaltags.py rename to awx/lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/filters/sanitizer.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/filters/sanitizer.py rename to awx/lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/filters/whitespace.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/filters/whitespace.py rename to awx/lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/html5parser.py b/awx/lib/site-packages/pip/_vendor/html5lib/html5parser.py similarity index 99% rename from awx/lib/site-packages/pip/vendor/html5lib/html5parser.py rename to awx/lib/site-packages/pip/_vendor/html5lib/html5parser.py index 9dfa4dd0a5..8a5acfeb02 100644 --- a/awx/lib/site-packages/pip/vendor/html5lib/html5parser.py +++ b/awx/lib/site-packages/pip/_vendor/html5lib/html5parser.py @@ -1,5 +1,5 @@ from __future__ import absolute_import, division, unicode_literals -from pip.vendor.six import with_metaclass +from pip._vendor.six import with_metaclass import types diff --git a/awx/lib/site-packages/pip/vendor/html5lib/ihatexml.py b/awx/lib/site-packages/pip/_vendor/html5lib/ihatexml.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/ihatexml.py rename to awx/lib/site-packages/pip/_vendor/html5lib/ihatexml.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/inputstream.py b/awx/lib/site-packages/pip/_vendor/html5lib/inputstream.py similarity index 99% rename from awx/lib/site-packages/pip/vendor/html5lib/inputstream.py rename to awx/lib/site-packages/pip/_vendor/html5lib/inputstream.py index 00d837fa51..0ac70bb3a4 100644 --- a/awx/lib/site-packages/pip/vendor/html5lib/inputstream.py +++ b/awx/lib/site-packages/pip/_vendor/html5lib/inputstream.py @@ -1,5 +1,5 @@ from __future__ import absolute_import, division, unicode_literals -from pip.vendor.six import text_type +from pip._vendor.six import text_type import codecs import re diff --git a/awx/lib/site-packages/pip/vendor/html5lib/sanitizer.py b/awx/lib/site-packages/pip/_vendor/html5lib/sanitizer.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/sanitizer.py rename to awx/lib/site-packages/pip/_vendor/html5lib/sanitizer.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/serializer/__init__.py b/awx/lib/site-packages/pip/_vendor/html5lib/serializer/__init__.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/serializer/__init__.py rename to awx/lib/site-packages/pip/_vendor/html5lib/serializer/__init__.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/serializer/htmlserializer.py b/awx/lib/site-packages/pip/_vendor/html5lib/serializer/htmlserializer.py similarity index 99% rename from awx/lib/site-packages/pip/vendor/html5lib/serializer/htmlserializer.py rename to awx/lib/site-packages/pip/_vendor/html5lib/serializer/htmlserializer.py index 11a932703b..08b60dfcc4 100644 --- a/awx/lib/site-packages/pip/vendor/html5lib/serializer/htmlserializer.py +++ b/awx/lib/site-packages/pip/_vendor/html5lib/serializer/htmlserializer.py @@ -1,5 +1,5 @@ from __future__ import absolute_import, division, unicode_literals -from pip.vendor.six import text_type +from pip._vendor.six import text_type import gettext _ = gettext.gettext diff --git a/awx/lib/site-packages/pip/vendor/html5lib/tokenizer.py b/awx/lib/site-packages/pip/_vendor/html5lib/tokenizer.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/tokenizer.py rename to awx/lib/site-packages/pip/_vendor/html5lib/tokenizer.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/treebuilders/__init__.py b/awx/lib/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/treebuilders/__init__.py rename to awx/lib/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/treebuilders/_base.py b/awx/lib/site-packages/pip/_vendor/html5lib/treebuilders/_base.py similarity index 99% rename from awx/lib/site-packages/pip/vendor/html5lib/treebuilders/_base.py rename to awx/lib/site-packages/pip/_vendor/html5lib/treebuilders/_base.py index 8d5bc7e8d4..970c9adb61 100644 --- a/awx/lib/site-packages/pip/vendor/html5lib/treebuilders/_base.py +++ b/awx/lib/site-packages/pip/_vendor/html5lib/treebuilders/_base.py @@ -1,5 +1,5 @@ from __future__ import absolute_import, division, unicode_literals -from pip.vendor.six import text_type +from pip._vendor.six import text_type from ..constants import scopingElements, tableInsertModeElements, namespaces diff --git a/awx/lib/site-packages/pip/vendor/html5lib/treebuilders/dom.py b/awx/lib/site-packages/pip/_vendor/html5lib/treebuilders/dom.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/treebuilders/dom.py rename to awx/lib/site-packages/pip/_vendor/html5lib/treebuilders/dom.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/treebuilders/etree.py b/awx/lib/site-packages/pip/_vendor/html5lib/treebuilders/etree.py similarity index 99% rename from awx/lib/site-packages/pip/vendor/html5lib/treebuilders/etree.py rename to awx/lib/site-packages/pip/_vendor/html5lib/treebuilders/etree.py index 7b0cdd8e6d..48fead7e2b 100644 --- a/awx/lib/site-packages/pip/vendor/html5lib/treebuilders/etree.py +++ b/awx/lib/site-packages/pip/_vendor/html5lib/treebuilders/etree.py @@ -1,5 +1,5 @@ from __future__ import absolute_import, division, unicode_literals -from pip.vendor.six import text_type +from pip._vendor.six import text_type import re diff --git a/awx/lib/site-packages/pip/vendor/html5lib/treebuilders/etree_lxml.py b/awx/lib/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/treebuilders/etree_lxml.py rename to awx/lib/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/treewalkers/__init__.py b/awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/treewalkers/__init__.py rename to awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/treewalkers/_base.py b/awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/_base.py similarity index 99% rename from awx/lib/site-packages/pip/vendor/html5lib/treewalkers/_base.py rename to awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/_base.py index 223ef21c87..a202359614 100644 --- a/awx/lib/site-packages/pip/vendor/html5lib/treewalkers/_base.py +++ b/awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/_base.py @@ -1,5 +1,5 @@ from __future__ import absolute_import, division, unicode_literals -from pip.vendor.six import text_type +from pip._vendor.six import text_type import gettext _ = gettext.gettext diff --git a/awx/lib/site-packages/pip/vendor/html5lib/treewalkers/dom.py b/awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/dom.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/treewalkers/dom.py rename to awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/dom.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/treewalkers/etree.py b/awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/etree.py similarity index 99% rename from awx/lib/site-packages/pip/vendor/html5lib/treewalkers/etree.py rename to awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/etree.py index 8d19f7db55..88fb9811a3 100644 --- a/awx/lib/site-packages/pip/vendor/html5lib/treewalkers/etree.py +++ b/awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/etree.py @@ -5,7 +5,7 @@ _ = gettext.gettext import re -from pip.vendor.six import text_type +from pip._vendor.six import text_type from . import _base from ..utils import moduleFactoryFactory diff --git a/awx/lib/site-packages/pip/vendor/html5lib/treewalkers/genshistream.py b/awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/genshistream.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/treewalkers/genshistream.py rename to awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/genshistream.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/treewalkers/lxmletree.py b/awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/lxmletree.py similarity index 99% rename from awx/lib/site-packages/pip/vendor/html5lib/treewalkers/lxmletree.py rename to awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/lxmletree.py index 66969ee352..4373383c57 100644 --- a/awx/lib/site-packages/pip/vendor/html5lib/treewalkers/lxmletree.py +++ b/awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/lxmletree.py @@ -1,5 +1,5 @@ from __future__ import absolute_import, division, unicode_literals -from pip.vendor.six import text_type +from pip._vendor.six import text_type from lxml import etree from ..treebuilders.etree import tag_regexp diff --git a/awx/lib/site-packages/pip/vendor/html5lib/treewalkers/pulldom.py b/awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/pulldom.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/treewalkers/pulldom.py rename to awx/lib/site-packages/pip/_vendor/html5lib/treewalkers/pulldom.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/trie/__init__.py b/awx/lib/site-packages/pip/_vendor/html5lib/trie/__init__.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/trie/__init__.py rename to awx/lib/site-packages/pip/_vendor/html5lib/trie/__init__.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/trie/_base.py b/awx/lib/site-packages/pip/_vendor/html5lib/trie/_base.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/trie/_base.py rename to awx/lib/site-packages/pip/_vendor/html5lib/trie/_base.py diff --git a/awx/lib/site-packages/pip/vendor/html5lib/trie/datrie.py b/awx/lib/site-packages/pip/_vendor/html5lib/trie/datrie.py similarity index 96% rename from awx/lib/site-packages/pip/vendor/html5lib/trie/datrie.py rename to awx/lib/site-packages/pip/_vendor/html5lib/trie/datrie.py index 1c3b43202c..e2e5f86621 100644 --- a/awx/lib/site-packages/pip/vendor/html5lib/trie/datrie.py +++ b/awx/lib/site-packages/pip/_vendor/html5lib/trie/datrie.py @@ -1,7 +1,7 @@ from __future__ import absolute_import, division, unicode_literals from datrie import Trie as DATrie -from pip.vendor.six import text_type +from pip._vendor.six import text_type from ._base import Trie as ABCTrie diff --git a/awx/lib/site-packages/pip/vendor/html5lib/trie/py.py b/awx/lib/site-packages/pip/_vendor/html5lib/trie/py.py similarity index 97% rename from awx/lib/site-packages/pip/vendor/html5lib/trie/py.py rename to awx/lib/site-packages/pip/_vendor/html5lib/trie/py.py index f2d3641134..c178b219de 100644 --- a/awx/lib/site-packages/pip/vendor/html5lib/trie/py.py +++ b/awx/lib/site-packages/pip/_vendor/html5lib/trie/py.py @@ -1,5 +1,5 @@ from __future__ import absolute_import, division, unicode_literals -from pip.vendor.six import text_type +from pip._vendor.six import text_type from bisect import bisect_left diff --git a/awx/lib/site-packages/pip/vendor/html5lib/utils.py b/awx/lib/site-packages/pip/_vendor/html5lib/utils.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/html5lib/utils.py rename to awx/lib/site-packages/pip/_vendor/html5lib/utils.py diff --git a/awx/lib/site-packages/pip/_vendor/re-vendor.py b/awx/lib/site-packages/pip/_vendor/re-vendor.py new file mode 100644 index 0000000000..0a52123e4f --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/re-vendor.py @@ -0,0 +1,34 @@ +import os +import sys +import pip +import glob +import shutil + +here = os.path.abspath(os.path.dirname(__file__)) + +def usage(): + print("Usage: re-vendor.py [clean|vendor]") + sys.exit(1) + +def clean(): + for fn in os.listdir(here): + dirname = os.path.join(here, fn) + if os.path.isdir(dirname): + shutil.rmtree(dirname) + # six is a single file, not a package + os.unlink(os.path.join(here, 'six.py')) + +def vendor(): + pip.main(['install', '-t', here, '-r', 'vendor.txt']) + for dirname in glob.glob('*.egg-info'): + shutil.rmtree(dirname) + +if __name__ == '__main__': + if len(sys.argv) != 2: + usage() + if sys.argv[1] == 'clean': + clean() + elif sys.argv[1] == 'vendor': + vendor() + else: + usage() diff --git a/awx/lib/site-packages/pip/_vendor/requests/__init__.py b/awx/lib/site-packages/pip/_vendor/requests/__init__.py new file mode 100644 index 0000000000..d5d258e84c --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/__init__.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- + +# __ +# /__) _ _ _ _ _/ _ +# / ( (- (/ (/ (- _) / _) +# / + +""" +requests HTTP library +~~~~~~~~~~~~~~~~~~~~~ + +Requests is an HTTP library, written in Python, for human beings. Basic GET +usage: + + >>> import requests + >>> r = requests.get('http://python.org') + >>> r.status_code + 200 + >>> 'Python is a programming language' in r.content + True + +... or POST: + + >>> payload = dict(key1='value1', key2='value2') + >>> r = requests.post("http://httpbin.org/post", data=payload) + >>> print(r.text) + { + ... + "form": { + "key2": "value2", + "key1": "value1" + }, + ... + } + +The other HTTP methods are supported - see `requests.api`. Full documentation +is at . + +:copyright: (c) 2013 by Kenneth Reitz. +:license: Apache 2.0, see LICENSE for more details. + +""" + +__title__ = 'requests' +__version__ = '2.1.0' +__build__ = 0x020100 +__author__ = 'Kenneth Reitz' +__license__ = 'Apache 2.0' +__copyright__ = 'Copyright 2013 Kenneth Reitz' + +# Attempt to enable urllib3's SNI support, if possible +try: + from .packages.urllib3.contrib import pyopenssl + pyopenssl.inject_into_urllib3() +except ImportError: + pass + +from . import utils +from .models import Request, Response, PreparedRequest +from .api import request, get, head, post, patch, put, delete, options +from .sessions import session, Session +from .status_codes import codes +from .exceptions import ( + RequestException, Timeout, URLRequired, + TooManyRedirects, HTTPError, ConnectionError +) + +# Set default logging handler to avoid "No handler found" warnings. +import logging +try: # Python 2.7+ + from logging import NullHandler +except ImportError: + class NullHandler(logging.Handler): + def emit(self, record): + pass + +logging.getLogger(__name__).addHandler(NullHandler()) diff --git a/awx/lib/site-packages/pip/_vendor/requests/adapters.py b/awx/lib/site-packages/pip/_vendor/requests/adapters.py new file mode 100644 index 0000000000..b62f64c85a --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/adapters.py @@ -0,0 +1,390 @@ +# -*- coding: utf-8 -*- + +""" +requests.adapters +~~~~~~~~~~~~~~~~~ + +This module contains the transport adapters that Requests uses to define +and maintain connections. +""" + +import socket + +from .models import Response +from .packages.urllib3.poolmanager import PoolManager, proxy_from_url +from .packages.urllib3.response import HTTPResponse +from .packages.urllib3.util import Timeout as TimeoutSauce +from .compat import urlparse, basestring, urldefrag, unquote +from .utils import (DEFAULT_CA_BUNDLE_PATH, get_encoding_from_headers, + except_on_missing_scheme, get_auth_from_url) +from .structures import CaseInsensitiveDict +from .packages.urllib3.exceptions import MaxRetryError +from .packages.urllib3.exceptions import TimeoutError +from .packages.urllib3.exceptions import SSLError as _SSLError +from .packages.urllib3.exceptions import HTTPError as _HTTPError +from .packages.urllib3.exceptions import ProxyError as _ProxyError +from .cookies import extract_cookies_to_jar +from .exceptions import ConnectionError, Timeout, SSLError, ProxyError +from .auth import _basic_auth_str + +DEFAULT_POOLBLOCK = False +DEFAULT_POOLSIZE = 10 +DEFAULT_RETRIES = 0 + + +class BaseAdapter(object): + """The Base Transport Adapter""" + + def __init__(self): + super(BaseAdapter, self).__init__() + + def send(self): + raise NotImplementedError + + def close(self): + raise NotImplementedError + + +class HTTPAdapter(BaseAdapter): + """The built-in HTTP Adapter for urllib3. + + Provides a general-case interface for Requests sessions to contact HTTP and + HTTPS urls by implementing the Transport Adapter interface. This class will + usually be created by the :class:`Session ` class under the + covers. + + :param pool_connections: The number of urllib3 connection pools to cache. + :param pool_maxsize: The maximum number of connections to save in the pool. + :param max_retries: The maximum number of retries each connection should attempt. + :param pool_block: Whether the connection pool should block for connections. + + Usage:: + + >>> import requests + >>> s = requests.Session() + >>> a = requests.adapters.HTTPAdapter() + >>> s.mount('http://', a) + """ + __attrs__ = ['max_retries', 'config', '_pool_connections', '_pool_maxsize', + '_pool_block'] + + def __init__(self, pool_connections=DEFAULT_POOLSIZE, + pool_maxsize=DEFAULT_POOLSIZE, max_retries=DEFAULT_RETRIES, + pool_block=DEFAULT_POOLBLOCK): + self.max_retries = max_retries + self.config = {} + self.proxy_manager = {} + + super(HTTPAdapter, self).__init__() + + self._pool_connections = pool_connections + self._pool_maxsize = pool_maxsize + self._pool_block = pool_block + + self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block) + + def __getstate__(self): + return dict((attr, getattr(self, attr, None)) for attr in + self.__attrs__) + + def __setstate__(self, state): + for attr, value in state.items(): + setattr(self, attr, value) + + self.init_poolmanager(self._pool_connections, self._pool_maxsize, + block=self._pool_block) + + def init_poolmanager(self, connections, maxsize, block=DEFAULT_POOLBLOCK): + """Initializes a urllib3 PoolManager. This method should not be called + from user code, and is only exposed for use when subclassing the + :class:`HTTPAdapter `. + + :param connections: The number of urllib3 connection pools to cache. + :param maxsize: The maximum number of connections to save in the pool. + :param block: Block when no free connections are available. + """ + # save these values for pickling + self._pool_connections = connections + self._pool_maxsize = maxsize + self._pool_block = block + + self.poolmanager = PoolManager(num_pools=connections, maxsize=maxsize, + block=block) + + def cert_verify(self, conn, url, verify, cert): + """Verify a SSL certificate. This method should not be called from user + code, and is only exposed for use when subclassing the + :class:`HTTPAdapter `. + + :param conn: The urllib3 connection object associated with the cert. + :param url: The requested URL. + :param verify: Whether we should actually verify the certificate. + :param cert: The SSL certificate to verify. + """ + if url.lower().startswith('https') and verify: + + cert_loc = None + + # Allow self-specified cert location. + if verify is not True: + cert_loc = verify + + if not cert_loc: + cert_loc = DEFAULT_CA_BUNDLE_PATH + + if not cert_loc: + raise Exception("Could not find a suitable SSL CA certificate bundle.") + + conn.cert_reqs = 'CERT_REQUIRED' + conn.ca_certs = cert_loc + else: + conn.cert_reqs = 'CERT_NONE' + conn.ca_certs = None + + if cert: + if not isinstance(cert, basestring): + conn.cert_file = cert[0] + conn.key_file = cert[1] + else: + conn.cert_file = cert + + def build_response(self, req, resp): + """Builds a :class:`Response ` object from a urllib3 + response. This should not be called from user code, and is only exposed + for use when subclassing the + :class:`HTTPAdapter ` + + :param req: The :class:`PreparedRequest ` used to generate the response. + :param resp: The urllib3 response object. + """ + response = Response() + + # Fallback to None if there's no status_code, for whatever reason. + response.status_code = getattr(resp, 'status', None) + + # Make headers case-insensitive. + response.headers = CaseInsensitiveDict(getattr(resp, 'headers', {})) + + # Set encoding. + response.encoding = get_encoding_from_headers(response.headers) + response.raw = resp + response.reason = response.raw.reason + + if isinstance(req.url, bytes): + response.url = req.url.decode('utf-8') + else: + response.url = req.url + + # Add new cookies from the server. + extract_cookies_to_jar(response.cookies, req, resp) + + # Give the Response some context. + response.request = req + response.connection = self + + return response + + def get_connection(self, url, proxies=None): + """Returns a urllib3 connection for the given URL. This should not be + called from user code, and is only exposed for use when subclassing the + :class:`HTTPAdapter `. + + :param url: The URL to connect to. + :param proxies: (optional) A Requests-style dictionary of proxies used on this request. + """ + proxies = proxies or {} + proxy = proxies.get(urlparse(url.lower()).scheme) + + if proxy: + except_on_missing_scheme(proxy) + proxy_headers = self.proxy_headers(proxy) + + if not proxy in self.proxy_manager: + self.proxy_manager[proxy] = proxy_from_url( + proxy, + proxy_headers=proxy_headers) + + conn = self.proxy_manager[proxy].connection_from_url(url) + else: + # Only scheme should be lower case + parsed = urlparse(url) + url = parsed.geturl() + conn = self.poolmanager.connection_from_url(url) + + return conn + + def close(self): + """Disposes of any internal state. + + Currently, this just closes the PoolManager, which closes pooled + connections. + """ + self.poolmanager.clear() + + def request_url(self, request, proxies): + """Obtain the url to use when making the final request. + + If the message is being sent through a HTTP proxy, the full URL has to + be used. Otherwise, we should only use the path portion of the URL. + + This should not be called from user code, and is only exposed for use + when subclassing the + :class:`HTTPAdapter `. + + :param request: The :class:`PreparedRequest ` being sent. + :param proxies: A dictionary of schemes to proxy URLs. + """ + proxies = proxies or {} + scheme = urlparse(request.url).scheme + proxy = proxies.get(scheme) + + if proxy and scheme != 'https': + url, _ = urldefrag(request.url) + else: + url = request.path_url + + return url + + def add_headers(self, request, **kwargs): + """Add any headers needed by the connection. As of v2.0 this does + nothing by default, but is left for overriding by users that subclass + the :class:`HTTPAdapter `. + + This should not be called from user code, and is only exposed for use + when subclassing the + :class:`HTTPAdapter `. + + :param request: The :class:`PreparedRequest ` to add headers to. + :param kwargs: The keyword arguments from the call to send(). + """ + pass + + def proxy_headers(self, proxy): + """Returns a dictionary of the headers to add to any request sent + through a proxy. This works with urllib3 magic to ensure that they are + correctly sent to the proxy, rather than in a tunnelled request if + CONNECT is being used. + + This should not be called from user code, and is only exposed for use + when subclassing the + :class:`HTTPAdapter `. + + :param proxies: The url of the proxy being used for this request. + :param kwargs: Optional additional keyword arguments. + """ + headers = {} + username, password = get_auth_from_url(proxy) + + if username and password: + # Proxy auth usernames and passwords will be urlencoded, we need + # to decode them. + username = unquote(username) + password = unquote(password) + headers['Proxy-Authorization'] = _basic_auth_str(username, + password) + + return headers + + def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None): + """Sends PreparedRequest object. Returns Response object. + + :param request: The :class:`PreparedRequest ` being sent. + :param stream: (optional) Whether to stream the request content. + :param timeout: (optional) The timeout on the request. + :param verify: (optional) Whether to verify SSL certificates. + :param cert: (optional) Any user-provided SSL certificate to be trusted. + :param proxies: (optional) The proxies dictionary to apply to the request. + """ + + conn = self.get_connection(request.url, proxies) + + self.cert_verify(conn, request.url, verify, cert) + url = self.request_url(request, proxies) + self.add_headers(request) + + chunked = not (request.body is None or 'Content-Length' in request.headers) + + if stream: + timeout = TimeoutSauce(connect=timeout) + else: + timeout = TimeoutSauce(connect=timeout, read=timeout) + + try: + if not chunked: + resp = conn.urlopen( + method=request.method, + url=url, + body=request.body, + headers=request.headers, + redirect=False, + assert_same_host=False, + preload_content=False, + decode_content=False, + retries=self.max_retries, + timeout=timeout + ) + + # Send the request. + else: + if hasattr(conn, 'proxy_pool'): + conn = conn.proxy_pool + + low_conn = conn._get_conn(timeout=timeout) + + try: + low_conn.putrequest(request.method, + url, + skip_accept_encoding=True) + + for header, value in request.headers.items(): + low_conn.putheader(header, value) + + low_conn.endheaders() + + for i in request.body: + low_conn.send(hex(len(i))[2:].encode('utf-8')) + low_conn.send(b'\r\n') + low_conn.send(i) + low_conn.send(b'\r\n') + low_conn.send(b'0\r\n\r\n') + + r = low_conn.getresponse() + resp = HTTPResponse.from_httplib( + r, + pool=conn, + connection=low_conn, + preload_content=False, + decode_content=False + ) + except: + # If we hit any problems here, clean up the connection. + # Then, reraise so that we can handle the actual exception. + low_conn.close() + raise + else: + # All is well, return the connection to the pool. + conn._put_conn(low_conn) + + except socket.error as sockerr: + raise ConnectionError(sockerr) + + except MaxRetryError as e: + raise ConnectionError(e) + + except _ProxyError as e: + raise ProxyError(e) + + except (_SSLError, _HTTPError) as e: + if isinstance(e, _SSLError): + raise SSLError(e) + elif isinstance(e, TimeoutError): + raise Timeout(e) + else: + raise + + r = self.build_response(request, resp) + + if not stream: + r.content + + return r diff --git a/awx/lib/site-packages/pip/_vendor/requests/api.py b/awx/lib/site-packages/pip/_vendor/requests/api.py new file mode 100644 index 0000000000..baf43dd613 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/api.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- + +""" +requests.api +~~~~~~~~~~~~ + +This module implements the Requests API. + +:copyright: (c) 2012 by Kenneth Reitz. +:license: Apache2, see LICENSE for more details. + +""" + +from . import sessions + + +def request(method, url, **kwargs): + """Constructs and sends a :class:`Request `. + Returns :class:`Response ` object. + + :param method: method for the new :class:`Request` object. + :param url: URL for the new :class:`Request` object. + :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`. + :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. + :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`. + :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`. + :param files: (optional) Dictionary of 'name': file-like-objects (or {'name': ('filename', fileobj)}) for multipart encoding upload. + :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth. + :param timeout: (optional) Float describing the timeout of the request. + :param allow_redirects: (optional) Boolean. Set to True if POST/PUT/DELETE redirect following is allowed. + :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy. + :param verify: (optional) if ``True``, the SSL cert will be verified. A CA_BUNDLE path can also be provided. + :param stream: (optional) if ``False``, the response content will be immediately downloaded. + :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. + + Usage:: + + >>> import requests + >>> req = requests.request('GET', 'http://httpbin.org/get') + + """ + + session = sessions.Session() + return session.request(method=method, url=url, **kwargs) + + +def get(url, **kwargs): + """Sends a GET request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + """ + + kwargs.setdefault('allow_redirects', True) + return request('get', url, **kwargs) + + +def options(url, **kwargs): + """Sends a OPTIONS request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + """ + + kwargs.setdefault('allow_redirects', True) + return request('options', url, **kwargs) + + +def head(url, **kwargs): + """Sends a HEAD request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + """ + + kwargs.setdefault('allow_redirects', False) + return request('head', url, **kwargs) + + +def post(url, data=None, **kwargs): + """Sends a POST request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + """ + + return request('post', url, data=data, **kwargs) + + +def put(url, data=None, **kwargs): + """Sends a PUT request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + """ + + return request('put', url, data=data, **kwargs) + + +def patch(url, data=None, **kwargs): + """Sends a PATCH request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + """ + + return request('patch', url, data=data, **kwargs) + + +def delete(url, **kwargs): + """Sends a DELETE request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + """ + + return request('delete', url, **kwargs) diff --git a/awx/lib/site-packages/pip/_vendor/requests/auth.py b/awx/lib/site-packages/pip/_vendor/requests/auth.py new file mode 100644 index 0000000000..6664cd80db --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/auth.py @@ -0,0 +1,196 @@ +# -*- coding: utf-8 -*- + +""" +requests.auth +~~~~~~~~~~~~~ + +This module contains the authentication handlers for Requests. +""" + +import os +import re +import time +import hashlib +import logging + +from base64 import b64encode + +from .compat import urlparse, str +from .cookies import extract_cookies_to_jar +from .utils import parse_dict_header + +log = logging.getLogger(__name__) + +CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded' +CONTENT_TYPE_MULTI_PART = 'multipart/form-data' + + +def _basic_auth_str(username, password): + """Returns a Basic Auth string.""" + + return 'Basic ' + b64encode(('%s:%s' % (username, password)).encode('latin1')).strip().decode('latin1') + + +class AuthBase(object): + """Base class that all auth implementations derive from""" + + def __call__(self, r): + raise NotImplementedError('Auth hooks must be callable.') + + +class HTTPBasicAuth(AuthBase): + """Attaches HTTP Basic Authentication to the given Request object.""" + def __init__(self, username, password): + self.username = username + self.password = password + + def __call__(self, r): + r.headers['Authorization'] = _basic_auth_str(self.username, self.password) + return r + + +class HTTPProxyAuth(HTTPBasicAuth): + """Attaches HTTP Proxy Authentication to a given Request object.""" + def __call__(self, r): + r.headers['Proxy-Authorization'] = _basic_auth_str(self.username, self.password) + return r + + +class HTTPDigestAuth(AuthBase): + """Attaches HTTP Digest Authentication to the given Request object.""" + def __init__(self, username, password): + self.username = username + self.password = password + self.last_nonce = '' + self.nonce_count = 0 + self.chal = {} + self.pos = None + + def build_digest_header(self, method, url): + + realm = self.chal['realm'] + nonce = self.chal['nonce'] + qop = self.chal.get('qop') + algorithm = self.chal.get('algorithm') + opaque = self.chal.get('opaque') + + if algorithm is None: + _algorithm = 'MD5' + else: + _algorithm = algorithm.upper() + # lambdas assume digest modules are imported at the top level + if _algorithm == 'MD5' or _algorithm == 'MD5-SESS': + def md5_utf8(x): + if isinstance(x, str): + x = x.encode('utf-8') + return hashlib.md5(x).hexdigest() + hash_utf8 = md5_utf8 + elif _algorithm == 'SHA': + def sha_utf8(x): + if isinstance(x, str): + x = x.encode('utf-8') + return hashlib.sha1(x).hexdigest() + hash_utf8 = sha_utf8 + + KD = lambda s, d: hash_utf8("%s:%s" % (s, d)) + + if hash_utf8 is None: + return None + + # XXX not implemented yet + entdig = None + p_parsed = urlparse(url) + path = p_parsed.path + if p_parsed.query: + path += '?' + p_parsed.query + + A1 = '%s:%s:%s' % (self.username, realm, self.password) + A2 = '%s:%s' % (method, path) + + HA1 = hash_utf8(A1) + HA2 = hash_utf8(A2) + + if nonce == self.last_nonce: + self.nonce_count += 1 + else: + self.nonce_count = 1 + ncvalue = '%08x' % self.nonce_count + s = str(self.nonce_count).encode('utf-8') + s += nonce.encode('utf-8') + s += time.ctime().encode('utf-8') + s += os.urandom(8) + + cnonce = (hashlib.sha1(s).hexdigest()[:16]) + noncebit = "%s:%s:%s:%s:%s" % (nonce, ncvalue, cnonce, qop, HA2) + if _algorithm == 'MD5-SESS': + HA1 = hash_utf8('%s:%s:%s' % (HA1, nonce, cnonce)) + + if qop is None: + respdig = KD(HA1, "%s:%s" % (nonce, HA2)) + elif qop == 'auth' or 'auth' in qop.split(','): + respdig = KD(HA1, noncebit) + else: + # XXX handle auth-int. + return None + + self.last_nonce = nonce + + # XXX should the partial digests be encoded too? + base = 'username="%s", realm="%s", nonce="%s", uri="%s", ' \ + 'response="%s"' % (self.username, realm, nonce, path, respdig) + if opaque: + base += ', opaque="%s"' % opaque + if algorithm: + base += ', algorithm="%s"' % algorithm + if entdig: + base += ', digest="%s"' % entdig + if qop: + base += ', qop="auth", nc=%s, cnonce="%s"' % (ncvalue, cnonce) + + return 'Digest %s' % (base) + + def handle_401(self, r, **kwargs): + """Takes the given response and tries digest-auth, if needed.""" + + if self.pos is not None: + # Rewind the file position indicator of the body to where + # it was to resend the request. + r.request.body.seek(self.pos) + num_401_calls = getattr(self, 'num_401_calls', 1) + s_auth = r.headers.get('www-authenticate', '') + + if 'digest' in s_auth.lower() and num_401_calls < 2: + + setattr(self, 'num_401_calls', num_401_calls + 1) + pat = re.compile(r'digest ', flags=re.IGNORECASE) + self.chal = parse_dict_header(pat.sub('', s_auth, count=1)) + + # Consume content and release the original connection + # to allow our new request to reuse the same one. + r.content + r.raw.release_conn() + prep = r.request.copy() + extract_cookies_to_jar(prep._cookies, r.request, r.raw) + prep.prepare_cookies(prep._cookies) + + prep.headers['Authorization'] = self.build_digest_header( + prep.method, prep.url) + _r = r.connection.send(prep, **kwargs) + _r.history.append(r) + _r.request = prep + + return _r + + setattr(self, 'num_401_calls', 1) + return r + + def __call__(self, r): + # If we have a saved nonce, skip the 401 + if self.last_nonce: + r.headers['Authorization'] = self.build_digest_header(r.method, r.url) + try: + self.pos = r.body.tell() + except AttributeError: + pass + r.register_hook('response', self.handle_401) + return r diff --git a/awx/lib/site-packages/pip/_vendor/requests/cacert.pem b/awx/lib/site-packages/pip/_vendor/requests/cacert.pem new file mode 100644 index 0000000000..729fe15d40 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/cacert.pem @@ -0,0 +1,5026 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Issuer: CN=GTE CyberTrust Global Root O=GTE Corporation OU=GTE CyberTrust Solutions, Inc. +# Subject: CN=GTE CyberTrust Global Root O=GTE Corporation OU=GTE CyberTrust Solutions, Inc. +# Label: "GTE CyberTrust Global Root" +# Serial: 421 +# MD5 Fingerprint: ca:3d:d3:68:f1:03:5c:d0:32:fa:b8:2b:59:e8:5a:db +# SHA1 Fingerprint: 97:81:79:50:d8:1c:96:70:cc:34:d8:09:cf:79:44:31:36:7e:f4:74 +# SHA256 Fingerprint: a5:31:25:18:8d:21:10:aa:96:4b:02:c7:b7:c6:da:32:03:17:08:94:e5:fb:71:ff:fb:66:67:d5:e6:81:0a:36 +-----BEGIN CERTIFICATE----- +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv +b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds +b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH +iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS +r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 +04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r +GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 +3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P +lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +-----END CERTIFICATE----- + +# Issuer: CN=Thawte Server CA O=Thawte Consulting cc OU=Certification Services Division +# Subject: CN=Thawte Server CA O=Thawte Consulting cc OU=Certification Services Division +# Label: "Thawte Server CA" +# Serial: 1 +# MD5 Fingerprint: c5:70:c4:a2:ed:53:78:0c:c8:10:53:81:64:cb:d0:1d +# SHA1 Fingerprint: 23:e5:94:94:51:95:f2:41:48:03:b4:d5:64:d2:a3:a3:f5:d8:8b:8c +# SHA256 Fingerprint: b4:41:0b:73:e2:e6:ea:ca:47:fb:c4:2f:8f:a4:01:8a:f4:38:1d:c5:4c:fa:a8:44:50:46:1e:ed:09:45:4d:e9 +-----BEGIN CERTIFICATE----- +MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD +VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm +MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx +MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 +dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl +cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 +DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 +yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX +L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj +EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG +7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e +QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ +qdq5snUb9kLy78fyGPmJvKP/iiMucEc= +-----END CERTIFICATE----- + +# Issuer: CN=Thawte Premium Server CA O=Thawte Consulting cc OU=Certification Services Division +# Subject: CN=Thawte Premium Server CA O=Thawte Consulting cc OU=Certification Services Division +# Label: "Thawte Premium Server CA" +# Serial: 1 +# MD5 Fingerprint: 06:9f:69:79:16:66:90:02:1b:8c:8c:a2:c3:07:6f:3a +# SHA1 Fingerprint: 62:7f:8d:78:27:65:63:99:d2:7d:7f:90:44:c9:fe:b3:f3:3e:fa:9a +# SHA256 Fingerprint: ab:70:36:36:5c:71:54:aa:29:c2:c2:9f:5d:41:91:16:3b:16:2a:22:25:01:13:57:d5:6d:07:ff:a7:bc:1f:72 +-----BEGIN CERTIFICATE----- +MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD +VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy +dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t +MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB +MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG +A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp +b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl +cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv +bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE +VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ +ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR +uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG +9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI +hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM +pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== +-----END CERTIFICATE----- + +# Issuer: O=Equifax OU=Equifax Secure Certificate Authority +# Subject: O=Equifax OU=Equifax Secure Certificate Authority +# Label: "Equifax Secure CA" +# Serial: 903804111 +# MD5 Fingerprint: 67:cb:9d:c0:13:24:8a:82:9b:b2:17:1e:d1:1b:ec:d4 +# SHA1 Fingerprint: d2:32:09:ad:23:d3:14:23:21:74:e4:0d:7f:9d:62:13:97:86:63:3a +# SHA256 Fingerprint: 08:29:7a:40:47:db:a2:36:80:c7:31:db:6e:31:76:53:ca:78:48:e1:be:bd:3a:0b:01:79:a7:07:f9:2c:f1:78 +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV +UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy +dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 +MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx +dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f +BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A +cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC +AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm +aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw +ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj +IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF +MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA +A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y +7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh +1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 +-----END CERTIFICATE----- + +# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority +# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority +# Label: "Verisign Class 3 Public Primary Certification Authority" +# Serial: 149843929435818692848040365716851702463 +# MD5 Fingerprint: 10:fc:63:5d:f6:26:3e:0d:f3:25:be:5f:79:cd:67:67 +# SHA1 Fingerprint: 74:2c:31:92:e6:07:e4:24:eb:45:49:54:2b:e1:bb:c5:3e:61:74:e2 +# SHA256 Fingerprint: e7:68:56:34:ef:ac:f6:9a:ce:93:9a:6b:25:5b:7b:4f:ab:ef:42:93:5b:50:a2:65:ac:b5:cb:60:27:e4:4e:70 +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE +BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is +I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G +CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do +lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc +AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k +-----END CERTIFICATE----- + +# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority - G2/(c) 1998 VeriSign, Inc. - For authorized use only/VeriSign Trust Network +# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority - G2/(c) 1998 VeriSign, Inc. - For authorized use only/VeriSign Trust Network +# Label: "Verisign Class 3 Public Primary Certification Authority - G2" +# Serial: 167285380242319648451154478808036881606 +# MD5 Fingerprint: a2:33:9b:4c:74:78:73:d4:6c:e7:c1:f3:8d:cb:5c:e9 +# SHA1 Fingerprint: 85:37:1c:a6:e5:50:14:3d:ce:28:03:47:1b:de:3a:09:e8:f8:77:0f +# SHA256 Fingerprint: 83:ce:3c:12:29:68:8a:59:3d:48:5f:81:97:3c:0f:91:95:43:1e:da:37:cc:5e:36:43:0e:79:c7:a8:88:63:8b +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 +pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 +13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk +U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i +F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY +oJ2daZH9 +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA +# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA +# Label: "GlobalSign Root CA" +# Serial: 4835703278459707669005204 +# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a +# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c +# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99 +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 +# Label: "GlobalSign Root CA - R2" +# Serial: 4835703278459682885658125 +# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30 +# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe +# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 1 Policy Validation Authority +# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 1 Policy Validation Authority +# Label: "ValiCert Class 1 VA" +# Serial: 1 +# MD5 Fingerprint: 65:58:ab:15:ad:57:6c:1e:a8:a7:b5:69:ac:bf:ff:eb +# SHA1 Fingerprint: e5:df:74:3c:b6:01:c4:9b:98:43:dc:ab:8c:e8:6a:81:10:9f:e4:8e +# SHA256 Fingerprint: f4:c1:49:55:1a:30:13:a3:5b:c7:bf:fe:17:a7:f3:44:9b:c1:ab:5b:5a:0a:e7:4b:06:c2:3b:90:00:4c:01:04 +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy +NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y +LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+ +TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y +TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0 +LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW +I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw +nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI +-----END CERTIFICATE----- + +# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 2 Policy Validation Authority +# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 2 Policy Validation Authority +# Label: "ValiCert Class 2 VA" +# Serial: 1 +# MD5 Fingerprint: a9:23:75:9b:ba:49:36:6e:31:c2:db:f2:e7:66:ba:87 +# SHA1 Fingerprint: 31:7a:2a:d0:7f:2b:33:5e:f5:a1:c3:4e:4b:57:e8:b7:d8:f1:fc:a6 +# SHA256 Fingerprint: 58:d0:17:27:9c:d4:dc:63:ab:dd:b1:96:a6:c9:90:6c:30:c4:e0:87:83:ea:e8:c1:60:99:54:d6:93:55:59:6b +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy +NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY +dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 +WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS +v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v +UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu +IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC +W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd +-----END CERTIFICATE----- + +# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 3 Policy Validation Authority +# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 3 Policy Validation Authority +# Label: "RSA Root Certificate 1" +# Serial: 1 +# MD5 Fingerprint: a2:6f:53:b7:ee:40:db:4a:68:e7:fa:18:d9:10:4b:72 +# SHA1 Fingerprint: 69:bd:8c:f4:9c:d3:00:fb:59:2e:17:93:ca:55:6a:f3:ec:aa:35:fb +# SHA256 Fingerprint: bc:23:f9:8a:31:3c:b9:2d:e3:bb:fc:3a:5a:9f:44:61:ac:39:49:4c:4a:e1:5a:9e:9d:f1:31:e9:9b:73:01:9a +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy +NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD +cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs +2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY +JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE +Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ +n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A +PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only +# Label: "Verisign Class 3 Public Primary Certification Authority - G3" +# Serial: 206684696279472310254277870180966723415 +# MD5 Fingerprint: cd:68:b6:a7:c7:c4:ce:75:e0:1d:4f:57:44:61:92:09 +# SHA1 Fingerprint: 13:2d:0d:45:53:4b:69:97:cd:b2:d5:c3:39:e2:55:76:60:9b:5c:c6 +# SHA256 Fingerprint: eb:04:cf:5e:b1:f3:9a:fa:76:2f:2b:b1:20:f2:96:cb:a5:20:c1:b9:7d:b1:58:95:65:b8:1c:b9:a1:7b:72:44 +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b +N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t +KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu +kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm +CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ +Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu +imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te +2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe +DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p +F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt +TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 4 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 4 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only +# Label: "Verisign Class 4 Public Primary Certification Authority - G3" +# Serial: 314531972711909413743075096039378935511 +# MD5 Fingerprint: db:c8:f2:27:2e:b1:ea:6a:29:23:5d:fe:56:3e:33:df +# SHA1 Fingerprint: c8:ec:8c:87:92:69:cb:4b:ab:39:e9:8d:7e:57:67:f3:14:95:73:9d +# SHA256 Fingerprint: e3:89:36:0d:0f:db:ae:b3:d2:50:58:4b:47:30:31:4e:22:2f:39:c1:56:a0:20:14:4e:8d:96:05:61:79:15:06 +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 +GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ ++mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd +U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm +NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY +ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ +ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 +CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq +g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm +fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c +2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ +bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== +-----END CERTIFICATE----- + +# Issuer: CN=Entrust.net Secure Server Certification Authority O=Entrust.net OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Subject: CN=Entrust.net Secure Server Certification Authority O=Entrust.net OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Label: "Entrust.net Secure Server CA" +# Serial: 927650371 +# MD5 Fingerprint: df:f2:80:73:cc:f1:e6:61:73:fc:f5:42:e9:c5:7c:ee +# SHA1 Fingerprint: 99:a6:9b:e6:1a:fe:88:6b:4d:2b:82:00:7c:b8:54:fc:31:7e:15:39 +# SHA256 Fingerprint: 62:f2:40:27:8c:56:4c:4d:d8:bf:7d:9d:4f:6f:36:6e:a8:94:d2:2f:5f:34:d9:89:a9:83:ac:ec:2f:ff:ed:50 +-----BEGIN CERTIFICATE----- +MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u +ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc +KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u +ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 +MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE +ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j +b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF +bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg +U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ +I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 +wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC +AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb +oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 +BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p +dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk +MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp +b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu +dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 +MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi +E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa +MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI +hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN +95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd +2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= +-----END CERTIFICATE----- + +# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Label: "Entrust.net Premium 2048 Secure Server CA" +# Serial: 946069240 +# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90 +# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31 +# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77 +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 +MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub +j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo +U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b +u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ +bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er +fF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- + +# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust +# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust +# Label: "Baltimore CyberTrust Root" +# Serial: 33554617 +# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4 +# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74 +# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +# Issuer: CN=Equifax Secure Global eBusiness CA-1 O=Equifax Secure Inc. +# Subject: CN=Equifax Secure Global eBusiness CA-1 O=Equifax Secure Inc. +# Label: "Equifax Secure Global eBusiness CA" +# Serial: 1 +# MD5 Fingerprint: 8f:5d:77:06:27:c4:98:3c:5b:93:78:e7:d7:7d:9b:cc +# SHA1 Fingerprint: 7e:78:4a:10:1c:82:65:cc:2d:e1:f1:6d:47:b4:40:ca:d9:0a:19:45 +# SHA256 Fingerprint: 5f:0b:62:ea:b5:e3:53:ea:65:21:65:16:58:fb:b6:53:59:f4:43:28:0a:4a:fb:d1:04:d7:7d:10:f9:f0:4c:07 +-----BEGIN CERTIFICATE----- +MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT +ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw +MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj +dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l +c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC +UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc +58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ +o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH +MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr +aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA +A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA +Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv +8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV +-----END CERTIFICATE----- + +# Issuer: CN=Equifax Secure eBusiness CA-1 O=Equifax Secure Inc. +# Subject: CN=Equifax Secure eBusiness CA-1 O=Equifax Secure Inc. +# Label: "Equifax Secure eBusiness CA 1" +# Serial: 4 +# MD5 Fingerprint: 64:9c:ef:2e:44:fc:c6:8f:52:07:d0:51:73:8f:cb:3d +# SHA1 Fingerprint: da:40:18:8b:91:89:a3:ed:ee:ae:da:97:fe:2f:9d:f5:b7:d1:8a:41 +# SHA256 Fingerprint: cf:56:ff:46:a4:a1:86:10:9d:d9:65:84:b5:ee:b5:8a:51:0c:42:75:b0:e5:f9:4f:40:bb:ae:86:5e:19:f6:73 +-----BEGIN CERTIFICATE----- +MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT +ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw +MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j +LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ +KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo +RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu +WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw +Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD +AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK +eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM +zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ +WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN +/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== +-----END CERTIFICATE----- + +# Issuer: CN=AddTrust Class 1 CA Root O=AddTrust AB OU=AddTrust TTP Network +# Subject: CN=AddTrust Class 1 CA Root O=AddTrust AB OU=AddTrust TTP Network +# Label: "AddTrust Low-Value Services Root" +# Serial: 1 +# MD5 Fingerprint: 1e:42:95:02:33:92:6b:b9:5f:c0:7f:da:d6:b2:4b:fc +# SHA1 Fingerprint: cc:ab:0e:a0:4c:23:01:d6:69:7b:dd:37:9f:cd:12:eb:24:e3:94:9d +# SHA256 Fingerprint: 8c:72:09:27:9a:c0:4e:27:5e:16:d0:7f:d3:b7:75:e8:01:54:b5:96:80:46:e3:1f:52:dd:25:76:63:24:e9:a7 +-----BEGIN CERTIFICATE----- +MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw +MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD +VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul +CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n +tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl +dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch +PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC ++Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O +BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl +MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk +ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB +IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X +7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz +43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY +eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl +pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA +WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= +-----END CERTIFICATE----- + +# Issuer: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network +# Subject: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network +# Label: "AddTrust External Root" +# Serial: 1 +# MD5 Fingerprint: 1d:35:54:04:85:78:b0:3f:42:42:4d:bf:20:73:0a:3f +# SHA1 Fingerprint: 02:fa:f3:e2:91:43:54:68:60:78:57:69:4d:f5:e4:5b:68:85:18:68 +# SHA256 Fingerprint: 68:7f:a4:51:38:22:78:ff:f0:c8:b1:1f:8d:43:d5:76:67:1c:6e:b2:bc:ea:b4:13:fb:83:d9:65:d0:6d:2f:f2 +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs +IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 +MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h +bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt +H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 +uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX +mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX +a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN +E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 +WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD +VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 +Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU +cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx +IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN +AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH +YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC +Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX +c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a +mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE----- + +# Issuer: CN=AddTrust Public CA Root O=AddTrust AB OU=AddTrust TTP Network +# Subject: CN=AddTrust Public CA Root O=AddTrust AB OU=AddTrust TTP Network +# Label: "AddTrust Public Services Root" +# Serial: 1 +# MD5 Fingerprint: c1:62:3e:23:c5:82:73:9c:03:59:4b:2b:e9:77:49:7f +# SHA1 Fingerprint: 2a:b6:28:48:5e:78:fb:f3:ad:9e:79:10:dd:6b:df:99:72:2c:96:e5 +# SHA256 Fingerprint: 07:91:ca:07:49:b2:07:82:aa:d3:c7:d7:bd:0c:df:c9:48:58:35:84:3e:b2:d7:99:60:09:ce:43:ab:6c:69:27 +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx +MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB +ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV +BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV +6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX +GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP +dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH +1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF +62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW +BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL +MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU +cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv +b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6 +IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/ +iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao +GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh +4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm +XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY= +-----END CERTIFICATE----- + +# Issuer: CN=AddTrust Qualified CA Root O=AddTrust AB OU=AddTrust TTP Network +# Subject: CN=AddTrust Qualified CA Root O=AddTrust AB OU=AddTrust TTP Network +# Label: "AddTrust Qualified Certificates Root" +# Serial: 1 +# MD5 Fingerprint: 27:ec:39:47:cd:da:5a:af:e2:9a:01:65:21:a9:4c:bb +# SHA1 Fingerprint: 4d:23:78:ec:91:95:39:b5:00:7f:75:8f:03:3b:21:1e:c5:4d:8b:cf +# SHA256 Fingerprint: 80:95:21:08:05:db:4b:bc:35:5e:44:28:d8:fd:6e:c2:cd:e3:ab:5f:b9:7a:99:42:98:8e:b8:f4:dc:d0:60:16 +-----BEGIN CERTIFICATE----- +MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1 +MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK +EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh +BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq +xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G +87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i +2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U +WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1 +0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G +A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr +pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL +ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm +aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv +hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm +hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X +dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3 +P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y +iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no +xqE= +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. +# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. +# Label: "Entrust Root Certification Authority" +# Serial: 1164660820 +# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4 +# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9 +# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 +Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW +KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw +NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw +NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy +ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV +BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo +Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 +4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 +KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI +rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi +94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB +sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi +gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo +kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE +vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t +O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua +AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP +9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ +eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m +0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +# Issuer: O=RSA Security Inc OU=RSA Security 2048 V3 +# Subject: O=RSA Security Inc OU=RSA Security 2048 V3 +# Label: "RSA Security 2048 v3" +# Serial: 13297492616345471454730593562152402946 +# MD5 Fingerprint: 77:0d:19:b1:21:fd:00:42:9c:3e:0c:a5:dd:0b:02:8e +# SHA1 Fingerprint: 25:01:90:19:cf:fb:d9:99:1c:b7:68:25:74:8d:94:5f:30:93:95:42 +# SHA256 Fingerprint: af:8b:67:62:a1:e5:28:22:81:61:a9:5d:5c:55:9e:e2:66:27:8f:75:d7:9e:83:01:89:a5:03:50:6a:bd:6b:4c +-----BEGIN CERTIFICATE----- +MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6 +MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp +dHkgMjA0OCBWMzAeFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAX +BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAy +MDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt49VcdKA3Xtp +eafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7Jylg +/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGl +wSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnh +AMFRD0xS+ARaqn1y07iHKrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2 +PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpu +AWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NR +MKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYc +HnmYv/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/ +Zb5gEydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+ +f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVO +rSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEkllgVsRch +6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kApKnXwiJPZ9d3 +7CAFYd4= +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Global CA O=GeoTrust Inc. +# Subject: CN=GeoTrust Global CA O=GeoTrust Inc. +# Label: "GeoTrust Global CA" +# Serial: 144470 +# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5 +# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12 +# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg +R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 +9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq +fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv +iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU +1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ +bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW +MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA +ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l +uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn +Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS +tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF +PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un +hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV +5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Global CA 2 O=GeoTrust Inc. +# Subject: CN=GeoTrust Global CA 2 O=GeoTrust Inc. +# Label: "GeoTrust Global CA 2" +# Serial: 1 +# MD5 Fingerprint: 0e:40:a7:6c:de:03:5d:8f:d1:0f:e4:d1:8d:f9:6c:a9 +# SHA1 Fingerprint: a9:e9:78:08:14:37:58:88:f2:05:19:b0:6d:2b:0d:2b:60:16:90:7d +# SHA256 Fingerprint: ca:2d:82:a0:86:77:07:2f:8a:b6:76:4f:f0:35:67:6c:fe:3e:5e:32:5e:01:21:72:df:3f:92:09:6d:b7:9b:85 +-----BEGIN CERTIFICATE----- +MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs +IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg +R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A +PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8 +Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL +TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL +5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7 +S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe +2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap +EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td +EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv +/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN +A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0 +abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF +I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz +4iIprn2DQKi6bA== +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Universal CA O=GeoTrust Inc. +# Subject: CN=GeoTrust Universal CA O=GeoTrust Inc. +# Label: "GeoTrust Universal CA" +# Serial: 1 +# MD5 Fingerprint: 92:65:58:8b:a2:1a:31:72:73:68:5c:b4:a5:7a:07:48 +# SHA1 Fingerprint: e6:21:f3:35:43:79:05:9a:4b:68:30:9d:8a:2f:74:22:15:87:ec:79 +# SHA256 Fingerprint: a0:45:9b:9f:63:b2:25:59:f5:fa:5d:4c:6d:b3:f9:f7:2f:f1:93:42:03:35:78:f0:73:bf:1d:1b:46:cb:b9:12 +-----BEGIN CERTIFICATE----- +MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy +c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE +BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 +IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV +VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 +cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT +QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh +F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v +c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w +mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd +VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX +teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ +f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe +Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ +nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB +/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY +MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG +9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc +aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX +IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn +ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z +uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN +Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja +QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW +koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 +ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt +DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm +bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. +# Subject: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. +# Label: "GeoTrust Universal CA 2" +# Serial: 1 +# MD5 Fingerprint: 34:fc:b8:d0:36:db:9e:14:b3:c2:f2:db:8f:e4:94:c7 +# SHA1 Fingerprint: 37:9a:19:7b:41:85:45:35:0c:a6:03:69:f3:3c:2e:af:47:4f:20:79 +# SHA256 Fingerprint: a0:23:4f:3b:c8:52:7c:a5:62:8e:ec:81:ad:5d:69:89:5d:a5:68:0d:c9:1d:1c:b8:47:7f:33:f8:78:b9:5b:0b +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy +c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD +VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 +c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 +WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG +FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq +XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL +se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb +KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd +IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 +y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt +hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc +QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 +Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV +HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ +KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z +dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ +L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr +Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo +ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY +T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz +GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m +1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV +OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH +6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX +QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS +-----END CERTIFICATE----- + +# Issuer: CN=America Online Root Certification Authority 1 O=America Online Inc. +# Subject: CN=America Online Root Certification Authority 1 O=America Online Inc. +# Label: "America Online Root Certification Authority 1" +# Serial: 1 +# MD5 Fingerprint: 14:f1:08:ad:9d:fa:64:e2:89:e7:1c:cf:a8:ad:7d:5e +# SHA1 Fingerprint: 39:21:c1:15:c1:5d:0e:ca:5c:cb:5b:c4:f0:7d:21:d8:05:0b:56:6a +# SHA256 Fingerprint: 77:40:73:12:c6:3a:15:3d:5b:c0:0b:4e:51:75:9c:df:da:c2:37:dc:2a:33:b6:79:46:e9:8e:9b:fa:68:0a:e3 +-----BEGIN CERTIFICATE----- +MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP +bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2 +MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft +ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lk +hsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym +1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW +OqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb +2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQko +O3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAU +AK3Zo/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +BQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF +Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAb +LjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTIdGcL+oir +oQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C +MMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds +sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 +-----END CERTIFICATE----- + +# Issuer: CN=America Online Root Certification Authority 2 O=America Online Inc. +# Subject: CN=America Online Root Certification Authority 2 O=America Online Inc. +# Label: "America Online Root Certification Authority 2" +# Serial: 1 +# MD5 Fingerprint: d6:ed:3c:ca:e2:66:0f:af:10:43:0d:77:9b:04:09:bf +# SHA1 Fingerprint: 85:b5:ff:67:9b:0c:79:96:1f:c8:6e:44:22:00:46:13:db:17:92:84 +# SHA256 Fingerprint: 7d:3b:46:5a:60:14:e5:26:c0:af:fc:ee:21:27:d2:31:17:27:ad:81:1c:26:84:2d:00:6a:f3:73:06:cc:80:bd +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP +bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2 +MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft +ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC +206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFci +KtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2 +JxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9 +BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7e +Xz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8B +PeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67 +Xnfn6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEq +Z8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ +o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3 ++L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124HhnAgMBAAGj +YzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj +FNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmn +xPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2 +LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzccc +obGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8 +CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMe +IjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMA +DjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2F +AjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX +Om/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPb +AZO1XB4Y3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQl +Zvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw +RY8mkaKO/qk= +-----END CERTIFICATE----- + +# Issuer: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association +# Subject: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association +# Label: "Visa eCommerce Root" +# Serial: 25952180776285836048024890241505565794 +# MD5 Fingerprint: fc:11:b8:d8:08:93:30:00:6d:23:f9:7e:eb:52:1e:02 +# SHA1 Fingerprint: 70:17:9b:86:8c:00:a4:fa:60:91:52:22:3f:9f:3e:32:bd:e0:05:62 +# SHA256 Fingerprint: 69:fa:c9:bd:55:fb:0a:c7:8d:53:bb:ee:5c:f1:d5:97:98:9f:d0:aa:ab:20:a2:51:51:bd:f1:73:3e:e7:d1:22 +-----BEGIN CERTIFICATE----- +MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr +MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl +cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv +bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw +CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h +dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l +cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h +2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E +lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV +ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq +299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t +vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL +dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF +AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR +zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 +LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd +7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw +++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt +398znM/jra6O1I7mT1GvFpLgXPYHDw== +-----END CERTIFICATE----- + +# Issuer: CN=Certum CA O=Unizeto Sp. z o.o. +# Subject: CN=Certum CA O=Unizeto Sp. z o.o. +# Label: "Certum Root CA" +# Serial: 65568 +# MD5 Fingerprint: 2c:8f:9f:66:1d:18:90:b1:47:26:9d:8e:86:82:8c:a9 +# SHA1 Fingerprint: 62:52:dc:40:f7:11:43:a2:2f:de:9e:f7:34:8e:06:42:51:b1:81:18 +# SHA256 Fingerprint: d8:e0:fe:bc:1d:b2:e3:8d:00:94:0f:37:d2:7d:41:34:4d:99:3e:73:4b:99:d5:65:6d:97:78:d4:d8:14:36:24 +-----BEGIN CERTIFICATE----- +MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBM +MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD +QTAeFw0wMjA2MTExMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBM +MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD +QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6xwS7TT3zNJc4YPk/E +jG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdLkKWo +ePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GI +ULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapu +Ob7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg +AKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7 +HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA +uI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQa +TOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTg +xSvgGrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1q +CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x +O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs +6GAqm4VKQPNriiTsBhYscw== +-----END CERTIFICATE----- + +# Issuer: CN=AAA Certificate Services O=Comodo CA Limited +# Subject: CN=AAA Certificate Services O=Comodo CA Limited +# Label: "Comodo AAA Services root" +# Serial: 1 +# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0 +# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49 +# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4 +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +# Issuer: CN=Secure Certificate Services O=Comodo CA Limited +# Subject: CN=Secure Certificate Services O=Comodo CA Limited +# Label: "Comodo Secure Services root" +# Serial: 1 +# MD5 Fingerprint: d3:d9:bd:ae:9f:ac:67:24:b3:c8:1b:52:e1:b9:a9:bd +# SHA1 Fingerprint: 4a:65:d5:f4:1d:ef:39:b8:b8:90:4a:4a:d3:64:81:33:cf:c7:a1:d1 +# SHA256 Fingerprint: bd:81:ce:3b:4f:65:91:d1:1a:67:b5:fc:7a:47:fd:ef:25:52:1b:f9:aa:4e:18:b9:e3:df:2e:34:a7:80:3b:e8 +-----BEGIN CERTIFICATE----- +MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp +ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow +fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV +BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM +cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S +HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996 +CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk +3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz +6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV +HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud +EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv +Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw +Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww +DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0 +5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj +Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI +gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ +aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl +izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk= +-----END CERTIFICATE----- + +# Issuer: CN=Trusted Certificate Services O=Comodo CA Limited +# Subject: CN=Trusted Certificate Services O=Comodo CA Limited +# Label: "Comodo Trusted Services root" +# Serial: 1 +# MD5 Fingerprint: 91:1b:3f:6e:cd:9e:ab:ee:07:fe:1f:71:d2:b3:61:27 +# SHA1 Fingerprint: e1:9f:e3:0e:8b:84:60:9e:80:9b:17:0d:72:a8:c5:ba:6e:14:09:bd +# SHA256 Fingerprint: 3f:06:e5:56:81:d4:96:f5:be:16:9e:b5:38:9f:9f:2b:8f:f6:1e:17:08:df:68:81:72:48:49:cd:5d:27:cb:69 +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0 +aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla +MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO +BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD +VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW +fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt +TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL +fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW +1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7 +kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G +A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v +ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo +dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu +Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/ +HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 +pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS +jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+ +xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn +dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority +# Subject: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority +# Label: "QuoVadis Root CA" +# Serial: 985026699 +# MD5 Fingerprint: 27:de:36:fe:72:b7:00:03:00:9d:f4:f0:1e:6c:04:24 +# SHA1 Fingerprint: de:3f:40:bd:50:93:d3:9b:6c:60:f6:da:bc:07:62:01:00:89:76:c9 +# SHA256 Fingerprint: a4:5e:de:3b:bb:f0:9c:8a:e1:5c:72:ef:c0:72:68:d6:93:a2:1c:99:6f:d5:1e:67:ca:07:94:60:fd:6d:88:73 +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz +MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw +IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR +dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp +li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D +rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ +WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug +F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU +xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC +Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv +dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw +ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl +IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh +c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy +ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI +KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T +KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq +y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p +dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD +VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL +MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk +fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 +7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R +cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y +mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW +xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK +SnQ2+Q== +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 2 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 2 O=QuoVadis Limited +# Label: "QuoVadis Root CA 2" +# Serial: 1289 +# MD5 Fingerprint: 5e:39:7b:dd:f8:ba:ec:82:e9:ac:62:ba:0c:54:00:2b +# SHA1 Fingerprint: ca:3a:fb:cf:12:40:36:4b:44:b2:16:20:88:80:48:39:19:93:7c:f7 +# SHA256 Fingerprint: 85:a0:dd:7d:d7:20:ad:b7:ff:05:f8:3d:54:2b:20:9d:c7:ff:45:28:f7:d6:77:b1:83:89:fe:a5:e5:c4:9e:86 +-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa +GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg +Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J +WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB +rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp ++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 +ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i +Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz +PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og +/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH +oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI +yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud +EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 +A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL +MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f +BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn +g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl +fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K +WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha +B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc +hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR +TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD +mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z +ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y +4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza +8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 3" +# Serial: 1478 +# MD5 Fingerprint: 31:85:3c:62:94:97:63:b9:aa:fd:89:4e:af:6f:e0:cf +# SHA1 Fingerprint: 1f:49:14:f7:d8:74:95:1d:dd:ae:02:c0:be:fd:3a:2d:82:75:51:85 +# SHA256 Fingerprint: 18:f1:fc:7f:20:5d:f8:ad:dd:eb:7f:e0:07:dd:57:e3:af:37:5a:9c:4d:8d:73:54:6b:f4:f1:fe:d1:e1:8d:35 +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM +V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB +4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr +H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd +8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv +vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT +mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe +btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc +T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt +WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ +c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A +4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD +VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG +CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 +aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu +dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw +czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G +A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg +Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 +7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem +d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd ++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B +4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN +t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x +DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 +k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s +zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j +Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT +mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK +4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- + +# Issuer: O=SECOM Trust.net OU=Security Communication RootCA1 +# Subject: O=SECOM Trust.net OU=Security Communication RootCA1 +# Label: "Security Communication Root CA" +# Serial: 0 +# MD5 Fingerprint: f1:bc:63:6a:54:e0:b5:27:f5:cd:e7:1a:e3:4d:6e:4a +# SHA1 Fingerprint: 36:b1:2b:49:f9:81:9e:d7:4c:9e:bc:38:0f:c6:56:8f:5d:ac:b2:f7 +# SHA256 Fingerprint: e7:5e:72:ed:9f:56:0e:ec:6e:b4:80:00:73:a4:3f:c3:ad:19:19:5a:39:22:82:01:78:95:97:4a:99:02:6b:6c +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY +MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t +dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 +WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD +VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 +9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ +DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 +Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N +QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ +xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G +A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG +kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr +Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 +Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU +JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot +RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== +-----END CERTIFICATE----- + +# Issuer: CN=Sonera Class2 CA O=Sonera +# Subject: CN=Sonera Class2 CA O=Sonera +# Label: "Sonera Class 2 Root CA" +# Serial: 29 +# MD5 Fingerprint: a3:ec:75:0f:2e:88:df:fa:48:01:4e:0b:5c:48:6f:fb +# SHA1 Fingerprint: 37:f7:6d:e6:07:7c:90:c5:b1:3e:93:1a:b7:41:10:b4:f2:e4:9a:27 +# SHA256 Fingerprint: 79:08:b4:03:14:c1:38:10:0b:51:8d:07:35:80:7f:fb:fc:f8:51:8a:00:95:33:71:05:ba:38:6b:15:3d:d9:27 +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP +MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx +MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV +BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o +Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt +5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s +3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej +vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu +8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw +DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil +zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ +3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD +FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 +Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 +ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M +-----END CERTIFICATE----- + +# Issuer: CN=Staat der Nederlanden Root CA O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden Root CA O=Staat der Nederlanden +# Label: "Staat der Nederlanden Root CA" +# Serial: 10000010 +# MD5 Fingerprint: 60:84:7c:5a:ce:db:0c:d4:cb:a7:e9:fe:02:c6:a9:c0 +# SHA1 Fingerprint: 10:1d:fa:3f:d5:0b:cb:bb:9b:b5:60:0c:19:55:a4:1a:f4:73:3a:04 +# SHA256 Fingerprint: d4:1d:82:9e:8c:16:59:82:2a:f9:3f:ce:62:bf:fc:de:26:4f:c8:4e:8b:95:0c:5f:f2:75:d0:52:35:46:95:a3 +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJO +TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEy +MTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVk +ZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENB +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFtvszn +ExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw71 +9tV2U02PjLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MO +hXeiD+EwR+4A5zN9RGcaC1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+U +tFE5A3+y3qcym7RHjm+0Sq7lr7HcsBthvJly3uSJt3omXdozSVtSnA71iq3DuD3o +BmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn622r+I/q85Ej0ZytqERAh +SQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRVHSAAMDww +OgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMv +cm9vdC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA +7Jbg0zTBLL9s+DANBgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k +/rvuFbQvBgwp8qiSpGEN/KtcCFtREytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzm +eafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbwMVcoEoJz6TMvplW0C5GUR5z6 +u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3ynGQI0DvDKcWy +7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR +iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== +-----END CERTIFICATE----- + +# Issuer: O=TDC Internet OU=TDC Internet Root CA +# Subject: O=TDC Internet OU=TDC Internet Root CA +# Label: "TDC Internet Root CA" +# Serial: 986490188 +# MD5 Fingerprint: 91:f4:03:55:20:a1:f8:63:2c:62:de:ac:fb:61:1c:8e +# SHA1 Fingerprint: 21:fc:bd:8e:7f:6c:af:05:1b:d1:b3:43:ec:a8:e7:61:47:f2:0f:8a +# SHA256 Fingerprint: 48:98:c6:88:8c:0c:ff:b0:d3:e3:1a:ca:8a:37:d4:e3:51:5f:f7:46:d0:26:35:d8:66:46:cf:a0:a3:18:5a:e7 +-----BEGIN CERTIFICATE----- +MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJE +SzEVMBMGA1UEChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQg +Um9vdCBDQTAeFw0wMTA0MDUxNjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNV +BAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJuZXQxHTAbBgNVBAsTFFREQyBJbnRl +cm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxLhA +vJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20jxsNu +Zp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a +0vnRrEvLznWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc1 +4izbSysseLlJ28TQx5yc5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGN +eGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcD +R0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZIAYb4QgEBBAQDAgAHMGUG +A1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMMVERDIElu +dGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxME +Q1JMMTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3 +WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAw +HQYDVR0OBBYEFGxkAcf9hW2syNqeUAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJ +KoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4IBAQBO +Q8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540mgwV5dOy0uaOX +wTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ +2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm89 +9qNLPg7kbWzbO0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0 +jUNAE4z9mQNUecYu6oah9jrUCbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38 +aQNiuJkFBT1reBK9sG9l +-----END CERTIFICATE----- + +# Issuer: CN=UTN - DATACorp SGC O=The USERTRUST Network OU=http://www.usertrust.com +# Subject: CN=UTN - DATACorp SGC O=The USERTRUST Network OU=http://www.usertrust.com +# Label: "UTN DATACorp SGC Root CA" +# Serial: 91374294542884689855167577680241077609 +# MD5 Fingerprint: b3:a5:3e:77:21:6d:ac:4a:c0:c9:fb:d5:41:3d:ca:06 +# SHA1 Fingerprint: 58:11:9f:0e:12:82:87:ea:50:fd:d9:87:45:6f:4f:78:dc:fa:d6:d4 +# SHA256 Fingerprint: 85:fb:2f:91:dd:12:27:5a:01:45:b6:36:53:4f:84:02:4a:d6:8b:69:b8:ee:88:68:4f:f7:11:37:58:05:b3:48 +-----BEGIN CERTIFICATE----- +MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB +kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw +IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD +VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu +dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 +E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ +D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK +4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq +lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW +bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB +o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT +MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js +LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr +BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB +AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft +Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj +j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH +KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv +2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 +mfnGV/TJVTl4uix5yaaIK/QI +-----END CERTIFICATE----- + +# Issuer: CN=UTN-USERFirst-Hardware O=The USERTRUST Network OU=http://www.usertrust.com +# Subject: CN=UTN-USERFirst-Hardware O=The USERTRUST Network OU=http://www.usertrust.com +# Label: "UTN USERFirst Hardware Root CA" +# Serial: 91374294542884704022267039221184531197 +# MD5 Fingerprint: 4c:56:41:e5:0d:bb:2b:e8:ca:a3:ed:18:08:ad:43:39 +# SHA1 Fingerprint: 04:83:ed:33:99:ac:36:08:05:87:22:ed:bc:5e:46:00:e3:be:f9:d7 +# SHA256 Fingerprint: 6e:a5:47:41:d0:04:66:7e:ed:1b:48:16:63:4a:a3:a7:9e:6e:4b:96:95:0f:82:79:da:fc:8d:9b:d8:81:21:37 +-----BEGIN CERTIFICATE----- +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB +lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt +SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe +MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v +d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh +cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn +0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ +M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a +MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd +oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI +DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy +oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 +dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy +bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF +BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli +CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE +CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t +3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS +KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== +-----END CERTIFICATE----- + +# Issuer: CN=Chambers of Commerce Root O=AC Camerfirma SA CIF A82743287 OU=http://www.chambersign.org +# Subject: CN=Chambers of Commerce Root O=AC Camerfirma SA CIF A82743287 OU=http://www.chambersign.org +# Label: "Camerfirma Chambers of Commerce Root" +# Serial: 0 +# MD5 Fingerprint: b0:01:ee:14:d9:af:29:18:94:76:8e:f1:69:33:2a:84 +# SHA1 Fingerprint: 6e:3a:55:a4:19:0c:19:5c:93:84:3c:c0:db:72:2e:31:30:61:f0:b1 +# SHA256 Fingerprint: 0c:25:8a:12:a5:67:4a:ef:25:f2:8b:a7:dc:fa:ec:ee:a3:48:e5:41:e6:f5:cc:4e:e6:3b:71:b3:61:60:6a:c3 +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn +MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg +b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa +MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB +ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw +IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B +AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb +unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d +BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq +7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 +0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX +roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG +A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j +aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p +26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA +BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud +EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN +BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz +aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB +AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd +p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi +1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc +XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 +eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu +tGWaIZDgqtCYvDi1czyL+Nw= +-----END CERTIFICATE----- + +# Issuer: CN=Global Chambersign Root O=AC Camerfirma SA CIF A82743287 OU=http://www.chambersign.org +# Subject: CN=Global Chambersign Root O=AC Camerfirma SA CIF A82743287 OU=http://www.chambersign.org +# Label: "Camerfirma Global Chambersign Root" +# Serial: 0 +# MD5 Fingerprint: c5:e6:7b:bf:06:d0:4f:43:ed:c4:7a:65:8a:fb:6b:19 +# SHA1 Fingerprint: 33:9b:6b:14:50:24:9b:55:7a:01:87:72:84:d9:e0:2f:c3:d2:d8:e9 +# SHA256 Fingerprint: ef:3c:b4:17:fc:8e:bf:6f:97:87:6c:9e:4e:ce:39:de:1e:a5:fe:64:91:41:d1:02:8b:7d:11:c0:b2:29:8c:ed +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn +MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo +YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9 +MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy +NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G +A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA +A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0 +Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s +QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV +eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795 +B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh +z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T +AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i +ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w +TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH +MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD +VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE +VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh +bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B +AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM +bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi +ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG +VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c +ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/ +AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== +-----END CERTIFICATE----- + +# Issuer: CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado O=NetLock Halozatbiztonsagi Kft. OU=Tanusitvanykiadok +# Subject: CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado O=NetLock Halozatbiztonsagi Kft. OU=Tanusitvanykiadok +# Label: "NetLock Notary (Class A) Root" +# Serial: 259 +# MD5 Fingerprint: 86:38:6d:5e:49:63:6c:85:5c:db:6d:dc:94:b7:d0:f7 +# SHA1 Fingerprint: ac:ed:5f:65:53:fd:25:ce:01:5f:1f:7a:48:3b:6a:74:9f:61:78:c6 +# SHA256 Fingerprint: 7f:12:cd:5f:7e:5e:29:0e:c7:d8:51:79:d5:b7:2c:20:a5:be:75:08:ff:db:5b:f8:1a:b9:68:4a:7f:c9:f6:67 +-----BEGIN CERTIFICATE----- +MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhV +MRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMe +TmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0 +dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFzcyBB +KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oXDTE5MDIxOTIzMTQ0 +N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhC +dWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQu +MRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBL +b3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeLVu0ThEDaiD +zl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX9EUi +3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8 +WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LY +Oph7tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2Esi +NCubMvJIH5+hCoR64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCC +ApswDgYDVR0PAQH/BAQDAgAGMBIGA1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4 +QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZRUxFTSEgRXplbiB0 +YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRhdGFz +aSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu +IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtm +ZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMg +ZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVs +amFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJhc2EgbWVndGFsYWxoYXRv +IGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBzOi8vd3d3 +Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6 +ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1 +YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3Qg +dG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRs +b2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNAbmV0bG9jay5uZXQuMA0G +CSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5ayZrU3/b39/zcT0mwBQO +xmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjPytoUMaFP +0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQ +QeJBCWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxk +f1qbFFgBJ34TUMdrKuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK +8CtmdWOMovsEPoMOmzbwGOQmIMOM8CgHrTwXZoi1/baI +-----END CERTIFICATE----- + +# Issuer: CN=NetLock Uzleti (Class B) Tanusitvanykiado O=NetLock Halozatbiztonsagi Kft. OU=Tanusitvanykiadok +# Subject: CN=NetLock Uzleti (Class B) Tanusitvanykiado O=NetLock Halozatbiztonsagi Kft. OU=Tanusitvanykiadok +# Label: "NetLock Business (Class B) Root" +# Serial: 105 +# MD5 Fingerprint: 39:16:aa:b9:6a:41:e1:14:69:df:9e:6c:3b:72:dc:b6 +# SHA1 Fingerprint: 87:9f:4b:ee:05:df:98:58:3b:e3:60:d6:33:e7:0d:3f:fe:98:71:af +# SHA256 Fingerprint: 39:df:7b:68:2b:7b:93:8f:84:71:54:81:cc:de:8d:60:d8:f2:2e:c5:98:87:7d:0a:aa:c1:2b:59:18:2b:03:12 +-----BEGIN CERTIFICATE----- +MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUx +ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 +b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQD +EylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikgVGFudXNpdHZhbnlraWFkbzAeFw05 +OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYDVQQGEwJIVTERMA8G +A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh +Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5l +dExvY2sgVXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xK +gZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX +iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvc +Q7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8E +BAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1G +SUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFu +b3MgU3pvbGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBh +bGFwamFuIGtlc3p1bHQuIEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExv +Y2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGln +aXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0 +IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh +c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGph +biBhIGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJo +ZXRvIGF6IGVsbGVub3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBP +UlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmlj +YXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBo +dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNA +bmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06 +sPgzTEdM43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXa +n3BukxowOR0w2y7jfLKRstE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKS +NitjrFgBazMpUIaD8QFI +-----END CERTIFICATE----- + +# Issuer: CN=NetLock Expressz (Class C) Tanusitvanykiado O=NetLock Halozatbiztonsagi Kft. OU=Tanusitvanykiadok +# Subject: CN=NetLock Expressz (Class C) Tanusitvanykiado O=NetLock Halozatbiztonsagi Kft. OU=Tanusitvanykiadok +# Label: "NetLock Express (Class C) Root" +# Serial: 104 +# MD5 Fingerprint: 4f:eb:f1:f0:70:c2:80:63:5d:58:9f:da:12:3c:a9:c4 +# SHA1 Fingerprint: e3:92:51:2f:0a:cf:f5:05:df:f6:de:06:7f:75:37:e1:65:ea:57:4b +# SHA256 Fingerprint: 0b:5e:ed:4e:84:64:03:cf:55:e0:65:84:84:40:ed:2a:82:75:8b:f5:b9:aa:1f:25:3d:46:13:cf:a0:80:ff:3f +-----BEGIN CERTIFICATE----- +MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUx +ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 +b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQD +EytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBDKSBUYW51c2l0dmFueWtpYWRvMB4X +DTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJBgNVBAYTAkhVMREw +DwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9u +c2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMr +TmV0TG9jayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNA +OoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3ZW3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC +2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63euyucYT2BDMIJTLrdKwW +RMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQwDgYDVR0P +AQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEW +ggJNRklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0 +YWxhbm9zIFN6b2xnYWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFz +b2sgYWxhcGphbiBrZXN6dWx0LiBBIGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBO +ZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1iaXp0b3NpdGFzYSB2ZWRpLiBB +IGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0ZWxlIGF6IGVs +b2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs +ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25s +YXBqYW4gYSBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kg +a2VyaGV0byBheiBlbGxlbm9yemVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4g +SU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5kIHRoZSB1c2Ugb2YgdGhpcyBjZXJ0 +aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQUyBhdmFpbGFibGUg +YXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwgYXQg +Y3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmY +ta3UzbM2xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2g +pO0u9f38vf5NNwgMvOOWgyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4 +Fp1hBWeAyNDYpQcCNJgEjTME1A== +-----END CERTIFICATE----- + +# Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com +# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com +# Label: "XRamp Global CA Root" +# Serial: 107108908803651509692980124233745014957 +# MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1 +# SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6 +# SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2 +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB +gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk +MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY +UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx +NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 +dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy +dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 +38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP +KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q +DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 +qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa +JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi +PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs +jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 +eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR +vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa +IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy +i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ +O+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority +# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority +# Label: "Go Daddy Class 2 CA" +# Serial: 0 +# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67 +# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4 +# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4 +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh +MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE +YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 +MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo +ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg +MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN +ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA +PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w +wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi +EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY +avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ +YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE +sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h +/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 +IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy +OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P +TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER +dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf +ReYNnyicsbkqWletNw+vHX/bvZ8= +-----END CERTIFICATE----- + +# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority +# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority +# Label: "Starfield Class 2 CA" +# Serial: 0 +# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24 +# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a +# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58 +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw +NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE +ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp +ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 +DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf +8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN ++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 +X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa +K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA +1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G +A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR +zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 +YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD +bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 +L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D +eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp +VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY +WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +# Issuer: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing +# Subject: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing +# Label: "StartCom Certification Authority" +# Serial: 1 +# MD5 Fingerprint: 22:4d:8f:8a:fc:f7:35:c2:bb:57:34:90:7b:8b:22:16 +# SHA1 Fingerprint: 3e:2b:f7:f2:03:1b:96:f3:8c:e6:c4:d8:a8:5d:3e:2d:58:47:6a:0f +# SHA256 Fingerprint: c7:66:a9:be:f2:d4:07:1c:86:3a:31:aa:49:20:e8:13:b2:d1:98:60:8c:b7:b7:cf:e2:11:43:b8:36:df:09:ea +-----BEGIN CERTIFICATE----- +MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW +MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg +Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 +MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi +U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh +cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk +pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf +OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C +Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT +Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi +HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM +Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w ++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ +Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 +Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B +26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID +AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE +FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j +ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js +LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM +BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 +Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy +dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh +cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh +YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg +dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp +bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ +YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT +TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ +9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 +jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW +FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz +ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 +ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L +EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu +L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq +yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC +O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V +um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh +NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= +-----END CERTIFICATE----- + +# Issuer: O=Government Root Certification Authority +# Subject: O=Government Root Certification Authority +# Label: "Taiwan GRCA" +# Serial: 42023070807708724159991140556527066870 +# MD5 Fingerprint: 37:85:44:53:32:45:1f:20:f0:f3:95:e1:25:c4:43:4e +# SHA1 Fingerprint: f4:8b:11:bf:de:ab:be:94:54:20:71:e6:41:de:6b:be:88:2b:40:b9 +# SHA256 Fingerprint: 76:00:29:5e:ef:e8:5b:9e:1f:d6:24:db:76:06:2a:aa:ae:59:81:8a:54:d2:77:4c:d4:c0:b2:c0:11:31:e1:b3 +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ +MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow +PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR +IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q +gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy +yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts +F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2 +jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx +ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC +VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK +YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH +EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN +Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud +DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE +MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK +UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ +TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf +qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK +ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE +JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7 +hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1 +EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm +nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX +udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz +ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe +LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl +pYYsfPQS +-----END CERTIFICATE----- + +# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Label: "Firmaprofesional Root CA" +# Serial: 1 +# MD5 Fingerprint: 11:92:79:40:3c:b1:83:40:e5:ab:66:4a:67:92:80:df +# SHA1 Fingerprint: a9:62:8f:4b:98:a9:1b:48:35:ba:d2:c1:46:32:86:bb:66:64:6a:8c +# SHA256 Fingerprint: c1:cf:0b:52:09:64:35:e3:f1:b7:1d:aa:ec:45:5a:23:11:c8:40:4f:55:83:a9:e2:13:c6:9d:85:7d:94:33:05 +-----BEGIN CERTIFICATE----- +MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMx +IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1 +dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w +HhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTELMAkGA1UEBhMCRVMx +IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1 +dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5u +Cp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5Vj1H5WuretXDE7aTt/6MNbg9kUDGvASdY +rv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJHlShbz++AbOCQl4oBPB3z +hxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf3H5idPay +BQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcL +iam8NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcb +AgMBAAGjgZ8wgZwwKgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lv +bmFsLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0 +MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E +FgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQADggEBAEdz/o0n +VPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq +u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36m +hoEyIwOdyPdfwUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzfl +ZKG+TQyTmAyX9odtsz/ny4Cm7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBp +QWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YGVM+h4k0460tQtcsm9MracEpqoeJ5 +quGnM/b9Sh/22WA= +-----END CERTIFICATE----- + +# Issuer: CN=Swisscom Root CA 1 O=Swisscom OU=Digital Certificate Services +# Subject: CN=Swisscom Root CA 1 O=Swisscom OU=Digital Certificate Services +# Label: "Swisscom Root CA 1" +# Serial: 122348795730808398873664200247279986742 +# MD5 Fingerprint: f8:38:7c:77:88:df:2c:16:68:2e:c2:e2:52:4b:b8:f9 +# SHA1 Fingerprint: 5f:3a:fc:0a:8b:64:f6:86:67:34:74:df:7e:a9:a2:fe:f9:fa:7a:51 +# SHA256 Fingerprint: 21:db:20:12:36:60:bb:2e:d4:18:20:5d:a1:1e:e7:a8:5a:65:e2:bc:6e:55:b5:af:7e:78:99:c8:a2:66:d9:2e +-----BEGIN CERTIFICATE----- +MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBk +MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 +YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg +Q0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4MTgyMjA2MjBaMGQxCzAJBgNVBAYT +AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp +Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9 +m2BtRsiMMW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdih +FvkcxC7mlSpnzNApbjyFNDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/ +TilftKaNXXsLmREDA/7n29uj/x2lzZAeAR81sH8A25Bvxn570e56eqeqDFdvpG3F +EzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkCb6dJtDZd0KTeByy2dbco +kdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn7uHbHaBu +HYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNF +vJbNcA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo +19AOeCMgkckkKmUpWyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjC +L3UcPX7ape8eYIVpQtPM+GP+HkM5haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJW +bjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNYMUJDLXT5xp6mig/p/r+D5kNX +JLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw +FDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j +BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzc +K6FptWfUjNP9MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzf +ky9NfEBWMXrrpA9gzXrzvsMnjgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7Ik +Vh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQMbFamIp1TpBcahQq4FJHgmDmHtqB +sfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4HVtA4oJVwIHaM190e +3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtlvrsR +ls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ip +mXeascClOS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HH +b6D0jqTsNFFbjCYDcKF31QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksf +rK/7DZBaZmBwXarNeNQk7shBoJMBkpxqnvy5JMWzFYJ+vq6VK+uxwNrjAWALXmms +hFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCyx/yP2FS1k2Kdzs9Z+z0Y +zirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMWNY6E0F/6 +MBr1mmz0DlP5OlvRHA== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root CA" +# Serial: 17154717934120587862167794914071425081 +# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72 +# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43 +# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c +JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP +mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ +wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 +VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ +AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB +AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun +pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC +dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf +fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm +NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx +H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root CA" +# Serial: 10944719598952040374951832963794454346 +# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e +# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36 +# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61 +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert High Assurance EV Root CA" +# Serial: 3553400076410547919724730734378100087 +# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a +# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25 +# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K +-----END CERTIFICATE----- + +# Issuer: CN=Class 2 Primary CA O=Certplus +# Subject: CN=Class 2 Primary CA O=Certplus +# Label: "Certplus Class 2 Primary CA" +# Serial: 177770208045934040241468760488327595043 +# MD5 Fingerprint: 88:2c:8c:52:b8:a2:3c:f3:f7:bb:03:ea:ae:ac:42:0b +# SHA1 Fingerprint: 74:20:74:41:72:9c:dd:92:ec:79:31:d8:23:10:8d:c2:81:92:e2:bb +# SHA256 Fingerprint: 0f:99:3c:8a:ef:97:ba:af:56:87:14:0e:d5:9a:d1:82:1b:b4:af:ac:f0:aa:9a:58:b5:d5:7a:33:8a:3a:fb:cb +-----BEGIN CERTIFICATE----- +MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw +PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz +cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 +MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz +IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ +ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR +VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL +kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd +EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas +H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 +HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud +DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 +QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu +Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ +AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 +yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR +FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA +ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB +kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 +l7+ijrRU +-----END CERTIFICATE----- + +# Issuer: CN=DST Root CA X3 O=Digital Signature Trust Co. +# Subject: CN=DST Root CA X3 O=Digital Signature Trust Co. +# Label: "DST Root CA X3" +# Serial: 91299735575339953335919266965803778155 +# MD5 Fingerprint: 41:03:52:dc:0f:f7:50:1b:16:f0:02:8e:ba:6f:45:c5 +# SHA1 Fingerprint: da:c9:02:4f:54:d8:f6:df:94:93:5f:b1:73:26:38:ca:6a:d7:7c:13 +# SHA256 Fingerprint: 06:87:26:03:31:a7:24:03:d9:09:f1:05:e6:9b:cf:0d:32:e1:bd:24:93:ff:c6:d9:20:6d:11:bc:d6:77:07:39 +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + +# Issuer: CN=DST ACES CA X6 O=Digital Signature Trust OU=DST ACES +# Subject: CN=DST ACES CA X6 O=Digital Signature Trust OU=DST ACES +# Label: "DST ACES CA X6" +# Serial: 17771143917277623872238992636097467865 +# MD5 Fingerprint: 21:d8:4c:82:2b:99:09:33:a2:eb:14:24:8d:8e:5f:e8 +# SHA1 Fingerprint: 40:54:da:6f:1c:3f:40:74:ac:ed:0f:ec:cd:db:79:d1:53:fb:90:1d +# SHA256 Fingerprint: 76:7c:95:5a:76:41:2c:89:af:68:8e:90:a1:c7:0f:55:6c:fd:6b:60:25:db:ea:10:41:6d:7e:b6:83:1f:8c:40 +-----BEGIN CERTIFICATE----- +MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBb +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3Qx +ETAPBgNVBAsTCERTVCBBQ0VTMRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0w +MzExMjAyMTE5NThaFw0xNzExMjAyMTE5NThaMFsxCzAJBgNVBAYTAlVTMSAwHgYD +VQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UECxMIRFNUIEFDRVMx +FzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPu +ktKe1jzIDZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7 +gLFViYsx+tC3dr5BPTCapCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZH +fAjIgrrep4c9oW24MFbCswKBXy314powGCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4a +ahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPyMjwmR/onJALJfh1biEIT +ajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rk +c3QuY29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjto +dHRwOi8vd3d3LnRydXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMt +aW5kZXguaHRtbDAdBgNVHQ4EFgQUCXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZI +hvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V25FYrnJmQ6AgwbN99Pe7lv7Uk +QIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6tFr8hlxCBPeP/ +h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq +nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpR +rscL9yuwNwXsvFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf2 +9w4LTJxoeHtxMcfrHuBnQfO3oKfN5XozNmr6mis= +-----END CERTIFICATE----- + +# Issuer: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı O=(c) 2005 TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. +# Subject: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı O=(c) 2005 TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. +# Label: "TURKTRUST Certificate Services Provider Root 1" +# Serial: 1 +# MD5 Fingerprint: f1:6a:22:18:c9:cd:df:ce:82:1d:1d:b7:78:5c:a9:a5 +# SHA1 Fingerprint: 79:98:a3:08:e1:4d:65:85:e6:c2:1e:15:3a:71:9f:ba:5a:d3:4a:d9 +# SHA256 Fingerprint: 44:04:e3:3b:5e:14:0d:cf:99:80:51:fd:fc:80:28:c7:c8:16:15:c5:ee:73:7b:11:1b:58:82:33:a9:b5:35:a0 +-----BEGIN CERTIFICATE----- +MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOc +UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx +c8SxMQswCQYDVQQGDAJUUjEPMA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykg +MjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 +dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMxMDI3MTdaFw0xNTAz +MjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2Vy +dGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYD +VQQHDAZBTktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kg +xLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEu +xZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7 +XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GXyGl8hMW0kWxsE2qkVa2k +heiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8iSi9BB35J +YbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5C +urKZ8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1 +JuTm5Rh8i27fbMx4W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51 +b0dewQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV +9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46sWrv7/hg0Uw2ZkUd82YCdAR7 +kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxEq8Sn5RTOPEFh +fEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy +B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdA +aLX/7KfS0zgYnNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKS +RGQDJereW26fyfJOrN3H +-----END CERTIFICATE----- + +# Issuer: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Kasım 2005 +# Subject: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Kasım 2005 +# Label: "TURKTRUST Certificate Services Provider Root 2" +# Serial: 1 +# MD5 Fingerprint: 37:a5:6e:d4:b1:25:84:97:b7:fd:56:15:7a:f9:a2:00 +# SHA1 Fingerprint: b4:35:d4:e1:11:9d:1c:66:90:a7:49:eb:b3:94:bd:63:7b:a7:82:b7 +# SHA256 Fingerprint: c4:70:cf:54:7e:23:02:b9:77:fb:29:dd:71:a8:9a:7b:6c:1f:60:77:7b:03:29:f5:60:17:f3:28:bf:4f:6b:e6 +-----BEGIN CERTIFICATE----- +MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOc +UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx +c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xS +S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg +SGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcNMDUxMTA3MTAwNzU3 +WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVrdHJv +bmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJU +UjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSw +bGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWe +LiAoYykgS2FzxLFtIDIwMDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqeLCDe2JAOCtFp0if7qnef +J1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKIx+XlZEdh +R3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJ +Qv2gQrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGX +JHpsmxcPbe9TmJEr5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1p +zpwACPI2/z7woQ8arBT9pmAPAgMBAAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58S +Fq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/nttRbj2hWyfIvwq +ECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 +Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFz +gw2lGh1uEpJ+hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotH +uFEJjOp9zYhys2AzsfAKRO8P9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LS +y3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5UrbnBEI= +-----END CERTIFICATE----- + +# Issuer: CN=SwissSign Gold CA - G2 O=SwissSign AG +# Subject: CN=SwissSign Gold CA - G2 O=SwissSign AG +# Label: "SwissSign Gold CA - G2" +# Serial: 13492815561806991280 +# MD5 Fingerprint: 24:77:d9:a8:91:d1:3b:fa:88:2d:c2:ff:f8:cd:33:93 +# SHA1 Fingerprint: d8:c5:38:8a:b7:30:1b:1b:6e:d4:7a:e6:45:25:3a:6f:9f:1a:27:61 +# SHA256 Fingerprint: 62:dd:0b:e9:b9:f5:0a:16:3e:a0:f8:e7:5c:05:3b:1e:ca:57:ea:55:c8:68:8f:64:7c:68:81:f2:c8:35:7b:95 +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=SwissSign Silver CA - G2 O=SwissSign AG +# Subject: CN=SwissSign Silver CA - G2 O=SwissSign AG +# Label: "SwissSign Silver CA - G2" +# Serial: 5700383053117599563 +# MD5 Fingerprint: e0:06:a1:c9:7d:cf:c9:fc:0d:c0:56:75:96:d8:62:13 +# SHA1 Fingerprint: 9b:aa:e5:9f:56:ee:21:cb:43:5a:be:25:93:df:a7:f0:40:d1:1d:cb +# SHA256 Fingerprint: be:6c:4d:a2:bb:b9:ba:59:b6:f3:93:97:68:37:42:46:c3:c0:05:99:3f:a9:8f:02:0d:1d:ed:be:d4:8a:81:d5 +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. +# Subject: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. +# Label: "GeoTrust Primary Certification Authority" +# Serial: 32798226551256963324313806436981982369 +# MD5 Fingerprint: 02:26:c3:01:5e:08:30:37:43:a9:d0:7d:cf:37:e6:bf +# SHA1 Fingerprint: 32:3c:11:8e:1b:f7:b8:b6:52:54:e2:e2:10:0d:d6:02:90:37:f0:96 +# SHA256 Fingerprint: 37:d5:10:06:c5:12:ea:ab:62:64:21:f1:ec:8c:92:01:3f:c5:f8:2a:e9:8e:e5:33:eb:46:19:b8:de:b4:d0:6c +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY +MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo +R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx +MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 +AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA +ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 +7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W +kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI +mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ +KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 +6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl +4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K +oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj +UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU +AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA" +# Serial: 69529181992039203566298953787712940909 +# MD5 Fingerprint: 8c:ca:dc:0b:22:ce:f5:be:72:ac:41:1a:11:a8:d8:12 +# SHA1 Fingerprint: 91:c6:d6:ee:3e:8a:c8:63:84:e5:48:c2:99:29:5c:75:6c:81:7b:81 +# SHA256 Fingerprint: 8d:72:2f:81:a9:c1:13:c0:79:1d:f1:36:a2:96:6d:b2:6c:95:0a:97:1d:b4:6b:41:99:f4:ea:54:b7:8b:fb:9f +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB +qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV +BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw +NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j +LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG +A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs +W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta +3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk +6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 +Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J +NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP +r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU +DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz +YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX +xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 +/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ +LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 +jVaMaA== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Class 3 Public Primary Certification Authority - G5" +# Serial: 33037644167568058970164719475676101450 +# MD5 Fingerprint: cb:17:e4:31:67:3e:e2:09:fe:45:57:93:f3:0a:fa:1c +# SHA1 Fingerprint: 4e:b6:d5:78:49:9b:1c:cf:5f:58:1e:ad:56:be:3d:9b:67:44:a5:e5 +# SHA256 Fingerprint: 9a:cf:ab:7e:43:c8:d8:80:d0:6b:26:2a:94:de:ee:e4:b4:65:99:89:c3:d0:ca:f1:9b:af:64:05:e4:1a:b7:df +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW +ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 +nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex +t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz +SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG +BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ +rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ +NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH +BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv +MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE +p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y +5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK +WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ +4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N +hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----END CERTIFICATE----- + +# Issuer: CN=SecureTrust CA O=SecureTrust Corporation +# Subject: CN=SecureTrust CA O=SecureTrust Corporation +# Label: "SecureTrust CA" +# Serial: 17199774589125277788362757014266862032 +# MD5 Fingerprint: dc:32:c3:a7:6d:25:57:c7:68:09:9d:ea:2d:a9:a2:d1 +# SHA1 Fingerprint: 87:82:c6:c3:04:35:3b:cf:d2:96:92:d2:59:3e:7d:44:d9:34:ff:11 +# SHA256 Fingerprint: f1:c1:b5:0a:e5:a2:0d:d8:03:0e:c9:f6:bc:24:82:3d:d3:67:b5:25:57:59:b4:e7:1b:61:fc:e9:f7:37:5d:73 +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz +MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv +cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz +Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO +0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao +wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj +7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS +8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT +BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg +JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 +6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ +3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm +D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS +CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +# Issuer: CN=Secure Global CA O=SecureTrust Corporation +# Subject: CN=Secure Global CA O=SecureTrust Corporation +# Label: "Secure Global CA" +# Serial: 9751836167731051554232119481456978597 +# MD5 Fingerprint: cf:f4:27:0d:d4:ed:dc:65:16:49:6d:3d:da:bf:6e:de +# SHA1 Fingerprint: 3a:44:73:5a:e5:81:90:1f:24:86:61:46:1e:3b:9c:c4:5f:f5:3a:1b +# SHA256 Fingerprint: 42:00:f5:04:3a:c8:59:0e:bb:52:7d:20:9e:d1:50:30:29:fb:cb:d4:1c:a1:b5:06:ec:27:f1:5a:de:7d:ac:69 +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx +MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg +Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ +iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa +/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ +jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI +HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 +sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w +gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw +KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG +AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L +URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO +H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm +I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY +iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO Certification Authority O=COMODO CA Limited +# Label: "COMODO Certification Authority" +# Serial: 104350513648249232941998508985834464573 +# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75 +# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b +# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66 +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl +YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P +RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 +UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI +2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 +Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp ++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ +DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O +nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW +/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g +PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u +QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY +SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv +IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 +zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd +BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB +ZQ== +-----END CERTIFICATE----- + +# Issuer: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. +# Subject: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. +# Label: "Network Solutions Certificate Authority" +# Serial: 116697915152937497490437556386812487904 +# MD5 Fingerprint: d3:f3:a6:16:c0:fa:6b:1d:59:b1:2d:96:4d:0e:11:2e +# SHA1 Fingerprint: 74:f8:a3:c3:ef:e7:b3:90:06:4b:83:90:3c:21:64:60:20:e5:df:ce +# SHA256 Fingerprint: 15:f0:ba:00:a3:ac:7a:f3:ac:88:4c:07:2b:10:11:a0:77:bd:77:c0:97:f4:01:64:b2:f8:59:8a:bd:83:86:0c +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi +MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV +UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO +ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz +c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP +OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl +mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF +BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 +qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw +gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu +bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp +dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 +6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ +h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH +/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN +pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- + +# Issuer: CN=WellsSecure Public Root Certificate Authority O=Wells Fargo WellsSecure OU=Wells Fargo Bank NA +# Subject: CN=WellsSecure Public Root Certificate Authority O=Wells Fargo WellsSecure OU=Wells Fargo Bank NA +# Label: "WellsSecure Public Root Certificate Authority" +# Serial: 1 +# MD5 Fingerprint: 15:ac:a5:c2:92:2d:79:bc:e8:7f:cb:67:ed:02:cf:36 +# SHA1 Fingerprint: e7:b4:f6:9d:61:ec:90:69:db:7e:90:a7:40:1a:3c:f4:7d:4f:e8:ee +# SHA256 Fingerprint: a7:12:72:ae:aa:a3:cf:e8:72:7f:7f:b3:9f:0f:b3:d1:e5:42:6e:90:60:b0:6e:e6:f1:3e:9a:3c:58:33:cd:43 +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMx +IDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxs +cyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9v +dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcxMjEzMTcwNzU0WhcNMjIxMjE0 +MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdl +bGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQD +DC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+r +WxxTkqxtnt3CxC5FlAM1iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjU +Dk/41itMpBb570OYj7OeUt9tkTmPOL13i0Nj67eT/DBMHAGTthP796EfvyXhdDcs +HqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8bJVhHlfXBIEyg1J55oNj +z7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiBK0HmOFaf +SZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/Slwxl +AgMBAAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqG +KGh0dHA6Ly9jcmwucGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0P +AQH/BAQDAgHGMB0GA1UdDgQWBBQmlRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0j +BIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGBi6SBiDCBhTELMAkGA1UEBhMC +VVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNX +ZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEB +ALkVsUSRzCPIK0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd +/ZDJPHV3V3p9+N701NX3leZ0bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pB +A4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSljqHyita04pO2t/caaH/+Xc/77szWn +k4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+esE2fDbbFwRnzVlhE9 +iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJtylv +2G0xffX8oRAHh84vWdw+WNs= +-----END CERTIFICATE----- + +# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited +# Label: "COMODO ECC Certification Authority" +# Serial: 41578283867086692638256921589707938090 +# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23 +# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11 +# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7 +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT +IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw +MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy +ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N +T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR +FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J +cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW +BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm +fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv +GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +# Issuer: CN=IGC/A O=PM/SGDN OU=DCSSI +# Subject: CN=IGC/A O=PM/SGDN OU=DCSSI +# Label: "IGC/A" +# Serial: 245102874772 +# MD5 Fingerprint: 0c:7f:dd:6a:f4:2a:b9:c8:9b:bd:20:7e:a9:db:5c:37 +# SHA1 Fingerprint: 60:d6:89:74:b5:c2:65:9e:8a:0f:c1:88:7c:88:d2:46:69:1b:18:2c +# SHA256 Fingerprint: b9:be:a7:86:0a:96:2e:a3:61:1d:ab:97:ab:6d:a3:e2:1c:10:68:b9:7d:55:57:5e:d0:e1:12:79:c1:1c:89:32 +-----BEGIN CERTIFICATE----- +MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYT +AkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQ +TS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG +9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMB4XDTAyMTIxMzE0MjkyM1oXDTIw +MTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAM +BgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEO +MAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2 +LmZyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaI +s9z4iPf930Pfeo2aSVz2TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2 +xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCWSo7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4 +u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYyHF2fYPepraX/z9E0+X1b +F8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNdfrGoRpAx +Vs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGd +PDPQtQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNV +HSAEDjAMMAoGCCqBegF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAx +NjAfBgNVHSMEGDAWgBSjBS8YYFDCiQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUF +AAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RKq89toB9RlPhJy3Q2FLwV3duJ +L92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3QMZsyK10XZZOY +YLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg +Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2a +NjSaTFR+FwNIlQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R +0982gaEbeC9xs/FZTEYYKKuF0mBWWg== +-----END CERTIFICATE----- + +# Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication EV RootCA1 +# Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication EV RootCA1 +# Label: "Security Communication EV RootCA1" +# Serial: 0 +# MD5 Fingerprint: 22:2d:a6:01:ea:7c:0a:f7:f0:6c:56:43:3f:77:76:d3 +# SHA1 Fingerprint: fe:b8:c4:32:dc:f9:76:9a:ce:ae:3d:d8:90:8f:fd:28:86:65:64:7d +# SHA256 Fingerprint: a2:2d:ba:68:1e:97:37:6e:2d:39:7d:72:8a:ae:3a:9b:62:96:b9:fd:ba:60:bc:2e:11:f6:47:f2:c6:75:fb:37 +-----BEGIN CERTIFICATE----- +MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMh +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIz +MloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09N +IFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNlY3VyaXR5IENvbW11 +bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSE +RMqm4miO/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gO +zXppFodEtZDkBp2uoQSXWHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5 +bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4zZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDF +MxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4bepJz11sS6/vmsJWXMY1 +VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK9U2vP9eC +OKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HW +tWS3irO4G8za+6xmiEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZ +q51ihPZRwSzJIxXYKLerJRO1RuGGAv8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDb +EJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnWmHyojf6GPgcWkuF75x3sM3Z+ +Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEWT1MKZPlO9L9O +VL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 +-----END CERTIFICATE----- + +# Issuer: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GA CA" +# Serial: 86718877871133159090080555911823548314 +# MD5 Fingerprint: bc:6c:51:33:a7:e9:d3:66:63:54:15:72:1b:21:92:93 +# SHA1 Fingerprint: 59:22:a1:e1:5a:ea:16:35:21:f8:98:39:6a:46:46:b0:44:1b:0f:a9 +# SHA256 Fingerprint: 41:c9:23:86:6a:b4:ca:d6:b7:ad:57:80:81:58:2e:02:07:97:a6:cb:df:4f:ff:78:ce:83:96:b3:89:37:d7:f5 +-----BEGIN CERTIFICATE----- +MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB +ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly +aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w +NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G +A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX +SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR +VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 +w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF +mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg +4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 +4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw +EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx +SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 +ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 +vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa +hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi +Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ +/L7fCg0= +-----END CERTIFICATE----- + +# Issuer: CN=Microsec e-Szigno Root CA O=Microsec Ltd. OU=e-Szigno CA +# Subject: CN=Microsec e-Szigno Root CA O=Microsec Ltd. OU=e-Szigno CA +# Label: "Microsec e-Szigno Root CA" +# Serial: 272122594155480254301341951808045322001 +# MD5 Fingerprint: f0:96:b6:2f:c5:10:d5:67:8e:83:25:32:e8:5e:2e:e5 +# SHA1 Fingerprint: 23:88:c9:d3:71:cc:9e:96:3d:ff:7d:3c:a7:ce:fc:d6:25:ec:19:0d +# SHA256 Fingerprint: 32:7a:3d:76:1a:ba:de:a0:34:eb:99:84:06:27:5c:b1:a4:77:6e:fd:ae:2f:df:6d:01:68:ea:1c:4f:55:67:d0 +-----BEGIN CERTIFICATE----- +MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAw +cjELMAkGA1UEBhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNy +b3NlYyBMdGQuMRQwEgYDVQQLEwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9z +ZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0MDYxMjI4NDRaFw0xNzA0MDYxMjI4 +NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEWMBQGA1UEChMN +TWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMTGU1p +Y3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2u +uO/TEdyB5s87lozWbxXGd36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+ +LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/NoqdNAoI/gqyFxuEPkEeZlApxcpMqyabA +vjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjcQR/Ji3HWVBTji1R4P770 +Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJPqW+jqpx +62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcB +AQRbMFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3Aw +LQYIKwYBBQUHMAKGIWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAP +BgNVHRMBAf8EBTADAQH/MIIBcwYDVR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIB +AQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3LmUtc3ppZ25vLmh1L1NaU1ov +MIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0AdAB2AOEAbgB5 +ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn +AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABT +AHoAbwBsAGcA4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABh +ACAAcwB6AGUAcgBpAG4AdAAgAGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABo +AHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMAegBpAGcAbgBvAC4AaAB1AC8AUwBa +AFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6Ly93d3cuZS1zemln +bm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NOPU1p +Y3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxP +PU1pY3Jvc2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZv +Y2F0aW9uTGlzdDtiaW5hcnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuB +EGluZm9AZS1zemlnbm8uaHWkdzB1MSMwIQYDVQQDDBpNaWNyb3NlYyBlLVN6aWdu +w7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhTWjEWMBQGA1UEChMNTWlj +cm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhVMIGsBgNV +HSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJI +VTERMA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDAS +BgNVBAsTC2UtU3ppZ25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBS +b290IENBghEAzLjnv04pGv2i3GalHCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS +8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMTnGZjWS7KXHAM/IO8VbH0jgds +ZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FEaGAHQzAxQmHl +7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a +86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfR +hUZLphK3dehKyVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/ +MPMMNz7UwiiAc7EBt51alhQBS6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= +-----END CERTIFICATE----- + +# Issuer: CN=Certigna O=Dhimyotis +# Subject: CN=Certigna O=Dhimyotis +# Label: "Certigna" +# Serial: 18364802974209362175 +# MD5 Fingerprint: ab:57:a6:5b:7d:42:82:19:b5:d8:58:26:28:5e:fd:ff +# SHA1 Fingerprint: b1:2e:13:63:45:86:a4:6f:1a:b2:60:68:37:58:2d:c4:ac:fd:94:97 +# SHA256 Fingerprint: e3:b6:a2:db:2e:d7:ce:48:84:2f:7a:c5:32:41:c7:b7:1d:54:14:4b:fb:40:c1:1f:3f:1d:0b:42:f5:ee:a1:2d +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV +BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X +DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ +BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 +QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny +gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw +zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q +130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 +JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw +ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT +AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj +AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG +9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h +bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc +fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu +HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w +t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +# Issuer: CN=AC Raíz Certicámara S.A. O=Sociedad Cameral de Certificación Digital - Certicámara S.A. +# Subject: CN=AC Raíz Certicámara S.A. O=Sociedad Cameral de Certificación Digital - Certicámara S.A. +# Label: "AC Ra\xC3\xADz Certic\xC3\xA1mara S.A." +# Serial: 38908203973182606954752843738508300 +# MD5 Fingerprint: 93:2a:3e:f6:fd:23:69:0d:71:20:d4:2b:47:99:2b:a6 +# SHA1 Fingerprint: cb:a1:c5:f8:b0:e3:5e:b8:b9:45:12:d3:f9:34:a2:e9:06:10:d3:36 +# SHA256 Fingerprint: a6:c5:1e:0d:a5:ca:0a:93:09:d2:e4:c0:e4:0c:2a:f9:10:7a:ae:82:03:85:7f:e1:98:e3:e7:69:e3:43:08:5c +-----BEGIN CERTIFICATE----- +MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsx +CzAJBgNVBAYTAkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRp +ZmljYWNpw7NuIERpZ2l0YWwgLSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwa +QUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4wHhcNMDYxMTI3MjA0NjI5WhcNMzAw +NDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+U29jaWVkYWQgQ2Ft +ZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJhIFMu +QS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeG +qentLhM0R7LQcNzJPNCNyu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzL +fDe3fezTf3MZsGqy2IiKLUV0qPezuMDU2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQ +Y5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU34ojC2I+GdV75LaeHM/J4 +Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP2yYe68yQ +54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+b +MMCm8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48j +ilSH5L887uvDdUhfHjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++Ej +YfDIJss2yKHzMI+ko6Kh3VOz3vCaMh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/zt +A/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK5lw1omdMEWux+IBkAC1vImHF +rEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1bczwmPS9KvqfJ +pxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE +AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCB +lTCBkgYEVR0gADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFy +YS5jb20vZHBjLzBaBggrBgEFBQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW50 +7WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2UgcHVlZGVuIGVuY29udHJhciBlbiBs +YSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEfAygPU3zmpFmps4p6 +xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuXEpBc +unvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/ +Jre7Ir5v/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dp +ezy4ydV/NgIlqmjCMRW3MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42 +gzmRkBDI8ck1fj+404HGIGQatlDCIaR43NAvO2STdPCWkPHv+wlaNECW8DYSwaN0 +jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wkeZBWN7PGKX6jD/EpOe9+ +XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f/RWmnkJD +W2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/ +RL5hRqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35r +MDOhYil/SrnhLecUIw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxk +BYn8eNZcLCZDqQ== +-----END CERTIFICATE----- + +# Issuer: CN=TC TrustCenter Class 2 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 2 CA +# Subject: CN=TC TrustCenter Class 2 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 2 CA +# Label: "TC TrustCenter Class 2 CA II" +# Serial: 941389028203453866782103406992443 +# MD5 Fingerprint: ce:78:33:5c:59:78:01:6e:18:ea:b9:36:a0:b9:2e:23 +# SHA1 Fingerprint: ae:50:83:ed:7c:f4:5c:bc:8f:61:c6:21:fe:68:5d:79:42:21:15:6e +# SHA256 Fingerprint: e6:b8:f8:76:64:85:f8:07:ae:7f:8d:ac:16:70:46:1f:07:c0:a1:3e:ef:3a:1f:f7:17:53:8d:7a:ba:d3:91:b4 +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjEL +MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV +BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 +Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYwMTEyMTQzODQzWhcNMjUxMjMxMjI1 +OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i +SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UEAxMc +VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jf +tMjWQ+nEdVl//OEd+DFwIxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKg +uNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2J +XjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQXa7pIXSSTYtZgo+U4+lK +8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7uSNQZu+99 +5OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3 +kUrL84J6E1wIqzCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy +dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6 +Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz +JTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 +Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u +TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iS +GNn3Bzn1LL4GdXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprt +ZjluS5TmVfwLG4t3wVMTZonZKNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8 +au0WOB9/WIFaGusyiC2y8zl3gK9etmF1KdsjTYjKUCjLhdLTEKJZbtOTVAB6okaV +hgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kPJOzHdiEoZa5X6AeI +dUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfkvQ== +-----END CERTIFICATE----- + +# Issuer: CN=TC TrustCenter Class 3 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 3 CA +# Subject: CN=TC TrustCenter Class 3 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 3 CA +# Label: "TC TrustCenter Class 3 CA II" +# Serial: 1506523511417715638772220530020799 +# MD5 Fingerprint: 56:5f:aa:80:61:12:17:f6:67:21:e6:2b:6d:61:56:8e +# SHA1 Fingerprint: 80:25:ef:f4:6e:70:c8:d4:72:24:65:84:fe:40:3b:8a:8d:6a:db:f5 +# SHA256 Fingerprint: 8d:a0:84:fc:f9:9c:e0:77:22:f8:9b:32:05:93:98:06:fa:5c:b8:11:e1:c8:13:f6:a1:08:c7:d3:36:b3:40:8e +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjEL +MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV +BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 +Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYwMTEyMTQ0MTU3WhcNMjUxMjMxMjI1 +OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i +SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UEAxMc +VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJW +Ht4bNwcwIi9v8Qbxq63WyKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+Q +Vl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo6SI7dYnWRBpl8huXJh0obazovVkdKyT2 +1oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZuV3bOx4a+9P/FRQI2Alq +ukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk2ZyqBwi1 +Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NX +XAek0CSnwPIA1DCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy +dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6 +Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz +JTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 +Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u +TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlN +irTzwppVMXzEO2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8 +TtXqluJucsG7Kv5sbviRmEb8yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6 +g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9IJqDnxrcOfHFcqMRA/07QlIp2+gB +95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal092Y+tTmBvTwtiBj +S+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc5A== +-----END CERTIFICATE----- + +# Issuer: CN=TC TrustCenter Universal CA I O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA +# Subject: CN=TC TrustCenter Universal CA I O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA +# Label: "TC TrustCenter Universal CA I" +# Serial: 601024842042189035295619584734726 +# MD5 Fingerprint: 45:e1:a5:72:c5:a9:36:64:40:9e:f5:e4:58:84:67:8c +# SHA1 Fingerprint: 6b:2f:34:ad:89:58:be:62:fd:b0:6b:5c:ce:bb:9d:d9:4f:4e:39:f3 +# SHA256 Fingerprint: eb:f3:c0:2a:87:89:b1:fb:7d:51:19:95:d6:63:b7:29:06:d9:13:ce:0d:5e:10:56:8a:8a:77:e2:58:61:67:e7 +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTEL +MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV +BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1 +c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcNMDYwMzIyMTU1NDI4WhcNMjUxMjMx +MjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIg +R21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYwJAYD +VQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSR +JJZ4Hgmgm5qVSkr1YnwCqMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3T +fCZdzHd55yx4Oagmcw6iXSVphU9VDprvxrlE4Vc93x9UIuVvZaozhDrzznq+VZeu +jRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtwag+1m7Z3W0hZneTvWq3z +wZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9OgdwZu5GQ +fezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYD +VR0jBBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0G +CSqGSIb3DQEBBQUAA4IBAQAo0uCG1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X1 +7caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/CyvwbZ71q+s2IhtNerNXxTPqYn +8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3ghUJGooWMNjs +ydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT +ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/ +2TYcuiUaUj0a7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY +-----END CERTIFICATE----- + +# Issuer: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center +# Subject: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center +# Label: "Deutsche Telekom Root CA 2" +# Serial: 38 +# MD5 Fingerprint: 74:01:4a:91:b1:08:c4:58:ce:47:cd:f0:dd:11:53:08 +# SHA1 Fingerprint: 85:a4:08:c0:9c:19:3e:5d:51:58:7d:cd:d6:13:30:fd:8c:de:37:bf +# SHA256 Fingerprint: b6:19:1a:50:d0:c3:97:7f:7d:a9:9b:cd:aa:c8:6a:22:7d:ae:b9:67:9e:c7:0b:a3:b0:c9:d9:22:71:c1:70:d3 +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc +MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj +IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB +IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE +RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl +U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 +IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU +ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC +QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr +rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S +NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc +QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH +txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP +BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC +AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp +tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa +IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl +6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ +xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU +Cm26OWMohpLzGITY+9HPBVZkVw== +-----END CERTIFICATE----- + +# Issuer: CN=ComSign Secured CA O=ComSign +# Subject: CN=ComSign Secured CA O=ComSign +# Label: "ComSign Secured CA" +# Serial: 264725503855295744117309814499492384489 +# MD5 Fingerprint: 40:01:25:06:8d:21:43:6a:0e:43:00:9c:e7:43:f3:d5 +# SHA1 Fingerprint: f9:cd:0e:2c:da:76:24:c1:8f:bd:f0:f0:ab:b6:45:b8:f7:fe:d5:7a +# SHA256 Fingerprint: 50:79:41:c7:44:60:a0:b4:70:86:22:0d:4e:99:32:57:2a:b5:d1:b5:bb:cb:89:80:ab:1c:b1:76:51:a8:44:d2 +-----BEGIN CERTIFICATE----- +MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAw +PDEbMBkGA1UEAxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWdu +MQswCQYDVQQGEwJJTDAeFw0wNDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwx +GzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjEL +MAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGtWhf +HZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs49oh +gHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sW +v+bznkqH7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ue +Mv5WJDmyVIRD9YTC2LxBkMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr +9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d19guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt +6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUwAwEB/zBEBgNVHR8EPTA7 +MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29tU2lnblNl +Y3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58 +ADsAj8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkq +hkiG9w0BAQUFAAOCAQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7p +iL1DRYHjZiM/EoZNGeQFsOY3wo3aBijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtC +dsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtpFhpFfTMDZflScZAmlaxMDPWL +kz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP51qJThRv4zdL +hfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz +OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== +-----END CERTIFICATE----- + +# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc +# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc +# Label: "Cybertrust Global Root" +# Serial: 4835703278459682877484360 +# MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1 +# SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6 +# SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3 +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG +A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh +bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE +ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS +b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5 +7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS +J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y +HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP +t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz +FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY +XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ +MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw +hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js +MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA +A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj +Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx +XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o +omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc +A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----END CERTIFICATE----- + +# Issuer: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority +# Subject: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority +# Label: "ePKI Root Certification Authority" +# Serial: 28956088682735189655030529057352760477 +# MD5 Fingerprint: 1b:2e:00:ca:26:06:90:3d:ad:fe:6f:15:68:d3:6b:b3 +# SHA1 Fingerprint: 67:65:0d:f1:7e:8e:7e:5b:82:40:a4:f4:56:4b:cf:e2:3d:69:c6:f0 +# SHA256 Fingerprint: c0:a6:f4:dc:63:a2:4b:fd:cf:54:ef:2a:6a:08:2a:0a:72:de:35:80:3e:2f:f5:ff:52:7a:e5:d8:72:06:df:d5 +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe +MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 +ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw +IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL +SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH +SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh +ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X +DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 +TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ +fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA +sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU +WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS +nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH +dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip +NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC +AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF +MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB +uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl +PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP +JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ +gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 +j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 +5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB +o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS +/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z +Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE +W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D +hNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +# Issuer: CN=TÜBİTAK UEKAE Kök Sertifika Hizmet Sağlayıcısı - Sürüm 3 O=Türkiye Bilimsel ve Teknolojik Araştırma Kurumu - TÜBİTAK OU=Ulusal Elektronik ve Kriptoloji Araştırma Enstitüsü - UEKAE/Kamu Sertifikasyon Merkezi +# Subject: CN=TÜBİTAK UEKAE Kök Sertifika Hizmet Sağlayıcısı - Sürüm 3 O=Türkiye Bilimsel ve Teknolojik Araştırma Kurumu - TÜBİTAK OU=Ulusal Elektronik ve Kriptoloji Araştırma Enstitüsü - UEKAE/Kamu Sertifikasyon Merkezi +# Label: "T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3" +# Serial: 17 +# MD5 Fingerprint: ed:41:f5:8c:50:c5:2b:9c:73:e6:ee:6c:eb:c2:a8:26 +# SHA1 Fingerprint: 1b:4b:39:61:26:27:6b:64:91:a2:68:6d:d7:02:43:21:2d:1f:1d:96 +# SHA256 Fingerprint: e4:c7:34:30:d7:a5:b5:09:25:df:43:37:0a:0d:21:6e:9a:79:b9:d6:db:83:73:a0:c6:9e:b1:cc:31:c7:c5:2a +-----BEGIN CERTIFICATE----- +MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRS +MRgwFgYDVQQHDA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJp +bGltc2VsIHZlIFRla25vbG9qaWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSw +VEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ryb25payB2ZSBLcmlwdG9sb2ppIEFy +YcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNVBAsMGkthbXUgU2Vy +dGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUgS8O2 +ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAe +Fw0wNzA4MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIx +GDAWBgNVBAcMD0dlYnplIC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmls +aW1zZWwgdmUgVGVrbm9sb2ppayBBcmHFn3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBU +QUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZlIEtyaXB0b2xvamkgQXJh +xZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2FtdSBTZXJ0 +aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7Zr +IFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4h +gb46ezzb8R1Sf1n68yJMlaCQvEhOEav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yK +O7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1xnnRFDDtG1hba+818qEhTsXO +fJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR6Oqeyjh1jmKw +lZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL +hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQID +AQABo0IwQDAdBgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/ +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmP +NOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4N5EY3ATIZJkrGG2AA1nJrvhY0D7t +wyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLTy9LQQfMmNkqblWwM +7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYhLBOh +gLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5n +oN+J1q2MdqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUs +yZyQ2uypQjyttgI= +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 2 CA 1 O=Buypass AS-983163327 +# Subject: CN=Buypass Class 2 CA 1 O=Buypass AS-983163327 +# Label: "Buypass Class 2 CA 1" +# Serial: 1 +# MD5 Fingerprint: b8:08:9a:f0:03:cc:1b:0d:c8:6c:0b:76:a1:75:64:23 +# SHA1 Fingerprint: a0:a1:ab:90:c9:fc:84:7b:3b:12:61:e8:97:7d:5f:d3:22:61:d3:cc +# SHA256 Fingerprint: 0f:4e:9c:dd:26:4b:02:55:50:d1:70:80:63:40:21:4f:e9:44:34:c9:b0:2f:69:7e:c7:10:fc:5f:ea:fb:5e:38 +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg +Q2xhc3MgMiBDQSAxMB4XDTA2MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzEL +MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD +VQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7McXA0 +ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLX +l18xoS830r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVB +HfCuuCkslFJgNJQ72uA40Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B +5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/RuFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3 +WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0PAQH/BAQD +AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLP +gcIV1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+ +DKhQ7SLHrQVMdvvt7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKu +BctN518fV4bVIJwo+28TOPX2EZL2fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHs +h7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5wwDX3OaJdZtB7WZ+oRxKaJyOk +LY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 3 CA 1 O=Buypass AS-983163327 +# Subject: CN=Buypass Class 3 CA 1 O=Buypass AS-983163327 +# Label: "Buypass Class 3 CA 1" +# Serial: 2 +# MD5 Fingerprint: df:3c:73:59:81:e7:39:50:81:04:4c:34:a2:cb:b3:7b +# SHA1 Fingerprint: 61:57:3a:11:df:0e:d8:7e:d5:92:65:22:ea:d0:56:d7:44:b3:23:71 +# SHA256 Fingerprint: b7:b1:2b:17:1f:82:1d:aa:99:0c:d0:fe:50:87:b1:28:44:8b:a8:e5:18:4f:84:c5:1e:02:b5:c8:fb:96:2b:24 +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg +Q2xhc3MgMyBDQSAxMB4XDTA1MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzEL +MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD +VQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKxifZg +isRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//z +NIqeKNc0n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI ++MkcVyzwPX6UvCWThOiaAJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2R +hzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+ +mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0PAQH/BAQD +AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFP +Bdy7pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27s +EzNxZy5p+qksP2bAEllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2 +mSlf56oBzKwzqBwKu5HEA6BvtjT5htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yC +e/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQjel/wroQk5PMr+4okoyeYZdow +dXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 +-----END CERTIFICATE----- + +# Issuer: CN=EBG Elektronik Sertifika Hizmet Sağlayıcısı O=EBG Bilişim Teknolojileri ve Hizmetleri A.Ş. +# Subject: CN=EBG Elektronik Sertifika Hizmet Sağlayıcısı O=EBG Bilişim Teknolojileri ve Hizmetleri A.Ş. +# Label: "EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1" +# Serial: 5525761995591021570 +# MD5 Fingerprint: 2c:20:26:9d:cb:1a:4a:00:85:b5:b7:5a:ae:c2:01:37 +# SHA1 Fingerprint: 8c:96:ba:eb:dd:2b:07:07:48:ee:30:32:66:a0:f3:98:6e:7c:ae:58 +# SHA256 Fingerprint: 35:ae:5b:dd:d8:f7:ae:63:5c:ff:ba:56:82:a8:f0:0b:95:f4:84:62:c7:10:8e:e9:a0:e5:29:2b:07:4a:af:b2 +-----BEGIN CERTIFICATE----- +MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNV +BAMML0VCRyBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx +c8SxMTcwNQYDVQQKDC5FQkcgQmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXpt +ZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAeFw0wNjA4MTcwMDIxMDlaFw0xNjA4 +MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25payBTZXJ0aWZpa2Eg +SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2ltIFRl +a25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h +4fuXd7hxlugTlkaDT7byX3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAk +tiHq6yOU/im/+4mRDGSaBUorzAzu8T2bgmmkTPiab+ci2hC6X5L8GCcKqKpE+i4s +tPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfreYteIAbTdgtsApWjluTL +dlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZTqNGFav4 +c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8Um +TDGyY5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z ++kI2sSXFCjEmN1ZnuqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0O +Lna9XvNRiYuoP1Vzv9s6xiQFlpJIqkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMW +OeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vmExH8nYQKE3vwO9D8owrXieqW +fo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0Nokb+Clsi7n2 +l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgw +FoAU587GT/wWZ5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+ +8ygjdsZs93/mQJ7ANtyVDR2tFcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI +6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgmzJNSroIBk5DKd8pNSe/iWtkqvTDO +TLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64kXPBfrAowzIpAoHME +wfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqTbCmY +Iai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJn +xk1Gj7sURT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4Q +DgZxGhBM/nV+/x5XOULK1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9q +Kd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11t +hie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQY9iJSrSq3RZj9W6+YKH4 +7ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9AahH3eU7 +QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT +-----END CERTIFICATE----- + +# Issuer: O=certSIGN OU=certSIGN ROOT CA +# Subject: O=certSIGN OU=certSIGN ROOT CA +# Label: "certSIGN ROOT CA" +# Serial: 35210227249154 +# MD5 Fingerprint: 18:98:c0:d6:e9:3a:fc:f9:b0:f5:0c:f7:4b:01:44:17 +# SHA1 Fingerprint: fa:b7:ee:36:97:26:62:fb:2d:b0:2a:f6:bf:03:fd:e8:7c:4b:2f:9b +# SHA256 Fingerprint: ea:a9:62:c4:fa:4a:6b:af:eb:e4:15:19:6d:35:1c:cd:88:8d:4f:53:f3:fa:8a:e6:d7:c4:66:a9:4e:60:42:bb +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT +AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD +QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP +MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do +0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ +UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d +RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ +OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv +JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C +AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O +BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ +LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY +MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ +44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I +Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw +i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN +9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +# Issuer: CN=CNNIC ROOT O=CNNIC +# Subject: CN=CNNIC ROOT O=CNNIC +# Label: "CNNIC ROOT" +# Serial: 1228079105 +# MD5 Fingerprint: 21:bc:82:ab:49:c4:13:3b:4b:b2:2b:5c:6b:90:9c:19 +# SHA1 Fingerprint: 8b:af:4c:9b:1d:f0:2a:92:f7:da:12:8e:b9:1b:ac:f4:98:60:4b:6f +# SHA256 Fingerprint: e2:83:93:77:3d:a8:45:a6:79:f2:08:0c:c7:fb:44:a3:b7:a1:c3:79:2c:b7:eb:77:29:fd:cb:6a:8d:99:ae:a7 +-----BEGIN CERTIFICATE----- +MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJD +TjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2 +MDcwOTE0WhcNMjcwNDE2MDcwOTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMF +Q05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzDo+/hn7E7SIX1mlwh +IhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tizVHa6 +dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZO +V/kbZKKTVrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrC +GHn2emU1z5DrvTOTn1OrczvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gN +v7Sg2Ca+I19zN38m5pIEo3/PIKe38zrKy5nLAgMBAAGjczBxMBEGCWCGSAGG+EIB +AQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscCwQ7vptU7ETAPBgNVHRMB +Af8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991SlgrHAsEO +76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnK +OOK5Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvH +ugDnuL8BV8F3RTIMO/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7Hgvi +yJA/qIYM/PmLXoXLT1tLYhFHxUV8BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fL +buXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2G8kS1sHNzYDzAgE8yGnLRUhj +2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5mmxE= +-----END CERTIFICATE----- + +# Issuer: O=Japanese Government OU=ApplicationCA +# Subject: O=Japanese Government OU=ApplicationCA +# Label: "ApplicationCA - Japanese Government" +# Serial: 49 +# MD5 Fingerprint: 7e:23:4e:5b:a7:a5:b4:25:e9:00:07:74:11:62:ae:d6 +# SHA1 Fingerprint: 7f:8a:b0:cf:d0:51:87:6a:66:f3:36:0f:47:c8:8d:8c:d3:35:fc:74 +# SHA256 Fingerprint: 2d:47:43:7d:e1:79:51:21:5a:12:f3:c5:8e:51:c7:29:a5:80:26:ef:1f:cc:0a:5f:b3:d9:dc:01:2f:60:0d:19 +-----BEGIN CERTIFICATE----- +MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEc +MBoGA1UEChMTSmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRp +b25DQTAeFw0wNzEyMTIxNTAwMDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYT +AkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zlcm5tZW50MRYwFAYDVQQLEw1BcHBs +aWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp23gdE6H +j6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4fl+K +f5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55 +IrmTwcrNwVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cw +FO5cjFW6WY2H/CPek9AEjP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDiht +QWEjdnjDuGWk81quzMKq2edY3rZ+nYVunyoKb58DKTCXKB28t89UKU5RMfkntigm +/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRUWssmP3HMlEYNllPqa0jQ +k/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNVBAYTAkpQ +MRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOC +seODvOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADlqRHZ3ODrso2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJ +hyzjVOGjprIIC8CFqMjSnHH2HZ9g/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+ +eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYDio+nEhEMy/0/ecGc/WLuo89U +DNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmWdupwX3kSa+Sj +B1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL +rosot4LKGAfmt1t06SAZf7IbiVQ= +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only +# Subject: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only +# Label: "GeoTrust Primary Certification Authority - G3" +# Serial: 28809105769928564313984085209975885599 +# MD5 Fingerprint: b5:e8:34:36:c9:10:44:58:48:70:6d:2e:83:d4:b8:05 +# SHA1 Fingerprint: 03:9e:ed:b8:0b:e7:a0:3c:69:53:89:3b:20:d2:d9:32:3a:4c:2a:fd +# SHA256 Fingerprint: b4:78:b8:12:25:0d:f8:78:63:5c:2a:a7:ec:7d:15:5e:aa:62:5e:e8:29:16:e2:cd:29:43:61:88:6c:d1:fb:d4 +-----BEGIN CERTIFICATE----- +MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB +mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT +MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ +BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg +MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 +BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz ++uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm +hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn +5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W +JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL +DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC +huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB +AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB +zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN +kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD +AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH +SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G +spki4cErx5z481+oghLrGREt +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA - G2" +# Serial: 71758320672825410020661621085256472406 +# MD5 Fingerprint: 74:9d:ea:60:24:c4:fd:22:53:3e:cc:3a:72:d9:29:4f +# SHA1 Fingerprint: aa:db:bc:22:23:8f:c4:01:a1:27:bb:38:dd:f4:1d:db:08:9e:f0:12 +# SHA256 Fingerprint: a4:31:0d:50:af:18:a6:44:71:90:37:2a:86:af:af:8b:95:1f:fb:43:1d:83:7f:1e:56:88:b4:59:71:ed:15:57 +-----BEGIN CERTIFICATE----- +MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp +IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi +BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw +MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh +d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig +YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v +dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ +BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 +papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K +DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 +KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox +XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA - G3" +# Serial: 127614157056681299805556476275995414779 +# MD5 Fingerprint: fb:1b:5d:43:8a:94:cd:44:c6:76:f2:43:4b:47:e7:31 +# SHA1 Fingerprint: f1:8b:53:8d:1b:e9:03:b6:a6:f0:56:43:5b:17:15:89:ca:f3:6b:f2 +# SHA256 Fingerprint: 4b:03:f4:58:07:ad:70:f2:1b:fc:2c:ae:71:c9:fd:e4:60:4c:06:4c:f5:ff:b6:86:ba:e5:db:aa:d7:fd:d3:4c +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB +rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV +BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa +Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl +LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u +MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl +ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm +gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 +YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf +b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 +9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S +zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk +OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV +HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA +2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW +oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu +t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c +KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM +m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu +MdRAGmI0Nj81Aa6sY6A= +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only +# Subject: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only +# Label: "GeoTrust Primary Certification Authority - G2" +# Serial: 80682863203381065782177908751794619243 +# MD5 Fingerprint: 01:5e:d8:6b:bd:6f:3d:8e:a1:31:f8:12:e0:98:73:6a +# SHA1 Fingerprint: 8d:17:84:d5:37:f3:03:7d:ec:70:fe:57:8b:51:9a:99:e6:10:d7:b0 +# SHA256 Fingerprint: 5e:db:7a:c4:3b:82:a0:6a:87:61:e8:d7:be:49:79:eb:f2:61:1f:7d:d7:9b:f9:1c:1c:6b:56:6a:21:9e:d7:66 +-----BEGIN CERTIFICATE----- +MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL +MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj +KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 +MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw +NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV +BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH +MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL +So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal +tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG +CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT +qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz +rD6ogRLQy7rQkgu2npaqBA+K +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Universal Root Certification Authority" +# Serial: 85209574734084581917763752644031726877 +# MD5 Fingerprint: 8e:ad:b5:01:aa:4d:81:e4:8c:1d:d1:e1:14:00:95:19 +# SHA1 Fingerprint: 36:79:ca:35:66:87:72:30:4d:30:a5:fb:87:3b:0f:a7:7b:b7:0d:54 +# SHA256 Fingerprint: 23:99:56:11:27:a5:71:25:de:8c:ef:ea:61:0d:df:2f:a0:78:b5:c8:06:7f:4e:82:82:90:bf:b8:60:e8:4b:3c +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB +vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W +ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX +MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 +IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y +IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh +bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF +9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH +H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H +LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN +/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT +rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw +WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs +exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud +DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 +sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ +seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz +4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ +BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR +lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 +7M2CYfE45k+XmCpajQ== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Class 3 Public Primary Certification Authority - G4" +# Serial: 63143484348153506665311985501458640051 +# MD5 Fingerprint: 3a:52:e1:e7:fd:6f:3a:e3:6f:f3:6f:99:1b:f9:22:41 +# SHA1 Fingerprint: 22:d5:d8:df:8f:02:31:d1:8d:f7:9d:b7:cf:8a:2d:64:c9:3f:6c:3a +# SHA256 Fingerprint: 69:dd:d7:ea:90:bb:57:c9:3e:13:5d:c8:5e:a6:fc:d5:48:0b:60:32:39:bd:c4:54:fc:75:8b:2a:26:cf:7f:79 +-----BEGIN CERTIFICATE----- +MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp +U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg +SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln +biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm +GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve +fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ +aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj +aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW +kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC +4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga +FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== +-----END CERTIFICATE----- + +# Issuer: CN=NetLock Arany (Class Gold) Főtanúsítvány O=NetLock Kft. OU=Tanúsítványkiadók (Certification Services) +# Subject: CN=NetLock Arany (Class Gold) Főtanúsítvány O=NetLock Kft. OU=Tanúsítványkiadók (Certification Services) +# Label: "NetLock Arany (Class Gold) Főtanúsítvány" +# Serial: 80544274841616 +# MD5 Fingerprint: c5:a1:b7:ff:73:dd:d6:d7:34:32:18:df:fc:3c:ad:88 +# SHA1 Fingerprint: 06:08:3f:59:3f:15:a1:04:a0:69:a4:6b:a9:03:d0:06:b7:97:09:91 +# SHA256 Fingerprint: 6c:61:da:c3:a2:de:f0:31:50:6b:e0:36:d2:a6:fe:40:19:94:fb:d1:3d:f9:c8:d4:66:59:92:74:c4:46:ec:98 +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG +EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 +MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl +cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR +dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB +pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM +b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm +aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz +IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT +lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz +AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 +VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG +ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 +BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG +AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M +U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh +bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C ++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F +uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 +XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +# Issuer: CN=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden +# Label: "Staat der Nederlanden Root CA - G2" +# Serial: 10000012 +# MD5 Fingerprint: 7c:a5:0f:f8:5b:9a:7d:6d:30:ae:54:5a:e3:42:a2:8a +# SHA1 Fingerprint: 59:af:82:79:91:86:c7:b4:75:07:cb:cf:03:57:46:eb:04:dd:b7:16 +# SHA256 Fingerprint: 66:8c:83:94:7d:a6:3b:72:4b:ec:e1:74:3c:31:a0:e6:ae:d0:db:8e:c5:b3:1b:e3:77:bb:78:4f:91:b6:71:6f +-----BEGIN CERTIFICATE----- +MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX +DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl +ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv +b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 +qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp +uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU +Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE +pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp +5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M +UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN +GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy +5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv +6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK +eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 +B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ +BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov +L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG +SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS +CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen +5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 +IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK +gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL ++63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL +vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm +bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk +N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC +Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z +ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== +-----END CERTIFICATE----- + +# Issuer: CN=CA Disig O=Disig a.s. +# Subject: CN=CA Disig O=Disig a.s. +# Label: "CA Disig" +# Serial: 1 +# MD5 Fingerprint: 3f:45:96:39:e2:50:87:f7:bb:fe:98:0c:3c:20:98:e6 +# SHA1 Fingerprint: 2a:c8:d5:8b:57:ce:bf:2f:49:af:f2:fc:76:8f:51:14:62:90:7a:41 +# SHA256 Fingerprint: 92:bf:51:19:ab:ec:ca:d0:b1:33:2d:c4:e1:d0:5f:ba:75:b5:67:90:44:ee:0c:a2:6e:93:1f:74:4f:2f:33:cf +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzET +MBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UE +AxMIQ0EgRGlzaWcwHhcNMDYwMzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQsw +CQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcg +YS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgmGErE +Nx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnX +mjxUizkDPw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYD +XcDtab86wYqg6I7ZuUUohwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhW +S8+2rT+MitcE5eN4TPWGqvWP+j1scaMtymfraHtuM6kMgiioTGohQBUgDCZbg8Kp +FhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8wgfwwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0PAQH/BAQD +AgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cu +ZGlzaWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5z +ay9jYS9jcmwvY2FfZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2sv +Y2EvY3JsL2NhX2Rpc2lnLmNybDAaBgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEw +DQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59tWDYcPQuBDRIrRhCA/ec8J9B6 +yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3mkkp7M5+cTxq +EEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ +CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeB +EicTXxChds6KezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFN +PGO+I++MzVpQuGhU+QqZMxEA4Z7CRneC9VkGjCFMhwnN5ag= +-----END CERTIFICATE----- + +# Issuer: CN=Juur-SK O=AS Sertifitseerimiskeskus +# Subject: CN=Juur-SK O=AS Sertifitseerimiskeskus +# Label: "Juur-SK" +# Serial: 999181308 +# MD5 Fingerprint: aa:8e:5d:d9:f8:db:0a:58:b7:8d:26:87:6c:82:35:55 +# SHA1 Fingerprint: 40:9d:4b:d9:17:b5:5c:27:b6:9b:64:cb:98:22:44:0d:cd:09:b8:89 +# SHA256 Fingerprint: ec:c3:e9:c3:40:75:03:be:e0:91:aa:95:2f:41:34:8f:f8:8b:aa:86:3b:22:64:be:fa:c8:07:90:15:74:e9:39 +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcN +AQkBFglwa2lAc2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZp +dHNlZXJpbWlza2Vza3VzMRAwDgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMw +MVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMQsw +CQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEQ +MA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOB +SvZiF3tfTQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkz +ABpTpyHhOEvWgxutr2TC+Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvH +LCu3GFH+4Hv2qEivbDtPL+/40UceJlfwUR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMP +PbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDaTpxt4brNj3pssAki14sL +2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQFMAMBAf8w +ggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwIC +MIHDHoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDk +AGwAagBhAHMAdABhAHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0 +AHMAZQBlAHIAaQBtAGkAcwBrAGUAcwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABz +AGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABrAGkAbgBuAGkAdABhAG0AaQBz +AGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nwcy8wKwYDVR0f +BCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE +FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcY +P2/v6X2+MA4GA1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOi +CfP+JmeaUOTDBS8rNXiRTHyoERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+g +kcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyLabVAyJRld/JXIWY7zoVAtjNjGr95 +HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678IIbsSt4beDI3poHS +na9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkhMp6q +qIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0Z +TbvGRNs2yyqcjg== +-----END CERTIFICATE----- + +# Issuer: CN=Hongkong Post Root CA 1 O=Hongkong Post +# Subject: CN=Hongkong Post Root CA 1 O=Hongkong Post +# Label: "Hongkong Post Root CA 1" +# Serial: 1000 +# MD5 Fingerprint: a8:0d:6f:39:78:b9:43:6d:77:42:6d:98:5a:cc:23:ca +# SHA1 Fingerprint: d6:da:a8:20:8d:09:d2:15:4d:24:b5:2f:cb:34:6e:b2:58:b2:8a:58 +# SHA256 Fingerprint: f9:e6:7d:33:6c:51:00:2a:c0:54:c6:32:02:2d:66:dd:a2:e7:e3:ff:f1:0a:d0:61:ed:31:d8:bb:b4:10:cf:b2 +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx +FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg +Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG +A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr +b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ +jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn +PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh +ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 +nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h +q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED +MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC +mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 +7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB +oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs +EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO +fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi +AmvZWg== +-----END CERTIFICATE----- + +# Issuer: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. +# Subject: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. +# Label: "SecureSign RootCA11" +# Serial: 1 +# MD5 Fingerprint: b7:52:74:e2:92:b4:80:93:f2:75:e4:cc:d7:f2:ea:26 +# SHA1 Fingerprint: 3b:c4:9f:48:f8:f3:73:a0:9c:1e:bd:f8:5b:b1:c3:65:c7:d8:11:b3 +# SHA256 Fingerprint: bf:0f:ee:fb:9e:3a:58:1a:d5:f9:e9:db:75:89:98:57:43:d2:61:08:5c:4d:31:4f:6f:5d:72:59:aa:42:16:12 +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr +MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG +A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 +MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp +Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD +QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz +i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8 +h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV +MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9 +UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni +8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC +h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD +VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB +AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm +KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ +X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr +QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5 +pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN +QSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +# Issuer: CN=ACEDICOM Root O=EDICOM OU=PKI +# Subject: CN=ACEDICOM Root O=EDICOM OU=PKI +# Label: "ACEDICOM Root" +# Serial: 7029493972724711941 +# MD5 Fingerprint: 42:81:a0:e2:1c:e3:55:10:de:55:89:42:65:96:22:e6 +# SHA1 Fingerprint: e0:b4:32:2e:b2:f6:a5:68:b6:54:53:84:48:18:4a:50:36:87:43:84 +# SHA256 Fingerprint: 03:95:0f:b4:9a:53:1f:3e:19:91:94:23:98:df:a9:e0:ea:32:d7:ba:1c:dd:9b:c8:5d:b5:7e:d9:40:0b:43:4a +-----BEGIN CERTIFICATE----- +MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UE +AwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00x +CzAJBgNVBAYTAkVTMB4XDTA4MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEW +MBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZF +RElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC +AgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHkWLn7 +09gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7 +XBZXehuDYAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5P +Grjm6gSSrj0RuVFCPYewMYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAK +t0SdE3QrwqXrIhWYENiLxQSfHY9g5QYbm8+5eaA9oiM/Qj9r+hwDezCNzmzAv+Yb +X79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbkHQl/Sog4P75n/TSW9R28 +MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTTxKJxqvQU +fecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI +2Sf23EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyH +K9caUPgn6C9D4zq92Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEae +ZAwUswdbxcJzbPEHXEUkFDWug/FqTYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAP +BgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz4SsrSbbXc6GqlPUB53NlTKxQ +MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU9QHnc2VMrFAw +RAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv +bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWIm +fQwng4/F9tqgaHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3 +gvoFNTPhNahXwOf9jU8/kzJPeGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKe +I6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1PwkzQSulgUV1qzOMPPKC8W64iLgpq0i +5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1ThCojz2GuHURwCRi +ipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oIKiMn +MCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZ +o5NjEFIqnxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6 +zqylfDJKZ0DcMDQj3dcEI2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacN +GHk0vFQYXlPKNFHtRQrmjseCNj6nOGOpMCwXEGCSn1WHElkQwg9naRHMTh5+Spqt +r0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3otkYNbn5XOmeUwssfnHdK +Z05phkOTOPu220+DkdRgfks+KzgHVZhepA== +-----END CERTIFICATE----- + +# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority +# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority +# Label: "Verisign Class 3 Public Primary Certification Authority" +# Serial: 80507572722862485515306429940691309246 +# MD5 Fingerprint: ef:5a:f1:33:ef:f1:cd:bb:51:02:ee:12:14:4b:96:c4 +# SHA1 Fingerprint: a1:db:63:93:91:6f:17:e4:18:55:09:40:04:15:c7:02:40:b0:ae:6b +# SHA256 Fingerprint: a4:b6:b3:99:6f:c2:f3:06:b3:fd:86:81:bd:63:41:3d:8c:50:09:cc:4f:a3:29:c2:cc:f0:e2:fa:1b:14:03:05 +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE +BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is +I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G +CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i +2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ +2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ +-----END CERTIFICATE----- + +# Issuer: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. +# Subject: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. +# Label: "Microsec e-Szigno Root CA 2009" +# Serial: 14014712776195784473 +# MD5 Fingerprint: f8:49:f4:03:bc:44:2d:83:be:48:69:7d:29:64:fc:b1 +# SHA1 Fingerprint: 89:df:74:fe:5c:f4:0f:4a:80:f9:e3:37:7d:54:da:91:e1:01:31:8e +# SHA256 Fingerprint: 3c:5f:81:fe:a5:fa:b8:2c:64:bf:a2:ea:ec:af:cd:e8:e0:77:fc:86:20:a7:ca:e5:37:16:3d:f3:6e:db:f3:78 +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD +VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 +ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G +CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y +OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx +FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp +Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP +kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc +cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U +fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 +N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC +xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 ++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM +Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG +SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h +mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk +ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c +2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t +HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +# Issuer: CN=e-Guven Kok Elektronik Sertifika Hizmet Saglayicisi O=Elektronik Bilgi Guvenligi A.S. +# Subject: CN=e-Guven Kok Elektronik Sertifika Hizmet Saglayicisi O=Elektronik Bilgi Guvenligi A.S. +# Label: "E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi" +# Serial: 91184789765598910059173000485363494069 +# MD5 Fingerprint: 3d:41:29:cb:1e:aa:11:74:cd:5d:b0:62:af:b0:43:5b +# SHA1 Fingerprint: dd:e1:d2:a9:01:80:2e:1d:87:5e:84:b3:80:7e:4b:b1:fd:99:41:34 +# SHA256 Fingerprint: e6:09:07:84:65:a4:19:78:0c:b6:ac:4c:1c:0b:fb:46:53:d9:d9:cc:6e:b3:94:6e:b7:f3:d6:99:97:ba:d5:98 +-----BEGIN CERTIFICATE----- +MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1 +MQswCQYDVQQGEwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxp +Z2kgQS5TLjE8MDoGA1UEAxMzZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZp +a2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3MDEwNDExMzI0OFoXDTE3MDEwNDEx +MzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0cm9uaWsgQmlsZ2kg +R3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9uaWsg +U2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdU +MZTe1RK6UxYC6lhj71vY8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlT +L/jDj/6z/P2douNffb7tC+Bg62nsM+3YjfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H +5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAIJjjcJRFHLfO6IxClv7wC +90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk9Ok0oSy1 +c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/ +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoE +VtstxNulMA0GCSqGSIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLP +qk/CaOv/gKlR6D1id4k9CnU58W5dF4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S +/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwqD2fK/A+JYZ1lpTzlvBNbCNvj +/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4Vwpm+Vganf2X +KWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq +fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 +# Label: "GlobalSign Root CA - R3" +# Serial: 4835703278459759426209954 +# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28 +# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad +# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f +-----END CERTIFICATE----- + +# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Label: "Autoridad de Certificacion Firmaprofesional CIF A62634068" +# Serial: 6047274297262753887 +# MD5 Fingerprint: 73:3a:74:7a:ec:bb:a3:96:a6:c2:e4:e2:c8:9b:c0:c3 +# SHA1 Fingerprint: ae:c5:fb:3f:c8:e1:bf:c4:e5:4f:03:07:5a:9a:e8:00:b7:f7:b6:fa +# SHA256 Fingerprint: 04:04:80:28:bf:1f:28:64:d4:8f:9a:d4:d8:32:94:36:6a:82:88:56:55:3f:3b:14:30:3f:90:14:7f:5d:40:ef +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE +BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h +cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy +MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg +Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 +thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM +cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG +L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i +NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h +X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b +m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy +Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja +EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T +KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF +6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh +OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD +VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv +ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl +AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF +661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9 +am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1 +ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481 +PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS +3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k +SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF +3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM +ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g +StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz +Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB +jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +# Issuer: CN=Izenpe.com O=IZENPE S.A. +# Subject: CN=Izenpe.com O=IZENPE S.A. +# Label: "Izenpe.com" +# Serial: 917563065490389241595536686991402621 +# MD5 Fingerprint: a6:b0:cd:85:80:da:5c:50:34:a3:39:90:2f:55:67:73 +# SHA1 Fingerprint: 2f:78:3d:25:52:18:a7:4a:65:39:71:b5:2c:a2:9c:45:15:6f:e9:19 +# SHA256 Fingerprint: 25:30:cc:8e:98:32:15:02:ba:d9:6f:9b:1f:ba:1b:09:9e:2d:29:9e:0f:45:48:bb:91:4f:36:3b:c0:d4:53:1f +-----BEGIN CERTIFICATE----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 +MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 +ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD +VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j +b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq +scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO +xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H +LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX +uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD +yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ +JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q +rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN +BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L +hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB +QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ +HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu +Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg +QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB +BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA +A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb +laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 +awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo +JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw +LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT +VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk +LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb +UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ +QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ +naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls +QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----END CERTIFICATE----- + +# Issuer: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. +# Subject: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. +# Label: "Chambers of Commerce Root - 2008" +# Serial: 11806822484801597146 +# MD5 Fingerprint: 5e:80:9e:84:5a:0e:65:0b:17:02:f3:55:18:2a:3e:d7 +# SHA1 Fingerprint: 78:6a:74:ac:76:ab:14:7f:9c:6a:30:50:ba:9e:a8:7e:fe:9a:ce:3c +# SHA256 Fingerprint: 06:3e:4a:fa:c4:91:df:d3:32:f3:08:9b:85:42:e9:46:17:d8:93:d7:fe:94:4e:10:a7:93:7e:e2:9d:96:93:c0 +-----BEGIN CERTIFICATE----- +MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD +VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz +IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz +MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj +dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw +EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp +MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9 +28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq +VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q +DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR +5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL +ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a +Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl +UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s ++12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5 +Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj +ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx +hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV +HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1 ++HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN +YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t +L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy +ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt +IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV +HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w +DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW +PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF +5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1 +glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH +FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2 +pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD +xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG +tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq +jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De +fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg +OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ +d0jQ +-----END CERTIFICATE----- + +# Issuer: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. +# Subject: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. +# Label: "Global Chambersign Root - 2008" +# Serial: 14541511773111788494 +# MD5 Fingerprint: 9e:80:ff:78:01:0c:2e:c1:36:bd:fe:96:90:6e:08:f3 +# SHA1 Fingerprint: 4a:bd:ee:ec:95:0d:35:9c:89:ae:c7:52:a1:2c:5b:29:f6:d6:aa:0c +# SHA256 Fingerprint: 13:63:35:43:93:34:a7:69:80:16:a0:d3:24:de:72:28:4e:07:9d:7b:52:20:bb:8f:bd:74:78:16:ee:be:ba:ca +-----BEGIN CERTIFICATE----- +MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD +VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx +MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy +cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG +A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl +BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed +KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 +G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 +zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 +ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG +HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 +Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V +yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e +beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r +6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog +zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW +BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr +ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp +ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk +cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt +YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC +CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow +KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI +hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ +UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz +X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x +fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz +a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd +Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd +SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O +AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso +M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge +v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +-----END CERTIFICATE----- + +# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. +# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. +# Label: "Go Daddy Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01 +# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b +# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT +EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp +ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz +NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH +EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE +AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD +E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH +/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy +DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh +GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR +tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA +AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX +WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu +9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr +gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo +2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI +4uJEvlz36hz1 +-----END CERTIFICATE----- + +# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Label: "Starfield Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96 +# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e +# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5 +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs +ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw +MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj +aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp +Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg +nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 +HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N +Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN +dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 +HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G +CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU +sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 +4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg +8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 +mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Label: "Starfield Services Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2 +# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f +# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5 +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs +ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy +ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy +dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p +OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 +8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K +Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe +hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk +6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q +AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI +bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB +ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z +qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn +0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN +sSi6 +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Commercial O=AffirmTrust +# Subject: CN=AffirmTrust Commercial O=AffirmTrust +# Label: "AffirmTrust Commercial" +# Serial: 8608355977964138876 +# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7 +# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7 +# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7 +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP +Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr +ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL +MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 +yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr +VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ +nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG +XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj +vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt +Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g +N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC +nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Networking O=AffirmTrust +# Subject: CN=AffirmTrust Networking O=AffirmTrust +# Label: "AffirmTrust Networking" +# Serial: 8957382827206547757 +# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f +# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f +# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y +YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua +kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL +QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp +6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG +yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i +QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO +tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu +QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ +Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u +olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 +x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Premium O=AffirmTrust +# Subject: CN=AffirmTrust Premium O=AffirmTrust +# Label: "AffirmTrust Premium" +# Serial: 7893706540734352110 +# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57 +# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27 +# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz +dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG +A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U +cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf +qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ +JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ ++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS +s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 +HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 +70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG +V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S +qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S +5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia +C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX +OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE +FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 +KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B +8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ +MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc +0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ +u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF +u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH +YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 +GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO +RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e +KeC2uAloGRwYQw== +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust +# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust +# Label: "AffirmTrust Premium ECC" +# Serial: 8401224907861490260 +# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d +# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb +# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23 +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC +VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ +cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ +BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt +VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D +0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 +ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G +A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs +aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I +flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Network CA" +# Serial: 279744 +# MD5 Fingerprint: d5:e9:81:40:c5:18:69:fc:46:2c:89:75:62:0f:aa:78 +# SHA1 Fingerprint: 07:e0:32:e0:20:b7:2c:3f:19:2f:06:28:a2:59:3a:19:a7:0f:06:9e +# SHA256 Fingerprint: 5c:58:46:8d:55:f5:8e:49:7e:74:39:82:d2:b5:00:10:b6:d1:65:37:4a:cf:83:a7:d4:a3:2d:b7:68:c4:40:8e +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM +MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D +ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU +cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 +WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg +Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw +IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH +UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM +TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU +BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM +kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x +AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV +HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y +sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL +I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 +J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY +VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +# Issuer: CN=Certinomis - Autorité Racine O=Certinomis OU=0002 433998903 +# Subject: CN=Certinomis - Autorité Racine O=Certinomis OU=0002 433998903 +# Label: "Certinomis - Autorité Racine" +# Serial: 1 +# MD5 Fingerprint: 7f:30:78:8c:03:e3:ca:c9:0a:e2:c9:ea:1e:aa:55:1a +# SHA1 Fingerprint: 2e:14:da:ec:28:f0:fa:1e:8e:38:9a:4e:ab:eb:26:c0:0a:d3:83:c3 +# SHA256 Fingerprint: fc:bf:e2:88:62:06:f7:2b:27:59:3c:8b:07:02:97:e1:2d:76:9e:d1:0e:d7:93:07:05:a8:09:8e:ff:c1:4d:17 +-----BEGIN CERTIFICATE----- +MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjET +MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAk +BgNVBAMMHUNlcnRpbm9taXMgLSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4 +Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNl +cnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYwJAYDVQQDDB1DZXJ0 +aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jY +F1AMnmHawE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N +8y4oH3DfVS9O7cdxbwlyLu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWe +rP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K +/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92NjMD2AR5vpTESOH2VwnHu +7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9qc1pkIuVC +28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6 +lSTClrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1E +nn1So2+WLhl+HPNbxxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB +0iSVL1N6aaLwD4ZFjliCK0wi1F6g530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql09 +5gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna4NH4+ej9Uji29YnfAgMBAAGj +WzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQN +jLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ +KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9s +ov3/4gbIOZ/xWqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZM +OH8oMDX/nyNTt7buFHAAQCvaR6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q +619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40nJ+U8/aGH88bc62UeYdocMMzpXDn +2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1BCxMjidPJC+iKunqj +o3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjvJL1v +nxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG +5ERQL1TEqkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWq +pdEdnV1j6CTmNhTih60bWfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZb +dsLLO7XSAPCjDuGtbkD326C00EauFddEwk01+dIL8hf2rGbVJLJP0RyZwG71fet0 +BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/vgt2Fl43N+bYdJeimUV5 +-----END CERTIFICATE----- + +# Issuer: CN=Root CA Generalitat Valenciana O=Generalitat Valenciana OU=PKIGVA +# Subject: CN=Root CA Generalitat Valenciana O=Generalitat Valenciana OU=PKIGVA +# Label: "Root CA Generalitat Valenciana" +# Serial: 994436456 +# MD5 Fingerprint: 2c:8c:17:5e:b1:54:ab:93:17:b5:36:5a:db:d1:c6:f2 +# SHA1 Fingerprint: a0:73:e5:c5:bd:43:61:0d:86:4c:21:13:0a:85:58:57:cc:9c:ea:46 +# SHA256 Fingerprint: 8c:4e:df:d0:43:48:f3:22:96:9e:7e:29:a4:cd:4d:ca:00:46:55:06:1c:16:e1:b0:76:42:2e:f3:42:ad:63:0e +-----BEGIN CERTIFICATE----- +MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJF +UzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJ +R1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcN +MDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3WjBoMQswCQYDVQQGEwJFUzEfMB0G +A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScw +JQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+ +WmmmO3I2F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKj +SgbwJ/BXufjpTjJ3Cj9BZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGl +u6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQD0EbtFpKd71ng+CT516nDOeB0/RSrFOy +A8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXteJajCq+TA81yc477OMUxk +Hl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMBAAGjggM7 +MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBr +aS5ndmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIIC +IwYKKwYBBAG/VQIBADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8A +cgBpAGQAYQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIA +YQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIAYQBsAGkAdABhAHQAIABWAGEA +bABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQByAGEAYwBpAPMA +bgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA +aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMA +aQBvAG4AYQBtAGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQA +ZQAgAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEA +YwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBuAHQAcgBhACAAZQBuACAAbABhACAA +ZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAAOgAvAC8AdwB3AHcA +LgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0dHA6 +Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+y +eAT8MIGVBgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQsw +CQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0G +A1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVu +Y2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRhTvW1yEICKrNcda3Fbcrn +lD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdzCkj+IHLt +b8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg +9J63NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XF +ducTZnV+ZfsBn5OHiJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmC +IoaZM3Fa6hlXPZHNqcCjbgcTpsnt+GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= +-----END CERTIFICATE----- + +# Issuer: CN=A-Trust-nQual-03 O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH OU=A-Trust-nQual-03 +# Subject: CN=A-Trust-nQual-03 O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH OU=A-Trust-nQual-03 +# Label: "A-Trust-nQual-03" +# Serial: 93214 +# MD5 Fingerprint: 49:63:ae:27:f4:d5:95:3d:d8:db:24:86:b8:9c:07:53 +# SHA1 Fingerprint: d3:c0:63:f2:19:ed:07:3e:34:ad:5d:75:0b:32:76:29:ff:d5:9a:f2 +# SHA256 Fingerprint: 79:3c:bf:45:59:b9:fd:e3:8a:b2:2d:f1:68:69:f6:98:81:ae:14:c4:b0:13:9a:c7:88:a7:8a:1a:fc:ca:02:fb +-----BEGIN CERTIFICATE----- +MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJB +VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp +bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5R +dWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5RdWFsLTAzMB4XDTA1MDgxNzIyMDAw +MFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgwRgYDVQQKDD9BLVRy +dXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0ZW52 +ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMM +EEEtVHJ1c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCtPWFuA/OQO8BBC4SAzewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUj +lUC5B3ilJfYKvUWG6Nm9wASOhURh73+nyfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZ +znF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPESU7l0+m0iKsMrmKS1GWH +2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4iHQF63n1 +k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs +2e3Vcuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYD +VR0OBAoECERqlWdVeRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC +AQEAVdRU0VlIXLOThaq/Yy/kgM40ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fG +KOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmrsQd7TZjTXLDR8KdCoLXEjq/+ +8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZdJXDRZslo+S4R +FGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS +mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmE +DNuxUCAKGkq6ahq97BvIxYSazQ== +-----END CERTIFICATE----- + +# Issuer: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA +# Subject: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA +# Label: "TWCA Root Certification Authority" +# Serial: 1 +# MD5 Fingerprint: aa:08:8f:f6:f9:7b:b7:f2:b1:a7:1e:9b:ea:ea:bd:79 +# SHA1 Fingerprint: cf:9e:87:6d:d3:eb:fc:42:26:97:a3:b5:a3:7a:a0:76:a9:06:23:48 +# SHA256 Fingerprint: bf:d8:8f:e1:10:1c:41:ae:3e:80:1b:f8:be:56:35:0e:e9:ba:d1:a6:b9:bd:51:5e:dc:5c:6d:5b:87:11:ac:44 +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES +MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU +V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz +WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO +LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE +AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH +K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX +RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z +rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx +3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq +hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC +MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls +XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D +lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn +aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ +YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +# Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 +# Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 +# Label: "Security Communication RootCA2" +# Serial: 0 +# MD5 Fingerprint: 6c:39:7d:a4:0e:55:59:b2:3f:d6:41:b1:12:50:de:43 +# SHA1 Fingerprint: 5f:3b:8c:f2:f8:10:b3:7d:78:b4:ce:ec:19:19:c3:73:34:b9:c7:74 +# SHA256 Fingerprint: 51:3b:2c:ec:b8:10:d4:cd:e5:dd:85:39:1a:df:c6:c2:dd:60:d8:7b:b7:36:d2:b5:21:48:4a:a4:7a:0e:be:f6 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX +DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy +dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj +YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV +OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr +zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM +VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ +hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO +ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw +awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs +OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF +coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc +okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 +t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy +1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ +SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions RootCA 2011" +# Serial: 0 +# MD5 Fingerprint: 73:9f:4c:4b:73:5b:79:e9:fa:ba:1c:ef:6e:cb:d5:c9 +# SHA1 Fingerprint: fe:45:65:9b:79:03:5b:98:a1:61:b5:51:2e:ac:da:58:09:48:22:4d +# SHA256 Fingerprint: bc:10:4f:15:a4:8b:e7:09:dc:a5:42:a7:e1:d4:b9:df:6f:05:45:27:e8:02:ea:a9:2d:59:54:44:25:8a:fe:71 +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix +RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p +YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw +NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK +EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl +cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz +dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ +fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns +bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD +75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP +FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV +HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp +5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu +b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA +A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p +6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7 +dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys +Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI +l7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----END CERTIFICATE----- + +# Issuer: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 +# Subject: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 +# Label: "Actalis Authentication Root CA" +# Serial: 6271844772424770508 +# MD5 Fingerprint: 69:c1:0d:4f:07:a3:1b:c3:fe:56:3d:04:bc:11:f6:a6 +# SHA1 Fingerprint: f3:73:b3:87:06:5a:28:84:8a:f2:f3:4a:ce:19:2b:dd:c7:8e:9c:ac +# SHA256 Fingerprint: 55:92:60:84:ec:96:3a:64:b9:6e:2a:be:01:ce:0b:a8:6a:64:fb:fe:bc:c7:aa:b5:af:c1:55:b3:7f:d7:60:66 +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE +BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w +MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC +SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 +ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv +UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX +4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 +KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ +gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb +rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ +51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F +be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe +KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F +v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn +fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 +jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz +ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL +e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 +jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz +WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V +SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j +pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX +X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok +fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R +K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU +ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU +LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT +LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----END CERTIFICATE----- + +# Issuer: O=Trustis Limited OU=Trustis FPS Root CA +# Subject: O=Trustis Limited OU=Trustis FPS Root CA +# Label: "Trustis FPS Root CA" +# Serial: 36053640375399034304724988975563710553 +# MD5 Fingerprint: 30:c9:e7:1e:6b:e6:14:eb:65:b2:16:69:20:31:67:4d +# SHA1 Fingerprint: 3b:c0:38:0b:33:c3:f6:a6:0c:86:15:22:93:d9:df:f5:4b:81:c0:04 +# SHA256 Fingerprint: c1:b4:82:99:ab:a5:20:8f:e9:63:0a:ce:55:ca:68:a0:3e:da:5a:51:9c:88:02:a0:d3:a6:73:be:8f:8e:55:7d +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF +MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL +ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx +MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc +MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ +AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH +iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj +vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA +0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB +OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ +BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E +FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 +GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW +zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 +1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE +f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F +jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN +ZetX2fNXlrtIzYE= +-----END CERTIFICATE----- + +# Issuer: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing +# Subject: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing +# Label: "StartCom Certification Authority" +# Serial: 45 +# MD5 Fingerprint: c9:3b:0d:84:41:fc:a4:76:79:23:08:57:de:10:19:16 +# SHA1 Fingerprint: a3:f1:33:3f:e2:42:bf:cf:c5:d1:4e:8f:39:42:98:40:68:10:d1:a0 +# SHA256 Fingerprint: e1:78:90:ee:09:a3:fb:f4:f4:8b:9c:41:4a:17:d6:37:b7:a5:06:47:e9:bc:75:23:22:72:7f:cc:17:42:a9:11 +-----BEGIN CERTIFICATE----- +MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW +MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg +Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9 +MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi +U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh +cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk +pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf +OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C +Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT +Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi +HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM +Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w ++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ +Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 +Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B +26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID +AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul +F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC +ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w +ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk +aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0 +YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg +c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93 +d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG +CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF +wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS +Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst +0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc +pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl +CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF +P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK +1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm +KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE +JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ +8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm +fyWl8kgAwKQB2j8= +-----END CERTIFICATE----- + +# Issuer: CN=StartCom Certification Authority G2 O=StartCom Ltd. +# Subject: CN=StartCom Certification Authority G2 O=StartCom Ltd. +# Label: "StartCom Certification Authority G2" +# Serial: 59 +# MD5 Fingerprint: 78:4b:fb:9e:64:82:0a:d3:b8:4c:62:f3:64:f2:90:64 +# SHA1 Fingerprint: 31:f1:fd:68:22:63:20:ee:c6:3b:3f:9d:ea:4a:3e:53:7c:7c:39:17 +# SHA256 Fingerprint: c7:ba:65:67:de:93:a7:98:ae:1f:aa:79:1e:71:2d:37:8f:ae:1f:93:c4:39:7f:ea:44:1b:b7:cb:e6:fd:59:95 +-----BEGIN CERTIFICATE----- +MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEW +MBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkgRzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1 +OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoG +A1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRzIwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8Oo1XJ +JZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsD +vfOpL9HG4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnoo +D/Uefyf3lLE3PbfHkffiAez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/ +Q0kGi4xDuFby2X8hQxfqp0iVAXV16iulQ5XqFYSdCI0mblWbq9zSOdIxHWDirMxW +RST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbsO+wmETRIjfaAKxojAuuK +HDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8HvKTlXcxN +nw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM +0D4LnMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/i +UUjXuG+v+E5+M5iSFGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9 +Ha90OrInwMEePnWjFqmveiJdnxMaz6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHg +TuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE +AwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJKoZIhvcNAQEL +BQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K +2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfX +UfEpY9Z1zRbkJ4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl +6/2o1PXWT6RbdejF0mCy2wl+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK +9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG/+gyRr61M3Z3qAFdlsHB1b6uJcDJ +HgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTcnIhT76IxW1hPkWLI +wpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/XldblhY +XzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5l +IxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo +hdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulr +so8uBtjRkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 +# Subject: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 +# Label: "Buypass Class 2 Root CA" +# Serial: 2 +# MD5 Fingerprint: 46:a7:d2:fe:45:fb:64:5a:a8:59:90:9b:78:44:9b:29 +# SHA1 Fingerprint: 49:0a:75:74:de:87:0a:47:fe:58:ee:f6:c7:6b:eb:c6:0b:12:40:99 +# SHA256 Fingerprint: 9a:11:40:25:19:7c:5b:b9:5d:94:e6:3d:55:cd:43:79:08:47:b6:46:b2:3c:df:11:ad:a4:a0:0e:ff:15:fb:48 +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr +6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV +L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 +1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx +MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ +QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB +arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr +Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi +FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS +P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN +9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz +uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h +9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t +OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo ++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 +KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 +DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us +H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ +I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 +5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h +3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz +Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 +# Subject: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 +# Label: "Buypass Class 3 Root CA" +# Serial: 2 +# MD5 Fingerprint: 3d:3b:18:9e:2c:64:5a:e8:d5:88:ce:0e:f9:37:c2:ec +# SHA1 Fingerprint: da:fa:f7:fa:66:84:ec:06:8f:14:50:bd:c7:c2:81:a5:bc:a9:64:57 +# SHA256 Fingerprint: ed:f7:eb:bc:a2:7a:2a:38:4d:38:7b:7d:40:10:c6:66:e2:ed:b4:84:3e:4c:29:b4:ae:1d:5b:93:32:e6:b2:4d +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y +ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E +N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 +tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX +0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c +/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X +KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY +zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS +O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D +34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP +K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv +Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj +QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS +IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 +HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa +O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv +033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u +dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE +kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 +3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD +u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq +4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= +-----END CERTIFICATE----- + +# Issuer: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Subject: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Label: "T-TeleSec GlobalRoot Class 3" +# Serial: 1 +# MD5 Fingerprint: ca:fb:40:a8:4e:39:92:8a:1d:fe:8e:2f:c4:27:ea:ef +# SHA1 Fingerprint: 55:a6:72:3e:cb:f2:ec:cd:c3:23:74:70:19:9d:2a:be:11:e3:81:d1 +# SHA256 Fingerprint: fd:73:da:d3:1c:64:4f:f1:b4:3b:ef:0c:cd:da:96:71:0b:9c:d9:87:5e:ca:7e:31:70:7a:f3:e9:6d:52:2b:bd +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN +8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ +RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 +hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 +ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM +EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 +A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy +WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ +1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 +6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT +91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p +TpPDpFQUWw== +-----END CERTIFICATE----- + +# Issuer: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus +# Subject: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus +# Label: "EE Certification Centre Root CA" +# Serial: 112324828676200291871926431888494945866 +# MD5 Fingerprint: 43:5e:88:d4:7d:1a:4a:7e:fd:84:2e:52:eb:01:d4:6f +# SHA1 Fingerprint: c9:a8:b9:e7:55:80:5e:58:e3:53:77:a7:25:eb:af:c3:7b:27:cc:d7 +# SHA256 Fingerprint: 3e:84:ba:43:42:90:85:16:e7:75:73:c0:99:2f:09:79:ca:08:4e:46:85:68:1f:f1:95:cc:ba:8a:22:9b:8a:76 +-----BEGIN CERTIFICATE----- +MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1 +MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1 +czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG +CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy +MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl +ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS +b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy +euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO +bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw +WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d +MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE +1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/ +zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB +BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF +BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV +v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG +E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u +uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW +iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v +GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0= +-----END CERTIFICATE----- + +# Issuer: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Aralık 2007 +# Subject: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Aralık 2007 +# Label: "TURKTRUST Certificate Services Provider Root 2007" +# Serial: 1 +# MD5 Fingerprint: 2b:70:20:56:86:82:a0:18:c8:07:53:12:28:70:21:72 +# SHA1 Fingerprint: f1:7f:6f:b6:31:dc:99:e3:a3:c8:7f:fe:1c:f1:81:10:88:d9:60:33 +# SHA256 Fingerprint: 97:8c:d9:66:f2:fa:a0:7b:a7:aa:95:00:d9:c0:2e:9d:77:f2:cd:ad:a6:ad:6b:a7:4a:f4:b9:1c:66:59:3c:50 +-----BEGIN CERTIFICATE----- +MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOc +UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx +c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xS +S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg +SGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4XDTA3MTIyNTE4Mzcx +OVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxla3Ry +b25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMC +VFIxDzANBgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDE +sGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7F +ni4gKGMpIEFyYWzEsWsgMjAwNzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9NYvDdE3ePYakqtdTyuTFY +KTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQvKUmi8wUG ++7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveG +HtyaKhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6P +IzdezKKqdfcYbwnTrqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M +733WB2+Y8a+xwXrXgTW4qhe04MsCAwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHk +Yb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/sPx+EnWVUXKgW +AkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I +aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5 +mxRZNTZPz/OOXl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsa +XRik7r4EW5nVcV9VZWRi1aKbBFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZ +qxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAKpoRq0Tl9 +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH +# Subject: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH +# Label: "D-TRUST Root Class 3 CA 2 2009" +# Serial: 623603 +# MD5 Fingerprint: cd:e0:25:69:8d:47:ac:9c:89:35:90:f7:fd:51:3d:2f +# SHA1 Fingerprint: 58:e8:ab:b0:36:15:33:fb:80:f7:9b:1b:6d:29:d3:ff:8d:5f:00:f0 +# SHA256 Fingerprint: 49:e7:a4:42:ac:f0:ea:62:87:05:00:54:b5:25:64:b6:50:e4:f4:9e:42:e3:48:d6:aa:38:e0:39:e9:57:b1:c1 +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha +ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM +HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 +UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 +tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R +ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM +lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp +/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G +A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G +A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy +MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl +cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js +L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL +BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni +acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K +zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 +PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y +Johw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH +# Subject: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH +# Label: "D-TRUST Root Class 3 CA 2 EV 2009" +# Serial: 623604 +# MD5 Fingerprint: aa:c6:43:2c:5e:2d:cd:c4:34:c0:50:4f:11:02:4f:b6 +# SHA1 Fingerprint: 96:c9:1b:0b:95:b4:10:98:42:fa:d0:d8:22:79:fe:60:fa:b9:16:83 +# SHA256 Fingerprint: ee:c5:49:6b:98:8c:e9:86:25:b9:34:09:2e:ec:29:08:be:d0:b0:f3:16:c2:d4:73:0c:84:ea:f1:f3:d3:48:81 +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw +NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV +BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn +ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 +3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z +qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR +p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 +HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw +ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea +HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw +Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh +c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E +RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt +dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku +Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp +3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF +CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na +xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX +KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- + +# Issuer: CN=Autoridad de Certificacion Raiz del Estado Venezolano O=Sistema Nacional de Certificacion Electronica OU=Superintendencia de Servicios de Certificacion Electronica +# Subject: CN=PSCProcert O=Sistema Nacional de Certificacion Electronica OU=Proveedor de Certificados PROCERT +# Label: "PSCProcert" +# Serial: 11 +# MD5 Fingerprint: e6:24:e9:12:01:ae:0c:de:8e:85:c4:ce:a3:12:dd:ec +# SHA1 Fingerprint: 70:c1:8d:74:b4:28:81:0a:e4:fd:a5:75:d7:01:9f:99:b0:3d:50:74 +# SHA256 Fingerprint: 3c:fc:3c:14:d1:f6:84:ff:17:e3:8c:43:ca:44:0c:00:b9:67:ec:93:3e:8b:fe:06:4c:a1:d7:2c:90:f2:ad:b0 +-----BEGIN CERTIFICATE----- +MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1 +dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9s +YW5vMQswCQYDVQQGEwJWRTEQMA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlz +dHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0 +aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBlcmludGVuZGVuY2lh +IGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUwIwYJ +KoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEw +MFoXDTIwMTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHBy +b2NlcnQubmV0LnZlMQ8wDQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGEx +KjAoBgNVBAsTIVByb3ZlZWRvciBkZSBDZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQG +A1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9u +aWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo9 +7BVCwfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74 +BCXfgI8Qhd19L3uA3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38G +ieU89RLAu9MLmV+QfI4tL3czkkohRqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9 +JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmOEO8GqQKJ/+MMbpfg353bIdD0 +PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG20qCZyFSTXai2 +0b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH +0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/ +6mnbVSKVUyqUtd+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1m +v6JpIzi4mWCZDlZTOpx+FIywBm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7 +K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvpr2uKGcfLFFb14dq12fy/czja+eev +bqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/AgEBMDcGA1UdEgQw +MC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAzNi0w +MB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFD +gBStuyIdxuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0 +b3JpZGFkIGRlIENlcnRpZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xh +bm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQHEwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0 +cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5hY2lvbmFsIGRlIENlcnRp +ZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5kZW5jaWEg +ZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkq +hkiG9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQD +AgEGME0GA1UdEQRGMESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0w +MDAwMDKgGwYFYIZeAgKgEgwQUklGLUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEag +RKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9sY3IvQ0VSVElGSUNBRE8t +UkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNyYWl6LnN1c2Nl +cnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v +Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsG +AQUFBwIBFh5odHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcN +AQELBQADggIBACtZ6yKZu4SqT96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS +1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmNg7+mvTV+LFwxNG9s2/NkAZiqlCxB +3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4quxtxj7mkoP3Yldmv +Wb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1n8Gh +HVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHm +pHmJWhSnFFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXz +sOfIt+FTvZLm8wyWuevo5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bE +qCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq3TNWOByyrYDT13K9mmyZY+gAu0F2Bbdb +mRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5poLWccret9W6aAjtmcz9 +opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3YeMLEYC/H +YvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km +-----END CERTIFICATE----- + +# Issuer: CN=China Internet Network Information Center EV Certificates Root O=China Internet Network Information Center +# Subject: CN=China Internet Network Information Center EV Certificates Root O=China Internet Network Information Center +# Label: "China Internet Network Information Center EV Certificates Root" +# Serial: 1218379777 +# MD5 Fingerprint: 55:5d:63:00:97:bd:6a:97:f5:67:ab:4b:fb:6e:63:15 +# SHA1 Fingerprint: 4f:99:aa:93:fb:2b:d1:37:26:a1:99:4a:ce:7f:f0:05:f2:93:5d:1e +# SHA256 Fingerprint: 1c:01:c6:f4:db:b2:fe:fc:22:55:8b:2b:ca:32:56:3f:49:84:4a:cf:c3:2b:7b:e4:b0:ff:59:9f:9e:8c:7a:f7 +-----BEGIN CERTIFICATE----- +MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC +Q04xMjAwBgNVBAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24g +Q2VudGVyMUcwRQYDVQQDDD5DaGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0 +aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMgUm9vdDAeFw0xMDA4MzEwNzExMjVa +Fw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAGA1UECgwpQ2hpbmEg +SW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMMPkNo +aW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRp +ZmljYXRlcyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z +7r07eKpkQ0H1UN+U8i6yjUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA// +DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV98YPjUesWgbdYavi7NifFy2cyjw1l1Vx +zUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2HklY0bBoQCxfVWhyXWIQ8 +hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23KzhmBsUs +4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54u +gQEC7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oY +NJKiyoOCWTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E +FgQUfHJLOcfA22KlT5uqGDSSosqDglkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3 +j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd50XPFtQO3WKwMVC/GVhMPMdoG +52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM7+czV0I664zB +echNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws +ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrI +zo9uoV1/A3U05K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATy +wy39FCqQmbkHzJ8= +-----END CERTIFICATE----- + +# Issuer: CN=Swisscom Root CA 2 O=Swisscom OU=Digital Certificate Services +# Subject: CN=Swisscom Root CA 2 O=Swisscom OU=Digital Certificate Services +# Label: "Swisscom Root CA 2" +# Serial: 40698052477090394928831521023204026294 +# MD5 Fingerprint: 5b:04:69:ec:a5:83:94:63:18:a7:86:d0:e4:f2:6e:19 +# SHA1 Fingerprint: 77:47:4f:c6:30:e4:0f:4c:47:64:3f:84:ba:b8:c6:95:4a:8a:41:ec +# SHA256 Fingerprint: f0:9b:12:2c:71:14:f4:a0:9b:d4:ea:4f:4a:99:d5:58:b4:6e:4c:25:cd:81:14:0d:29:c0:56:13:91:4c:38:41 +-----BEGIN CERTIFICATE----- +MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBk +MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 +YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg +Q0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2MjUwNzM4MTRaMGQxCzAJBgNVBAYT +AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp +Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvEr +jw0DzpPMLgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r +0rk0X2s682Q2zsKwzxNoysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f +2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJwDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVP +ACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpHWrumnf2U5NGKpV+GY3aF +y6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1aSgJA/MTA +tukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL +6yxSNLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0 +uPoTXGiTOmekl9AbmbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrAL +acywlKinh/LTSlDcX3KwFnUey7QYYpqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velh +k6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3qPyZ7iVNTA6z00yPhOgpD/0Q +VAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw +FDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O +BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqh +b97iEoHF8TwuMA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4R +fbgZPnm3qKhyN2abGu2sEzsOv2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv +/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ82YqZh6NM4OKb3xuqFp1mrjX2lhI +REeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLzo9v/tdhZsnPdTSpx +srpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcsa0vv +aGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciAT +woCqISxxOQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99n +Bjx8Oto0QuFmtEYE3saWmA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5W +t6NlUe07qxS/TFED6F+KBZvuim6c779o+sjaC+NCydAXFJy3SuCvkychVSa1ZC+N +8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TCrvJcwhbtkj6EPnNgiLx2 +9CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX5OfNeOI5 +wSsSnqaeG8XmDtkx2Q== +-----END CERTIFICATE----- + +# Issuer: CN=Swisscom Root EV CA 2 O=Swisscom OU=Digital Certificate Services +# Subject: CN=Swisscom Root EV CA 2 O=Swisscom OU=Digital Certificate Services +# Label: "Swisscom Root EV CA 2" +# Serial: 322973295377129385374608406479535262296 +# MD5 Fingerprint: 7b:30:34:9f:dd:0a:4b:6b:35:ca:31:51:28:5d:ae:ec +# SHA1 Fingerprint: e7:a1:90:29:d3:d5:52:dc:0d:0f:c6:92:d3:ea:88:0d:15:2e:1a:6b +# SHA256 Fingerprint: d9:5f:ea:3c:a4:ee:dc:e7:4c:d7:6e:75:fc:6d:1f:f6:2c:44:1f:0f:a8:bc:77:f0:34:b1:9e:5d:b2:58:01:5d +-----BEGIN CERTIFICATE----- +MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAw +ZzELMAkGA1UEBhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdp +dGFsIENlcnRpZmljYXRlIFNlcnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290 +IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcNMzEwNjI1MDg0NTA4WjBnMQswCQYD +VQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2Vy +dGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYgQ0Eg +MjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7Bx +UglgRCgzo3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD +1ycfMQ4jFrclyxy0uYAyXhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPH +oCE2G3pXKSinLr9xJZDzRINpUKTk4RtiGZQJo/PDvO/0vezbE53PnUgJUmfANykR +HvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8LiqG12W0OfvrSdsyaGOx9/ +5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaHZa0zKcQv +idm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHL +OdAGalNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaC +NYGu+HuB5ur+rPQam3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f +46Fq9mDU5zXNysRojddxyNMkM3OxbPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCB +UWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDixzgHcgplwLa7JSnaFp6LNYth +7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/BAQDAgGGMB0G +A1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED +MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWB +bj2ITY1x0kbBbkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6x +XCX5145v9Ydkn+0UjrgEjihLj6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98T +PLr+flaYC/NUn81ETm484T4VvwYmneTwkLbUwp4wLh/vx3rEUMfqe9pQy3omywC0 +Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7XwgiG/W9mR4U9s70 +WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH59yL +Gn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm +7JFe3VE/23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4S +nr8PyQUQ3nqjsTzyP6WqJ3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VN +vBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyAHmBR3NdUIR7KYndP+tiPsys6DXhyyWhB +WkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/giuMod89a2GQ+fYWVq6nTI +fI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuWl8PVP3wb +I+2ksx0WckNLIOFZfsLorSa/ovc= +-----END CERTIFICATE----- + +# Issuer: CN=CA Disig Root R1 O=Disig a.s. +# Subject: CN=CA Disig Root R1 O=Disig a.s. +# Label: "CA Disig Root R1" +# Serial: 14052245610670616104 +# MD5 Fingerprint: be:ec:11:93:9a:f5:69:21:bc:d7:c1:c0:67:89:cc:2a +# SHA1 Fingerprint: 8e:1c:74:f8:a6:20:b9:e5:8a:f4:61:fa:ec:2b:47:56:51:1a:52:c6 +# SHA256 Fingerprint: f9:6f:23:f4:c3:e7:9c:07:7a:46:98:8d:5a:f5:90:06:76:a0:f0:39:cb:64:5d:d1:75:49:b2:16:c8:24:40:ce +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNV +BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu +MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQy +MDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx +EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjEw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy3QRk +D2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/o +OI7bm+V8u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3A +fQ+lekLZWnDZv6fXARz2m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJe +IgpFy4QxTaz+29FHuvlglzmxZcfe+5nkCiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8n +oc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTaYVKvJrT1cU/J19IG32PK +/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6vpmumwKj +rckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD +3AjLLhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE +7cderVC6xkGbrPAXZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkC +yC2fg69naQanMVXVz0tv/wQFx1isXxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLd +qvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ04IwDQYJKoZI +hvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR +xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaA +SfX8MPWbTx9BLxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXo +HqJPYNcHKfyyo6SdbhWSVhlMCrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpB +emOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5GfbVSUZP/3oNn6z4eGBrxEWi1CXYBmC +AMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85YmLLW1AL14FABZyb +7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKSds+x +DzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvk +F7mGnjixlAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqF +a3qdnom2piiZk4hA9z7NUaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsT +Q6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJa7+h89n07eLw4+1knj0vllJPgFOL +-----END CERTIFICATE----- + +# Issuer: CN=CA Disig Root R2 O=Disig a.s. +# Subject: CN=CA Disig Root R2 O=Disig a.s. +# Label: "CA Disig Root R2" +# Serial: 10572350602393338211 +# MD5 Fingerprint: 26:01:fb:d8:27:a7:17:9a:45:54:38:1a:43:01:3b:03 +# SHA1 Fingerprint: b5:61:eb:ea:a4:de:e4:25:4b:69:1a:98:a5:57:47:c2:34:c7:d9:71 +# SHA256 Fingerprint: e2:3d:4a:03:6d:7b:70:e9:f5:95:b1:42:20:79:d2:b9:1e:df:bb:1f:b6:51:a0:63:3e:aa:8a:9d:c5:f8:07:03 +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV +BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu +MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy +MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx +EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe +NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH +PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I +x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe +QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR +yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO +QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 +H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ +QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD +i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs +nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 +rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI +hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf +GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb +lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka ++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal +TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i +nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 +gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr +G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os +zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x +L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- + +# Issuer: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV +# Subject: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV +# Label: "ACCVRAIZ1" +# Serial: 6828503384748696800 +# MD5 Fingerprint: d0:a0:5a:ee:05:b6:09:94:21:a1:7d:f1:b2:29:82:02 +# SHA1 Fingerprint: 93:05:7a:88:15:c6:4f:ce:88:2f:fa:91:16:52:28:78:bc:53:64:17 +# SHA256 Fingerprint: 9a:6e:c0:12:e1:a7:da:9d:be:34:19:4d:47:8a:d7:c0:db:18:22:fb:07:1d:f1:29:81:49:6e:d1:04:38:41:13 +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE +AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw +CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ +BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND +VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb +qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY +HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo +G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA +lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr +IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ +0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH +k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 +4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO +m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa +cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl +uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI +KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls +ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG +AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT +VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG +CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA +cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA +QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA +7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA +cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA +QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA +czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu +aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt +aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud +DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF +BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp +D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU +JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m +AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD +vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms +tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH +7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA +h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF +d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H +pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- + +# Issuer: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA +# Subject: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA +# Label: "TWCA Global Root CA" +# Serial: 3262 +# MD5 Fingerprint: f9:03:7e:cf:e6:9e:3c:73:7a:2a:90:07:69:ff:2b:96 +# SHA1 Fingerprint: 9c:bb:48:53:f6:a4:f6:d3:52:a4:e8:32:52:55:60:13:f5:ad:af:65 +# SHA256 Fingerprint: 59:76:90:07:f7:68:5d:0f:cd:50:87:2f:9f:95:d5:75:5a:5b:2b:45:7d:81:f3:69:2b:61:0a:98:67:2f:0e:1b +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx +EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT +VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 +NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT +B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF +10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz +0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh +MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH +zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc +46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 +yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi +laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP +oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA +BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE +qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm +4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL +1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF +H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo +RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ +nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh +15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW +6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW +nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j +wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz +aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy +KwbQBM0= +-----END CERTIFICATE----- diff --git a/awx/lib/site-packages/pip/_vendor/requests/certs.py b/awx/lib/site-packages/pip/_vendor/requests/certs.py new file mode 100644 index 0000000000..bc00826191 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/certs.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +certs.py +~~~~~~~~ + +This module returns the preferred default CA certificate bundle. + +If you are packaging Requests, e.g., for a Linux distribution or a managed +environment, you can change the definition of where() to return a separately +packaged CA bundle. +""" + +import os.path + + +def where(): + """Return the preferred certificate bundle.""" + # vendored bundle inside Requests + return os.path.join(os.path.dirname(__file__), 'cacert.pem') + +if __name__ == '__main__': + print(where()) diff --git a/awx/lib/site-packages/pip/_vendor/requests/compat.py b/awx/lib/site-packages/pip/_vendor/requests/compat.py new file mode 100644 index 0000000000..0d61a572df --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/compat.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- + +""" +pythoncompat +""" + +from .packages import charade as chardet + +import sys + +# ------- +# Pythons +# ------- + +# Syntax sugar. +_ver = sys.version_info + +#: Python 2.x? +is_py2 = (_ver[0] == 2) + +#: Python 3.x? +is_py3 = (_ver[0] == 3) + +#: Python 3.0.x +is_py30 = (is_py3 and _ver[1] == 0) + +#: Python 3.1.x +is_py31 = (is_py3 and _ver[1] == 1) + +#: Python 3.2.x +is_py32 = (is_py3 and _ver[1] == 2) + +#: Python 3.3.x +is_py33 = (is_py3 and _ver[1] == 3) + +#: Python 3.4.x +is_py34 = (is_py3 and _ver[1] == 4) + +#: Python 2.7.x +is_py27 = (is_py2 and _ver[1] == 7) + +#: Python 2.6.x +is_py26 = (is_py2 and _ver[1] == 6) + +#: Python 2.5.x +is_py25 = (is_py2 and _ver[1] == 5) + +#: Python 2.4.x +is_py24 = (is_py2 and _ver[1] == 4) # I'm assuming this is not by choice. + + +# --------- +# Platforms +# --------- + + +# Syntax sugar. +_ver = sys.version.lower() + +is_pypy = ('pypy' in _ver) +is_jython = ('jython' in _ver) +is_ironpython = ('iron' in _ver) + +# Assume CPython, if nothing else. +is_cpython = not any((is_pypy, is_jython, is_ironpython)) + +# Windows-based system. +is_windows = 'win32' in str(sys.platform).lower() + +# Standard Linux 2+ system. +is_linux = ('linux' in str(sys.platform).lower()) +is_osx = ('darwin' in str(sys.platform).lower()) +is_hpux = ('hpux' in str(sys.platform).lower()) # Complete guess. +is_solaris = ('solar==' in str(sys.platform).lower()) # Complete guess. + +try: + import simplejson as json +except ImportError: + import json + +# --------- +# Specifics +# --------- + +if is_py2: + from urllib import quote, unquote, quote_plus, unquote_plus, urlencode, getproxies, proxy_bypass + from urlparse import urlparse, urlunparse, urljoin, urlsplit, urldefrag + from urllib2 import parse_http_list + import cookielib + from Cookie import Morsel + from StringIO import StringIO + from .packages.urllib3.packages.ordered_dict import OrderedDict + from httplib import IncompleteRead + + builtin_str = str + bytes = str + str = unicode + basestring = basestring + numeric_types = (int, long, float) + + +elif is_py3: + from urllib.parse import urlparse, urlunparse, urljoin, urlsplit, urlencode, quote, unquote, quote_plus, unquote_plus, urldefrag + from urllib.request import parse_http_list, getproxies, proxy_bypass + from http import cookiejar as cookielib + from http.cookies import Morsel + from io import StringIO + from collections import OrderedDict + from http.client import IncompleteRead + + builtin_str = str + str = str + bytes = bytes + basestring = (str, bytes) + numeric_types = (int, float) diff --git a/awx/lib/site-packages/pip/_vendor/requests/cookies.py b/awx/lib/site-packages/pip/_vendor/requests/cookies.py new file mode 100644 index 0000000000..c465f5521a --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/cookies.py @@ -0,0 +1,445 @@ +# -*- coding: utf-8 -*- + +""" +Compatibility code to be able to use `cookielib.CookieJar` with requests. + +requests.utils imports from here, so be careful with imports. +""" + +import time +import collections +from .compat import cookielib, urlparse, urlunparse, Morsel + +try: + import threading + # grr, pyflakes: this fixes "redefinition of unused 'threading'" + threading +except ImportError: + import dummy_threading as threading + + +class MockRequest(object): + """Wraps a `requests.Request` to mimic a `urllib2.Request`. + + The code in `cookielib.CookieJar` expects this interface in order to correctly + manage cookie policies, i.e., determine whether a cookie can be set, given the + domains of the request and the cookie. + + The original request object is read-only. The client is responsible for collecting + the new headers via `get_new_headers()` and interpreting them appropriately. You + probably want `get_cookie_header`, defined below. + """ + + def __init__(self, request): + self._r = request + self._new_headers = {} + self.type = urlparse(self._r.url).scheme + + def get_type(self): + return self.type + + def get_host(self): + return urlparse(self._r.url).netloc + + def get_origin_req_host(self): + return self.get_host() + + def get_full_url(self): + # Only return the response's URL if the user hadn't set the Host + # header + if not self._r.headers.get('Host'): + return self._r.url + # If they did set it, retrieve it and reconstruct the expected domain + host = self._r.headers['Host'] + parsed = urlparse(self._r.url) + # Reconstruct the URL as we expect it + return urlunparse([ + parsed.scheme, host, parsed.path, parsed.params, parsed.query, + parsed.fragment + ]) + + def is_unverifiable(self): + return True + + def has_header(self, name): + return name in self._r.headers or name in self._new_headers + + def get_header(self, name, default=None): + return self._r.headers.get(name, self._new_headers.get(name, default)) + + def add_header(self, key, val): + """cookielib has no legitimate use for this method; add it back if you find one.""" + raise NotImplementedError("Cookie headers should be added with add_unredirected_header()") + + def add_unredirected_header(self, name, value): + self._new_headers[name] = value + + def get_new_headers(self): + return self._new_headers + + @property + def unverifiable(self): + return self.is_unverifiable() + + @property + def origin_req_host(self): + return self.get_origin_req_host() + + @property + def host(self): + return self.get_host() + + +class MockResponse(object): + """Wraps a `httplib.HTTPMessage` to mimic a `urllib.addinfourl`. + + ...what? Basically, expose the parsed HTTP headers from the server response + the way `cookielib` expects to see them. + """ + + def __init__(self, headers): + """Make a MockResponse for `cookielib` to read. + + :param headers: a httplib.HTTPMessage or analogous carrying the headers + """ + self._headers = headers + + def info(self): + return self._headers + + def getheaders(self, name): + self._headers.getheaders(name) + + +def extract_cookies_to_jar(jar, request, response): + """Extract the cookies from the response into a CookieJar. + + :param jar: cookielib.CookieJar (not necessarily a RequestsCookieJar) + :param request: our own requests.Request object + :param response: urllib3.HTTPResponse object + """ + if not (hasattr(response, '_original_response') and + response._original_response): + return + # the _original_response field is the wrapped httplib.HTTPResponse object, + req = MockRequest(request) + # pull out the HTTPMessage with the headers and put it in the mock: + res = MockResponse(response._original_response.msg) + jar.extract_cookies(res, req) + + +def get_cookie_header(jar, request): + """Produce an appropriate Cookie header string to be sent with `request`, or None.""" + r = MockRequest(request) + jar.add_cookie_header(r) + return r.get_new_headers().get('Cookie') + + +def remove_cookie_by_name(cookiejar, name, domain=None, path=None): + """Unsets a cookie by name, by default over all domains and paths. + + Wraps CookieJar.clear(), is O(n). + """ + clearables = [] + for cookie in cookiejar: + if cookie.name == name: + if domain is None or domain == cookie.domain: + if path is None or path == cookie.path: + clearables.append((cookie.domain, cookie.path, cookie.name)) + + for domain, path, name in clearables: + cookiejar.clear(domain, path, name) + + +class CookieConflictError(RuntimeError): + """There are two cookies that meet the criteria specified in the cookie jar. + Use .get and .set and include domain and path args in order to be more specific.""" + + +class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping): + """Compatibility class; is a cookielib.CookieJar, but exposes a dict interface. + + This is the CookieJar we create by default for requests and sessions that + don't specify one, since some clients may expect response.cookies and + session.cookies to support dict operations. + + Don't use the dict interface internally; it's just for compatibility with + with external client code. All `requests` code should work out of the box + with externally provided instances of CookieJar, e.g., LWPCookieJar and + FileCookieJar. + + Caution: dictionary operations that are normally O(1) may be O(n). + + Unlike a regular CookieJar, this class is pickleable. + """ + + def get(self, name, default=None, domain=None, path=None): + """Dict-like get() that also supports optional domain and path args in + order to resolve naming collisions from using one cookie jar over + multiple domains. Caution: operation is O(n), not O(1).""" + try: + return self._find_no_duplicates(name, domain, path) + except KeyError: + return default + + def set(self, name, value, **kwargs): + """Dict-like set() that also supports optional domain and path args in + order to resolve naming collisions from using one cookie jar over + multiple domains.""" + # support client code that unsets cookies by assignment of a None value: + if value is None: + remove_cookie_by_name(self, name, domain=kwargs.get('domain'), path=kwargs.get('path')) + return + + if isinstance(value, Morsel): + c = morsel_to_cookie(value) + else: + c = create_cookie(name, value, **kwargs) + self.set_cookie(c) + return c + + def keys(self): + """Dict-like keys() that returns a list of names of cookies from the jar. + See values() and items().""" + keys = [] + for cookie in iter(self): + keys.append(cookie.name) + return keys + + def values(self): + """Dict-like values() that returns a list of values of cookies from the jar. + See keys() and items().""" + values = [] + for cookie in iter(self): + values.append(cookie.value) + return values + + def items(self): + """Dict-like items() that returns a list of name-value tuples from the jar. + See keys() and values(). Allows client-code to call "dict(RequestsCookieJar) + and get a vanilla python dict of key value pairs.""" + items = [] + for cookie in iter(self): + items.append((cookie.name, cookie.value)) + return items + + def list_domains(self): + """Utility method to list all the domains in the jar.""" + domains = [] + for cookie in iter(self): + if cookie.domain not in domains: + domains.append(cookie.domain) + return domains + + def list_paths(self): + """Utility method to list all the paths in the jar.""" + paths = [] + for cookie in iter(self): + if cookie.path not in paths: + paths.append(cookie.path) + return paths + + def multiple_domains(self): + """Returns True if there are multiple domains in the jar. + Returns False otherwise.""" + domains = [] + for cookie in iter(self): + if cookie.domain is not None and cookie.domain in domains: + return True + domains.append(cookie.domain) + return False # there is only one domain in jar + + def get_dict(self, domain=None, path=None): + """Takes as an argument an optional domain and path and returns a plain old + Python dict of name-value pairs of cookies that meet the requirements.""" + dictionary = {} + for cookie in iter(self): + if (domain is None or cookie.domain == domain) and (path is None + or cookie.path == path): + dictionary[cookie.name] = cookie.value + return dictionary + + def __getitem__(self, name): + """Dict-like __getitem__() for compatibility with client code. Throws exception + if there are more than one cookie with name. In that case, use the more + explicit get() method instead. Caution: operation is O(n), not O(1).""" + + return self._find_no_duplicates(name) + + def __setitem__(self, name, value): + """Dict-like __setitem__ for compatibility with client code. Throws exception + if there is already a cookie of that name in the jar. In that case, use the more + explicit set() method instead.""" + + self.set(name, value) + + def __delitem__(self, name): + """Deletes a cookie given a name. Wraps cookielib.CookieJar's remove_cookie_by_name().""" + remove_cookie_by_name(self, name) + + def set_cookie(self, cookie, *args, **kwargs): + if hasattr(cookie.value, 'startswith') and cookie.value.startswith('"') and cookie.value.endswith('"'): + cookie.value = cookie.value.replace('\\"', '') + return super(RequestsCookieJar, self).set_cookie(cookie, *args, **kwargs) + + def update(self, other): + """Updates this jar with cookies from another CookieJar or dict-like""" + if isinstance(other, cookielib.CookieJar): + for cookie in other: + self.set_cookie(cookie) + else: + super(RequestsCookieJar, self).update(other) + + def _find(self, name, domain=None, path=None): + """Requests uses this method internally to get cookie values. Takes as args name + and optional domain and path. Returns a cookie.value. If there are conflicting cookies, + _find arbitrarily chooses one. See _find_no_duplicates if you want an exception thrown + if there are conflicting cookies.""" + for cookie in iter(self): + if cookie.name == name: + if domain is None or cookie.domain == domain: + if path is None or cookie.path == path: + return cookie.value + + raise KeyError('name=%r, domain=%r, path=%r' % (name, domain, path)) + + def _find_no_duplicates(self, name, domain=None, path=None): + """__get_item__ and get call _find_no_duplicates -- never used in Requests internally. + Takes as args name and optional domain and path. Returns a cookie.value. + Throws KeyError if cookie is not found and CookieConflictError if there are + multiple cookies that match name and optionally domain and path.""" + toReturn = None + for cookie in iter(self): + if cookie.name == name: + if domain is None or cookie.domain == domain: + if path is None or cookie.path == path: + if toReturn is not None: # if there are multiple cookies that meet passed in criteria + raise CookieConflictError('There are multiple cookies with name, %r' % (name)) + toReturn = cookie.value # we will eventually return this as long as no cookie conflict + + if toReturn: + return toReturn + raise KeyError('name=%r, domain=%r, path=%r' % (name, domain, path)) + + def __getstate__(self): + """Unlike a normal CookieJar, this class is pickleable.""" + state = self.__dict__.copy() + # remove the unpickleable RLock object + state.pop('_cookies_lock') + return state + + def __setstate__(self, state): + """Unlike a normal CookieJar, this class is pickleable.""" + self.__dict__.update(state) + if '_cookies_lock' not in self.__dict__: + self._cookies_lock = threading.RLock() + + def copy(self): + """Return a copy of this RequestsCookieJar.""" + new_cj = RequestsCookieJar() + new_cj.update(self) + return new_cj + + +def create_cookie(name, value, **kwargs): + """Make a cookie from underspecified parameters. + + By default, the pair of `name` and `value` will be set for the domain '' + and sent on every request (this is sometimes called a "supercookie"). + """ + result = dict( + version=0, + name=name, + value=value, + port=None, + domain='', + path='/', + secure=False, + expires=None, + discard=True, + comment=None, + comment_url=None, + rest={'HttpOnly': None}, + rfc2109=False,) + + badargs = set(kwargs) - set(result) + if badargs: + err = 'create_cookie() got unexpected keyword arguments: %s' + raise TypeError(err % list(badargs)) + + result.update(kwargs) + result['port_specified'] = bool(result['port']) + result['domain_specified'] = bool(result['domain']) + result['domain_initial_dot'] = result['domain'].startswith('.') + result['path_specified'] = bool(result['path']) + + return cookielib.Cookie(**result) + + +def morsel_to_cookie(morsel): + """Convert a Morsel object into a Cookie containing the one k/v pair.""" + expires = None + if morsel["max-age"]: + expires = time.time() + morsel["max-age"] + elif morsel['expires']: + expires = morsel['expires'] + if type(expires) == type(""): + time_template = "%a, %d-%b-%Y %H:%M:%S GMT" + expires = time.mktime(time.strptime(expires, time_template)) + c = create_cookie( + name=morsel.key, + value=morsel.value, + version=morsel['version'] or 0, + port=None, + domain=morsel['domain'], + path=morsel['path'], + secure=bool(morsel['secure']), + expires=expires, + discard=False, + comment=morsel['comment'], + comment_url=bool(morsel['comment']), + rest={'HttpOnly': morsel['httponly']}, + rfc2109=False,) + return c + + +def cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True): + """Returns a CookieJar from a key/value dictionary. + + :param cookie_dict: Dict of key/values to insert into CookieJar. + :param cookiejar: (optional) A cookiejar to add the cookies to. + :param overwrite: (optional) If False, will not replace cookies + already in the jar with new ones. + """ + if cookiejar is None: + cookiejar = RequestsCookieJar() + + if cookie_dict is not None: + names_from_jar = [cookie.name for cookie in cookiejar] + for name in cookie_dict: + if overwrite or (name not in names_from_jar): + cookiejar.set_cookie(create_cookie(name, cookie_dict[name])) + + return cookiejar + + +def merge_cookies(cookiejar, cookies): + """Add cookies to cookiejar and returns a merged CookieJar. + + :param cookiejar: CookieJar object to add the cookies to. + :param cookies: Dictionary or CookieJar object to be added. + """ + if not isinstance(cookiejar, cookielib.CookieJar): + raise ValueError('You can only merge into CookieJar') + + if isinstance(cookies, dict): + cookiejar = cookiejar_from_dict( + cookies, cookiejar=cookiejar, overwrite=False) + elif isinstance(cookies, cookielib.CookieJar): + try: + cookiejar.update(cookies) + except AttributeError: + for cookie_in_jar in cookies: + cookiejar.set_cookie(cookie_in_jar) + + return cookiejar diff --git a/awx/lib/site-packages/pip/_vendor/requests/exceptions.py b/awx/lib/site-packages/pip/_vendor/requests/exceptions.py new file mode 100644 index 0000000000..bc42b5fff0 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/exceptions.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- + +""" +requests.exceptions +~~~~~~~~~~~~~~~~~~~ + +This module contains the set of Requests' exceptions. + +""" + + +class RequestException(IOError): + """There was an ambiguous exception that occurred while handling your + request.""" + + +class HTTPError(RequestException): + """An HTTP error occurred.""" + + def __init__(self, *args, **kwargs): + """ Initializes HTTPError with optional `response` object. """ + self.response = kwargs.pop('response', None) + super(HTTPError, self).__init__(*args, **kwargs) + + +class ConnectionError(RequestException): + """A Connection error occurred.""" + + +class ProxyError(ConnectionError): + """A proxy error occurred.""" + + +class SSLError(ConnectionError): + """An SSL error occurred.""" + + +class Timeout(RequestException): + """The request timed out.""" + + +class URLRequired(RequestException): + """A valid URL is required to make a request.""" + + +class TooManyRedirects(RequestException): + """Too many redirects.""" + + +class MissingSchema(RequestException, ValueError): + """The URL schema (e.g. http or https) is missing.""" + + +class InvalidSchema(RequestException, ValueError): + """See defaults.py for valid schemas.""" + + +class InvalidURL(RequestException, ValueError): + """ The URL provided was somehow invalid. """ + + +class ChunkedEncodingError(RequestException): + """The server declared chunked encoding but sent an invalid chunk.""" diff --git a/awx/lib/site-packages/pip/_vendor/requests/hooks.py b/awx/lib/site-packages/pip/_vendor/requests/hooks.py new file mode 100644 index 0000000000..5dfaf6b680 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/hooks.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- + +""" +requests.hooks +~~~~~~~~~~~~~~ + +This module provides the capabilities for the Requests hooks system. + +Available hooks: + +``response``: + The response generated from a Request. + +""" + + +HOOKS = ['response'] + + +def default_hooks(): + hooks = {} + for event in HOOKS: + hooks[event] = [] + return hooks + +# TODO: response is the only one + + +def dispatch_hook(key, hooks, hook_data, **kwargs): + """Dispatches a hook dictionary on a given piece of data.""" + + hooks = hooks or dict() + + if key in hooks: + hooks = hooks.get(key) + + if hasattr(hooks, '__call__'): + hooks = [hooks] + + for hook in hooks: + _hook_data = hook(hook_data, **kwargs) + if _hook_data is not None: + hook_data = _hook_data + + return hook_data diff --git a/awx/lib/site-packages/pip/_vendor/requests/models.py b/awx/lib/site-packages/pip/_vendor/requests/models.py new file mode 100644 index 0000000000..34dce1819c --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/models.py @@ -0,0 +1,773 @@ +# -*- coding: utf-8 -*- + +""" +requests.models +~~~~~~~~~~~~~~~ + +This module contains the primary objects that power Requests. +""" + +import collections +import logging +import datetime + +from io import BytesIO, UnsupportedOperation +from .hooks import default_hooks +from .structures import CaseInsensitiveDict + +from .auth import HTTPBasicAuth +from .cookies import cookiejar_from_dict, get_cookie_header +from .packages.urllib3.fields import RequestField +from .packages.urllib3.filepost import encode_multipart_formdata +from .packages.urllib3.util import parse_url +from .exceptions import ( + HTTPError, RequestException, MissingSchema, InvalidURL, + ChunkedEncodingError) +from .utils import ( + guess_filename, get_auth_from_url, requote_uri, + stream_decode_response_unicode, to_key_val_list, parse_header_links, + iter_slices, guess_json_utf, super_len, to_native_string) +from .compat import ( + cookielib, urlunparse, urlsplit, urlencode, str, bytes, StringIO, + is_py2, chardet, json, builtin_str, basestring, IncompleteRead) + +CONTENT_CHUNK_SIZE = 10 * 1024 +ITER_CHUNK_SIZE = 512 + +log = logging.getLogger(__name__) + + +class RequestEncodingMixin(object): + @property + def path_url(self): + """Build the path URL to use.""" + + url = [] + + p = urlsplit(self.url) + + path = p.path + if not path: + path = '/' + + url.append(path) + + query = p.query + if query: + url.append('?') + url.append(query) + + return ''.join(url) + + @staticmethod + def _encode_params(data): + """Encode parameters in a piece of data. + + Will successfully encode parameters when passed as a dict or a list of + 2-tuples. Order is retained if data is a list of 2-tuples but arbitrary + if parameters are supplied as a dict. + """ + + if isinstance(data, (str, bytes)): + return data + elif hasattr(data, 'read'): + return data + elif hasattr(data, '__iter__'): + result = [] + for k, vs in to_key_val_list(data): + if isinstance(vs, basestring) or not hasattr(vs, '__iter__'): + vs = [vs] + for v in vs: + if v is not None: + result.append( + (k.encode('utf-8') if isinstance(k, str) else k, + v.encode('utf-8') if isinstance(v, str) else v)) + return urlencode(result, doseq=True) + else: + return data + + @staticmethod + def _encode_files(files, data): + """Build the body for a multipart/form-data request. + + Will successfully encode files when passed as a dict or a list of + 2-tuples. Order is retained if data is a list of 2-tuples but arbitrary + if parameters are supplied as a dict. + + """ + if (not files): + raise ValueError("Files must be provided.") + elif isinstance(data, basestring): + raise ValueError("Data must not be a string.") + + new_fields = [] + fields = to_key_val_list(data or {}) + files = to_key_val_list(files or {}) + + for field, val in fields: + if isinstance(val, basestring) or not hasattr(val, '__iter__'): + val = [val] + for v in val: + if v is not None: + # Don't call str() on bytestrings: in Py3 it all goes wrong. + if not isinstance(v, bytes): + v = str(v) + + new_fields.append( + (field.decode('utf-8') if isinstance(field, bytes) else field, + v.encode('utf-8') if isinstance(v, str) else v)) + + for (k, v) in files: + # support for explicit filename + ft = None + fh = None + if isinstance(v, (tuple, list)): + if len(v) == 2: + fn, fp = v + elif len(v) == 3: + fn, fp, ft = v + else: + fn, fp, ft, fh = v + else: + fn = guess_filename(v) or k + fp = v + if isinstance(fp, str): + fp = StringIO(fp) + if isinstance(fp, bytes): + fp = BytesIO(fp) + + rf = RequestField(name=k, data=fp.read(), + filename=fn, headers=fh) + rf.make_multipart(content_type=ft) + new_fields.append(rf) + + body, content_type = encode_multipart_formdata(new_fields) + + return body, content_type + + +class RequestHooksMixin(object): + def register_hook(self, event, hook): + """Properly register a hook.""" + + if event not in self.hooks: + raise ValueError('Unsupported event specified, with event name "%s"' % (event)) + + if isinstance(hook, collections.Callable): + self.hooks[event].append(hook) + elif hasattr(hook, '__iter__'): + self.hooks[event].extend(h for h in hook if isinstance(h, collections.Callable)) + + def deregister_hook(self, event, hook): + """Deregister a previously registered hook. + Returns True if the hook existed, False if not. + """ + + try: + self.hooks[event].remove(hook) + return True + except ValueError: + return False + + +class Request(RequestHooksMixin): + """A user-created :class:`Request ` object. + + Used to prepare a :class:`PreparedRequest `, which is sent to the server. + + :param method: HTTP method to use. + :param url: URL to send. + :param headers: dictionary of headers to send. + :param files: dictionary of {filename: fileobject} files to multipart upload. + :param data: the body to attach the request. If a dictionary is provided, form-encoding will take place. + :param params: dictionary of URL parameters to append to the URL. + :param auth: Auth handler or (user, pass) tuple. + :param cookies: dictionary or CookieJar of cookies to attach to this request. + :param hooks: dictionary of callback hooks, for internal usage. + + Usage:: + + >>> import requests + >>> req = requests.Request('GET', 'http://httpbin.org/get') + >>> req.prepare() + + + """ + def __init__(self, + method=None, + url=None, + headers=None, + files=None, + data=None, + params=None, + auth=None, + cookies=None, + hooks=None): + + # Default empty dicts for dict params. + data = [] if data is None else data + files = [] if files is None else files + headers = {} if headers is None else headers + params = {} if params is None else params + hooks = {} if hooks is None else hooks + + self.hooks = default_hooks() + for (k, v) in list(hooks.items()): + self.register_hook(event=k, hook=v) + + self.method = method + self.url = url + self.headers = headers + self.files = files + self.data = data + self.params = params + self.auth = auth + self.cookies = cookies + + def __repr__(self): + return '' % (self.method) + + def prepare(self): + """Constructs a :class:`PreparedRequest ` for transmission and returns it.""" + p = PreparedRequest() + p.prepare( + method=self.method, + url=self.url, + headers=self.headers, + files=self.files, + data=self.data, + params=self.params, + auth=self.auth, + cookies=self.cookies, + hooks=self.hooks, + ) + return p + + +class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): + """The fully mutable :class:`PreparedRequest ` object, + containing the exact bytes that will be sent to the server. + + Generated from either a :class:`Request ` object or manually. + + Usage:: + + >>> import requests + >>> req = requests.Request('GET', 'http://httpbin.org/get') + >>> r = req.prepare() + + + >>> s = requests.Session() + >>> s.send(r) + + + """ + + def __init__(self): + #: HTTP verb to send to the server. + self.method = None + #: HTTP URL to send the request to. + self.url = None + #: dictionary of HTTP headers. + self.headers = None + # The `CookieJar` used to create the Cookie header will be stored here + # after prepare_cookies is called + self._cookies = None + #: request body to send to the server. + self.body = None + #: dictionary of callback hooks, for internal usage. + self.hooks = default_hooks() + + def prepare(self, method=None, url=None, headers=None, files=None, + data=None, params=None, auth=None, cookies=None, hooks=None): + """Prepares the entire request with the given parameters.""" + + self.prepare_method(method) + self.prepare_url(url, params) + self.prepare_headers(headers) + self.prepare_cookies(cookies) + self.prepare_body(data, files) + self.prepare_auth(auth, url) + # Note that prepare_auth must be last to enable authentication schemes + # such as OAuth to work on a fully prepared request. + + # This MUST go after prepare_auth. Authenticators could add a hook + self.prepare_hooks(hooks) + + def __repr__(self): + return '' % (self.method) + + def copy(self): + p = PreparedRequest() + p.method = self.method + p.url = self.url + p.headers = self.headers.copy() + p._cookies = self._cookies.copy() + p.body = self.body + p.hooks = self.hooks + return p + + def prepare_method(self, method): + """Prepares the given HTTP method.""" + self.method = method + if self.method is not None: + self.method = self.method.upper() + + def prepare_url(self, url, params): + """Prepares the given HTTP URL.""" + #: Accept objects that have string representations. + try: + url = unicode(url) + except NameError: + # We're on Python 3. + url = str(url) + except UnicodeDecodeError: + pass + + # Don't do any URL preparation for oddball schemes + if ':' in url and not url.lower().startswith('http'): + self.url = url + return + + # Support for unicode domain names and paths. + scheme, auth, host, port, path, query, fragment = parse_url(url) + + if not scheme: + raise MissingSchema("Invalid URL {0!r}: No schema supplied. " + "Perhaps you meant http://{0}?".format(url)) + + if not host: + raise InvalidURL("Invalid URL %r: No host supplied" % url) + + # Only want to apply IDNA to the hostname + try: + host = host.encode('idna').decode('utf-8') + except UnicodeError: + raise InvalidURL('URL has an invalid label.') + + # Carefully reconstruct the network location + netloc = auth or '' + if netloc: + netloc += '@' + netloc += host + if port: + netloc += ':' + str(port) + + # Bare domains aren't valid URLs. + if not path: + path = '/' + + if is_py2: + if isinstance(scheme, str): + scheme = scheme.encode('utf-8') + if isinstance(netloc, str): + netloc = netloc.encode('utf-8') + if isinstance(path, str): + path = path.encode('utf-8') + if isinstance(query, str): + query = query.encode('utf-8') + if isinstance(fragment, str): + fragment = fragment.encode('utf-8') + + enc_params = self._encode_params(params) + if enc_params: + if query: + query = '%s&%s' % (query, enc_params) + else: + query = enc_params + + url = requote_uri(urlunparse([scheme, netloc, path, None, query, fragment])) + self.url = url + + def prepare_headers(self, headers): + """Prepares the given HTTP headers.""" + + if headers: + self.headers = CaseInsensitiveDict((to_native_string(name), value) for name, value in headers.items()) + else: + self.headers = CaseInsensitiveDict() + + def prepare_body(self, data, files): + """Prepares the given HTTP body data.""" + + # Check if file, fo, generator, iterator. + # If not, run through normal process. + + # Nottin' on you. + body = None + content_type = None + length = None + + is_stream = all([ + hasattr(data, '__iter__'), + not isinstance(data, basestring), + not isinstance(data, list), + not isinstance(data, dict) + ]) + + try: + length = super_len(data) + except (TypeError, AttributeError, UnsupportedOperation): + length = None + + if is_stream: + body = data + + if files: + raise NotImplementedError('Streamed bodies and files are mutually exclusive.') + + if length is not None: + self.headers['Content-Length'] = builtin_str(length) + else: + self.headers['Transfer-Encoding'] = 'chunked' + else: + # Multi-part file uploads. + if files: + (body, content_type) = self._encode_files(files, data) + else: + if data: + body = self._encode_params(data) + if isinstance(data, str) or isinstance(data, builtin_str) or hasattr(data, 'read'): + content_type = None + else: + content_type = 'application/x-www-form-urlencoded' + + self.prepare_content_length(body) + + # Add content-type if it wasn't explicitly provided. + if (content_type) and (not 'content-type' in self.headers): + self.headers['Content-Type'] = content_type + + self.body = body + + def prepare_content_length(self, body): + if hasattr(body, 'seek') and hasattr(body, 'tell'): + body.seek(0, 2) + self.headers['Content-Length'] = builtin_str(body.tell()) + body.seek(0, 0) + elif body is not None: + l = super_len(body) + if l: + self.headers['Content-Length'] = builtin_str(l) + elif self.method not in ('GET', 'HEAD'): + self.headers['Content-Length'] = '0' + + def prepare_auth(self, auth, url=''): + """Prepares the given HTTP auth data.""" + + # If no Auth is explicitly provided, extract it from the URL first. + if auth is None: + url_auth = get_auth_from_url(self.url) + auth = url_auth if any(url_auth) else None + + if auth: + if isinstance(auth, tuple) and len(auth) == 2: + # special-case basic HTTP auth + auth = HTTPBasicAuth(*auth) + + # Allow auth to make its changes. + r = auth(self) + + # Update self to reflect the auth changes. + self.__dict__.update(r.__dict__) + + # Recompute Content-Length + self.prepare_content_length(self.body) + + def prepare_cookies(self, cookies): + """Prepares the given HTTP cookie data.""" + + if isinstance(cookies, cookielib.CookieJar): + self._cookies = cookies + else: + self._cookies = cookiejar_from_dict(cookies) + + cookie_header = get_cookie_header(self._cookies, self) + if cookie_header is not None: + self.headers['Cookie'] = cookie_header + + def prepare_hooks(self, hooks): + """Prepares the given hooks.""" + for event in hooks: + self.register_hook(event, hooks[event]) + + +class Response(object): + """The :class:`Response ` object, which contains a + server's response to an HTTP request. + """ + + __attrs__ = [ + '_content', + 'status_code', + 'headers', + 'url', + 'history', + 'encoding', + 'reason', + 'cookies', + 'elapsed', + 'request', + ] + + def __init__(self): + super(Response, self).__init__() + + self._content = False + self._content_consumed = False + + #: Integer Code of responded HTTP Status. + self.status_code = None + + #: Case-insensitive Dictionary of Response Headers. + #: For example, ``headers['content-encoding']`` will return the + #: value of a ``'Content-Encoding'`` response header. + self.headers = CaseInsensitiveDict() + + #: File-like object representation of response (for advanced usage). + #: Requires that ``stream=True` on the request. + # This requirement does not apply for use internally to Requests. + self.raw = None + + #: Final URL location of Response. + self.url = None + + #: Encoding to decode with when accessing r.text. + self.encoding = None + + #: A list of :class:`Response ` objects from + #: the history of the Request. Any redirect responses will end + #: up here. The list is sorted from the oldest to the most recent request. + self.history = [] + + self.reason = None + + #: A CookieJar of Cookies the server sent back. + self.cookies = cookiejar_from_dict({}) + + #: The amount of time elapsed between sending the request + #: and the arrival of the response (as a timedelta) + self.elapsed = datetime.timedelta(0) + + def __getstate__(self): + # Consume everything; accessing the content attribute makes + # sure the content has been fully read. + if not self._content_consumed: + self.content + + return dict( + (attr, getattr(self, attr, None)) + for attr in self.__attrs__ + ) + + def __setstate__(self, state): + for name, value in state.items(): + setattr(self, name, value) + + # pickled objects do not have .raw + setattr(self, '_content_consumed', True) + + def __repr__(self): + return '' % (self.status_code) + + def __bool__(self): + """Returns true if :attr:`status_code` is 'OK'.""" + return self.ok + + def __nonzero__(self): + """Returns true if :attr:`status_code` is 'OK'.""" + return self.ok + + def __iter__(self): + """Allows you to use a response as an iterator.""" + return self.iter_content(128) + + @property + def ok(self): + try: + self.raise_for_status() + except RequestException: + return False + return True + + @property + def apparent_encoding(self): + """The apparent encoding, provided by the lovely Charade library + (Thanks, Ian!).""" + return chardet.detect(self.content)['encoding'] + + def iter_content(self, chunk_size=1, decode_unicode=False): + """Iterates over the response data. When stream=True is set on the + request, this avoids reading the content at once into memory for + large responses. The chunk size is the number of bytes it should + read into memory. This is not necessarily the length of each item + returned as decoding can take place. + """ + if self._content_consumed: + # simulate reading small chunks of the content + return iter_slices(self._content, chunk_size) + + def generate(): + try: + # Special case for urllib3. + try: + for chunk in self.raw.stream(chunk_size, + decode_content=True): + yield chunk + except IncompleteRead as e: + raise ChunkedEncodingError(e) + except AttributeError: + # Standard file-like object. + while True: + chunk = self.raw.read(chunk_size) + if not chunk: + break + yield chunk + + self._content_consumed = True + + gen = generate() + + if decode_unicode: + gen = stream_decode_response_unicode(gen, self) + + return gen + + def iter_lines(self, chunk_size=ITER_CHUNK_SIZE, decode_unicode=None): + """Iterates over the response data, one line at a time. When + stream=True is set on the request, this avoids reading the + content at once into memory for large responses. + """ + + pending = None + + for chunk in self.iter_content(chunk_size=chunk_size, + decode_unicode=decode_unicode): + + if pending is not None: + chunk = pending + chunk + lines = chunk.splitlines() + + if lines and lines[-1] and chunk and lines[-1][-1] == chunk[-1]: + pending = lines.pop() + else: + pending = None + + for line in lines: + yield line + + if pending is not None: + yield pending + + @property + def content(self): + """Content of the response, in bytes.""" + + if self._content is False: + # Read the contents. + try: + if self._content_consumed: + raise RuntimeError( + 'The content for this response was already consumed') + + if self.status_code == 0: + self._content = None + else: + self._content = bytes().join(self.iter_content(CONTENT_CHUNK_SIZE)) or bytes() + + except AttributeError: + self._content = None + + self._content_consumed = True + # don't need to release the connection; that's been handled by urllib3 + # since we exhausted the data. + return self._content + + @property + def text(self): + """Content of the response, in unicode. + + If Response.encoding is None, encoding will be guessed using + ``charade``. + """ + + # Try charset from content-type + content = None + encoding = self.encoding + + if not self.content: + return str('') + + # Fallback to auto-detected encoding. + if self.encoding is None: + encoding = self.apparent_encoding + + # Decode unicode from given encoding. + try: + content = str(self.content, encoding, errors='replace') + except (LookupError, TypeError): + # A LookupError is raised if the encoding was not found which could + # indicate a misspelling or similar mistake. + # + # A TypeError can be raised if encoding is None + # + # So we try blindly encoding. + content = str(self.content, errors='replace') + + return content + + def json(self, **kwargs): + """Returns the json-encoded content of a response, if any. + + :param \*\*kwargs: Optional arguments that ``json.loads`` takes. + """ + + if not self.encoding and len(self.content) > 3: + # No encoding set. JSON RFC 4627 section 3 states we should expect + # UTF-8, -16 or -32. Detect which one to use; If the detection or + # decoding fails, fall back to `self.text` (using chardet to make + # a best guess). + encoding = guess_json_utf(self.content) + if encoding is not None: + return json.loads(self.content.decode(encoding), **kwargs) + return json.loads(self.text, **kwargs) + + @property + def links(self): + """Returns the parsed header links of the response, if any.""" + + header = self.headers.get('link') + + # l = MultiDict() + l = {} + + if header: + links = parse_header_links(header) + + for link in links: + key = link.get('rel') or link.get('url') + l[key] = link + + return l + + def raise_for_status(self): + """Raises stored :class:`HTTPError`, if one occurred.""" + + http_error_msg = '' + + if 400 <= self.status_code < 500: + http_error_msg = '%s Client Error: %s' % (self.status_code, self.reason) + + elif 500 <= self.status_code < 600: + http_error_msg = '%s Server Error: %s' % (self.status_code, self.reason) + + if http_error_msg: + raise HTTPError(http_error_msg, response=self) + + def close(self): + """Closes the underlying file descriptor and releases the connection + back to the pool. + + *Note: Should not normally need to be called explicitly.* + """ + return self.raw.release_conn() diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/__init__.py b/awx/lib/site-packages/pip/_vendor/requests/packages/__init__.py new file mode 100644 index 0000000000..d62c4b7111 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/__init__.py @@ -0,0 +1,3 @@ +from __future__ import absolute_import + +from . import urllib3 diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/__init__.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/__init__.py new file mode 100644 index 0000000000..26362e9739 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/__init__.py @@ -0,0 +1,66 @@ +######################## BEGIN LICENSE BLOCK ######################## +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +__version__ = "1.0.3" +from sys import version_info + + +def detect(aBuf): + if ((version_info < (3, 0) and isinstance(aBuf, unicode)) or + (version_info >= (3, 0) and not isinstance(aBuf, bytes))): + raise ValueError('Expected a bytes object, not a unicode object') + + from . import universaldetector + u = universaldetector.UniversalDetector() + u.reset() + u.feed(aBuf) + u.close() + return u.result + +def _description_of(path): + """Return a string describing the probable encoding of a file.""" + from charade.universaldetector import UniversalDetector + + u = UniversalDetector() + for line in open(path, 'rb'): + u.feed(line) + u.close() + result = u.result + if result['encoding']: + return '%s: %s with confidence %s' % (path, + result['encoding'], + result['confidence']) + else: + return '%s: no result' % path + + +def charade_cli(): + """ + Script which takes one or more file paths and reports on their detected + encodings + + Example:: + + % chardetect.py somefile someotherfile + somefile: windows-1252 with confidence 0.5 + someotherfile: ascii with confidence 1.0 + + """ + from sys import argv + for path in argv[1:]: + print(_description_of(path)) + \ No newline at end of file diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/__main__.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/__main__.py new file mode 100644 index 0000000000..c0d587fa9e --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/__main__.py @@ -0,0 +1,7 @@ +''' +support ';python -m charade [file2] ...' package execution syntax (2.7+) +''' + +from charade import charade_cli + +charade_cli() diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/big5freq.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/big5freq.py new file mode 100644 index 0000000000..65bffc04b0 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/big5freq.py @@ -0,0 +1,925 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Big5 frequency table +# by Taiwan's Mandarin Promotion Council +# +# +# 128 --> 0.42261 +# 256 --> 0.57851 +# 512 --> 0.74851 +# 1024 --> 0.89384 +# 2048 --> 0.97583 +# +# Ideal Distribution Ratio = 0.74851/(1-0.74851) =2.98 +# Random Distribution Ration = 512/(5401-512)=0.105 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR + +BIG5_TYPICAL_DISTRIBUTION_RATIO = 0.75 + +#Char to FreqOrder table +BIG5_TABLE_SIZE = 5376 + +Big5CharToFreqOrder = ( + 1,1801,1506, 255,1431, 198, 9, 82, 6,5008, 177, 202,3681,1256,2821, 110, # 16 +3814, 33,3274, 261, 76, 44,2114, 16,2946,2187,1176, 659,3971, 26,3451,2653, # 32 +1198,3972,3350,4202, 410,2215, 302, 590, 361,1964, 8, 204, 58,4510,5009,1932, # 48 + 63,5010,5011, 317,1614, 75, 222, 159,4203,2417,1480,5012,3555,3091, 224,2822, # 64 +3682, 3, 10,3973,1471, 29,2787,1135,2866,1940, 873, 130,3275,1123, 312,5013, # 80 +4511,2052, 507, 252, 682,5014, 142,1915, 124, 206,2947, 34,3556,3204, 64, 604, # 96 +5015,2501,1977,1978, 155,1991, 645, 641,1606,5016,3452, 337, 72, 406,5017, 80, # 112 + 630, 238,3205,1509, 263, 939,1092,2654, 756,1440,1094,3453, 449, 69,2987, 591, # 128 + 179,2096, 471, 115,2035,1844, 60, 50,2988, 134, 806,1869, 734,2036,3454, 180, # 144 + 995,1607, 156, 537,2907, 688,5018, 319,1305, 779,2145, 514,2379, 298,4512, 359, # 160 +2502, 90,2716,1338, 663, 11, 906,1099,2553, 20,2441, 182, 532,1716,5019, 732, # 176 +1376,4204,1311,1420,3206, 25,2317,1056, 113, 399, 382,1950, 242,3455,2474, 529, # 192 +3276, 475,1447,3683,5020, 117, 21, 656, 810,1297,2300,2334,3557,5021, 126,4205, # 208 + 706, 456, 150, 613,4513, 71,1118,2037,4206, 145,3092, 85, 835, 486,2115,1246, # 224 +1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,5022,2128,2359, 347,3815, 221, # 240 +3558,3135,5023,1956,1153,4207, 83, 296,1199,3093, 192, 624, 93,5024, 822,1898, # 256 +2823,3136, 795,2065, 991,1554,1542,1592, 27, 43,2867, 859, 139,1456, 860,4514, # 272 + 437, 712,3974, 164,2397,3137, 695, 211,3037,2097, 195,3975,1608,3559,3560,3684, # 288 +3976, 234, 811,2989,2098,3977,2233,1441,3561,1615,2380, 668,2077,1638, 305, 228, # 304 +1664,4515, 467, 415,5025, 262,2099,1593, 239, 108, 300, 200,1033, 512,1247,2078, # 320 +5026,5027,2176,3207,3685,2682, 593, 845,1062,3277, 88,1723,2038,3978,1951, 212, # 336 + 266, 152, 149, 468,1899,4208,4516, 77, 187,5028,3038, 37, 5,2990,5029,3979, # 352 +5030,5031, 39,2524,4517,2908,3208,2079, 55, 148, 74,4518, 545, 483,1474,1029, # 368 +1665, 217,1870,1531,3138,1104,2655,4209, 24, 172,3562, 900,3980,3563,3564,4519, # 384 + 32,1408,2824,1312, 329, 487,2360,2251,2717, 784,2683, 4,3039,3351,1427,1789, # 400 + 188, 109, 499,5032,3686,1717,1790, 888,1217,3040,4520,5033,3565,5034,3352,1520, # 416 +3687,3981, 196,1034, 775,5035,5036, 929,1816, 249, 439, 38,5037,1063,5038, 794, # 432 +3982,1435,2301, 46, 178,3278,2066,5039,2381,5040, 214,1709,4521, 804, 35, 707, # 448 + 324,3688,1601,2554, 140, 459,4210,5041,5042,1365, 839, 272, 978,2262,2580,3456, # 464 +2129,1363,3689,1423, 697, 100,3094, 48, 70,1231, 495,3139,2196,5043,1294,5044, # 480 +2080, 462, 586,1042,3279, 853, 256, 988, 185,2382,3457,1698, 434,1084,5045,3458, # 496 + 314,2625,2788,4522,2335,2336, 569,2285, 637,1817,2525, 757,1162,1879,1616,3459, # 512 + 287,1577,2116, 768,4523,1671,2868,3566,2526,1321,3816, 909,2418,5046,4211, 933, # 528 +3817,4212,2053,2361,1222,4524, 765,2419,1322, 786,4525,5047,1920,1462,1677,2909, # 544 +1699,5048,4526,1424,2442,3140,3690,2600,3353,1775,1941,3460,3983,4213, 309,1369, # 560 +1130,2825, 364,2234,1653,1299,3984,3567,3985,3986,2656, 525,1085,3041, 902,2001, # 576 +1475, 964,4527, 421,1845,1415,1057,2286, 940,1364,3141, 376,4528,4529,1381, 7, # 592 +2527, 983,2383, 336,1710,2684,1846, 321,3461, 559,1131,3042,2752,1809,1132,1313, # 608 + 265,1481,1858,5049, 352,1203,2826,3280, 167,1089, 420,2827, 776, 792,1724,3568, # 624 +4214,2443,3281,5050,4215,5051, 446, 229, 333,2753, 901,3818,1200,1557,4530,2657, # 640 +1921, 395,2754,2685,3819,4216,1836, 125, 916,3209,2626,4531,5052,5053,3820,5054, # 656 +5055,5056,4532,3142,3691,1133,2555,1757,3462,1510,2318,1409,3569,5057,2146, 438, # 672 +2601,2910,2384,3354,1068, 958,3043, 461, 311,2869,2686,4217,1916,3210,4218,1979, # 688 + 383, 750,2755,2627,4219, 274, 539, 385,1278,1442,5058,1154,1965, 384, 561, 210, # 704 + 98,1295,2556,3570,5059,1711,2420,1482,3463,3987,2911,1257, 129,5060,3821, 642, # 720 + 523,2789,2790,2658,5061, 141,2235,1333, 68, 176, 441, 876, 907,4220, 603,2602, # 736 + 710, 171,3464, 404, 549, 18,3143,2398,1410,3692,1666,5062,3571,4533,2912,4534, # 752 +5063,2991, 368,5064, 146, 366, 99, 871,3693,1543, 748, 807,1586,1185, 22,2263, # 768 + 379,3822,3211,5065,3212, 505,1942,2628,1992,1382,2319,5066, 380,2362, 218, 702, # 784 +1818,1248,3465,3044,3572,3355,3282,5067,2992,3694, 930,3283,3823,5068, 59,5069, # 800 + 585, 601,4221, 497,3466,1112,1314,4535,1802,5070,1223,1472,2177,5071, 749,1837, # 816 + 690,1900,3824,1773,3988,1476, 429,1043,1791,2236,2117, 917,4222, 447,1086,1629, # 832 +5072, 556,5073,5074,2021,1654, 844,1090, 105, 550, 966,1758,2828,1008,1783, 686, # 848 +1095,5075,2287, 793,1602,5076,3573,2603,4536,4223,2948,2302,4537,3825, 980,2503, # 864 + 544, 353, 527,4538, 908,2687,2913,5077, 381,2629,1943,1348,5078,1341,1252, 560, # 880 +3095,5079,3467,2870,5080,2054, 973, 886,2081, 143,4539,5081,5082, 157,3989, 496, # 896 +4224, 57, 840, 540,2039,4540,4541,3468,2118,1445, 970,2264,1748,1966,2082,4225, # 912 +3144,1234,1776,3284,2829,3695, 773,1206,2130,1066,2040,1326,3990,1738,1725,4226, # 928 + 279,3145, 51,1544,2604, 423,1578,2131,2067, 173,4542,1880,5083,5084,1583, 264, # 944 + 610,3696,4543,2444, 280, 154,5085,5086,5087,1739, 338,1282,3096, 693,2871,1411, # 960 +1074,3826,2445,5088,4544,5089,5090,1240, 952,2399,5091,2914,1538,2688, 685,1483, # 976 +4227,2475,1436, 953,4228,2055,4545, 671,2400, 79,4229,2446,3285, 608, 567,2689, # 992 +3469,4230,4231,1691, 393,1261,1792,2401,5092,4546,5093,5094,5095,5096,1383,1672, # 1008 +3827,3213,1464, 522,1119, 661,1150, 216, 675,4547,3991,1432,3574, 609,4548,2690, # 1024 +2402,5097,5098,5099,4232,3045, 0,5100,2476, 315, 231,2447, 301,3356,4549,2385, # 1040 +5101, 233,4233,3697,1819,4550,4551,5102, 96,1777,1315,2083,5103, 257,5104,1810, # 1056 +3698,2718,1139,1820,4234,2022,1124,2164,2791,1778,2659,5105,3097, 363,1655,3214, # 1072 +5106,2993,5107,5108,5109,3992,1567,3993, 718, 103,3215, 849,1443, 341,3357,2949, # 1088 +1484,5110,1712, 127, 67, 339,4235,2403, 679,1412, 821,5111,5112, 834, 738, 351, # 1104 +2994,2147, 846, 235,1497,1881, 418,1993,3828,2719, 186,1100,2148,2756,3575,1545, # 1120 +1355,2950,2872,1377, 583,3994,4236,2581,2995,5113,1298,3699,1078,2557,3700,2363, # 1136 + 78,3829,3830, 267,1289,2100,2002,1594,4237, 348, 369,1274,2197,2178,1838,4552, # 1152 +1821,2830,3701,2757,2288,2003,4553,2951,2758, 144,3358, 882,4554,3995,2759,3470, # 1168 +4555,2915,5114,4238,1726, 320,5115,3996,3046, 788,2996,5116,2831,1774,1327,2873, # 1184 +3997,2832,5117,1306,4556,2004,1700,3831,3576,2364,2660, 787,2023, 506, 824,3702, # 1200 + 534, 323,4557,1044,3359,2024,1901, 946,3471,5118,1779,1500,1678,5119,1882,4558, # 1216 + 165, 243,4559,3703,2528, 123, 683,4239, 764,4560, 36,3998,1793, 589,2916, 816, # 1232 + 626,1667,3047,2237,1639,1555,1622,3832,3999,5120,4000,2874,1370,1228,1933, 891, # 1248 +2084,2917, 304,4240,5121, 292,2997,2720,3577, 691,2101,4241,1115,4561, 118, 662, # 1264 +5122, 611,1156, 854,2386,1316,2875, 2, 386, 515,2918,5123,5124,3286, 868,2238, # 1280 +1486, 855,2661, 785,2216,3048,5125,1040,3216,3578,5126,3146, 448,5127,1525,5128, # 1296 +2165,4562,5129,3833,5130,4242,2833,3579,3147, 503, 818,4001,3148,1568, 814, 676, # 1312 +1444, 306,1749,5131,3834,1416,1030, 197,1428, 805,2834,1501,4563,5132,5133,5134, # 1328 +1994,5135,4564,5136,5137,2198, 13,2792,3704,2998,3149,1229,1917,5138,3835,2132, # 1344 +5139,4243,4565,2404,3580,5140,2217,1511,1727,1120,5141,5142, 646,3836,2448, 307, # 1360 +5143,5144,1595,3217,5145,5146,5147,3705,1113,1356,4002,1465,2529,2530,5148, 519, # 1376 +5149, 128,2133, 92,2289,1980,5150,4003,1512, 342,3150,2199,5151,2793,2218,1981, # 1392 +3360,4244, 290,1656,1317, 789, 827,2365,5152,3837,4566, 562, 581,4004,5153, 401, # 1408 +4567,2252, 94,4568,5154,1399,2794,5155,1463,2025,4569,3218,1944,5156, 828,1105, # 1424 +4245,1262,1394,5157,4246, 605,4570,5158,1784,2876,5159,2835, 819,2102, 578,2200, # 1440 +2952,5160,1502, 436,3287,4247,3288,2836,4005,2919,3472,3473,5161,2721,2320,5162, # 1456 +5163,2337,2068, 23,4571, 193, 826,3838,2103, 699,1630,4248,3098, 390,1794,1064, # 1472 +3581,5164,1579,3099,3100,1400,5165,4249,1839,1640,2877,5166,4572,4573, 137,4250, # 1488 + 598,3101,1967, 780, 104, 974,2953,5167, 278, 899, 253, 402, 572, 504, 493,1339, # 1504 +5168,4006,1275,4574,2582,2558,5169,3706,3049,3102,2253, 565,1334,2722, 863, 41, # 1520 +5170,5171,4575,5172,1657,2338, 19, 463,2760,4251, 606,5173,2999,3289,1087,2085, # 1536 +1323,2662,3000,5174,1631,1623,1750,4252,2691,5175,2878, 791,2723,2663,2339, 232, # 1552 +2421,5176,3001,1498,5177,2664,2630, 755,1366,3707,3290,3151,2026,1609, 119,1918, # 1568 +3474, 862,1026,4253,5178,4007,3839,4576,4008,4577,2265,1952,2477,5179,1125, 817, # 1584 +4254,4255,4009,1513,1766,2041,1487,4256,3050,3291,2837,3840,3152,5180,5181,1507, # 1600 +5182,2692, 733, 40,1632,1106,2879, 345,4257, 841,2531, 230,4578,3002,1847,3292, # 1616 +3475,5183,1263, 986,3476,5184, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562, # 1632 +4010,4011,2954, 967,2761,2665,1349, 592,2134,1692,3361,3003,1995,4258,1679,4012, # 1648 +1902,2188,5185, 739,3708,2724,1296,1290,5186,4259,2201,2202,1922,1563,2605,2559, # 1664 +1871,2762,3004,5187, 435,5188, 343,1108, 596, 17,1751,4579,2239,3477,3709,5189, # 1680 +4580, 294,3582,2955,1693, 477, 979, 281,2042,3583, 643,2043,3710,2631,2795,2266, # 1696 +1031,2340,2135,2303,3584,4581, 367,1249,2560,5190,3585,5191,4582,1283,3362,2005, # 1712 + 240,1762,3363,4583,4584, 836,1069,3153, 474,5192,2149,2532, 268,3586,5193,3219, # 1728 +1521,1284,5194,1658,1546,4260,5195,3587,3588,5196,4261,3364,2693,1685,4262, 961, # 1744 +1673,2632, 190,2006,2203,3841,4585,4586,5197, 570,2504,3711,1490,5198,4587,2633, # 1760 +3293,1957,4588, 584,1514, 396,1045,1945,5199,4589,1968,2449,5200,5201,4590,4013, # 1776 + 619,5202,3154,3294, 215,2007,2796,2561,3220,4591,3221,4592, 763,4263,3842,4593, # 1792 +5203,5204,1958,1767,2956,3365,3712,1174, 452,1477,4594,3366,3155,5205,2838,1253, # 1808 +2387,2189,1091,2290,4264, 492,5206, 638,1169,1825,2136,1752,4014, 648, 926,1021, # 1824 +1324,4595, 520,4596, 997, 847,1007, 892,4597,3843,2267,1872,3713,2405,1785,4598, # 1840 +1953,2957,3103,3222,1728,4265,2044,3714,4599,2008,1701,3156,1551, 30,2268,4266, # 1856 +5207,2027,4600,3589,5208, 501,5209,4267, 594,3478,2166,1822,3590,3479,3591,3223, # 1872 + 829,2839,4268,5210,1680,3157,1225,4269,5211,3295,4601,4270,3158,2341,5212,4602, # 1888 +4271,5213,4015,4016,5214,1848,2388,2606,3367,5215,4603, 374,4017, 652,4272,4273, # 1904 + 375,1140, 798,5216,5217,5218,2366,4604,2269, 546,1659, 138,3051,2450,4605,5219, # 1920 +2254, 612,1849, 910, 796,3844,1740,1371, 825,3845,3846,5220,2920,2562,5221, 692, # 1936 + 444,3052,2634, 801,4606,4274,5222,1491, 244,1053,3053,4275,4276, 340,5223,4018, # 1952 +1041,3005, 293,1168, 87,1357,5224,1539, 959,5225,2240, 721, 694,4277,3847, 219, # 1968 +1478, 644,1417,3368,2666,1413,1401,1335,1389,4019,5226,5227,3006,2367,3159,1826, # 1984 + 730,1515, 184,2840, 66,4607,5228,1660,2958, 246,3369, 378,1457, 226,3480, 975, # 2000 +4020,2959,1264,3592, 674, 696,5229, 163,5230,1141,2422,2167, 713,3593,3370,4608, # 2016 +4021,5231,5232,1186, 15,5233,1079,1070,5234,1522,3224,3594, 276,1050,2725, 758, # 2032 +1126, 653,2960,3296,5235,2342, 889,3595,4022,3104,3007, 903,1250,4609,4023,3481, # 2048 +3596,1342,1681,1718, 766,3297, 286, 89,2961,3715,5236,1713,5237,2607,3371,3008, # 2064 +5238,2962,2219,3225,2880,5239,4610,2505,2533, 181, 387,1075,4024, 731,2190,3372, # 2080 +5240,3298, 310, 313,3482,2304, 770,4278, 54,3054, 189,4611,3105,3848,4025,5241, # 2096 +1230,1617,1850, 355,3597,4279,4612,3373, 111,4280,3716,1350,3160,3483,3055,4281, # 2112 +2150,3299,3598,5242,2797,4026,4027,3009, 722,2009,5243,1071, 247,1207,2343,2478, # 2128 +1378,4613,2010, 864,1437,1214,4614, 373,3849,1142,2220, 667,4615, 442,2763,2563, # 2144 +3850,4028,1969,4282,3300,1840, 837, 170,1107, 934,1336,1883,5244,5245,2119,4283, # 2160 +2841, 743,1569,5246,4616,4284, 582,2389,1418,3484,5247,1803,5248, 357,1395,1729, # 2176 +3717,3301,2423,1564,2241,5249,3106,3851,1633,4617,1114,2086,4285,1532,5250, 482, # 2192 +2451,4618,5251,5252,1492, 833,1466,5253,2726,3599,1641,2842,5254,1526,1272,3718, # 2208 +4286,1686,1795, 416,2564,1903,1954,1804,5255,3852,2798,3853,1159,2321,5256,2881, # 2224 +4619,1610,1584,3056,2424,2764, 443,3302,1163,3161,5257,5258,4029,5259,4287,2506, # 2240 +3057,4620,4030,3162,2104,1647,3600,2011,1873,4288,5260,4289, 431,3485,5261, 250, # 2256 + 97, 81,4290,5262,1648,1851,1558, 160, 848,5263, 866, 740,1694,5264,2204,2843, # 2272 +3226,4291,4621,3719,1687, 950,2479, 426, 469,3227,3720,3721,4031,5265,5266,1188, # 2288 + 424,1996, 861,3601,4292,3854,2205,2694, 168,1235,3602,4293,5267,2087,1674,4622, # 2304 +3374,3303, 220,2565,1009,5268,3855, 670,3010, 332,1208, 717,5269,5270,3603,2452, # 2320 +4032,3375,5271, 513,5272,1209,2882,3376,3163,4623,1080,5273,5274,5275,5276,2534, # 2336 +3722,3604, 815,1587,4033,4034,5277,3605,3486,3856,1254,4624,1328,3058,1390,4035, # 2352 +1741,4036,3857,4037,5278, 236,3858,2453,3304,5279,5280,3723,3859,1273,3860,4625, # 2368 +5281, 308,5282,4626, 245,4627,1852,2480,1307,2583, 430, 715,2137,2454,5283, 270, # 2384 + 199,2883,4038,5284,3606,2727,1753, 761,1754, 725,1661,1841,4628,3487,3724,5285, # 2400 +5286, 587, 14,3305, 227,2608, 326, 480,2270, 943,2765,3607, 291, 650,1884,5287, # 2416 +1702,1226, 102,1547, 62,3488, 904,4629,3489,1164,4294,5288,5289,1224,1548,2766, # 2432 + 391, 498,1493,5290,1386,1419,5291,2056,1177,4630, 813, 880,1081,2368, 566,1145, # 2448 +4631,2291,1001,1035,2566,2609,2242, 394,1286,5292,5293,2069,5294, 86,1494,1730, # 2464 +4039, 491,1588, 745, 897,2963, 843,3377,4040,2767,2884,3306,1768, 998,2221,2070, # 2480 + 397,1827,1195,1970,3725,3011,3378, 284,5295,3861,2507,2138,2120,1904,5296,4041, # 2496 +2151,4042,4295,1036,3490,1905, 114,2567,4296, 209,1527,5297,5298,2964,2844,2635, # 2512 +2390,2728,3164, 812,2568,5299,3307,5300,1559, 737,1885,3726,1210, 885, 28,2695, # 2528 +3608,3862,5301,4297,1004,1780,4632,5302, 346,1982,2222,2696,4633,3863,1742, 797, # 2544 +1642,4043,1934,1072,1384,2152, 896,4044,3308,3727,3228,2885,3609,5303,2569,1959, # 2560 +4634,2455,1786,5304,5305,5306,4045,4298,1005,1308,3728,4299,2729,4635,4636,1528, # 2576 +2610, 161,1178,4300,1983, 987,4637,1101,4301, 631,4046,1157,3229,2425,1343,1241, # 2592 +1016,2243,2570, 372, 877,2344,2508,1160, 555,1935, 911,4047,5307, 466,1170, 169, # 2608 +1051,2921,2697,3729,2481,3012,1182,2012,2571,1251,2636,5308, 992,2345,3491,1540, # 2624 +2730,1201,2071,2406,1997,2482,5309,4638, 528,1923,2191,1503,1874,1570,2369,3379, # 2640 +3309,5310, 557,1073,5311,1828,3492,2088,2271,3165,3059,3107, 767,3108,2799,4639, # 2656 +1006,4302,4640,2346,1267,2179,3730,3230, 778,4048,3231,2731,1597,2667,5312,4641, # 2672 +5313,3493,5314,5315,5316,3310,2698,1433,3311, 131, 95,1504,4049, 723,4303,3166, # 2688 +1842,3610,2768,2192,4050,2028,2105,3731,5317,3013,4051,1218,5318,3380,3232,4052, # 2704 +4304,2584, 248,1634,3864, 912,5319,2845,3732,3060,3865, 654, 53,5320,3014,5321, # 2720 +1688,4642, 777,3494,1032,4053,1425,5322, 191, 820,2121,2846, 971,4643, 931,3233, # 2736 + 135, 664, 783,3866,1998, 772,2922,1936,4054,3867,4644,2923,3234, 282,2732, 640, # 2752 +1372,3495,1127, 922, 325,3381,5323,5324, 711,2045,5325,5326,4055,2223,2800,1937, # 2768 +4056,3382,2224,2255,3868,2305,5327,4645,3869,1258,3312,4057,3235,2139,2965,4058, # 2784 +4059,5328,2225, 258,3236,4646, 101,1227,5329,3313,1755,5330,1391,3314,5331,2924, # 2800 +2057, 893,5332,5333,5334,1402,4305,2347,5335,5336,3237,3611,5337,5338, 878,1325, # 2816 +1781,2801,4647, 259,1385,2585, 744,1183,2272,4648,5339,4060,2509,5340, 684,1024, # 2832 +4306,5341, 472,3612,3496,1165,3315,4061,4062, 322,2153, 881, 455,1695,1152,1340, # 2848 + 660, 554,2154,4649,1058,4650,4307, 830,1065,3383,4063,4651,1924,5342,1703,1919, # 2864 +5343, 932,2273, 122,5344,4652, 947, 677,5345,3870,2637, 297,1906,1925,2274,4653, # 2880 +2322,3316,5346,5347,4308,5348,4309, 84,4310, 112, 989,5349, 547,1059,4064, 701, # 2896 +3613,1019,5350,4311,5351,3497, 942, 639, 457,2306,2456, 993,2966, 407, 851, 494, # 2912 +4654,3384, 927,5352,1237,5353,2426,3385, 573,4312, 680, 921,2925,1279,1875, 285, # 2928 + 790,1448,1984, 719,2168,5354,5355,4655,4065,4066,1649,5356,1541, 563,5357,1077, # 2944 +5358,3386,3061,3498, 511,3015,4067,4068,3733,4069,1268,2572,3387,3238,4656,4657, # 2960 +5359, 535,1048,1276,1189,2926,2029,3167,1438,1373,2847,2967,1134,2013,5360,4313, # 2976 +1238,2586,3109,1259,5361, 700,5362,2968,3168,3734,4314,5363,4315,1146,1876,1907, # 2992 +4658,2611,4070, 781,2427, 132,1589, 203, 147, 273,2802,2407, 898,1787,2155,4071, # 3008 +4072,5364,3871,2803,5365,5366,4659,4660,5367,3239,5368,1635,3872, 965,5369,1805, # 3024 +2699,1516,3614,1121,1082,1329,3317,4073,1449,3873, 65,1128,2848,2927,2769,1590, # 3040 +3874,5370,5371, 12,2668, 45, 976,2587,3169,4661, 517,2535,1013,1037,3240,5372, # 3056 +3875,2849,5373,3876,5374,3499,5375,2612, 614,1999,2323,3877,3110,2733,2638,5376, # 3072 +2588,4316, 599,1269,5377,1811,3735,5378,2700,3111, 759,1060, 489,1806,3388,3318, # 3088 +1358,5379,5380,2391,1387,1215,2639,2256, 490,5381,5382,4317,1759,2392,2348,5383, # 3104 +4662,3878,1908,4074,2640,1807,3241,4663,3500,3319,2770,2349, 874,5384,5385,3501, # 3120 +3736,1859, 91,2928,3737,3062,3879,4664,5386,3170,4075,2669,5387,3502,1202,1403, # 3136 +3880,2969,2536,1517,2510,4665,3503,2511,5388,4666,5389,2701,1886,1495,1731,4076, # 3152 +2370,4667,5390,2030,5391,5392,4077,2702,1216, 237,2589,4318,2324,4078,3881,4668, # 3168 +4669,2703,3615,3504, 445,4670,5393,5394,5395,5396,2771, 61,4079,3738,1823,4080, # 3184 +5397, 687,2046, 935, 925, 405,2670, 703,1096,1860,2734,4671,4081,1877,1367,2704, # 3200 +3389, 918,2106,1782,2483, 334,3320,1611,1093,4672, 564,3171,3505,3739,3390, 945, # 3216 +2641,2058,4673,5398,1926, 872,4319,5399,3506,2705,3112, 349,4320,3740,4082,4674, # 3232 +3882,4321,3741,2156,4083,4675,4676,4322,4677,2408,2047, 782,4084, 400, 251,4323, # 3248 +1624,5400,5401, 277,3742, 299,1265, 476,1191,3883,2122,4324,4325,1109, 205,5402, # 3264 +2590,1000,2157,3616,1861,5403,5404,5405,4678,5406,4679,2573, 107,2484,2158,4085, # 3280 +3507,3172,5407,1533, 541,1301, 158, 753,4326,2886,3617,5408,1696, 370,1088,4327, # 3296 +4680,3618, 579, 327, 440, 162,2244, 269,1938,1374,3508, 968,3063, 56,1396,3113, # 3312 +2107,3321,3391,5409,1927,2159,4681,3016,5410,3619,5411,5412,3743,4682,2485,5413, # 3328 +2804,5414,1650,4683,5415,2613,5416,5417,4086,2671,3392,1149,3393,4087,3884,4088, # 3344 +5418,1076, 49,5419, 951,3242,3322,3323, 450,2850, 920,5420,1812,2805,2371,4328, # 3360 +1909,1138,2372,3885,3509,5421,3243,4684,1910,1147,1518,2428,4685,3886,5422,4686, # 3376 +2393,2614, 260,1796,3244,5423,5424,3887,3324, 708,5425,3620,1704,5426,3621,1351, # 3392 +1618,3394,3017,1887, 944,4329,3395,4330,3064,3396,4331,5427,3744, 422, 413,1714, # 3408 +3325, 500,2059,2350,4332,2486,5428,1344,1911, 954,5429,1668,5430,5431,4089,2409, # 3424 +4333,3622,3888,4334,5432,2307,1318,2512,3114, 133,3115,2887,4687, 629, 31,2851, # 3440 +2706,3889,4688, 850, 949,4689,4090,2970,1732,2089,4335,1496,1853,5433,4091, 620, # 3456 +3245, 981,1242,3745,3397,1619,3746,1643,3326,2140,2457,1971,1719,3510,2169,5434, # 3472 +3246,5435,5436,3398,1829,5437,1277,4690,1565,2048,5438,1636,3623,3116,5439, 869, # 3488 +2852, 655,3890,3891,3117,4092,3018,3892,1310,3624,4691,5440,5441,5442,1733, 558, # 3504 +4692,3747, 335,1549,3065,1756,4336,3748,1946,3511,1830,1291,1192, 470,2735,2108, # 3520 +2806, 913,1054,4093,5443,1027,5444,3066,4094,4693, 982,2672,3399,3173,3512,3247, # 3536 +3248,1947,2807,5445, 571,4694,5446,1831,5447,3625,2591,1523,2429,5448,2090, 984, # 3552 +4695,3749,1960,5449,3750, 852, 923,2808,3513,3751, 969,1519, 999,2049,2325,1705, # 3568 +5450,3118, 615,1662, 151, 597,4095,2410,2326,1049, 275,4696,3752,4337, 568,3753, # 3584 +3626,2487,4338,3754,5451,2430,2275, 409,3249,5452,1566,2888,3514,1002, 769,2853, # 3600 + 194,2091,3174,3755,2226,3327,4339, 628,1505,5453,5454,1763,2180,3019,4096, 521, # 3616 +1161,2592,1788,2206,2411,4697,4097,1625,4340,4341, 412, 42,3119, 464,5455,2642, # 3632 +4698,3400,1760,1571,2889,3515,2537,1219,2207,3893,2643,2141,2373,4699,4700,3328, # 3648 +1651,3401,3627,5456,5457,3628,2488,3516,5458,3756,5459,5460,2276,2092, 460,5461, # 3664 +4701,5462,3020, 962, 588,3629, 289,3250,2644,1116, 52,5463,3067,1797,5464,5465, # 3680 +5466,1467,5467,1598,1143,3757,4342,1985,1734,1067,4702,1280,3402, 465,4703,1572, # 3696 + 510,5468,1928,2245,1813,1644,3630,5469,4704,3758,5470,5471,2673,1573,1534,5472, # 3712 +5473, 536,1808,1761,3517,3894,3175,2645,5474,5475,5476,4705,3518,2929,1912,2809, # 3728 +5477,3329,1122, 377,3251,5478, 360,5479,5480,4343,1529, 551,5481,2060,3759,1769, # 3744 +2431,5482,2930,4344,3330,3120,2327,2109,2031,4706,1404, 136,1468,1479, 672,1171, # 3760 +3252,2308, 271,3176,5483,2772,5484,2050, 678,2736, 865,1948,4707,5485,2014,4098, # 3776 +2971,5486,2737,2227,1397,3068,3760,4708,4709,1735,2931,3403,3631,5487,3895, 509, # 3792 +2854,2458,2890,3896,5488,5489,3177,3178,4710,4345,2538,4711,2309,1166,1010, 552, # 3808 + 681,1888,5490,5491,2972,2973,4099,1287,1596,1862,3179, 358, 453, 736, 175, 478, # 3824 +1117, 905,1167,1097,5492,1854,1530,5493,1706,5494,2181,3519,2292,3761,3520,3632, # 3840 +4346,2093,4347,5495,3404,1193,2489,4348,1458,2193,2208,1863,1889,1421,3331,2932, # 3856 +3069,2182,3521, 595,2123,5496,4100,5497,5498,4349,1707,2646, 223,3762,1359, 751, # 3872 +3121, 183,3522,5499,2810,3021, 419,2374, 633, 704,3897,2394, 241,5500,5501,5502, # 3888 + 838,3022,3763,2277,2773,2459,3898,1939,2051,4101,1309,3122,2246,1181,5503,1136, # 3904 +2209,3899,2375,1446,4350,2310,4712,5504,5505,4351,1055,2615, 484,3764,5506,4102, # 3920 + 625,4352,2278,3405,1499,4353,4103,5507,4104,4354,3253,2279,2280,3523,5508,5509, # 3936 +2774, 808,2616,3765,3406,4105,4355,3123,2539, 526,3407,3900,4356, 955,5510,1620, # 3952 +4357,2647,2432,5511,1429,3766,1669,1832, 994, 928,5512,3633,1260,5513,5514,5515, # 3968 +1949,2293, 741,2933,1626,4358,2738,2460, 867,1184, 362,3408,1392,5516,5517,4106, # 3984 +4359,1770,1736,3254,2934,4713,4714,1929,2707,1459,1158,5518,3070,3409,2891,1292, # 4000 +1930,2513,2855,3767,1986,1187,2072,2015,2617,4360,5519,2574,2514,2170,3768,2490, # 4016 +3332,5520,3769,4715,5521,5522, 666,1003,3023,1022,3634,4361,5523,4716,1814,2257, # 4032 + 574,3901,1603, 295,1535, 705,3902,4362, 283, 858, 417,5524,5525,3255,4717,4718, # 4048 +3071,1220,1890,1046,2281,2461,4107,1393,1599, 689,2575, 388,4363,5526,2491, 802, # 4064 +5527,2811,3903,2061,1405,2258,5528,4719,3904,2110,1052,1345,3256,1585,5529, 809, # 4080 +5530,5531,5532, 575,2739,3524, 956,1552,1469,1144,2328,5533,2329,1560,2462,3635, # 4096 +3257,4108, 616,2210,4364,3180,2183,2294,5534,1833,5535,3525,4720,5536,1319,3770, # 4112 +3771,1211,3636,1023,3258,1293,2812,5537,5538,5539,3905, 607,2311,3906, 762,2892, # 4128 +1439,4365,1360,4721,1485,3072,5540,4722,1038,4366,1450,2062,2648,4367,1379,4723, # 4144 +2593,5541,5542,4368,1352,1414,2330,2935,1172,5543,5544,3907,3908,4724,1798,1451, # 4160 +5545,5546,5547,5548,2936,4109,4110,2492,2351, 411,4111,4112,3637,3333,3124,4725, # 4176 +1561,2674,1452,4113,1375,5549,5550, 47,2974, 316,5551,1406,1591,2937,3181,5552, # 4192 +1025,2142,3125,3182, 354,2740, 884,2228,4369,2412, 508,3772, 726,3638, 996,2433, # 4208 +3639, 729,5553, 392,2194,1453,4114,4726,3773,5554,5555,2463,3640,2618,1675,2813, # 4224 + 919,2352,2975,2353,1270,4727,4115, 73,5556,5557, 647,5558,3259,2856,2259,1550, # 4240 +1346,3024,5559,1332, 883,3526,5560,5561,5562,5563,3334,2775,5564,1212, 831,1347, # 4256 +4370,4728,2331,3909,1864,3073, 720,3910,4729,4730,3911,5565,4371,5566,5567,4731, # 4272 +5568,5569,1799,4732,3774,2619,4733,3641,1645,2376,4734,5570,2938, 669,2211,2675, # 4288 +2434,5571,2893,5572,5573,1028,3260,5574,4372,2413,5575,2260,1353,5576,5577,4735, # 4304 +3183, 518,5578,4116,5579,4373,1961,5580,2143,4374,5581,5582,3025,2354,2355,3912, # 4320 + 516,1834,1454,4117,2708,4375,4736,2229,2620,1972,1129,3642,5583,2776,5584,2976, # 4336 +1422, 577,1470,3026,1524,3410,5585,5586, 432,4376,3074,3527,5587,2594,1455,2515, # 4352 +2230,1973,1175,5588,1020,2741,4118,3528,4737,5589,2742,5590,1743,1361,3075,3529, # 4368 +2649,4119,4377,4738,2295, 895, 924,4378,2171, 331,2247,3076, 166,1627,3077,1098, # 4384 +5591,1232,2894,2231,3411,4739, 657, 403,1196,2377, 542,3775,3412,1600,4379,3530, # 4400 +5592,4740,2777,3261, 576, 530,1362,4741,4742,2540,2676,3776,4120,5593, 842,3913, # 4416 +5594,2814,2032,1014,4121, 213,2709,3413, 665, 621,4380,5595,3777,2939,2435,5596, # 4432 +2436,3335,3643,3414,4743,4381,2541,4382,4744,3644,1682,4383,3531,1380,5597, 724, # 4448 +2282, 600,1670,5598,1337,1233,4745,3126,2248,5599,1621,4746,5600, 651,4384,5601, # 4464 +1612,4385,2621,5602,2857,5603,2743,2312,3078,5604, 716,2464,3079, 174,1255,2710, # 4480 +4122,3645, 548,1320,1398, 728,4123,1574,5605,1891,1197,3080,4124,5606,3081,3082, # 4496 +3778,3646,3779, 747,5607, 635,4386,4747,5608,5609,5610,4387,5611,5612,4748,5613, # 4512 +3415,4749,2437, 451,5614,3780,2542,2073,4388,2744,4389,4125,5615,1764,4750,5616, # 4528 +4390, 350,4751,2283,2395,2493,5617,4391,4126,2249,1434,4127, 488,4752, 458,4392, # 4544 +4128,3781, 771,1330,2396,3914,2576,3184,2160,2414,1553,2677,3185,4393,5618,2494, # 4560 +2895,2622,1720,2711,4394,3416,4753,5619,2543,4395,5620,3262,4396,2778,5621,2016, # 4576 +2745,5622,1155,1017,3782,3915,5623,3336,2313, 201,1865,4397,1430,5624,4129,5625, # 4592 +5626,5627,5628,5629,4398,1604,5630, 414,1866, 371,2595,4754,4755,3532,2017,3127, # 4608 +4756,1708, 960,4399, 887, 389,2172,1536,1663,1721,5631,2232,4130,2356,2940,1580, # 4624 +5632,5633,1744,4757,2544,4758,4759,5634,4760,5635,2074,5636,4761,3647,3417,2896, # 4640 +4400,5637,4401,2650,3418,2815, 673,2712,2465, 709,3533,4131,3648,4402,5638,1148, # 4656 + 502, 634,5639,5640,1204,4762,3649,1575,4763,2623,3783,5641,3784,3128, 948,3263, # 4672 + 121,1745,3916,1110,5642,4403,3083,2516,3027,4132,3785,1151,1771,3917,1488,4133, # 4688 +1987,5643,2438,3534,5644,5645,2094,5646,4404,3918,1213,1407,2816, 531,2746,2545, # 4704 +3264,1011,1537,4764,2779,4405,3129,1061,5647,3786,3787,1867,2897,5648,2018, 120, # 4720 +4406,4407,2063,3650,3265,2314,3919,2678,3419,1955,4765,4134,5649,3535,1047,2713, # 4736 +1266,5650,1368,4766,2858, 649,3420,3920,2546,2747,1102,2859,2679,5651,5652,2000, # 4752 +5653,1111,3651,2977,5654,2495,3921,3652,2817,1855,3421,3788,5655,5656,3422,2415, # 4768 +2898,3337,3266,3653,5657,2577,5658,3654,2818,4135,1460, 856,5659,3655,5660,2899, # 4784 +2978,5661,2900,3922,5662,4408, 632,2517, 875,3923,1697,3924,2296,5663,5664,4767, # 4800 +3028,1239, 580,4768,4409,5665, 914, 936,2075,1190,4136,1039,2124,5666,5667,5668, # 4816 +5669,3423,1473,5670,1354,4410,3925,4769,2173,3084,4137, 915,3338,4411,4412,3339, # 4832 +1605,1835,5671,2748, 398,3656,4413,3926,4138, 328,1913,2860,4139,3927,1331,4414, # 4848 +3029, 937,4415,5672,3657,4140,4141,3424,2161,4770,3425, 524, 742, 538,3085,1012, # 4864 +5673,5674,3928,2466,5675, 658,1103, 225,3929,5676,5677,4771,5678,4772,5679,3267, # 4880 +1243,5680,4142, 963,2250,4773,5681,2714,3658,3186,5682,5683,2596,2332,5684,4774, # 4896 +5685,5686,5687,3536, 957,3426,2547,2033,1931,2941,2467, 870,2019,3659,1746,2780, # 4912 +2781,2439,2468,5688,3930,5689,3789,3130,3790,3537,3427,3791,5690,1179,3086,5691, # 4928 +3187,2378,4416,3792,2548,3188,3131,2749,4143,5692,3428,1556,2549,2297, 977,2901, # 4944 +2034,4144,1205,3429,5693,1765,3430,3189,2125,1271, 714,1689,4775,3538,5694,2333, # 4960 +3931, 533,4417,3660,2184, 617,5695,2469,3340,3539,2315,5696,5697,3190,5698,5699, # 4976 +3932,1988, 618, 427,2651,3540,3431,5700,5701,1244,1690,5702,2819,4418,4776,5703, # 4992 +3541,4777,5704,2284,1576, 473,3661,4419,3432, 972,5705,3662,5706,3087,5707,5708, # 5008 +4778,4779,5709,3793,4145,4146,5710, 153,4780, 356,5711,1892,2902,4420,2144, 408, # 5024 + 803,2357,5712,3933,5713,4421,1646,2578,2518,4781,4782,3934,5714,3935,4422,5715, # 5040 +2416,3433, 752,5716,5717,1962,3341,2979,5718, 746,3030,2470,4783,4423,3794, 698, # 5056 +4784,1893,4424,3663,2550,4785,3664,3936,5719,3191,3434,5720,1824,1302,4147,2715, # 5072 +3937,1974,4425,5721,4426,3192, 823,1303,1288,1236,2861,3542,4148,3435, 774,3938, # 5088 +5722,1581,4786,1304,2862,3939,4787,5723,2440,2162,1083,3268,4427,4149,4428, 344, # 5104 +1173, 288,2316, 454,1683,5724,5725,1461,4788,4150,2597,5726,5727,4789, 985, 894, # 5120 +5728,3436,3193,5729,1914,2942,3795,1989,5730,2111,1975,5731,4151,5732,2579,1194, # 5136 + 425,5733,4790,3194,1245,3796,4429,5734,5735,2863,5736, 636,4791,1856,3940, 760, # 5152 +1800,5737,4430,2212,1508,4792,4152,1894,1684,2298,5738,5739,4793,4431,4432,2213, # 5168 + 479,5740,5741, 832,5742,4153,2496,5743,2980,2497,3797, 990,3132, 627,1815,2652, # 5184 +4433,1582,4434,2126,2112,3543,4794,5744, 799,4435,3195,5745,4795,2113,1737,3031, # 5200 +1018, 543, 754,4436,3342,1676,4796,4797,4154,4798,1489,5746,3544,5747,2624,2903, # 5216 +4155,5748,5749,2981,5750,5751,5752,5753,3196,4799,4800,2185,1722,5754,3269,3270, # 5232 +1843,3665,1715, 481, 365,1976,1857,5755,5756,1963,2498,4801,5757,2127,3666,3271, # 5248 + 433,1895,2064,2076,5758, 602,2750,5759,5760,5761,5762,5763,3032,1628,3437,5764, # 5264 +3197,4802,4156,2904,4803,2519,5765,2551,2782,5766,5767,5768,3343,4804,2905,5769, # 5280 +4805,5770,2864,4806,4807,1221,2982,4157,2520,5771,5772,5773,1868,1990,5774,5775, # 5296 +5776,1896,5777,5778,4808,1897,4158, 318,5779,2095,4159,4437,5780,5781, 485,5782, # 5312 + 938,3941, 553,2680, 116,5783,3942,3667,5784,3545,2681,2783,3438,3344,2820,5785, # 5328 +3668,2943,4160,1747,2944,2983,5786,5787, 207,5788,4809,5789,4810,2521,5790,3033, # 5344 + 890,3669,3943,5791,1878,3798,3439,5792,2186,2358,3440,1652,5793,5794,5795, 941, # 5360 +2299, 208,3546,4161,2020, 330,4438,3944,2906,2499,3799,4439,4811,5796,5797,5798, # 5376 #last 512 +#Everything below is of no interest for detection purpose +2522,1613,4812,5799,3345,3945,2523,5800,4162,5801,1637,4163,2471,4813,3946,5802, # 5392 +2500,3034,3800,5803,5804,2195,4814,5805,2163,5806,5807,5808,5809,5810,5811,5812, # 5408 +5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828, # 5424 +5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844, # 5440 +5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,5860, # 5456 +5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,5874,5875,5876, # 5472 +5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,5889,5890,5891,5892, # 5488 +5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,5905,5906,5907,5908, # 5504 +5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920,5921,5922,5923,5924, # 5520 +5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936,5937,5938,5939,5940, # 5536 +5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952,5953,5954,5955,5956, # 5552 +5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968,5969,5970,5971,5972, # 5568 +5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,5984,5985,5986,5987,5988, # 5584 +5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,5999,6000,6001,6002,6003,6004, # 5600 +6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020, # 5616 +6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036, # 5632 +6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052, # 5648 +6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068, # 5664 +6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084, # 5680 +6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6100, # 5696 +6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,6115,6116, # 5712 +6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,6130,6131,6132, # 5728 +6133,6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,6144,6145,6146,6147,6148, # 5744 +6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,6160,6161,6162,6163,6164, # 5760 +6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,6175,6176,6177,6178,6179,6180, # 5776 +6181,6182,6183,6184,6185,6186,6187,6188,6189,6190,6191,6192,6193,6194,6195,6196, # 5792 +6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,6207,6208,6209,6210,6211,6212, # 5808 +6213,6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,3670,6224,6225,6226,6227, # 5824 +6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,6239,6240,6241,6242,6243, # 5840 +6244,6245,6246,6247,6248,6249,6250,6251,6252,6253,6254,6255,6256,6257,6258,6259, # 5856 +6260,6261,6262,6263,6264,6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275, # 5872 +6276,6277,6278,6279,6280,6281,6282,6283,6284,6285,4815,6286,6287,6288,6289,6290, # 5888 +6291,6292,4816,6293,6294,6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305, # 5904 +6306,6307,6308,6309,6310,6311,4817,4818,6312,6313,6314,6315,6316,6317,6318,4819, # 5920 +6319,6320,6321,6322,6323,6324,6325,6326,6327,6328,6329,6330,6331,6332,6333,6334, # 5936 +6335,6336,6337,4820,6338,6339,6340,6341,6342,6343,6344,6345,6346,6347,6348,6349, # 5952 +6350,6351,6352,6353,6354,6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365, # 5968 +6366,6367,6368,6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381, # 5984 +6382,6383,6384,6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397, # 6000 +6398,6399,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,3441,6411,6412, # 6016 +6413,6414,6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,4440,6426,6427, # 6032 +6428,6429,6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443, # 6048 +6444,6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,4821,6455,6456,6457,6458, # 6064 +6459,6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,6474, # 6080 +6475,6476,6477,3947,3948,6478,6479,6480,6481,3272,4441,6482,6483,6484,6485,4442, # 6096 +6486,6487,6488,6489,6490,6491,6492,6493,6494,6495,6496,4822,6497,6498,6499,6500, # 6112 +6501,6502,6503,6504,6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516, # 6128 +6517,6518,6519,6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532, # 6144 +6533,6534,6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548, # 6160 +6549,6550,6551,6552,6553,6554,6555,6556,2784,6557,4823,6558,6559,6560,6561,6562, # 6176 +6563,6564,6565,6566,6567,6568,6569,3949,6570,6571,6572,4824,6573,6574,6575,6576, # 6192 +6577,6578,6579,6580,6581,6582,6583,4825,6584,6585,6586,3950,2785,6587,6588,6589, # 6208 +6590,6591,6592,6593,6594,6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605, # 6224 +6606,6607,6608,6609,6610,6611,6612,4826,6613,6614,6615,4827,6616,6617,6618,6619, # 6240 +6620,6621,6622,6623,6624,6625,4164,6626,6627,6628,6629,6630,6631,6632,6633,6634, # 6256 +3547,6635,4828,6636,6637,6638,6639,6640,6641,6642,3951,2984,6643,6644,6645,6646, # 6272 +6647,6648,6649,4165,6650,4829,6651,6652,4830,6653,6654,6655,6656,6657,6658,6659, # 6288 +6660,6661,6662,4831,6663,6664,6665,6666,6667,6668,6669,6670,6671,4166,6672,4832, # 6304 +3952,6673,6674,6675,6676,4833,6677,6678,6679,4167,6680,6681,6682,3198,6683,6684, # 6320 +6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,4834,6698,6699, # 6336 +6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,6715, # 6352 +6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,6730,6731, # 6368 +6732,6733,6734,4443,6735,6736,6737,6738,6739,6740,6741,6742,6743,6744,6745,4444, # 6384 +6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,6759,6760,6761, # 6400 +6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777, # 6416 +6778,6779,6780,6781,4168,6782,6783,3442,6784,6785,6786,6787,6788,6789,6790,6791, # 6432 +4169,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,6805,6806, # 6448 +6807,6808,6809,6810,6811,4835,6812,6813,6814,4445,6815,6816,4446,6817,6818,6819, # 6464 +6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,6834,6835, # 6480 +3548,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,4836,6847,6848,6849, # 6496 +6850,6851,6852,6853,6854,3953,6855,6856,6857,6858,6859,6860,6861,6862,6863,6864, # 6512 +6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,3199,6878,6879, # 6528 +6880,6881,6882,4447,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,6894, # 6544 +6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,4170,6905,6906,6907,6908,6909, # 6560 +6910,6911,6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,6924,6925, # 6576 +6926,6927,4837,6928,6929,6930,6931,6932,6933,6934,6935,6936,3346,6937,6938,4838, # 6592 +6939,6940,6941,4448,6942,6943,6944,6945,6946,4449,6947,6948,6949,6950,6951,6952, # 6608 +6953,6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968, # 6624 +6969,6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,6984, # 6640 +6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,3671,6995,6996,6997,6998,4839, # 6656 +6999,7000,7001,7002,3549,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013, # 6672 +7014,7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,7029, # 6688 +7030,4840,7031,7032,7033,7034,7035,7036,7037,7038,4841,7039,7040,7041,7042,7043, # 6704 +7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059, # 6720 +7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,2985,7071,7072,7073,7074, # 6736 +7075,7076,7077,7078,7079,7080,4842,7081,7082,7083,7084,7085,7086,7087,7088,7089, # 6752 +7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,7105, # 6768 +7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,4450,7119,7120, # 6784 +7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136, # 6800 +7137,7138,7139,7140,7141,7142,7143,4843,7144,7145,7146,7147,7148,7149,7150,7151, # 6816 +7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,7165,7166,7167, # 6832 +7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183, # 6848 +7184,7185,7186,7187,7188,4171,4172,7189,7190,7191,7192,7193,7194,7195,7196,7197, # 6864 +7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,7209,7210,7211,7212,7213, # 6880 +7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7224,7225,7226,7227,7228,7229, # 6896 +7230,7231,7232,7233,7234,7235,7236,7237,7238,7239,7240,7241,7242,7243,7244,7245, # 6912 +7246,7247,7248,7249,7250,7251,7252,7253,7254,7255,7256,7257,7258,7259,7260,7261, # 6928 +7262,7263,7264,7265,7266,7267,7268,7269,7270,7271,7272,7273,7274,7275,7276,7277, # 6944 +7278,7279,7280,7281,7282,7283,7284,7285,7286,7287,7288,7289,7290,7291,7292,7293, # 6960 +7294,7295,7296,4844,7297,7298,7299,7300,7301,7302,7303,7304,7305,7306,7307,7308, # 6976 +7309,7310,7311,7312,7313,7314,7315,7316,4451,7317,7318,7319,7320,7321,7322,7323, # 6992 +7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339, # 7008 +7340,7341,7342,7343,7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,4173,7354, # 7024 +7355,4845,7356,7357,7358,7359,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369, # 7040 +7370,7371,7372,7373,7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385, # 7056 +7386,7387,7388,4846,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400, # 7072 +7401,7402,7403,7404,7405,3672,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415, # 7088 +7416,7417,7418,7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431, # 7104 +7432,7433,7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447, # 7120 +7448,7449,7450,7451,7452,7453,4452,7454,3200,7455,7456,7457,7458,7459,7460,7461, # 7136 +7462,7463,7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,4847,7475,7476, # 7152 +7477,3133,7478,7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491, # 7168 +7492,7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,3347,7503,7504,7505,7506, # 7184 +7507,7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,4848, # 7200 +7522,7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537, # 7216 +7538,7539,7540,7541,7542,7543,7544,7545,7546,7547,7548,7549,3801,4849,7550,7551, # 7232 +7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567, # 7248 +7568,7569,3035,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582, # 7264 +7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598, # 7280 +7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614, # 7296 +7615,7616,4850,7617,7618,3802,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628, # 7312 +7629,7630,7631,7632,4851,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643, # 7328 +7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659, # 7344 +7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7670,4453,7671,7672,7673,7674, # 7360 +7675,7676,7677,7678,7679,7680,7681,7682,7683,7684,7685,7686,7687,7688,7689,7690, # 7376 +7691,7692,7693,7694,7695,7696,7697,3443,7698,7699,7700,7701,7702,4454,7703,7704, # 7392 +7705,7706,7707,7708,7709,7710,7711,7712,7713,2472,7714,7715,7716,7717,7718,7719, # 7408 +7720,7721,7722,7723,7724,7725,7726,7727,7728,7729,7730,7731,3954,7732,7733,7734, # 7424 +7735,7736,7737,7738,7739,7740,7741,7742,7743,7744,7745,7746,7747,7748,7749,7750, # 7440 +3134,7751,7752,4852,7753,7754,7755,4853,7756,7757,7758,7759,7760,4174,7761,7762, # 7456 +7763,7764,7765,7766,7767,7768,7769,7770,7771,7772,7773,7774,7775,7776,7777,7778, # 7472 +7779,7780,7781,7782,7783,7784,7785,7786,7787,7788,7789,7790,7791,7792,7793,7794, # 7488 +7795,7796,7797,7798,7799,7800,7801,7802,7803,7804,7805,4854,7806,7807,7808,7809, # 7504 +7810,7811,7812,7813,7814,7815,7816,7817,7818,7819,7820,7821,7822,7823,7824,7825, # 7520 +4855,7826,7827,7828,7829,7830,7831,7832,7833,7834,7835,7836,7837,7838,7839,7840, # 7536 +7841,7842,7843,7844,7845,7846,7847,3955,7848,7849,7850,7851,7852,7853,7854,7855, # 7552 +7856,7857,7858,7859,7860,3444,7861,7862,7863,7864,7865,7866,7867,7868,7869,7870, # 7568 +7871,7872,7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886, # 7584 +7887,7888,7889,7890,7891,4175,7892,7893,7894,7895,7896,4856,4857,7897,7898,7899, # 7600 +7900,2598,7901,7902,7903,7904,7905,7906,7907,7908,4455,7909,7910,7911,7912,7913, # 7616 +7914,3201,7915,7916,7917,7918,7919,7920,7921,4858,7922,7923,7924,7925,7926,7927, # 7632 +7928,7929,7930,7931,7932,7933,7934,7935,7936,7937,7938,7939,7940,7941,7942,7943, # 7648 +7944,7945,7946,7947,7948,7949,7950,7951,7952,7953,7954,7955,7956,7957,7958,7959, # 7664 +7960,7961,7962,7963,7964,7965,7966,7967,7968,7969,7970,7971,7972,7973,7974,7975, # 7680 +7976,7977,7978,7979,7980,7981,4859,7982,7983,7984,7985,7986,7987,7988,7989,7990, # 7696 +7991,7992,7993,7994,7995,7996,4860,7997,7998,7999,8000,8001,8002,8003,8004,8005, # 7712 +8006,8007,8008,8009,8010,8011,8012,8013,8014,8015,8016,4176,8017,8018,8019,8020, # 7728 +8021,8022,8023,4861,8024,8025,8026,8027,8028,8029,8030,8031,8032,8033,8034,8035, # 7744 +8036,4862,4456,8037,8038,8039,8040,4863,8041,8042,8043,8044,8045,8046,8047,8048, # 7760 +8049,8050,8051,8052,8053,8054,8055,8056,8057,8058,8059,8060,8061,8062,8063,8064, # 7776 +8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079,8080, # 7792 +8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,8096, # 7808 +8097,8098,8099,4864,4177,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110, # 7824 +8111,8112,8113,8114,8115,8116,8117,8118,8119,8120,4178,8121,8122,8123,8124,8125, # 7840 +8126,8127,8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,8138,8139,8140,8141, # 7856 +8142,8143,8144,8145,4865,4866,8146,8147,8148,8149,8150,8151,8152,8153,8154,8155, # 7872 +8156,8157,8158,8159,8160,8161,8162,8163,8164,8165,4179,8166,8167,8168,8169,8170, # 7888 +8171,8172,8173,8174,8175,8176,8177,8178,8179,8180,8181,4457,8182,8183,8184,8185, # 7904 +8186,8187,8188,8189,8190,8191,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201, # 7920 +8202,8203,8204,8205,8206,8207,8208,8209,8210,8211,8212,8213,8214,8215,8216,8217, # 7936 +8218,8219,8220,8221,8222,8223,8224,8225,8226,8227,8228,8229,8230,8231,8232,8233, # 7952 +8234,8235,8236,8237,8238,8239,8240,8241,8242,8243,8244,8245,8246,8247,8248,8249, # 7968 +8250,8251,8252,8253,8254,8255,8256,3445,8257,8258,8259,8260,8261,8262,4458,8263, # 7984 +8264,8265,8266,8267,8268,8269,8270,8271,8272,4459,8273,8274,8275,8276,3550,8277, # 8000 +8278,8279,8280,8281,8282,8283,8284,8285,8286,8287,8288,8289,4460,8290,8291,8292, # 8016 +8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,8304,8305,8306,8307,4867, # 8032 +8308,8309,8310,8311,8312,3551,8313,8314,8315,8316,8317,8318,8319,8320,8321,8322, # 8048 +8323,8324,8325,8326,4868,8327,8328,8329,8330,8331,8332,8333,8334,8335,8336,8337, # 8064 +8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,8348,8349,8350,8351,8352,8353, # 8080 +8354,8355,8356,8357,8358,8359,8360,8361,8362,8363,4869,4461,8364,8365,8366,8367, # 8096 +8368,8369,8370,4870,8371,8372,8373,8374,8375,8376,8377,8378,8379,8380,8381,8382, # 8112 +8383,8384,8385,8386,8387,8388,8389,8390,8391,8392,8393,8394,8395,8396,8397,8398, # 8128 +8399,8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,4871,8411,8412,8413, # 8144 +8414,8415,8416,8417,8418,8419,8420,8421,8422,4462,8423,8424,8425,8426,8427,8428, # 8160 +8429,8430,8431,8432,8433,2986,8434,8435,8436,8437,8438,8439,8440,8441,8442,8443, # 8176 +8444,8445,8446,8447,8448,8449,8450,8451,8452,8453,8454,8455,8456,8457,8458,8459, # 8192 +8460,8461,8462,8463,8464,8465,8466,8467,8468,8469,8470,8471,8472,8473,8474,8475, # 8208 +8476,8477,8478,4180,8479,8480,8481,8482,8483,8484,8485,8486,8487,8488,8489,8490, # 8224 +8491,8492,8493,8494,8495,8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8506, # 8240 +8507,8508,8509,8510,8511,8512,8513,8514,8515,8516,8517,8518,8519,8520,8521,8522, # 8256 +8523,8524,8525,8526,8527,8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538, # 8272 +8539,8540,8541,8542,8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554, # 8288 +8555,8556,8557,8558,8559,8560,8561,8562,8563,8564,4872,8565,8566,8567,8568,8569, # 8304 +8570,8571,8572,8573,4873,8574,8575,8576,8577,8578,8579,8580,8581,8582,8583,8584, # 8320 +8585,8586,8587,8588,8589,8590,8591,8592,8593,8594,8595,8596,8597,8598,8599,8600, # 8336 +8601,8602,8603,8604,8605,3803,8606,8607,8608,8609,8610,8611,8612,8613,4874,3804, # 8352 +8614,8615,8616,8617,8618,8619,8620,8621,3956,8622,8623,8624,8625,8626,8627,8628, # 8368 +8629,8630,8631,8632,8633,8634,8635,8636,8637,8638,2865,8639,8640,8641,8642,8643, # 8384 +8644,8645,8646,8647,8648,8649,8650,8651,8652,8653,8654,8655,8656,4463,8657,8658, # 8400 +8659,4875,4876,8660,8661,8662,8663,8664,8665,8666,8667,8668,8669,8670,8671,8672, # 8416 +8673,8674,8675,8676,8677,8678,8679,8680,8681,4464,8682,8683,8684,8685,8686,8687, # 8432 +8688,8689,8690,8691,8692,8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703, # 8448 +8704,8705,8706,8707,8708,8709,2261,8710,8711,8712,8713,8714,8715,8716,8717,8718, # 8464 +8719,8720,8721,8722,8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,4181, # 8480 +8734,8735,8736,8737,8738,8739,8740,8741,8742,8743,8744,8745,8746,8747,8748,8749, # 8496 +8750,8751,8752,8753,8754,8755,8756,8757,8758,8759,8760,8761,8762,8763,4877,8764, # 8512 +8765,8766,8767,8768,8769,8770,8771,8772,8773,8774,8775,8776,8777,8778,8779,8780, # 8528 +8781,8782,8783,8784,8785,8786,8787,8788,4878,8789,4879,8790,8791,8792,4880,8793, # 8544 +8794,8795,8796,8797,8798,8799,8800,8801,4881,8802,8803,8804,8805,8806,8807,8808, # 8560 +8809,8810,8811,8812,8813,8814,8815,3957,8816,8817,8818,8819,8820,8821,8822,8823, # 8576 +8824,8825,8826,8827,8828,8829,8830,8831,8832,8833,8834,8835,8836,8837,8838,8839, # 8592 +8840,8841,8842,8843,8844,8845,8846,8847,4882,8848,8849,8850,8851,8852,8853,8854, # 8608 +8855,8856,8857,8858,8859,8860,8861,8862,8863,8864,8865,8866,8867,8868,8869,8870, # 8624 +8871,8872,8873,8874,8875,8876,8877,8878,8879,8880,8881,8882,8883,8884,3202,8885, # 8640 +8886,8887,8888,8889,8890,8891,8892,8893,8894,8895,8896,8897,8898,8899,8900,8901, # 8656 +8902,8903,8904,8905,8906,8907,8908,8909,8910,8911,8912,8913,8914,8915,8916,8917, # 8672 +8918,8919,8920,8921,8922,8923,8924,4465,8925,8926,8927,8928,8929,8930,8931,8932, # 8688 +4883,8933,8934,8935,8936,8937,8938,8939,8940,8941,8942,8943,2214,8944,8945,8946, # 8704 +8947,8948,8949,8950,8951,8952,8953,8954,8955,8956,8957,8958,8959,8960,8961,8962, # 8720 +8963,8964,8965,4884,8966,8967,8968,8969,8970,8971,8972,8973,8974,8975,8976,8977, # 8736 +8978,8979,8980,8981,8982,8983,8984,8985,8986,8987,8988,8989,8990,8991,8992,4885, # 8752 +8993,8994,8995,8996,8997,8998,8999,9000,9001,9002,9003,9004,9005,9006,9007,9008, # 8768 +9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,9020,9021,4182,9022,9023, # 8784 +9024,9025,9026,9027,9028,9029,9030,9031,9032,9033,9034,9035,9036,9037,9038,9039, # 8800 +9040,9041,9042,9043,9044,9045,9046,9047,9048,9049,9050,9051,9052,9053,9054,9055, # 8816 +9056,9057,9058,9059,9060,9061,9062,9063,4886,9064,9065,9066,9067,9068,9069,4887, # 8832 +9070,9071,9072,9073,9074,9075,9076,9077,9078,9079,9080,9081,9082,9083,9084,9085, # 8848 +9086,9087,9088,9089,9090,9091,9092,9093,9094,9095,9096,9097,9098,9099,9100,9101, # 8864 +9102,9103,9104,9105,9106,9107,9108,9109,9110,9111,9112,9113,9114,9115,9116,9117, # 8880 +9118,9119,9120,9121,9122,9123,9124,9125,9126,9127,9128,9129,9130,9131,9132,9133, # 8896 +9134,9135,9136,9137,9138,9139,9140,9141,3958,9142,9143,9144,9145,9146,9147,9148, # 8912 +9149,9150,9151,4888,9152,9153,9154,9155,9156,9157,9158,9159,9160,9161,9162,9163, # 8928 +9164,9165,9166,9167,9168,9169,9170,9171,9172,9173,9174,9175,4889,9176,9177,9178, # 8944 +9179,9180,9181,9182,9183,9184,9185,9186,9187,9188,9189,9190,9191,9192,9193,9194, # 8960 +9195,9196,9197,9198,9199,9200,9201,9202,9203,4890,9204,9205,9206,9207,9208,9209, # 8976 +9210,9211,9212,9213,9214,9215,9216,9217,9218,9219,9220,9221,9222,4466,9223,9224, # 8992 +9225,9226,9227,9228,9229,9230,9231,9232,9233,9234,9235,9236,9237,9238,9239,9240, # 9008 +9241,9242,9243,9244,9245,4891,9246,9247,9248,9249,9250,9251,9252,9253,9254,9255, # 9024 +9256,9257,4892,9258,9259,9260,9261,4893,4894,9262,9263,9264,9265,9266,9267,9268, # 9040 +9269,9270,9271,9272,9273,4467,9274,9275,9276,9277,9278,9279,9280,9281,9282,9283, # 9056 +9284,9285,3673,9286,9287,9288,9289,9290,9291,9292,9293,9294,9295,9296,9297,9298, # 9072 +9299,9300,9301,9302,9303,9304,9305,9306,9307,9308,9309,9310,9311,9312,9313,9314, # 9088 +9315,9316,9317,9318,9319,9320,9321,9322,4895,9323,9324,9325,9326,9327,9328,9329, # 9104 +9330,9331,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345, # 9120 +9346,9347,4468,9348,9349,9350,9351,9352,9353,9354,9355,9356,9357,9358,9359,9360, # 9136 +9361,9362,9363,9364,9365,9366,9367,9368,9369,9370,9371,9372,9373,4896,9374,4469, # 9152 +9375,9376,9377,9378,9379,4897,9380,9381,9382,9383,9384,9385,9386,9387,9388,9389, # 9168 +9390,9391,9392,9393,9394,9395,9396,9397,9398,9399,9400,9401,9402,9403,9404,9405, # 9184 +9406,4470,9407,2751,9408,9409,3674,3552,9410,9411,9412,9413,9414,9415,9416,9417, # 9200 +9418,9419,9420,9421,4898,9422,9423,9424,9425,9426,9427,9428,9429,3959,9430,9431, # 9216 +9432,9433,9434,9435,9436,4471,9437,9438,9439,9440,9441,9442,9443,9444,9445,9446, # 9232 +9447,9448,9449,9450,3348,9451,9452,9453,9454,9455,9456,9457,9458,9459,9460,9461, # 9248 +9462,9463,9464,9465,9466,9467,9468,9469,9470,9471,9472,4899,9473,9474,9475,9476, # 9264 +9477,4900,9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,9488,3349,9489,9490, # 9280 +9491,9492,9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,9503,9504,9505,9506, # 9296 +9507,9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,9518,9519,9520,4901,9521, # 9312 +9522,9523,9524,9525,9526,4902,9527,9528,9529,9530,9531,9532,9533,9534,9535,9536, # 9328 +9537,9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,9548,9549,9550,9551,9552, # 9344 +9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568, # 9360 +9569,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,9581,9582,9583,9584, # 9376 +3805,9585,9586,9587,9588,9589,9590,9591,9592,9593,9594,9595,9596,9597,9598,9599, # 9392 +9600,9601,9602,4903,9603,9604,9605,9606,9607,4904,9608,9609,9610,9611,9612,9613, # 9408 +9614,4905,9615,9616,9617,9618,9619,9620,9621,9622,9623,9624,9625,9626,9627,9628, # 9424 +9629,9630,9631,9632,4906,9633,9634,9635,9636,9637,9638,9639,9640,9641,9642,9643, # 9440 +4907,9644,9645,9646,9647,9648,9649,9650,9651,9652,9653,9654,9655,9656,9657,9658, # 9456 +9659,9660,9661,9662,9663,9664,9665,9666,9667,9668,9669,9670,9671,9672,4183,9673, # 9472 +9674,9675,9676,9677,4908,9678,9679,9680,9681,4909,9682,9683,9684,9685,9686,9687, # 9488 +9688,9689,9690,4910,9691,9692,9693,3675,9694,9695,9696,2945,9697,9698,9699,9700, # 9504 +9701,9702,9703,9704,9705,4911,9706,9707,9708,9709,9710,9711,9712,9713,9714,9715, # 9520 +9716,9717,9718,9719,9720,9721,9722,9723,9724,9725,9726,9727,9728,9729,9730,9731, # 9536 +9732,9733,9734,9735,4912,9736,9737,9738,9739,9740,4913,9741,9742,9743,9744,9745, # 9552 +9746,9747,9748,9749,9750,9751,9752,9753,9754,9755,9756,9757,9758,4914,9759,9760, # 9568 +9761,9762,9763,9764,9765,9766,9767,9768,9769,9770,9771,9772,9773,9774,9775,9776, # 9584 +9777,9778,9779,9780,9781,9782,4915,9783,9784,9785,9786,9787,9788,9789,9790,9791, # 9600 +9792,9793,4916,9794,9795,9796,9797,9798,9799,9800,9801,9802,9803,9804,9805,9806, # 9616 +9807,9808,9809,9810,9811,9812,9813,9814,9815,9816,9817,9818,9819,9820,9821,9822, # 9632 +9823,9824,9825,9826,9827,9828,9829,9830,9831,9832,9833,9834,9835,9836,9837,9838, # 9648 +9839,9840,9841,9842,9843,9844,9845,9846,9847,9848,9849,9850,9851,9852,9853,9854, # 9664 +9855,9856,9857,9858,9859,9860,9861,9862,9863,9864,9865,9866,9867,9868,4917,9869, # 9680 +9870,9871,9872,9873,9874,9875,9876,9877,9878,9879,9880,9881,9882,9883,9884,9885, # 9696 +9886,9887,9888,9889,9890,9891,9892,4472,9893,9894,9895,9896,9897,3806,9898,9899, # 9712 +9900,9901,9902,9903,9904,9905,9906,9907,9908,9909,9910,9911,9912,9913,9914,4918, # 9728 +9915,9916,9917,4919,9918,9919,9920,9921,4184,9922,9923,9924,9925,9926,9927,9928, # 9744 +9929,9930,9931,9932,9933,9934,9935,9936,9937,9938,9939,9940,9941,9942,9943,9944, # 9760 +9945,9946,4920,9947,9948,9949,9950,9951,9952,9953,9954,9955,4185,9956,9957,9958, # 9776 +9959,9960,9961,9962,9963,9964,9965,4921,9966,9967,9968,4473,9969,9970,9971,9972, # 9792 +9973,9974,9975,9976,9977,4474,9978,9979,9980,9981,9982,9983,9984,9985,9986,9987, # 9808 +9988,9989,9990,9991,9992,9993,9994,9995,9996,9997,9998,9999,10000,10001,10002,10003, # 9824 +10004,10005,10006,10007,10008,10009,10010,10011,10012,10013,10014,10015,10016,10017,10018,10019, # 9840 +10020,10021,4922,10022,4923,10023,10024,10025,10026,10027,10028,10029,10030,10031,10032,10033, # 9856 +10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,10044,10045,10046,10047,10048,4924, # 9872 +10049,10050,10051,10052,10053,10054,10055,10056,10057,10058,10059,10060,10061,10062,10063,10064, # 9888 +10065,10066,10067,10068,10069,10070,10071,10072,10073,10074,10075,10076,10077,10078,10079,10080, # 9904 +10081,10082,10083,10084,10085,10086,10087,4475,10088,10089,10090,10091,10092,10093,10094,10095, # 9920 +10096,10097,4476,10098,10099,10100,10101,10102,10103,10104,10105,10106,10107,10108,10109,10110, # 9936 +10111,2174,10112,10113,10114,10115,10116,10117,10118,10119,10120,10121,10122,10123,10124,10125, # 9952 +10126,10127,10128,10129,10130,10131,10132,10133,10134,10135,10136,10137,10138,10139,10140,3807, # 9968 +4186,4925,10141,10142,10143,10144,10145,10146,10147,4477,4187,10148,10149,10150,10151,10152, # 9984 +10153,4188,10154,10155,10156,10157,10158,10159,10160,10161,4926,10162,10163,10164,10165,10166, #10000 +10167,10168,10169,10170,10171,10172,10173,10174,10175,10176,10177,10178,10179,10180,10181,10182, #10016 +10183,10184,10185,10186,10187,10188,10189,10190,10191,10192,3203,10193,10194,10195,10196,10197, #10032 +10198,10199,10200,4478,10201,10202,10203,10204,4479,10205,10206,10207,10208,10209,10210,10211, #10048 +10212,10213,10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,10224,10225,10226,10227, #10064 +10228,10229,10230,10231,10232,10233,10234,4927,10235,10236,10237,10238,10239,10240,10241,10242, #10080 +10243,10244,10245,10246,10247,10248,10249,10250,10251,10252,10253,10254,10255,10256,10257,10258, #10096 +10259,10260,10261,10262,10263,10264,10265,10266,10267,10268,10269,10270,10271,10272,10273,4480, #10112 +4928,4929,10274,10275,10276,10277,10278,10279,10280,10281,10282,10283,10284,10285,10286,10287, #10128 +10288,10289,10290,10291,10292,10293,10294,10295,10296,10297,10298,10299,10300,10301,10302,10303, #10144 +10304,10305,10306,10307,10308,10309,10310,10311,10312,10313,10314,10315,10316,10317,10318,10319, #10160 +10320,10321,10322,10323,10324,10325,10326,10327,10328,10329,10330,10331,10332,10333,10334,4930, #10176 +10335,10336,10337,10338,10339,10340,10341,10342,4931,10343,10344,10345,10346,10347,10348,10349, #10192 +10350,10351,10352,10353,10354,10355,3088,10356,2786,10357,10358,10359,10360,4189,10361,10362, #10208 +10363,10364,10365,10366,10367,10368,10369,10370,10371,10372,10373,10374,10375,4932,10376,10377, #10224 +10378,10379,10380,10381,10382,10383,10384,10385,10386,10387,10388,10389,10390,10391,10392,4933, #10240 +10393,10394,10395,4934,10396,10397,10398,10399,10400,10401,10402,10403,10404,10405,10406,10407, #10256 +10408,10409,10410,10411,10412,3446,10413,10414,10415,10416,10417,10418,10419,10420,10421,10422, #10272 +10423,4935,10424,10425,10426,10427,10428,10429,10430,4936,10431,10432,10433,10434,10435,10436, #10288 +10437,10438,10439,10440,10441,10442,10443,4937,10444,10445,10446,10447,4481,10448,10449,10450, #10304 +10451,10452,10453,10454,10455,10456,10457,10458,10459,10460,10461,10462,10463,10464,10465,10466, #10320 +10467,10468,10469,10470,10471,10472,10473,10474,10475,10476,10477,10478,10479,10480,10481,10482, #10336 +10483,10484,10485,10486,10487,10488,10489,10490,10491,10492,10493,10494,10495,10496,10497,10498, #10352 +10499,10500,10501,10502,10503,10504,10505,4938,10506,10507,10508,10509,10510,2552,10511,10512, #10368 +10513,10514,10515,10516,3447,10517,10518,10519,10520,10521,10522,10523,10524,10525,10526,10527, #10384 +10528,10529,10530,10531,10532,10533,10534,10535,10536,10537,10538,10539,10540,10541,10542,10543, #10400 +4482,10544,4939,10545,10546,10547,10548,10549,10550,10551,10552,10553,10554,10555,10556,10557, #10416 +10558,10559,10560,10561,10562,10563,10564,10565,10566,10567,3676,4483,10568,10569,10570,10571, #10432 +10572,3448,10573,10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,10584,10585,10586, #10448 +10587,10588,10589,10590,10591,10592,10593,10594,10595,10596,10597,10598,10599,10600,10601,10602, #10464 +10603,10604,10605,10606,10607,10608,10609,10610,10611,10612,10613,10614,10615,10616,10617,10618, #10480 +10619,10620,10621,10622,10623,10624,10625,10626,10627,4484,10628,10629,10630,10631,10632,4940, #10496 +10633,10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,10644,10645,10646,10647,10648, #10512 +10649,10650,10651,10652,10653,10654,10655,10656,4941,10657,10658,10659,2599,10660,10661,10662, #10528 +10663,10664,10665,10666,3089,10667,10668,10669,10670,10671,10672,10673,10674,10675,10676,10677, #10544 +10678,10679,10680,4942,10681,10682,10683,10684,10685,10686,10687,10688,10689,10690,10691,10692, #10560 +10693,10694,10695,10696,10697,4485,10698,10699,10700,10701,10702,10703,10704,4943,10705,3677, #10576 +10706,10707,10708,10709,10710,10711,10712,4944,10713,10714,10715,10716,10717,10718,10719,10720, #10592 +10721,10722,10723,10724,10725,10726,10727,10728,4945,10729,10730,10731,10732,10733,10734,10735, #10608 +10736,10737,10738,10739,10740,10741,10742,10743,10744,10745,10746,10747,10748,10749,10750,10751, #10624 +10752,10753,10754,10755,10756,10757,10758,10759,10760,10761,4946,10762,10763,10764,10765,10766, #10640 +10767,4947,4948,10768,10769,10770,10771,10772,10773,10774,10775,10776,10777,10778,10779,10780, #10656 +10781,10782,10783,10784,10785,10786,10787,10788,10789,10790,10791,10792,10793,10794,10795,10796, #10672 +10797,10798,10799,10800,10801,10802,10803,10804,10805,10806,10807,10808,10809,10810,10811,10812, #10688 +10813,10814,10815,10816,10817,10818,10819,10820,10821,10822,10823,10824,10825,10826,10827,10828, #10704 +10829,10830,10831,10832,10833,10834,10835,10836,10837,10838,10839,10840,10841,10842,10843,10844, #10720 +10845,10846,10847,10848,10849,10850,10851,10852,10853,10854,10855,10856,10857,10858,10859,10860, #10736 +10861,10862,10863,10864,10865,10866,10867,10868,10869,10870,10871,10872,10873,10874,10875,10876, #10752 +10877,10878,4486,10879,10880,10881,10882,10883,10884,10885,4949,10886,10887,10888,10889,10890, #10768 +10891,10892,10893,10894,10895,10896,10897,10898,10899,10900,10901,10902,10903,10904,10905,10906, #10784 +10907,10908,10909,10910,10911,10912,10913,10914,10915,10916,10917,10918,10919,4487,10920,10921, #10800 +10922,10923,10924,10925,10926,10927,10928,10929,10930,10931,10932,4950,10933,10934,10935,10936, #10816 +10937,10938,10939,10940,10941,10942,10943,10944,10945,10946,10947,10948,10949,4488,10950,10951, #10832 +10952,10953,10954,10955,10956,10957,10958,10959,4190,10960,10961,10962,10963,10964,10965,10966, #10848 +10967,10968,10969,10970,10971,10972,10973,10974,10975,10976,10977,10978,10979,10980,10981,10982, #10864 +10983,10984,10985,10986,10987,10988,10989,10990,10991,10992,10993,10994,10995,10996,10997,10998, #10880 +10999,11000,11001,11002,11003,11004,11005,11006,3960,11007,11008,11009,11010,11011,11012,11013, #10896 +11014,11015,11016,11017,11018,11019,11020,11021,11022,11023,11024,11025,11026,11027,11028,11029, #10912 +11030,11031,11032,4951,11033,11034,11035,11036,11037,11038,11039,11040,11041,11042,11043,11044, #10928 +11045,11046,11047,4489,11048,11049,11050,11051,4952,11052,11053,11054,11055,11056,11057,11058, #10944 +4953,11059,11060,11061,11062,11063,11064,11065,11066,11067,11068,11069,11070,11071,4954,11072, #10960 +11073,11074,11075,11076,11077,11078,11079,11080,11081,11082,11083,11084,11085,11086,11087,11088, #10976 +11089,11090,11091,11092,11093,11094,11095,11096,11097,11098,11099,11100,11101,11102,11103,11104, #10992 +11105,11106,11107,11108,11109,11110,11111,11112,11113,11114,11115,3808,11116,11117,11118,11119, #11008 +11120,11121,11122,11123,11124,11125,11126,11127,11128,11129,11130,11131,11132,11133,11134,4955, #11024 +11135,11136,11137,11138,11139,11140,11141,11142,11143,11144,11145,11146,11147,11148,11149,11150, #11040 +11151,11152,11153,11154,11155,11156,11157,11158,11159,11160,11161,4956,11162,11163,11164,11165, #11056 +11166,11167,11168,11169,11170,11171,11172,11173,11174,11175,11176,11177,11178,11179,11180,4957, #11072 +11181,11182,11183,11184,11185,11186,4958,11187,11188,11189,11190,11191,11192,11193,11194,11195, #11088 +11196,11197,11198,11199,11200,3678,11201,11202,11203,11204,11205,11206,4191,11207,11208,11209, #11104 +11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,11220,11221,11222,11223,11224,11225, #11120 +11226,11227,11228,11229,11230,11231,11232,11233,11234,11235,11236,11237,11238,11239,11240,11241, #11136 +11242,11243,11244,11245,11246,11247,11248,11249,11250,11251,4959,11252,11253,11254,11255,11256, #11152 +11257,11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,11268,11269,11270,11271,11272, #11168 +11273,11274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,11286,11287,11288, #11184 +11289,11290,11291,11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304, #11200 +11305,11306,11307,11308,11309,11310,11311,11312,11313,11314,3679,11315,11316,11317,11318,4490, #11216 +11319,11320,11321,11322,11323,11324,11325,11326,11327,11328,11329,11330,11331,11332,11333,11334, #11232 +11335,11336,11337,11338,11339,11340,11341,11342,11343,11344,11345,11346,11347,4960,11348,11349, #11248 +11350,11351,11352,11353,11354,11355,11356,11357,11358,11359,11360,11361,11362,11363,11364,11365, #11264 +11366,11367,11368,11369,11370,11371,11372,11373,11374,11375,11376,11377,3961,4961,11378,11379, #11280 +11380,11381,11382,11383,11384,11385,11386,11387,11388,11389,11390,11391,11392,11393,11394,11395, #11296 +11396,11397,4192,11398,11399,11400,11401,11402,11403,11404,11405,11406,11407,11408,11409,11410, #11312 +11411,4962,11412,11413,11414,11415,11416,11417,11418,11419,11420,11421,11422,11423,11424,11425, #11328 +11426,11427,11428,11429,11430,11431,11432,11433,11434,11435,11436,11437,11438,11439,11440,11441, #11344 +11442,11443,11444,11445,11446,11447,11448,11449,11450,11451,11452,11453,11454,11455,11456,11457, #11360 +11458,11459,11460,11461,11462,11463,11464,11465,11466,11467,11468,11469,4963,11470,11471,4491, #11376 +11472,11473,11474,11475,4964,11476,11477,11478,11479,11480,11481,11482,11483,11484,11485,11486, #11392 +11487,11488,11489,11490,11491,11492,4965,11493,11494,11495,11496,11497,11498,11499,11500,11501, #11408 +11502,11503,11504,11505,11506,11507,11508,11509,11510,11511,11512,11513,11514,11515,11516,11517, #11424 +11518,11519,11520,11521,11522,11523,11524,11525,11526,11527,11528,11529,3962,11530,11531,11532, #11440 +11533,11534,11535,11536,11537,11538,11539,11540,11541,11542,11543,11544,11545,11546,11547,11548, #11456 +11549,11550,11551,11552,11553,11554,11555,11556,11557,11558,11559,11560,11561,11562,11563,11564, #11472 +4193,4194,11565,11566,11567,11568,11569,11570,11571,11572,11573,11574,11575,11576,11577,11578, #11488 +11579,11580,11581,11582,11583,11584,11585,11586,11587,11588,11589,11590,11591,4966,4195,11592, #11504 +11593,11594,11595,11596,11597,11598,11599,11600,11601,11602,11603,11604,3090,11605,11606,11607, #11520 +11608,11609,11610,4967,11611,11612,11613,11614,11615,11616,11617,11618,11619,11620,11621,11622, #11536 +11623,11624,11625,11626,11627,11628,11629,11630,11631,11632,11633,11634,11635,11636,11637,11638, #11552 +11639,11640,11641,11642,11643,11644,11645,11646,11647,11648,11649,11650,11651,11652,11653,11654, #11568 +11655,11656,11657,11658,11659,11660,11661,11662,11663,11664,11665,11666,11667,11668,11669,11670, #11584 +11671,11672,11673,11674,4968,11675,11676,11677,11678,11679,11680,11681,11682,11683,11684,11685, #11600 +11686,11687,11688,11689,11690,11691,11692,11693,3809,11694,11695,11696,11697,11698,11699,11700, #11616 +11701,11702,11703,11704,11705,11706,11707,11708,11709,11710,11711,11712,11713,11714,11715,11716, #11632 +11717,11718,3553,11719,11720,11721,11722,11723,11724,11725,11726,11727,11728,11729,11730,4969, #11648 +11731,11732,11733,11734,11735,11736,11737,11738,11739,11740,4492,11741,11742,11743,11744,11745, #11664 +11746,11747,11748,11749,11750,11751,11752,4970,11753,11754,11755,11756,11757,11758,11759,11760, #11680 +11761,11762,11763,11764,11765,11766,11767,11768,11769,11770,11771,11772,11773,11774,11775,11776, #11696 +11777,11778,11779,11780,11781,11782,11783,11784,11785,11786,11787,11788,11789,11790,4971,11791, #11712 +11792,11793,11794,11795,11796,11797,4972,11798,11799,11800,11801,11802,11803,11804,11805,11806, #11728 +11807,11808,11809,11810,4973,11811,11812,11813,11814,11815,11816,11817,11818,11819,11820,11821, #11744 +11822,11823,11824,11825,11826,11827,11828,11829,11830,11831,11832,11833,11834,3680,3810,11835, #11760 +11836,4974,11837,11838,11839,11840,11841,11842,11843,11844,11845,11846,11847,11848,11849,11850, #11776 +11851,11852,11853,11854,11855,11856,11857,11858,11859,11860,11861,11862,11863,11864,11865,11866, #11792 +11867,11868,11869,11870,11871,11872,11873,11874,11875,11876,11877,11878,11879,11880,11881,11882, #11808 +11883,11884,4493,11885,11886,11887,11888,11889,11890,11891,11892,11893,11894,11895,11896,11897, #11824 +11898,11899,11900,11901,11902,11903,11904,11905,11906,11907,11908,11909,11910,11911,11912,11913, #11840 +11914,11915,4975,11916,11917,11918,11919,11920,11921,11922,11923,11924,11925,11926,11927,11928, #11856 +11929,11930,11931,11932,11933,11934,11935,11936,11937,11938,11939,11940,11941,11942,11943,11944, #11872 +11945,11946,11947,11948,11949,4976,11950,11951,11952,11953,11954,11955,11956,11957,11958,11959, #11888 +11960,11961,11962,11963,11964,11965,11966,11967,11968,11969,11970,11971,11972,11973,11974,11975, #11904 +11976,11977,11978,11979,11980,11981,11982,11983,11984,11985,11986,11987,4196,11988,11989,11990, #11920 +11991,11992,4977,11993,11994,11995,11996,11997,11998,11999,12000,12001,12002,12003,12004,12005, #11936 +12006,12007,12008,12009,12010,12011,12012,12013,12014,12015,12016,12017,12018,12019,12020,12021, #11952 +12022,12023,12024,12025,12026,12027,12028,12029,12030,12031,12032,12033,12034,12035,12036,12037, #11968 +12038,12039,12040,12041,12042,12043,12044,12045,12046,12047,12048,12049,12050,12051,12052,12053, #11984 +12054,12055,12056,12057,12058,12059,12060,12061,4978,12062,12063,12064,12065,12066,12067,12068, #12000 +12069,12070,12071,12072,12073,12074,12075,12076,12077,12078,12079,12080,12081,12082,12083,12084, #12016 +12085,12086,12087,12088,12089,12090,12091,12092,12093,12094,12095,12096,12097,12098,12099,12100, #12032 +12101,12102,12103,12104,12105,12106,12107,12108,12109,12110,12111,12112,12113,12114,12115,12116, #12048 +12117,12118,12119,12120,12121,12122,12123,4979,12124,12125,12126,12127,12128,4197,12129,12130, #12064 +12131,12132,12133,12134,12135,12136,12137,12138,12139,12140,12141,12142,12143,12144,12145,12146, #12080 +12147,12148,12149,12150,12151,12152,12153,12154,4980,12155,12156,12157,12158,12159,12160,4494, #12096 +12161,12162,12163,12164,3811,12165,12166,12167,12168,12169,4495,12170,12171,4496,12172,12173, #12112 +12174,12175,12176,3812,12177,12178,12179,12180,12181,12182,12183,12184,12185,12186,12187,12188, #12128 +12189,12190,12191,12192,12193,12194,12195,12196,12197,12198,12199,12200,12201,12202,12203,12204, #12144 +12205,12206,12207,12208,12209,12210,12211,12212,12213,12214,12215,12216,12217,12218,12219,12220, #12160 +12221,4981,12222,12223,12224,12225,12226,12227,12228,12229,12230,12231,12232,12233,12234,12235, #12176 +4982,12236,12237,12238,12239,12240,12241,12242,12243,12244,12245,4983,12246,12247,12248,12249, #12192 +4984,12250,12251,12252,12253,12254,12255,12256,12257,12258,12259,12260,12261,12262,12263,12264, #12208 +4985,12265,4497,12266,12267,12268,12269,12270,12271,12272,12273,12274,12275,12276,12277,12278, #12224 +12279,12280,12281,12282,12283,12284,12285,12286,12287,4986,12288,12289,12290,12291,12292,12293, #12240 +12294,12295,12296,2473,12297,12298,12299,12300,12301,12302,12303,12304,12305,12306,12307,12308, #12256 +12309,12310,12311,12312,12313,12314,12315,12316,12317,12318,12319,3963,12320,12321,12322,12323, #12272 +12324,12325,12326,12327,12328,12329,12330,12331,12332,4987,12333,12334,12335,12336,12337,12338, #12288 +12339,12340,12341,12342,12343,12344,12345,12346,12347,12348,12349,12350,12351,12352,12353,12354, #12304 +12355,12356,12357,12358,12359,3964,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369, #12320 +12370,3965,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384, #12336 +12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400, #12352 +12401,12402,12403,12404,12405,12406,12407,12408,4988,12409,12410,12411,12412,12413,12414,12415, #12368 +12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431, #12384 +12432,12433,12434,12435,12436,12437,12438,3554,12439,12440,12441,12442,12443,12444,12445,12446, #12400 +12447,12448,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462, #12416 +12463,12464,4989,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477, #12432 +12478,12479,12480,4990,12481,12482,12483,12484,12485,12486,12487,12488,12489,4498,12490,12491, #12448 +12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507, #12464 +12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523, #12480 +12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,12535,12536,12537,12538,12539, #12496 +12540,12541,12542,12543,12544,12545,12546,12547,12548,12549,12550,12551,4991,12552,12553,12554, #12512 +12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570, #12528 +12571,12572,12573,12574,12575,12576,12577,12578,3036,12579,12580,12581,12582,12583,3966,12584, #12544 +12585,12586,12587,12588,12589,12590,12591,12592,12593,12594,12595,12596,12597,12598,12599,12600, #12560 +12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,12614,12615,12616, #12576 +12617,12618,12619,12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,12632, #12592 +12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,4499,12647, #12608 +12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,12662,12663, #12624 +12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679, #12640 +12680,12681,12682,12683,12684,12685,12686,12687,12688,12689,12690,12691,12692,12693,12694,12695, #12656 +12696,12697,12698,4992,12699,12700,12701,12702,12703,12704,12705,12706,12707,12708,12709,12710, #12672 +12711,12712,12713,12714,12715,12716,12717,12718,12719,12720,12721,12722,12723,12724,12725,12726, #12688 +12727,12728,12729,12730,12731,12732,12733,12734,12735,12736,12737,12738,12739,12740,12741,12742, #12704 +12743,12744,12745,12746,12747,12748,12749,12750,12751,12752,12753,12754,12755,12756,12757,12758, #12720 +12759,12760,12761,12762,12763,12764,12765,12766,12767,12768,12769,12770,12771,12772,12773,12774, #12736 +12775,12776,12777,12778,4993,2175,12779,12780,12781,12782,12783,12784,12785,12786,4500,12787, #12752 +12788,12789,12790,12791,12792,12793,12794,12795,12796,12797,12798,12799,12800,12801,12802,12803, #12768 +12804,12805,12806,12807,12808,12809,12810,12811,12812,12813,12814,12815,12816,12817,12818,12819, #12784 +12820,12821,12822,12823,12824,12825,12826,4198,3967,12827,12828,12829,12830,12831,12832,12833, #12800 +12834,12835,12836,12837,12838,12839,12840,12841,12842,12843,12844,12845,12846,12847,12848,12849, #12816 +12850,12851,12852,12853,12854,12855,12856,12857,12858,12859,12860,12861,4199,12862,12863,12864, #12832 +12865,12866,12867,12868,12869,12870,12871,12872,12873,12874,12875,12876,12877,12878,12879,12880, #12848 +12881,12882,12883,12884,12885,12886,12887,4501,12888,12889,12890,12891,12892,12893,12894,12895, #12864 +12896,12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,12910,12911, #12880 +12912,4994,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,12923,12924,12925,12926, #12896 +12927,12928,12929,12930,12931,12932,12933,12934,12935,12936,12937,12938,12939,12940,12941,12942, #12912 +12943,12944,12945,12946,12947,12948,12949,12950,12951,12952,12953,12954,12955,12956,1772,12957, #12928 +12958,12959,12960,12961,12962,12963,12964,12965,12966,12967,12968,12969,12970,12971,12972,12973, #12944 +12974,12975,12976,12977,12978,12979,12980,12981,12982,12983,12984,12985,12986,12987,12988,12989, #12960 +12990,12991,12992,12993,12994,12995,12996,12997,4502,12998,4503,12999,13000,13001,13002,13003, #12976 +4504,13004,13005,13006,13007,13008,13009,13010,13011,13012,13013,13014,13015,13016,13017,13018, #12992 +13019,13020,13021,13022,13023,13024,13025,13026,13027,13028,13029,3449,13030,13031,13032,13033, #13008 +13034,13035,13036,13037,13038,13039,13040,13041,13042,13043,13044,13045,13046,13047,13048,13049, #13024 +13050,13051,13052,13053,13054,13055,13056,13057,13058,13059,13060,13061,13062,13063,13064,13065, #13040 +13066,13067,13068,13069,13070,13071,13072,13073,13074,13075,13076,13077,13078,13079,13080,13081, #13056 +13082,13083,13084,13085,13086,13087,13088,13089,13090,13091,13092,13093,13094,13095,13096,13097, #13072 +13098,13099,13100,13101,13102,13103,13104,13105,13106,13107,13108,13109,13110,13111,13112,13113, #13088 +13114,13115,13116,13117,13118,3968,13119,4995,13120,13121,13122,13123,13124,13125,13126,13127, #13104 +4505,13128,13129,13130,13131,13132,13133,13134,4996,4506,13135,13136,13137,13138,13139,4997, #13120 +13140,13141,13142,13143,13144,13145,13146,13147,13148,13149,13150,13151,13152,13153,13154,13155, #13136 +13156,13157,13158,13159,4998,13160,13161,13162,13163,13164,13165,13166,13167,13168,13169,13170, #13152 +13171,13172,13173,13174,13175,13176,4999,13177,13178,13179,13180,13181,13182,13183,13184,13185, #13168 +13186,13187,13188,13189,13190,13191,13192,13193,13194,13195,13196,13197,13198,13199,13200,13201, #13184 +13202,13203,13204,13205,13206,5000,13207,13208,13209,13210,13211,13212,13213,13214,13215,13216, #13200 +13217,13218,13219,13220,13221,13222,13223,13224,13225,13226,13227,4200,5001,13228,13229,13230, #13216 +13231,13232,13233,13234,13235,13236,13237,13238,13239,13240,3969,13241,13242,13243,13244,3970, #13232 +13245,13246,13247,13248,13249,13250,13251,13252,13253,13254,13255,13256,13257,13258,13259,13260, #13248 +13261,13262,13263,13264,13265,13266,13267,13268,3450,13269,13270,13271,13272,13273,13274,13275, #13264 +13276,5002,13277,13278,13279,13280,13281,13282,13283,13284,13285,13286,13287,13288,13289,13290, #13280 +13291,13292,13293,13294,13295,13296,13297,13298,13299,13300,13301,13302,3813,13303,13304,13305, #13296 +13306,13307,13308,13309,13310,13311,13312,13313,13314,13315,13316,13317,13318,13319,13320,13321, #13312 +13322,13323,13324,13325,13326,13327,13328,4507,13329,13330,13331,13332,13333,13334,13335,13336, #13328 +13337,13338,13339,13340,13341,5003,13342,13343,13344,13345,13346,13347,13348,13349,13350,13351, #13344 +13352,13353,13354,13355,13356,13357,13358,13359,13360,13361,13362,13363,13364,13365,13366,13367, #13360 +5004,13368,13369,13370,13371,13372,13373,13374,13375,13376,13377,13378,13379,13380,13381,13382, #13376 +13383,13384,13385,13386,13387,13388,13389,13390,13391,13392,13393,13394,13395,13396,13397,13398, #13392 +13399,13400,13401,13402,13403,13404,13405,13406,13407,13408,13409,13410,13411,13412,13413,13414, #13408 +13415,13416,13417,13418,13419,13420,13421,13422,13423,13424,13425,13426,13427,13428,13429,13430, #13424 +13431,13432,4508,13433,13434,13435,4201,13436,13437,13438,13439,13440,13441,13442,13443,13444, #13440 +13445,13446,13447,13448,13449,13450,13451,13452,13453,13454,13455,13456,13457,5005,13458,13459, #13456 +13460,13461,13462,13463,13464,13465,13466,13467,13468,13469,13470,4509,13471,13472,13473,13474, #13472 +13475,13476,13477,13478,13479,13480,13481,13482,13483,13484,13485,13486,13487,13488,13489,13490, #13488 +13491,13492,13493,13494,13495,13496,13497,13498,13499,13500,13501,13502,13503,13504,13505,13506, #13504 +13507,13508,13509,13510,13511,13512,13513,13514,13515,13516,13517,13518,13519,13520,13521,13522, #13520 +13523,13524,13525,13526,13527,13528,13529,13530,13531,13532,13533,13534,13535,13536,13537,13538, #13536 +13539,13540,13541,13542,13543,13544,13545,13546,13547,13548,13549,13550,13551,13552,13553,13554, #13552 +13555,13556,13557,13558,13559,13560,13561,13562,13563,13564,13565,13566,13567,13568,13569,13570, #13568 +13571,13572,13573,13574,13575,13576,13577,13578,13579,13580,13581,13582,13583,13584,13585,13586, #13584 +13587,13588,13589,13590,13591,13592,13593,13594,13595,13596,13597,13598,13599,13600,13601,13602, #13600 +13603,13604,13605,13606,13607,13608,13609,13610,13611,13612,13613,13614,13615,13616,13617,13618, #13616 +13619,13620,13621,13622,13623,13624,13625,13626,13627,13628,13629,13630,13631,13632,13633,13634, #13632 +13635,13636,13637,13638,13639,13640,13641,13642,5006,13643,13644,13645,13646,13647,13648,13649, #13648 +13650,13651,5007,13652,13653,13654,13655,13656,13657,13658,13659,13660,13661,13662,13663,13664, #13664 +13665,13666,13667,13668,13669,13670,13671,13672,13673,13674,13675,13676,13677,13678,13679,13680, #13680 +13681,13682,13683,13684,13685,13686,13687,13688,13689,13690,13691,13692,13693,13694,13695,13696, #13696 +13697,13698,13699,13700,13701,13702,13703,13704,13705,13706,13707,13708,13709,13710,13711,13712, #13712 +13713,13714,13715,13716,13717,13718,13719,13720,13721,13722,13723,13724,13725,13726,13727,13728, #13728 +13729,13730,13731,13732,13733,13734,13735,13736,13737,13738,13739,13740,13741,13742,13743,13744, #13744 +13745,13746,13747,13748,13749,13750,13751,13752,13753,13754,13755,13756,13757,13758,13759,13760, #13760 +13761,13762,13763,13764,13765,13766,13767,13768,13769,13770,13771,13772,13773,13774,3273,13775, #13776 +13776,13777,13778,13779,13780,13781,13782,13783,13784,13785,13786,13787,13788,13789,13790,13791, #13792 +13792,13793,13794,13795,13796,13797,13798,13799,13800,13801,13802,13803,13804,13805,13806,13807, #13808 +13808,13809,13810,13811,13812,13813,13814,13815,13816,13817,13818,13819,13820,13821,13822,13823, #13824 +13824,13825,13826,13827,13828,13829,13830,13831,13832,13833,13834,13835,13836,13837,13838,13839, #13840 +13840,13841,13842,13843,13844,13845,13846,13847,13848,13849,13850,13851,13852,13853,13854,13855, #13856 +13856,13857,13858,13859,13860,13861,13862,13863,13864,13865,13866,13867,13868,13869,13870,13871, #13872 +13872,13873,13874,13875,13876,13877,13878,13879,13880,13881,13882,13883,13884,13885,13886,13887, #13888 +13888,13889,13890,13891,13892,13893,13894,13895,13896,13897,13898,13899,13900,13901,13902,13903, #13904 +13904,13905,13906,13907,13908,13909,13910,13911,13912,13913,13914,13915,13916,13917,13918,13919, #13920 +13920,13921,13922,13923,13924,13925,13926,13927,13928,13929,13930,13931,13932,13933,13934,13935, #13936 +13936,13937,13938,13939,13940,13941,13942,13943,13944,13945,13946,13947,13948,13949,13950,13951, #13952 +13952,13953,13954,13955,13956,13957,13958,13959,13960,13961,13962,13963,13964,13965,13966,13967, #13968 +13968,13969,13970,13971,13972) #13973 + +# flake8: noqa diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/big5prober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/big5prober.py new file mode 100644 index 0000000000..7382f7c5d4 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/big5prober.py @@ -0,0 +1,42 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import Big5DistributionAnalysis +from .mbcssm import Big5SMModel + + +class Big5Prober(MultiByteCharSetProber): + def __init__(self): + MultiByteCharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(Big5SMModel) + self._mDistributionAnalyzer = Big5DistributionAnalysis() + self.reset() + + def get_charset_name(self): + return "Big5" diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/chardistribution.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/chardistribution.py new file mode 100644 index 0000000000..dfd3355e91 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/chardistribution.py @@ -0,0 +1,231 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .euctwfreq import (EUCTWCharToFreqOrder, EUCTW_TABLE_SIZE, + EUCTW_TYPICAL_DISTRIBUTION_RATIO) +from .euckrfreq import (EUCKRCharToFreqOrder, EUCKR_TABLE_SIZE, + EUCKR_TYPICAL_DISTRIBUTION_RATIO) +from .gb2312freq import (GB2312CharToFreqOrder, GB2312_TABLE_SIZE, + GB2312_TYPICAL_DISTRIBUTION_RATIO) +from .big5freq import (Big5CharToFreqOrder, BIG5_TABLE_SIZE, + BIG5_TYPICAL_DISTRIBUTION_RATIO) +from .jisfreq import (JISCharToFreqOrder, JIS_TABLE_SIZE, + JIS_TYPICAL_DISTRIBUTION_RATIO) +from .compat import wrap_ord + +ENOUGH_DATA_THRESHOLD = 1024 +SURE_YES = 0.99 +SURE_NO = 0.01 +MINIMUM_DATA_THRESHOLD = 3 + + +class CharDistributionAnalysis: + def __init__(self): + # Mapping table to get frequency order from char order (get from + # GetOrder()) + self._mCharToFreqOrder = None + self._mTableSize = None # Size of above table + # This is a constant value which varies from language to language, + # used in calculating confidence. See + # http://www.mozilla.org/projects/intl/UniversalCharsetDetection.html + # for further detail. + self._mTypicalDistributionRatio = None + self.reset() + + def reset(self): + """reset analyser, clear any state""" + # If this flag is set to True, detection is done and conclusion has + # been made + self._mDone = False + self._mTotalChars = 0 # Total characters encountered + # The number of characters whose frequency order is less than 512 + self._mFreqChars = 0 + + def feed(self, aBuf, aCharLen): + """feed a character with known length""" + if aCharLen == 2: + # we only care about 2-bytes character in our distribution analysis + order = self.get_order(aBuf) + else: + order = -1 + if order >= 0: + self._mTotalChars += 1 + # order is valid + if order < self._mTableSize: + if 512 > self._mCharToFreqOrder[order]: + self._mFreqChars += 1 + + def get_confidence(self): + """return confidence based on existing data""" + # if we didn't receive any character in our consideration range, + # return negative answer + if self._mTotalChars <= 0 or self._mFreqChars <= MINIMUM_DATA_THRESHOLD: + return SURE_NO + + if self._mTotalChars != self._mFreqChars: + r = (self._mFreqChars / ((self._mTotalChars - self._mFreqChars) + * self._mTypicalDistributionRatio)) + if r < SURE_YES: + return r + + # normalize confidence (we don't want to be 100% sure) + return SURE_YES + + def got_enough_data(self): + # It is not necessary to receive all data to draw conclusion. + # For charset detection, certain amount of data is enough + return self._mTotalChars > ENOUGH_DATA_THRESHOLD + + def get_order(self, aBuf): + # We do not handle characters based on the original encoding string, + # but convert this encoding string to a number, here called order. + # This allows multiple encodings of a language to share one frequency + # table. + return -1 + + +class EUCTWDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + CharDistributionAnalysis.__init__(self) + self._mCharToFreqOrder = EUCTWCharToFreqOrder + self._mTableSize = EUCTW_TABLE_SIZE + self._mTypicalDistributionRatio = EUCTW_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, aBuf): + # for euc-TW encoding, we are interested + # first byte range: 0xc4 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char = wrap_ord(aBuf[0]) + if first_char >= 0xC4: + return 94 * (first_char - 0xC4) + wrap_ord(aBuf[1]) - 0xA1 + else: + return -1 + + +class EUCKRDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + CharDistributionAnalysis.__init__(self) + self._mCharToFreqOrder = EUCKRCharToFreqOrder + self._mTableSize = EUCKR_TABLE_SIZE + self._mTypicalDistributionRatio = EUCKR_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, aBuf): + # for euc-KR encoding, we are interested + # first byte range: 0xb0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char = wrap_ord(aBuf[0]) + if first_char >= 0xB0: + return 94 * (first_char - 0xB0) + wrap_ord(aBuf[1]) - 0xA1 + else: + return -1 + + +class GB2312DistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + CharDistributionAnalysis.__init__(self) + self._mCharToFreqOrder = GB2312CharToFreqOrder + self._mTableSize = GB2312_TABLE_SIZE + self._mTypicalDistributionRatio = GB2312_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, aBuf): + # for GB2312 encoding, we are interested + # first byte range: 0xb0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char, second_char = wrap_ord(aBuf[0]), wrap_ord(aBuf[1]) + if (first_char >= 0xB0) and (second_char >= 0xA1): + return 94 * (first_char - 0xB0) + second_char - 0xA1 + else: + return -1 + + +class Big5DistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + CharDistributionAnalysis.__init__(self) + self._mCharToFreqOrder = Big5CharToFreqOrder + self._mTableSize = BIG5_TABLE_SIZE + self._mTypicalDistributionRatio = BIG5_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, aBuf): + # for big5 encoding, we are interested + # first byte range: 0xa4 -- 0xfe + # second byte range: 0x40 -- 0x7e , 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char, second_char = wrap_ord(aBuf[0]), wrap_ord(aBuf[1]) + if first_char >= 0xA4: + if second_char >= 0xA1: + return 157 * (first_char - 0xA4) + second_char - 0xA1 + 63 + else: + return 157 * (first_char - 0xA4) + second_char - 0x40 + else: + return -1 + + +class SJISDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + CharDistributionAnalysis.__init__(self) + self._mCharToFreqOrder = JISCharToFreqOrder + self._mTableSize = JIS_TABLE_SIZE + self._mTypicalDistributionRatio = JIS_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, aBuf): + # for sjis encoding, we are interested + # first byte range: 0x81 -- 0x9f , 0xe0 -- 0xfe + # second byte range: 0x40 -- 0x7e, 0x81 -- oxfe + # no validation needed here. State machine has done that + first_char, second_char = wrap_ord(aBuf[0]), wrap_ord(aBuf[1]) + if (first_char >= 0x81) and (first_char <= 0x9F): + order = 188 * (first_char - 0x81) + elif (first_char >= 0xE0) and (first_char <= 0xEF): + order = 188 * (first_char - 0xE0 + 31) + else: + return -1 + order = order + second_char - 0x40 + if second_char > 0x7F: + order = -1 + return order + + +class EUCJPDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + CharDistributionAnalysis.__init__(self) + self._mCharToFreqOrder = JISCharToFreqOrder + self._mTableSize = JIS_TABLE_SIZE + self._mTypicalDistributionRatio = JIS_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, aBuf): + # for euc-JP encoding, we are interested + # first byte range: 0xa0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + char = wrap_ord(aBuf[0]) + if char >= 0xA0: + return 94 * (char - 0xA1) + wrap_ord(aBuf[1]) - 0xa1 + else: + return -1 diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/charsetgroupprober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/charsetgroupprober.py new file mode 100644 index 0000000000..2959654748 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/charsetgroupprober.py @@ -0,0 +1,106 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from . import constants +import sys +from .charsetprober import CharSetProber + + +class CharSetGroupProber(CharSetProber): + def __init__(self): + CharSetProber.__init__(self) + self._mActiveNum = 0 + self._mProbers = [] + self._mBestGuessProber = None + + def reset(self): + CharSetProber.reset(self) + self._mActiveNum = 0 + for prober in self._mProbers: + if prober: + prober.reset() + prober.active = True + self._mActiveNum += 1 + self._mBestGuessProber = None + + def get_charset_name(self): + if not self._mBestGuessProber: + self.get_confidence() + if not self._mBestGuessProber: + return None +# self._mBestGuessProber = self._mProbers[0] + return self._mBestGuessProber.get_charset_name() + + def feed(self, aBuf): + for prober in self._mProbers: + if not prober: + continue + if not prober.active: + continue + st = prober.feed(aBuf) + if not st: + continue + if st == constants.eFoundIt: + self._mBestGuessProber = prober + return self.get_state() + elif st == constants.eNotMe: + prober.active = False + self._mActiveNum -= 1 + if self._mActiveNum <= 0: + self._mState = constants.eNotMe + return self.get_state() + return self.get_state() + + def get_confidence(self): + st = self.get_state() + if st == constants.eFoundIt: + return 0.99 + elif st == constants.eNotMe: + return 0.01 + bestConf = 0.0 + self._mBestGuessProber = None + for prober in self._mProbers: + if not prober: + continue + if not prober.active: + if constants._debug: + sys.stderr.write(prober.get_charset_name() + + ' not active\n') + continue + cf = prober.get_confidence() + if constants._debug: + sys.stderr.write('%s confidence = %s\n' % + (prober.get_charset_name(), cf)) + if bestConf < cf: + bestConf = cf + self._mBestGuessProber = prober + if not self._mBestGuessProber: + return 0.0 + return bestConf +# else: +# self._mBestGuessProber = self._mProbers[0] +# return self._mBestGuessProber.get_confidence() diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/charsetprober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/charsetprober.py new file mode 100644 index 0000000000..97581712c1 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/charsetprober.py @@ -0,0 +1,62 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from . import constants +import re + + +class CharSetProber: + def __init__(self): + pass + + def reset(self): + self._mState = constants.eDetecting + + def get_charset_name(self): + return None + + def feed(self, aBuf): + pass + + def get_state(self): + return self._mState + + def get_confidence(self): + return 0.0 + + def filter_high_bit_only(self, aBuf): + aBuf = re.sub(b'([\x00-\x7F])+', b' ', aBuf) + return aBuf + + def filter_without_english_letters(self, aBuf): + aBuf = re.sub(b'([A-Za-z])+', b' ', aBuf) + return aBuf + + def filter_with_english_letters(self, aBuf): + # TODO + return aBuf diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/codingstatemachine.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/codingstatemachine.py new file mode 100644 index 0000000000..1bda9ff162 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/codingstatemachine.py @@ -0,0 +1,61 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .constants import eStart +from .compat import wrap_ord + + +class CodingStateMachine: + def __init__(self, sm): + self._mModel = sm + self._mCurrentBytePos = 0 + self._mCurrentCharLen = 0 + self.reset() + + def reset(self): + self._mCurrentState = eStart + + def next_state(self, c): + # for each byte we get its class + # if it is first byte, we also get byte length + # PY3K: aBuf is a byte stream, so c is an int, not a byte + byteCls = self._mModel['classTable'][wrap_ord(c)] + if self._mCurrentState == eStart: + self._mCurrentBytePos = 0 + self._mCurrentCharLen = self._mModel['charLenTable'][byteCls] + # from byte's class and stateTable, we get its next state + curr_state = (self._mCurrentState * self._mModel['classFactor'] + + byteCls) + self._mCurrentState = self._mModel['stateTable'][curr_state] + self._mCurrentBytePos += 1 + return self._mCurrentState + + def get_current_charlen(self): + return self._mCurrentCharLen + + def get_coding_state_machine(self): + return self._mModel['name'] diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/compat.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/compat.py new file mode 100644 index 0000000000..d9e30addf9 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/compat.py @@ -0,0 +1,34 @@ +######################## BEGIN LICENSE BLOCK ######################## +# Contributor(s): +# Ian Cordasco - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import sys + + +if sys.version_info < (3, 0): + base_str = (str, unicode) +else: + base_str = (bytes, str) + + +def wrap_ord(a): + if sys.version_info < (3, 0) and isinstance(a, base_str): + return ord(a) + else: + return a diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/constants.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/constants.py new file mode 100644 index 0000000000..a3d27de250 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/constants.py @@ -0,0 +1,39 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +_debug = 0 + +eDetecting = 0 +eFoundIt = 1 +eNotMe = 2 + +eStart = 0 +eError = 1 +eItsMe = 2 + +SHORTCUT_THRESHOLD = 0.95 diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/cp949prober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/cp949prober.py new file mode 100644 index 0000000000..543501fe09 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/cp949prober.py @@ -0,0 +1,44 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCKRDistributionAnalysis +from .mbcssm import CP949SMModel + + +class CP949Prober(MultiByteCharSetProber): + def __init__(self): + MultiByteCharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(CP949SMModel) + # NOTE: CP949 is a superset of EUC-KR, so the distribution should be + # not different. + self._mDistributionAnalyzer = EUCKRDistributionAnalysis() + self.reset() + + def get_charset_name(self): + return "CP949" diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/escprober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/escprober.py new file mode 100644 index 0000000000..0063935ce6 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/escprober.py @@ -0,0 +1,86 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from . import constants +from .escsm import (HZSMModel, ISO2022CNSMModel, ISO2022JPSMModel, + ISO2022KRSMModel) +from .charsetprober import CharSetProber +from .codingstatemachine import CodingStateMachine +from .compat import wrap_ord + + +class EscCharSetProber(CharSetProber): + def __init__(self): + CharSetProber.__init__(self) + self._mCodingSM = [ + CodingStateMachine(HZSMModel), + CodingStateMachine(ISO2022CNSMModel), + CodingStateMachine(ISO2022JPSMModel), + CodingStateMachine(ISO2022KRSMModel) + ] + self.reset() + + def reset(self): + CharSetProber.reset(self) + for codingSM in self._mCodingSM: + if not codingSM: + continue + codingSM.active = True + codingSM.reset() + self._mActiveSM = len(self._mCodingSM) + self._mDetectedCharset = None + + def get_charset_name(self): + return self._mDetectedCharset + + def get_confidence(self): + if self._mDetectedCharset: + return 0.99 + else: + return 0.00 + + def feed(self, aBuf): + for c in aBuf: + # PY3K: aBuf is a byte array, so c is an int, not a byte + for codingSM in self._mCodingSM: + if not codingSM: + continue + if not codingSM.active: + continue + codingState = codingSM.next_state(wrap_ord(c)) + if codingState == constants.eError: + codingSM.active = False + self._mActiveSM -= 1 + if self._mActiveSM <= 0: + self._mState = constants.eNotMe + return self.get_state() + elif codingState == constants.eItsMe: + self._mState = constants.eFoundIt + self._mDetectedCharset = codingSM.get_coding_state_machine() # nopep8 + return self.get_state() + + return self.get_state() diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/escsm.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/escsm.py new file mode 100644 index 0000000000..1cf3aa6db6 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/escsm.py @@ -0,0 +1,242 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .constants import eStart, eError, eItsMe + +HZ_cls = ( +1,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,0,0,0,0, # 20 - 27 +0,0,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,0,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,4,0,5,2,0, # 78 - 7f +1,1,1,1,1,1,1,1, # 80 - 87 +1,1,1,1,1,1,1,1, # 88 - 8f +1,1,1,1,1,1,1,1, # 90 - 97 +1,1,1,1,1,1,1,1, # 98 - 9f +1,1,1,1,1,1,1,1, # a0 - a7 +1,1,1,1,1,1,1,1, # a8 - af +1,1,1,1,1,1,1,1, # b0 - b7 +1,1,1,1,1,1,1,1, # b8 - bf +1,1,1,1,1,1,1,1, # c0 - c7 +1,1,1,1,1,1,1,1, # c8 - cf +1,1,1,1,1,1,1,1, # d0 - d7 +1,1,1,1,1,1,1,1, # d8 - df +1,1,1,1,1,1,1,1, # e0 - e7 +1,1,1,1,1,1,1,1, # e8 - ef +1,1,1,1,1,1,1,1, # f0 - f7 +1,1,1,1,1,1,1,1, # f8 - ff +) + +HZ_st = ( +eStart,eError, 3,eStart,eStart,eStart,eError,eError,# 00-07 +eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,# 08-0f +eItsMe,eItsMe,eError,eError,eStart,eStart, 4,eError,# 10-17 + 5,eError, 6,eError, 5, 5, 4,eError,# 18-1f + 4,eError, 4, 4, 4,eError, 4,eError,# 20-27 + 4,eItsMe,eStart,eStart,eStart,eStart,eStart,eStart,# 28-2f +) + +HZCharLenTable = (0, 0, 0, 0, 0, 0) + +HZSMModel = {'classTable': HZ_cls, + 'classFactor': 6, + 'stateTable': HZ_st, + 'charLenTable': HZCharLenTable, + 'name': "HZ-GB-2312"} + +ISO2022CN_cls = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,0,0,0,0, # 20 - 27 +0,3,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,4,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022CN_st = ( +eStart, 3,eError,eStart,eStart,eStart,eStart,eStart,# 00-07 +eStart,eError,eError,eError,eError,eError,eError,eError,# 08-0f +eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,# 10-17 +eItsMe,eItsMe,eItsMe,eError,eError,eError, 4,eError,# 18-1f +eError,eError,eError,eItsMe,eError,eError,eError,eError,# 20-27 + 5, 6,eError,eError,eError,eError,eError,eError,# 28-2f +eError,eError,eError,eItsMe,eError,eError,eError,eError,# 30-37 +eError,eError,eError,eError,eError,eItsMe,eError,eStart,# 38-3f +) + +ISO2022CNCharLenTable = (0, 0, 0, 0, 0, 0, 0, 0, 0) + +ISO2022CNSMModel = {'classTable': ISO2022CN_cls, + 'classFactor': 9, + 'stateTable': ISO2022CN_st, + 'charLenTable': ISO2022CNCharLenTable, + 'name': "ISO-2022-CN"} + +ISO2022JP_cls = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,2,2, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,7,0,0,0, # 20 - 27 +3,0,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +6,0,4,0,8,0,0,0, # 40 - 47 +0,9,5,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022JP_st = ( +eStart, 3,eError,eStart,eStart,eStart,eStart,eStart,# 00-07 +eStart,eStart,eError,eError,eError,eError,eError,eError,# 08-0f +eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,# 10-17 +eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eError,eError,# 18-1f +eError, 5,eError,eError,eError, 4,eError,eError,# 20-27 +eError,eError,eError, 6,eItsMe,eError,eItsMe,eError,# 28-2f +eError,eError,eError,eError,eError,eError,eItsMe,eItsMe,# 30-37 +eError,eError,eError,eItsMe,eError,eError,eError,eError,# 38-3f +eError,eError,eError,eError,eItsMe,eError,eStart,eStart,# 40-47 +) + +ISO2022JPCharLenTable = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +ISO2022JPSMModel = {'classTable': ISO2022JP_cls, + 'classFactor': 10, + 'stateTable': ISO2022JP_st, + 'charLenTable': ISO2022JPCharLenTable, + 'name': "ISO-2022-JP"} + +ISO2022KR_cls = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,3,0,0,0, # 20 - 27 +0,4,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,5,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022KR_st = ( +eStart, 3,eError,eStart,eStart,eStart,eError,eError,# 00-07 +eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,# 08-0f +eItsMe,eItsMe,eError,eError,eError, 4,eError,eError,# 10-17 +eError,eError,eError,eError, 5,eError,eError,eError,# 18-1f +eError,eError,eError,eItsMe,eStart,eStart,eStart,eStart,# 20-27 +) + +ISO2022KRCharLenTable = (0, 0, 0, 0, 0, 0) + +ISO2022KRSMModel = {'classTable': ISO2022KR_cls, + 'classFactor': 6, + 'stateTable': ISO2022KR_st, + 'charLenTable': ISO2022KRCharLenTable, + 'name': "ISO-2022-KR"} + +# flake8: noqa diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/eucjpprober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/eucjpprober.py new file mode 100644 index 0000000000..d70cfbbb01 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/eucjpprober.py @@ -0,0 +1,90 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import sys +from . import constants +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCJPDistributionAnalysis +from .jpcntx import EUCJPContextAnalysis +from .mbcssm import EUCJPSMModel + + +class EUCJPProber(MultiByteCharSetProber): + def __init__(self): + MultiByteCharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(EUCJPSMModel) + self._mDistributionAnalyzer = EUCJPDistributionAnalysis() + self._mContextAnalyzer = EUCJPContextAnalysis() + self.reset() + + def reset(self): + MultiByteCharSetProber.reset(self) + self._mContextAnalyzer.reset() + + def get_charset_name(self): + return "EUC-JP" + + def feed(self, aBuf): + aLen = len(aBuf) + for i in range(0, aLen): + # PY3K: aBuf is a byte array, so aBuf[i] is an int, not a byte + codingState = self._mCodingSM.next_state(aBuf[i]) + if codingState == constants.eError: + if constants._debug: + sys.stderr.write(self.get_charset_name() + + ' prober hit error at byte ' + str(i) + + '\n') + self._mState = constants.eNotMe + break + elif codingState == constants.eItsMe: + self._mState = constants.eFoundIt + break + elif codingState == constants.eStart: + charLen = self._mCodingSM.get_current_charlen() + if i == 0: + self._mLastChar[1] = aBuf[0] + self._mContextAnalyzer.feed(self._mLastChar, charLen) + self._mDistributionAnalyzer.feed(self._mLastChar, charLen) + else: + self._mContextAnalyzer.feed(aBuf[i - 1:i + 1], charLen) + self._mDistributionAnalyzer.feed(aBuf[i - 1:i + 1], + charLen) + + self._mLastChar[0] = aBuf[aLen - 1] + + if self.get_state() == constants.eDetecting: + if (self._mContextAnalyzer.got_enough_data() and + (self.get_confidence() > constants.SHORTCUT_THRESHOLD)): + self._mState = constants.eFoundIt + + return self.get_state() + + def get_confidence(self): + contxtCf = self._mContextAnalyzer.get_confidence() + distribCf = self._mDistributionAnalyzer.get_confidence() + return max(contxtCf, distribCf) diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/euckrfreq.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/euckrfreq.py new file mode 100644 index 0000000000..a179e4c21c --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/euckrfreq.py @@ -0,0 +1,596 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Sampling from about 20M text materials include literature and computer technology + +# 128 --> 0.79 +# 256 --> 0.92 +# 512 --> 0.986 +# 1024 --> 0.99944 +# 2048 --> 0.99999 +# +# Idea Distribution Ratio = 0.98653 / (1-0.98653) = 73.24 +# Random Distribution Ration = 512 / (2350-512) = 0.279. +# +# Typical Distribution Ratio + +EUCKR_TYPICAL_DISTRIBUTION_RATIO = 6.0 + +EUCKR_TABLE_SIZE = 2352 + +# Char to FreqOrder table , +EUCKRCharToFreqOrder = ( \ + 13, 130, 120,1396, 481,1719,1720, 328, 609, 212,1721, 707, 400, 299,1722, 87, +1397,1723, 104, 536,1117,1203,1724,1267, 685,1268, 508,1725,1726,1727,1728,1398, +1399,1729,1730,1731, 141, 621, 326,1057, 368,1732, 267, 488, 20,1733,1269,1734, + 945,1400,1735, 47, 904,1270,1736,1737, 773, 248,1738, 409, 313, 786, 429,1739, + 116, 987, 813,1401, 683, 75,1204, 145,1740,1741,1742,1743, 16, 847, 667, 622, + 708,1744,1745,1746, 966, 787, 304, 129,1747, 60, 820, 123, 676,1748,1749,1750, +1751, 617,1752, 626,1753,1754,1755,1756, 653,1757,1758,1759,1760,1761,1762, 856, + 344,1763,1764,1765,1766, 89, 401, 418, 806, 905, 848,1767,1768,1769, 946,1205, + 709,1770,1118,1771, 241,1772,1773,1774,1271,1775, 569,1776, 999,1777,1778,1779, +1780, 337, 751,1058, 28, 628, 254,1781, 177, 906, 270, 349, 891,1079,1782, 19, +1783, 379,1784, 315,1785, 629, 754,1402, 559,1786, 636, 203,1206,1787, 710, 567, +1788, 935, 814,1789,1790,1207, 766, 528,1791,1792,1208,1793,1794,1795,1796,1797, +1403,1798,1799, 533,1059,1404,1405,1156,1406, 936, 884,1080,1800, 351,1801,1802, +1803,1804,1805, 801,1806,1807,1808,1119,1809,1157, 714, 474,1407,1810, 298, 899, + 885,1811,1120, 802,1158,1812, 892,1813,1814,1408, 659,1815,1816,1121,1817,1818, +1819,1820,1821,1822, 319,1823, 594, 545,1824, 815, 937,1209,1825,1826, 573,1409, +1022,1827,1210,1828,1829,1830,1831,1832,1833, 556, 722, 807,1122,1060,1834, 697, +1835, 900, 557, 715,1836,1410, 540,1411, 752,1159, 294, 597,1211, 976, 803, 770, +1412,1837,1838, 39, 794,1413, 358,1839, 371, 925,1840, 453, 661, 788, 531, 723, + 544,1023,1081, 869, 91,1841, 392, 430, 790, 602,1414, 677,1082, 457,1415,1416, +1842,1843, 475, 327,1024,1417, 795, 121,1844, 733, 403,1418,1845,1846,1847, 300, + 119, 711,1212, 627,1848,1272, 207,1849,1850, 796,1213, 382,1851, 519,1852,1083, + 893,1853,1854,1855, 367, 809, 487, 671,1856, 663,1857,1858, 956, 471, 306, 857, +1859,1860,1160,1084,1861,1862,1863,1864,1865,1061,1866,1867,1868,1869,1870,1871, + 282, 96, 574,1872, 502,1085,1873,1214,1874, 907,1875,1876, 827, 977,1419,1420, +1421, 268,1877,1422,1878,1879,1880, 308,1881, 2, 537,1882,1883,1215,1884,1885, + 127, 791,1886,1273,1423,1887, 34, 336, 404, 643,1888, 571, 654, 894, 840,1889, + 0, 886,1274, 122, 575, 260, 908, 938,1890,1275, 410, 316,1891,1892, 100,1893, +1894,1123, 48,1161,1124,1025,1895, 633, 901,1276,1896,1897, 115, 816,1898, 317, +1899, 694,1900, 909, 734,1424, 572, 866,1425, 691, 85, 524,1010, 543, 394, 841, +1901,1902,1903,1026,1904,1905,1906,1907,1908,1909, 30, 451, 651, 988, 310,1910, +1911,1426, 810,1216, 93,1912,1913,1277,1217,1914, 858, 759, 45, 58, 181, 610, + 269,1915,1916, 131,1062, 551, 443,1000, 821,1427, 957, 895,1086,1917,1918, 375, +1919, 359,1920, 687,1921, 822,1922, 293,1923,1924, 40, 662, 118, 692, 29, 939, + 887, 640, 482, 174,1925, 69,1162, 728,1428, 910,1926,1278,1218,1279, 386, 870, + 217, 854,1163, 823,1927,1928,1929,1930, 834,1931, 78,1932, 859,1933,1063,1934, +1935,1936,1937, 438,1164, 208, 595,1938,1939,1940,1941,1219,1125,1942, 280, 888, +1429,1430,1220,1431,1943,1944,1945,1946,1947,1280, 150, 510,1432,1948,1949,1950, +1951,1952,1953,1954,1011,1087,1955,1433,1043,1956, 881,1957, 614, 958,1064,1065, +1221,1958, 638,1001, 860, 967, 896,1434, 989, 492, 553,1281,1165,1959,1282,1002, +1283,1222,1960,1961,1962,1963, 36, 383, 228, 753, 247, 454,1964, 876, 678,1965, +1966,1284, 126, 464, 490, 835, 136, 672, 529, 940,1088,1435, 473,1967,1968, 467, + 50, 390, 227, 587, 279, 378, 598, 792, 968, 240, 151, 160, 849, 882,1126,1285, + 639,1044, 133, 140, 288, 360, 811, 563,1027, 561, 142, 523,1969,1970,1971, 7, + 103, 296, 439, 407, 506, 634, 990,1972,1973,1974,1975, 645,1976,1977,1978,1979, +1980,1981, 236,1982,1436,1983,1984,1089, 192, 828, 618, 518,1166, 333,1127,1985, + 818,1223,1986,1987,1988,1989,1990,1991,1992,1993, 342,1128,1286, 746, 842,1994, +1995, 560, 223,1287, 98, 8, 189, 650, 978,1288,1996,1437,1997, 17, 345, 250, + 423, 277, 234, 512, 226, 97, 289, 42, 167,1998, 201,1999,2000, 843, 836, 824, + 532, 338, 783,1090, 182, 576, 436,1438,1439, 527, 500,2001, 947, 889,2002,2003, +2004,2005, 262, 600, 314, 447,2006, 547,2007, 693, 738,1129,2008, 71,1440, 745, + 619, 688,2009, 829,2010,2011, 147,2012, 33, 948,2013,2014, 74, 224,2015, 61, + 191, 918, 399, 637,2016,1028,1130, 257, 902,2017,2018,2019,2020,2021,2022,2023, +2024,2025,2026, 837,2027,2028,2029,2030, 179, 874, 591, 52, 724, 246,2031,2032, +2033,2034,1167, 969,2035,1289, 630, 605, 911,1091,1168,2036,2037,2038,1441, 912, +2039, 623,2040,2041, 253,1169,1290,2042,1442, 146, 620, 611, 577, 433,2043,1224, + 719,1170, 959, 440, 437, 534, 84, 388, 480,1131, 159, 220, 198, 679,2044,1012, + 819,1066,1443, 113,1225, 194, 318,1003,1029,2045,2046,2047,2048,1067,2049,2050, +2051,2052,2053, 59, 913, 112,2054, 632,2055, 455, 144, 739,1291,2056, 273, 681, + 499,2057, 448,2058,2059, 760,2060,2061, 970, 384, 169, 245,1132,2062,2063, 414, +1444,2064,2065, 41, 235,2066, 157, 252, 877, 568, 919, 789, 580,2067, 725,2068, +2069,1292,2070,2071,1445,2072,1446,2073,2074, 55, 588, 66,1447, 271,1092,2075, +1226,2076, 960,1013, 372,2077,2078,2079,2080,2081,1293,2082,2083,2084,2085, 850, +2086,2087,2088,2089,2090, 186,2091,1068, 180,2092,2093,2094, 109,1227, 522, 606, +2095, 867,1448,1093, 991,1171, 926, 353,1133,2096, 581,2097,2098,2099,1294,1449, +1450,2100, 596,1172,1014,1228,2101,1451,1295,1173,1229,2102,2103,1296,1134,1452, + 949,1135,2104,2105,1094,1453,1454,1455,2106,1095,2107,2108,2109,2110,2111,2112, +2113,2114,2115,2116,2117, 804,2118,2119,1230,1231, 805,1456, 405,1136,2120,2121, +2122,2123,2124, 720, 701,1297, 992,1457, 927,1004,2125,2126,2127,2128,2129,2130, + 22, 417,2131, 303,2132, 385,2133, 971, 520, 513,2134,1174, 73,1096, 231, 274, + 962,1458, 673,2135,1459,2136, 152,1137,2137,2138,2139,2140,1005,1138,1460,1139, +2141,2142,2143,2144, 11, 374, 844,2145, 154,1232, 46,1461,2146, 838, 830, 721, +1233, 106,2147, 90, 428, 462, 578, 566,1175, 352,2148,2149, 538,1234, 124,1298, +2150,1462, 761, 565,2151, 686,2152, 649,2153, 72, 173,2154, 460, 415,2155,1463, +2156,1235, 305,2157,2158,2159,2160,2161,2162, 579,2163,2164,2165,2166,2167, 747, +2168,2169,2170,2171,1464, 669,2172,2173,2174,2175,2176,1465,2177, 23, 530, 285, +2178, 335, 729,2179, 397,2180,2181,2182,1030,2183,2184, 698,2185,2186, 325,2187, +2188, 369,2189, 799,1097,1015, 348,2190,1069, 680,2191, 851,1466,2192,2193, 10, +2194, 613, 424,2195, 979, 108, 449, 589, 27, 172, 81,1031, 80, 774, 281, 350, +1032, 525, 301, 582,1176,2196, 674,1045,2197,2198,1467, 730, 762,2199,2200,2201, +2202,1468,2203, 993,2204,2205, 266,1070, 963,1140,2206,2207,2208, 664,1098, 972, +2209,2210,2211,1177,1469,1470, 871,2212,2213,2214,2215,2216,1471,2217,2218,2219, +2220,2221,2222,2223,2224,2225,2226,2227,1472,1236,2228,2229,2230,2231,2232,2233, +2234,2235,1299,2236,2237, 200,2238, 477, 373,2239,2240, 731, 825, 777,2241,2242, +2243, 521, 486, 548,2244,2245,2246,1473,1300, 53, 549, 137, 875, 76, 158,2247, +1301,1474, 469, 396,1016, 278, 712,2248, 321, 442, 503, 767, 744, 941,1237,1178, +1475,2249, 82, 178,1141,1179, 973,2250,1302,2251, 297,2252,2253, 570,2254,2255, +2256, 18, 450, 206,2257, 290, 292,1142,2258, 511, 162, 99, 346, 164, 735,2259, +1476,1477, 4, 554, 343, 798,1099,2260,1100,2261, 43, 171,1303, 139, 215,2262, +2263, 717, 775,2264,1033, 322, 216,2265, 831,2266, 149,2267,1304,2268,2269, 702, +1238, 135, 845, 347, 309,2270, 484,2271, 878, 655, 238,1006,1478,2272, 67,2273, + 295,2274,2275, 461,2276, 478, 942, 412,2277,1034,2278,2279,2280, 265,2281, 541, +2282,2283,2284,2285,2286, 70, 852,1071,2287,2288,2289,2290, 21, 56, 509, 117, + 432,2291,2292, 331, 980, 552,1101, 148, 284, 105, 393,1180,1239, 755,2293, 187, +2294,1046,1479,2295, 340,2296, 63,1047, 230,2297,2298,1305, 763,1306, 101, 800, + 808, 494,2299,2300,2301, 903,2302, 37,1072, 14, 5,2303, 79, 675,2304, 312, +2305,2306,2307,2308,2309,1480, 6,1307,2310,2311,2312, 1, 470, 35, 24, 229, +2313, 695, 210, 86, 778, 15, 784, 592, 779, 32, 77, 855, 964,2314, 259,2315, + 501, 380,2316,2317, 83, 981, 153, 689,1308,1481,1482,1483,2318,2319, 716,1484, +2320,2321,2322,2323,2324,2325,1485,2326,2327, 128, 57, 68, 261,1048, 211, 170, +1240, 31,2328, 51, 435, 742,2329,2330,2331, 635,2332, 264, 456,2333,2334,2335, + 425,2336,1486, 143, 507, 263, 943,2337, 363, 920,1487, 256,1488,1102, 243, 601, +1489,2338,2339,2340,2341,2342,2343,2344, 861,2345,2346,2347,2348,2349,2350, 395, +2351,1490,1491, 62, 535, 166, 225,2352,2353, 668, 419,1241, 138, 604, 928,2354, +1181,2355,1492,1493,2356,2357,2358,1143,2359, 696,2360, 387, 307,1309, 682, 476, +2361,2362, 332, 12, 222, 156,2363, 232,2364, 641, 276, 656, 517,1494,1495,1035, + 416, 736,1496,2365,1017, 586,2366,2367,2368,1497,2369, 242,2370,2371,2372,1498, +2373, 965, 713,2374,2375,2376,2377, 740, 982,1499, 944,1500,1007,2378,2379,1310, +1501,2380,2381,2382, 785, 329,2383,2384,1502,2385,2386,2387, 932,2388,1503,2389, +2390,2391,2392,1242,2393,2394,2395,2396,2397, 994, 950,2398,2399,2400,2401,1504, +1311,2402,2403,2404,2405,1049, 749,2406,2407, 853, 718,1144,1312,2408,1182,1505, +2409,2410, 255, 516, 479, 564, 550, 214,1506,1507,1313, 413, 239, 444, 339,1145, +1036,1508,1509,1314,1037,1510,1315,2411,1511,2412,2413,2414, 176, 703, 497, 624, + 593, 921, 302,2415, 341, 165,1103,1512,2416,1513,2417,2418,2419, 376,2420, 700, +2421,2422,2423, 258, 768,1316,2424,1183,2425, 995, 608,2426,2427,2428,2429, 221, +2430,2431,2432,2433,2434,2435,2436,2437, 195, 323, 726, 188, 897, 983,1317, 377, + 644,1050, 879,2438, 452,2439,2440,2441,2442,2443,2444, 914,2445,2446,2447,2448, + 915, 489,2449,1514,1184,2450,2451, 515, 64, 427, 495,2452, 583,2453, 483, 485, +1038, 562, 213,1515, 748, 666,2454,2455,2456,2457, 334,2458, 780, 996,1008, 705, +1243,2459,2460,2461,2462,2463, 114,2464, 493,1146, 366, 163,1516, 961,1104,2465, + 291,2466,1318,1105,2467,1517, 365,2468, 355, 951,1244,2469,1319,2470, 631,2471, +2472, 218,1320, 364, 320, 756,1518,1519,1321,1520,1322,2473,2474,2475,2476, 997, +2477,2478,2479,2480, 665,1185,2481, 916,1521,2482,2483,2484, 584, 684,2485,2486, + 797,2487,1051,1186,2488,2489,2490,1522,2491,2492, 370,2493,1039,1187, 65,2494, + 434, 205, 463,1188,2495, 125, 812, 391, 402, 826, 699, 286, 398, 155, 781, 771, + 585,2496, 590, 505,1073,2497, 599, 244, 219, 917,1018, 952, 646,1523,2498,1323, +2499,2500, 49, 984, 354, 741,2501, 625,2502,1324,2503,1019, 190, 357, 757, 491, + 95, 782, 868,2504,2505,2506,2507,2508,2509, 134,1524,1074, 422,1525, 898,2510, + 161,2511,2512,2513,2514, 769,2515,1526,2516,2517, 411,1325,2518, 472,1527,2519, +2520,2521,2522,2523,2524, 985,2525,2526,2527,2528,2529,2530, 764,2531,1245,2532, +2533, 25, 204, 311,2534, 496,2535,1052,2536,2537,2538,2539,2540,2541,2542, 199, + 704, 504, 468, 758, 657,1528, 196, 44, 839,1246, 272, 750,2543, 765, 862,2544, +2545,1326,2546, 132, 615, 933,2547, 732,2548,2549,2550,1189,1529,2551, 283,1247, +1053, 607, 929,2552,2553,2554, 930, 183, 872, 616,1040,1147,2555,1148,1020, 441, + 249,1075,2556,2557,2558, 466, 743,2559,2560,2561, 92, 514, 426, 420, 526,2562, +2563,2564,2565,2566,2567,2568, 185,2569,2570,2571,2572, 776,1530, 658,2573, 362, +2574, 361, 922,1076, 793,2575,2576,2577,2578,2579,2580,1531, 251,2581,2582,2583, +2584,1532, 54, 612, 237,1327,2585,2586, 275, 408, 647, 111,2587,1533,1106, 465, + 3, 458, 9, 38,2588, 107, 110, 890, 209, 26, 737, 498,2589,1534,2590, 431, + 202, 88,1535, 356, 287,1107, 660,1149,2591, 381,1536, 986,1150, 445,1248,1151, + 974,2592,2593, 846,2594, 446, 953, 184,1249,1250, 727,2595, 923, 193, 883,2596, +2597,2598, 102, 324, 539, 817,2599, 421,1041,2600, 832,2601, 94, 175, 197, 406, +2602, 459,2603,2604,2605,2606,2607, 330, 555,2608,2609,2610, 706,1108, 389,2611, +2612,2613,2614, 233,2615, 833, 558, 931, 954,1251,2616,2617,1537, 546,2618,2619, +1009,2620,2621,2622,1538, 690,1328,2623, 955,2624,1539,2625,2626, 772,2627,2628, +2629,2630,2631, 924, 648, 863, 603,2632,2633, 934,1540, 864, 865,2634, 642,1042, + 670,1190,2635,2636,2637,2638, 168,2639, 652, 873, 542,1054,1541,2640,2641,2642, # 512, 256 +#Everything below is of no interest for detection purpose +2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658, +2659,2660,2661,2662,2663,2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674, +2675,2676,2677,2678,2679,2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690, +2691,2692,2693,2694,2695,2696,2697,2698,2699,1542, 880,2700,2701,2702,2703,2704, +2705,2706,2707,2708,2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720, +2721,2722,2723,2724,2725,1543,2726,2727,2728,2729,2730,2731,2732,1544,2733,2734, +2735,2736,2737,2738,2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750, +2751,2752,2753,2754,1545,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765, +2766,1546,2767,1547,2768,2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779, +2780,2781,2782,2783,2784,2785,2786,1548,2787,2788,2789,1109,2790,2791,2792,2793, +2794,2795,2796,2797,2798,2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809, +2810,2811,2812,1329,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824, +2825,2826,2827,2828,2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840, +2841,2842,2843,2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856, +1549,2857,2858,2859,2860,1550,2861,2862,1551,2863,2864,2865,2866,2867,2868,2869, +2870,2871,2872,2873,2874,1110,1330,2875,2876,2877,2878,2879,2880,2881,2882,2883, +2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899, +2900,2901,2902,2903,2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915, +2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,1331, +2931,2932,2933,2934,2935,2936,2937,2938,2939,2940,2941,2942,2943,1552,2944,2945, +2946,2947,2948,2949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961, +2962,2963,2964,1252,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976, +2977,2978,2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992, +2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008, +3009,3010,3011,3012,1553,3013,3014,3015,3016,3017,1554,3018,1332,3019,3020,3021, +3022,3023,3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037, +3038,3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,1555,3051,3052, +3053,1556,1557,3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066, +3067,1558,3068,3069,3070,3071,3072,3073,3074,3075,3076,1559,3077,3078,3079,3080, +3081,3082,3083,1253,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095, +3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,1152,3109,3110, +3111,3112,3113,1560,3114,3115,3116,3117,1111,3118,3119,3120,3121,3122,3123,3124, +3125,3126,3127,3128,3129,3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140, +3141,3142,3143,3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156, +3157,3158,3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172, +3173,3174,3175,3176,1333,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187, +3188,3189,1561,3190,3191,1334,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201, +3202,3203,3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217, +3218,3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233, +3234,1562,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248, +3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264, +3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,1563,3278,3279, +3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,3295, +3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311, +3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,3325,3326,3327, +3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343, +3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,3359, +3360,3361,3362,3363,3364,1335,3365,3366,3367,3368,3369,3370,3371,3372,3373,3374, +3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,1336,3388,3389, +3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403,3404,3405, +3406,3407,3408,3409,3410,3411,3412,3413,3414,1337,3415,3416,3417,3418,3419,1338, +3420,3421,3422,1564,1565,3423,3424,3425,3426,3427,3428,3429,3430,3431,1254,3432, +3433,3434,1339,3435,3436,3437,3438,3439,1566,3440,3441,3442,3443,3444,3445,3446, +3447,3448,3449,3450,3451,3452,3453,3454,1255,3455,3456,3457,3458,3459,1567,1191, +3460,1568,1569,3461,3462,3463,1570,3464,3465,3466,3467,3468,1571,3469,3470,3471, +3472,3473,1572,3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486, +1340,3487,3488,3489,3490,3491,3492,1021,3493,3494,3495,3496,3497,3498,1573,3499, +1341,3500,3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511,1342,3512,3513, +3514,3515,3516,1574,1343,3517,3518,3519,1575,3520,1576,3521,3522,3523,3524,3525, +3526,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,3539,3540,3541, +3542,3543,3544,3545,3546,3547,3548,3549,3550,3551,3552,3553,3554,3555,3556,3557, +3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,3569,3570,3571,3572,3573, +3574,3575,3576,3577,3578,3579,3580,1577,3581,3582,1578,3583,3584,3585,3586,3587, +3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603, +3604,1579,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618, +3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,1580,3630,3631,1581,3632, +3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644,3645,3646,3647,3648, +3649,3650,3651,3652,3653,3654,3655,3656,1582,3657,3658,3659,3660,3661,3662,3663, +3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,3676,3677,3678,3679, +3680,3681,3682,3683,3684,3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695, +3696,3697,3698,3699,3700,1192,3701,3702,3703,3704,1256,3705,3706,3707,3708,1583, +1257,3709,3710,3711,3712,3713,3714,3715,3716,1584,3717,3718,3719,3720,3721,3722, +3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738, +3739,3740,3741,3742,3743,3744,3745,1344,3746,3747,3748,3749,3750,3751,3752,3753, +3754,3755,3756,1585,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,1586,3767, +3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,1345,3779,3780,3781,3782, +3783,3784,3785,3786,3787,3788,3789,3790,3791,3792,3793,3794,3795,1346,1587,3796, +3797,1588,3798,3799,3800,3801,3802,3803,3804,3805,3806,1347,3807,3808,3809,3810, +3811,1589,3812,3813,3814,3815,3816,3817,3818,3819,3820,3821,1590,3822,3823,1591, +1348,3824,3825,3826,3827,3828,3829,3830,1592,3831,3832,1593,3833,3834,3835,3836, +3837,3838,3839,3840,3841,3842,3843,3844,1349,3845,3846,3847,3848,3849,3850,3851, +3852,3853,3854,3855,3856,3857,3858,1594,3859,3860,3861,3862,3863,3864,3865,3866, +3867,3868,3869,1595,3870,3871,3872,3873,1596,3874,3875,3876,3877,3878,3879,3880, +3881,3882,3883,3884,3885,3886,1597,3887,3888,3889,3890,3891,3892,3893,3894,3895, +1598,3896,3897,3898,1599,1600,3899,1350,3900,1351,3901,3902,1352,3903,3904,3905, +3906,3907,3908,3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921, +3922,3923,3924,1258,3925,3926,3927,3928,3929,3930,3931,1193,3932,1601,3933,3934, +3935,3936,3937,3938,3939,3940,3941,3942,3943,1602,3944,3945,3946,3947,3948,1603, +3949,3950,3951,3952,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964, +3965,1604,3966,3967,3968,3969,3970,3971,3972,3973,3974,3975,3976,3977,1353,3978, +3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,1354,3992,3993, +3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009, +4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,1355,4024, +4025,4026,4027,4028,4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040, +1605,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055, +4056,4057,4058,4059,4060,1606,4061,4062,4063,4064,1607,4065,4066,4067,4068,4069, +4070,4071,4072,4073,4074,4075,4076,1194,4077,4078,1608,4079,4080,4081,4082,4083, +4084,4085,4086,4087,1609,4088,4089,4090,4091,4092,4093,4094,4095,4096,4097,4098, +4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,1259,4109,4110,4111,4112,4113, +4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,4124,1195,4125,4126,4127,1610, +4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,1356,4138,4139,4140,4141,4142, +4143,4144,1611,4145,4146,4147,4148,4149,4150,4151,4152,4153,4154,4155,4156,4157, +4158,4159,4160,4161,4162,4163,4164,4165,4166,4167,4168,4169,4170,4171,4172,4173, +4174,4175,4176,4177,4178,4179,4180,4181,4182,4183,4184,4185,4186,4187,4188,4189, +4190,4191,4192,4193,4194,4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205, +4206,4207,4208,4209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,1612,4220, +4221,4222,4223,4224,4225,4226,4227,1357,4228,1613,4229,4230,4231,4232,4233,4234, +4235,4236,4237,4238,4239,4240,4241,4242,4243,1614,4244,4245,4246,4247,4248,4249, +4250,4251,4252,4253,4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265, +4266,4267,4268,4269,4270,1196,1358,4271,4272,4273,4274,4275,4276,4277,4278,4279, +4280,4281,4282,4283,4284,4285,4286,4287,1615,4288,4289,4290,4291,4292,4293,4294, +4295,4296,4297,4298,4299,4300,4301,4302,4303,4304,4305,4306,4307,4308,4309,4310, +4311,4312,4313,4314,4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326, +4327,4328,4329,4330,4331,4332,4333,4334,1616,4335,4336,4337,4338,4339,4340,4341, +4342,4343,4344,4345,4346,4347,4348,4349,4350,4351,4352,4353,4354,4355,4356,4357, +4358,4359,4360,1617,4361,4362,4363,4364,4365,1618,4366,4367,4368,4369,4370,4371, +4372,4373,4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387, +4388,4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403, +4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,1619,4417,4418, +4419,4420,4421,4422,4423,4424,4425,1112,4426,4427,4428,4429,4430,1620,4431,4432, +4433,4434,4435,4436,4437,4438,4439,4440,4441,4442,1260,1261,4443,4444,4445,4446, +4447,4448,4449,4450,4451,4452,4453,4454,4455,1359,4456,4457,4458,4459,4460,4461, +4462,4463,4464,4465,1621,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476, +4477,4478,4479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,1055,4490,4491, +4492,4493,4494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507, +4508,4509,4510,4511,4512,4513,4514,4515,4516,4517,4518,1622,4519,4520,4521,1623, +4522,4523,4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,1360,4536, +4537,4538,4539,4540,4541,4542,4543, 975,4544,4545,4546,4547,4548,4549,4550,4551, +4552,4553,4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567, +4568,4569,4570,4571,1624,4572,4573,4574,4575,4576,1625,4577,4578,4579,4580,4581, +4582,4583,4584,1626,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,1627, +4596,4597,4598,4599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611, +4612,4613,4614,4615,1628,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626, +4627,4628,4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642, +4643,4644,4645,4646,4647,4648,4649,1361,4650,4651,4652,4653,4654,4655,4656,4657, +4658,4659,4660,4661,1362,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672, +4673,4674,4675,4676,4677,4678,4679,4680,4681,4682,1629,4683,4684,4685,4686,4687, +1630,4688,4689,4690,4691,1153,4692,4693,4694,1113,4695,4696,4697,4698,4699,4700, +4701,4702,4703,4704,4705,4706,4707,4708,4709,4710,4711,1197,4712,4713,4714,4715, +4716,4717,4718,4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731, +4732,4733,4734,4735,1631,4736,1632,4737,4738,4739,4740,4741,4742,4743,4744,1633, +4745,4746,4747,4748,4749,1262,4750,4751,4752,4753,4754,1363,4755,4756,4757,4758, +4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,1634,4769,4770,4771,4772,4773, +4774,4775,4776,4777,4778,1635,4779,4780,4781,4782,4783,4784,4785,4786,4787,4788, +4789,1636,4790,4791,4792,4793,4794,4795,4796,4797,4798,4799,4800,4801,4802,4803, +4804,4805,4806,1637,4807,4808,4809,1638,4810,4811,4812,4813,4814,4815,4816,4817, +4818,1639,4819,4820,4821,4822,4823,4824,4825,4826,4827,4828,4829,4830,4831,4832, +4833,1077,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,4844,4845,4846,4847, +4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,4859,4860,4861,4862,4863, +4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879, +4880,4881,4882,4883,1640,4884,4885,1641,4886,4887,4888,4889,4890,4891,4892,4893, +4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909, +4910,4911,1642,4912,4913,4914,1364,4915,4916,4917,4918,4919,4920,4921,4922,4923, +4924,4925,4926,4927,4928,4929,4930,4931,1643,4932,4933,4934,4935,4936,4937,4938, +4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954, +4955,4956,4957,4958,4959,4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970, +4971,4972,4973,4974,4975,4976,4977,4978,4979,4980,1644,4981,4982,4983,4984,1645, +4985,4986,1646,4987,4988,4989,4990,4991,4992,4993,4994,4995,4996,4997,4998,4999, +5000,5001,5002,5003,5004,5005,1647,5006,1648,5007,5008,5009,5010,5011,5012,1078, +5013,5014,5015,5016,5017,5018,5019,5020,5021,5022,5023,5024,5025,5026,5027,5028, +1365,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,1649,5040,5041,5042, +5043,5044,5045,1366,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,1650,5056, +5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072, +5073,5074,5075,5076,5077,1651,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087, +5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103, +5104,5105,5106,5107,5108,5109,5110,1652,5111,5112,5113,5114,5115,5116,5117,5118, +1367,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,1653,5130,5131,5132, +5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148, +5149,1368,5150,1654,5151,1369,5152,5153,5154,5155,5156,5157,5158,5159,5160,5161, +5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,5176,5177, +5178,1370,5179,5180,5181,5182,5183,5184,5185,5186,5187,5188,5189,5190,5191,5192, +5193,5194,5195,5196,5197,5198,1655,5199,5200,5201,5202,1656,5203,5204,5205,5206, +1371,5207,1372,5208,5209,5210,5211,1373,5212,5213,1374,5214,5215,5216,5217,5218, +5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234, +5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,5247,1657,5248,5249, +5250,5251,1658,1263,5252,5253,5254,5255,5256,1375,5257,5258,5259,5260,5261,5262, +5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278, +5279,5280,5281,5282,5283,1659,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293, +5294,5295,5296,5297,5298,5299,5300,1660,5301,5302,5303,5304,5305,5306,5307,5308, +5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,1376,5322,5323, +5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,1198,5334,5335,5336,5337,5338, +5339,5340,5341,5342,5343,1661,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353, +5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,5369, +5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,5380,5381,5382,5383,5384,5385, +5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,1264,5399,5400, +5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,1662,5413,5414,5415, +5416,1663,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,5429,5430, +5431,5432,5433,5434,5435,5436,5437,5438,1664,5439,5440,5441,5442,5443,5444,5445, +5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,5458,5459,5460,5461, +5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,5474,5475,5476,5477, +5478,1154,5479,5480,5481,5482,5483,5484,5485,1665,5486,5487,5488,5489,5490,5491, +5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504,5505,5506,5507, +5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520,5521,5522,5523, +5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539, +5540,5541,5542,5543,5544,5545,5546,5547,5548,1377,5549,5550,5551,5552,5553,5554, +5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570, +1114,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585, +5586,5587,5588,5589,5590,5591,5592,1378,5593,5594,5595,5596,5597,5598,5599,5600, +5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,1379,5615, +5616,5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631, +5632,5633,5634,1380,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646, +5647,5648,5649,1381,1056,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660, +1666,5661,5662,5663,5664,5665,5666,5667,5668,1667,5669,1668,5670,5671,5672,5673, +5674,5675,5676,5677,5678,1155,5679,5680,5681,5682,5683,5684,5685,5686,5687,5688, +5689,5690,5691,5692,5693,5694,5695,5696,5697,5698,1669,5699,5700,5701,5702,5703, +5704,5705,1670,5706,5707,5708,5709,5710,1671,5711,5712,5713,5714,1382,5715,5716, +5717,5718,5719,5720,5721,5722,5723,5724,5725,1672,5726,5727,1673,1674,5728,5729, +5730,5731,5732,5733,5734,5735,5736,1675,5737,5738,5739,5740,5741,5742,5743,5744, +1676,5745,5746,5747,5748,5749,5750,5751,1383,5752,5753,5754,5755,5756,5757,5758, +5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,1677,5769,5770,5771,5772,5773, +1678,5774,5775,5776, 998,5777,5778,5779,5780,5781,5782,5783,5784,5785,1384,5786, +5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,5799,5800,1679,5801, +5802,5803,1115,1116,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,5815, +5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,5830,5831, +5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,5845,5846,5847, +5848,5849,5850,5851,5852,5853,5854,5855,1680,5856,5857,5858,5859,5860,5861,5862, +5863,5864,1681,5865,5866,5867,1682,5868,5869,5870,5871,5872,5873,5874,5875,5876, +5877,5878,5879,1683,5880,1684,5881,5882,5883,5884,1685,5885,5886,5887,5888,5889, +5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,5905, +5906,5907,1686,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920, +5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,1687, +5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951, +5952,1688,1689,5953,1199,5954,5955,5956,5957,5958,5959,5960,5961,1690,5962,5963, +5964,5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979, +5980,5981,1385,5982,1386,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993, +5994,5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009, +6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,6024,6025, +6026,6027,1265,6028,6029,1691,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039, +6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,6055, +6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,6069,6070,6071, +6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,1692,6085,6086, +6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6100,6101,6102, +6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,6115,6116,6117,6118, +6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,6130,6131,1693,6132,6133, +6134,6135,6136,1694,6137,6138,6139,6140,6141,1695,6142,6143,6144,6145,6146,6147, +6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,6160,6161,6162,6163, +6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,6175,6176,6177,6178,6179, +6180,6181,6182,6183,6184,6185,1696,6186,6187,6188,6189,6190,6191,6192,6193,6194, +6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,6207,6208,6209,6210, +6211,6212,6213,6214,6215,6216,6217,6218,6219,1697,6220,6221,6222,6223,6224,6225, +6226,6227,6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,6239,6240,6241, +6242,6243,6244,6245,6246,6247,6248,6249,6250,6251,6252,6253,1698,6254,6255,6256, +6257,6258,6259,6260,6261,6262,6263,1200,6264,6265,6266,6267,6268,6269,6270,6271, #1024 +6272,6273,6274,6275,6276,6277,6278,6279,6280,6281,6282,6283,6284,6285,6286,6287, +6288,6289,6290,6291,6292,6293,6294,6295,6296,6297,6298,6299,6300,6301,6302,1699, +6303,6304,1700,6305,6306,6307,6308,6309,6310,6311,6312,6313,6314,6315,6316,6317, +6318,6319,6320,6321,6322,6323,6324,6325,6326,6327,6328,6329,6330,6331,6332,6333, +6334,6335,6336,6337,6338,6339,1701,6340,6341,6342,6343,6344,1387,6345,6346,6347, +6348,6349,6350,6351,6352,6353,6354,6355,6356,6357,6358,6359,6360,6361,6362,6363, +6364,6365,6366,6367,6368,6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379, +6380,6381,6382,6383,6384,6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395, +6396,6397,6398,6399,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411, +6412,6413,1702,6414,6415,6416,6417,6418,6419,6420,6421,6422,1703,6423,6424,6425, +6426,6427,6428,6429,6430,6431,6432,6433,6434,6435,6436,6437,6438,1704,6439,6440, +6441,6442,6443,6444,6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456, +6457,6458,6459,6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472, +6473,6474,6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488, +6489,6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,1266, +6504,6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,6519, +6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,6534,6535, +6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,6550,6551, +1705,1706,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,6565, +6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,6579,6580,6581, +6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,6595,6596,6597, +6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,6609,6610,6611,6612,6613, +6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,6624,6625,6626,6627,6628,6629, +6630,6631,6632,6633,6634,6635,6636,6637,1388,6638,6639,6640,6641,6642,6643,6644, +1707,6645,6646,6647,6648,6649,6650,6651,6652,6653,6654,6655,6656,6657,6658,6659, +6660,6661,6662,6663,1708,6664,6665,6666,6667,6668,6669,6670,6671,6672,6673,6674, +1201,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,6685,6686,6687,6688,6689, +6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,6700,6701,6702,6703,6704,6705, +6706,6707,6708,6709,6710,6711,6712,6713,6714,6715,6716,6717,6718,6719,6720,6721, +6722,6723,6724,6725,1389,6726,6727,6728,6729,6730,6731,6732,6733,6734,6735,6736, +1390,1709,6737,6738,6739,6740,6741,6742,1710,6743,6744,6745,6746,1391,6747,6748, +6749,6750,6751,6752,6753,6754,6755,6756,6757,1392,6758,6759,6760,6761,6762,6763, +6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,6779, +6780,1202,6781,6782,6783,6784,6785,6786,6787,6788,6789,6790,6791,6792,6793,6794, +6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,6805,6806,6807,6808,6809,1711, +6810,6811,6812,6813,6814,6815,6816,6817,6818,6819,6820,6821,6822,6823,6824,6825, +6826,6827,6828,6829,6830,6831,6832,6833,6834,6835,6836,1393,6837,6838,6839,6840, +6841,6842,6843,6844,6845,6846,6847,6848,6849,6850,6851,6852,6853,6854,6855,6856, +6857,6858,6859,6860,6861,6862,6863,6864,6865,6866,6867,6868,6869,6870,6871,6872, +6873,6874,6875,6876,6877,6878,6879,6880,6881,6882,6883,6884,6885,6886,6887,6888, +6889,6890,6891,6892,6893,6894,6895,6896,6897,6898,6899,6900,6901,6902,1712,6903, +6904,6905,6906,6907,6908,6909,6910,1713,6911,6912,6913,6914,6915,6916,6917,6918, +6919,6920,6921,6922,6923,6924,6925,6926,6927,6928,6929,6930,6931,6932,6933,6934, +6935,6936,6937,6938,6939,6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950, +6951,6952,6953,6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966, +6967,6968,6969,6970,6971,6972,6973,6974,1714,6975,6976,6977,6978,6979,6980,6981, +6982,6983,6984,6985,6986,6987,6988,1394,6989,6990,6991,6992,6993,6994,6995,6996, +6997,6998,6999,7000,1715,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011, +7012,7013,7014,7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027, +7028,1716,7029,7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042, +7043,7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058, +7059,7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,7074, +7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,7089,7090, +7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,7105,7106, +7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,7120,7121,7122, +7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136,7137,7138, +7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,7149,7150,7151,7152,7153,7154, +7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,7165,7166,7167,7168,7169,7170, +7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183,7184,7185,7186, +7187,7188,7189,7190,7191,7192,7193,7194,7195,7196,7197,7198,7199,7200,7201,7202, +7203,7204,7205,7206,7207,1395,7208,7209,7210,7211,7212,7213,1717,7214,7215,7216, +7217,7218,7219,7220,7221,7222,7223,7224,7225,7226,7227,7228,7229,7230,7231,7232, +7233,7234,7235,7236,7237,7238,7239,7240,7241,7242,7243,7244,7245,7246,7247,7248, +7249,7250,7251,7252,7253,7254,7255,7256,7257,7258,7259,7260,7261,7262,7263,7264, +7265,7266,7267,7268,7269,7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280, +7281,7282,7283,7284,7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,7296, +7297,7298,7299,7300,7301,7302,7303,7304,7305,7306,7307,7308,7309,7310,7311,7312, +7313,1718,7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327, +7328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,7343, +7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,7358,7359, +7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,7373,7374,7375, +7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,7388,7389,7390,7391, +7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,7403,7404,7405,7406,7407, +7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,7418,7419,7420,7421,7422,7423, +7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,7434,7435,7436,7437,7438,7439, +7440,7441,7442,7443,7444,7445,7446,7447,7448,7449,7450,7451,7452,7453,7454,7455, +7456,7457,7458,7459,7460,7461,7462,7463,7464,7465,7466,7467,7468,7469,7470,7471, +7472,7473,7474,7475,7476,7477,7478,7479,7480,7481,7482,7483,7484,7485,7486,7487, +7488,7489,7490,7491,7492,7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,7503, +7504,7505,7506,7507,7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519, +7520,7521,7522,7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535, +7536,7537,7538,7539,7540,7541,7542,7543,7544,7545,7546,7547,7548,7549,7550,7551, +7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567, +7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,7583, +7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598,7599, +7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614,7615, +7616,7617,7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628,7629,7630,7631, +7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643,7644,7645,7646,7647, +7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659,7660,7661,7662,7663, +7664,7665,7666,7667,7668,7669,7670,7671,7672,7673,7674,7675,7676,7677,7678,7679, +7680,7681,7682,7683,7684,7685,7686,7687,7688,7689,7690,7691,7692,7693,7694,7695, +7696,7697,7698,7699,7700,7701,7702,7703,7704,7705,7706,7707,7708,7709,7710,7711, +7712,7713,7714,7715,7716,7717,7718,7719,7720,7721,7722,7723,7724,7725,7726,7727, +7728,7729,7730,7731,7732,7733,7734,7735,7736,7737,7738,7739,7740,7741,7742,7743, +7744,7745,7746,7747,7748,7749,7750,7751,7752,7753,7754,7755,7756,7757,7758,7759, +7760,7761,7762,7763,7764,7765,7766,7767,7768,7769,7770,7771,7772,7773,7774,7775, +7776,7777,7778,7779,7780,7781,7782,7783,7784,7785,7786,7787,7788,7789,7790,7791, +7792,7793,7794,7795,7796,7797,7798,7799,7800,7801,7802,7803,7804,7805,7806,7807, +7808,7809,7810,7811,7812,7813,7814,7815,7816,7817,7818,7819,7820,7821,7822,7823, +7824,7825,7826,7827,7828,7829,7830,7831,7832,7833,7834,7835,7836,7837,7838,7839, +7840,7841,7842,7843,7844,7845,7846,7847,7848,7849,7850,7851,7852,7853,7854,7855, +7856,7857,7858,7859,7860,7861,7862,7863,7864,7865,7866,7867,7868,7869,7870,7871, +7872,7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886,7887, +7888,7889,7890,7891,7892,7893,7894,7895,7896,7897,7898,7899,7900,7901,7902,7903, +7904,7905,7906,7907,7908,7909,7910,7911,7912,7913,7914,7915,7916,7917,7918,7919, +7920,7921,7922,7923,7924,7925,7926,7927,7928,7929,7930,7931,7932,7933,7934,7935, +7936,7937,7938,7939,7940,7941,7942,7943,7944,7945,7946,7947,7948,7949,7950,7951, +7952,7953,7954,7955,7956,7957,7958,7959,7960,7961,7962,7963,7964,7965,7966,7967, +7968,7969,7970,7971,7972,7973,7974,7975,7976,7977,7978,7979,7980,7981,7982,7983, +7984,7985,7986,7987,7988,7989,7990,7991,7992,7993,7994,7995,7996,7997,7998,7999, +8000,8001,8002,8003,8004,8005,8006,8007,8008,8009,8010,8011,8012,8013,8014,8015, +8016,8017,8018,8019,8020,8021,8022,8023,8024,8025,8026,8027,8028,8029,8030,8031, +8032,8033,8034,8035,8036,8037,8038,8039,8040,8041,8042,8043,8044,8045,8046,8047, +8048,8049,8050,8051,8052,8053,8054,8055,8056,8057,8058,8059,8060,8061,8062,8063, +8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079, +8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095, +8096,8097,8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110,8111, +8112,8113,8114,8115,8116,8117,8118,8119,8120,8121,8122,8123,8124,8125,8126,8127, +8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,8138,8139,8140,8141,8142,8143, +8144,8145,8146,8147,8148,8149,8150,8151,8152,8153,8154,8155,8156,8157,8158,8159, +8160,8161,8162,8163,8164,8165,8166,8167,8168,8169,8170,8171,8172,8173,8174,8175, +8176,8177,8178,8179,8180,8181,8182,8183,8184,8185,8186,8187,8188,8189,8190,8191, +8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207, +8208,8209,8210,8211,8212,8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223, +8224,8225,8226,8227,8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239, +8240,8241,8242,8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,8255, +8256,8257,8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,8270,8271, +8272,8273,8274,8275,8276,8277,8278,8279,8280,8281,8282,8283,8284,8285,8286,8287, +8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,8303, +8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,8315,8316,8317,8318,8319, +8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,8330,8331,8332,8333,8334,8335, +8336,8337,8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,8348,8349,8350,8351, +8352,8353,8354,8355,8356,8357,8358,8359,8360,8361,8362,8363,8364,8365,8366,8367, +8368,8369,8370,8371,8372,8373,8374,8375,8376,8377,8378,8379,8380,8381,8382,8383, +8384,8385,8386,8387,8388,8389,8390,8391,8392,8393,8394,8395,8396,8397,8398,8399, +8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,8411,8412,8413,8414,8415, +8416,8417,8418,8419,8420,8421,8422,8423,8424,8425,8426,8427,8428,8429,8430,8431, +8432,8433,8434,8435,8436,8437,8438,8439,8440,8441,8442,8443,8444,8445,8446,8447, +8448,8449,8450,8451,8452,8453,8454,8455,8456,8457,8458,8459,8460,8461,8462,8463, +8464,8465,8466,8467,8468,8469,8470,8471,8472,8473,8474,8475,8476,8477,8478,8479, +8480,8481,8482,8483,8484,8485,8486,8487,8488,8489,8490,8491,8492,8493,8494,8495, +8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8506,8507,8508,8509,8510,8511, +8512,8513,8514,8515,8516,8517,8518,8519,8520,8521,8522,8523,8524,8525,8526,8527, +8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,8540,8541,8542,8543, +8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559, +8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,8570,8571,8572,8573,8574,8575, +8576,8577,8578,8579,8580,8581,8582,8583,8584,8585,8586,8587,8588,8589,8590,8591, +8592,8593,8594,8595,8596,8597,8598,8599,8600,8601,8602,8603,8604,8605,8606,8607, +8608,8609,8610,8611,8612,8613,8614,8615,8616,8617,8618,8619,8620,8621,8622,8623, +8624,8625,8626,8627,8628,8629,8630,8631,8632,8633,8634,8635,8636,8637,8638,8639, +8640,8641,8642,8643,8644,8645,8646,8647,8648,8649,8650,8651,8652,8653,8654,8655, +8656,8657,8658,8659,8660,8661,8662,8663,8664,8665,8666,8667,8668,8669,8670,8671, +8672,8673,8674,8675,8676,8677,8678,8679,8680,8681,8682,8683,8684,8685,8686,8687, +8688,8689,8690,8691,8692,8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703, +8704,8705,8706,8707,8708,8709,8710,8711,8712,8713,8714,8715,8716,8717,8718,8719, +8720,8721,8722,8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,8734,8735, +8736,8737,8738,8739,8740,8741) + +# flake8: noqa diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/euckrprober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/euckrprober.py new file mode 100644 index 0000000000..def3e42902 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/euckrprober.py @@ -0,0 +1,42 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCKRDistributionAnalysis +from .mbcssm import EUCKRSMModel + + +class EUCKRProber(MultiByteCharSetProber): + def __init__(self): + MultiByteCharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(EUCKRSMModel) + self._mDistributionAnalyzer = EUCKRDistributionAnalysis() + self.reset() + + def get_charset_name(self): + return "EUC-KR" diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/euctwfreq.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/euctwfreq.py new file mode 100644 index 0000000000..576e7504dc --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/euctwfreq.py @@ -0,0 +1,428 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# EUCTW frequency table +# Converted from big5 work +# by Taiwan's Mandarin Promotion Council +# + +# 128 --> 0.42261 +# 256 --> 0.57851 +# 512 --> 0.74851 +# 1024 --> 0.89384 +# 2048 --> 0.97583 +# +# Idea Distribution Ratio = 0.74851/(1-0.74851) =2.98 +# Random Distribution Ration = 512/(5401-512)=0.105 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR + +EUCTW_TYPICAL_DISTRIBUTION_RATIO = 0.75 + +# Char to FreqOrder table , +EUCTW_TABLE_SIZE = 8102 + +EUCTWCharToFreqOrder = ( + 1,1800,1506, 255,1431, 198, 9, 82, 6,7310, 177, 202,3615,1256,2808, 110, # 2742 +3735, 33,3241, 261, 76, 44,2113, 16,2931,2184,1176, 659,3868, 26,3404,2643, # 2758 +1198,3869,3313,4060, 410,2211, 302, 590, 361,1963, 8, 204, 58,4296,7311,1931, # 2774 + 63,7312,7313, 317,1614, 75, 222, 159,4061,2412,1480,7314,3500,3068, 224,2809, # 2790 +3616, 3, 10,3870,1471, 29,2774,1135,2852,1939, 873, 130,3242,1123, 312,7315, # 2806 +4297,2051, 507, 252, 682,7316, 142,1914, 124, 206,2932, 34,3501,3173, 64, 604, # 2822 +7317,2494,1976,1977, 155,1990, 645, 641,1606,7318,3405, 337, 72, 406,7319, 80, # 2838 + 630, 238,3174,1509, 263, 939,1092,2644, 756,1440,1094,3406, 449, 69,2969, 591, # 2854 + 179,2095, 471, 115,2034,1843, 60, 50,2970, 134, 806,1868, 734,2035,3407, 180, # 2870 + 995,1607, 156, 537,2893, 688,7320, 319,1305, 779,2144, 514,2374, 298,4298, 359, # 2886 +2495, 90,2707,1338, 663, 11, 906,1099,2545, 20,2436, 182, 532,1716,7321, 732, # 2902 +1376,4062,1311,1420,3175, 25,2312,1056, 113, 399, 382,1949, 242,3408,2467, 529, # 2918 +3243, 475,1447,3617,7322, 117, 21, 656, 810,1297,2295,2329,3502,7323, 126,4063, # 2934 + 706, 456, 150, 613,4299, 71,1118,2036,4064, 145,3069, 85, 835, 486,2114,1246, # 2950 +1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,7324,2127,2354, 347,3736, 221, # 2966 +3503,3110,7325,1955,1153,4065, 83, 296,1199,3070, 192, 624, 93,7326, 822,1897, # 2982 +2810,3111, 795,2064, 991,1554,1542,1592, 27, 43,2853, 859, 139,1456, 860,4300, # 2998 + 437, 712,3871, 164,2392,3112, 695, 211,3017,2096, 195,3872,1608,3504,3505,3618, # 3014 +3873, 234, 811,2971,2097,3874,2229,1441,3506,1615,2375, 668,2076,1638, 305, 228, # 3030 +1664,4301, 467, 415,7327, 262,2098,1593, 239, 108, 300, 200,1033, 512,1247,2077, # 3046 +7328,7329,2173,3176,3619,2673, 593, 845,1062,3244, 88,1723,2037,3875,1950, 212, # 3062 + 266, 152, 149, 468,1898,4066,4302, 77, 187,7330,3018, 37, 5,2972,7331,3876, # 3078 +7332,7333, 39,2517,4303,2894,3177,2078, 55, 148, 74,4304, 545, 483,1474,1029, # 3094 +1665, 217,1869,1531,3113,1104,2645,4067, 24, 172,3507, 900,3877,3508,3509,4305, # 3110 + 32,1408,2811,1312, 329, 487,2355,2247,2708, 784,2674, 4,3019,3314,1427,1788, # 3126 + 188, 109, 499,7334,3620,1717,1789, 888,1217,3020,4306,7335,3510,7336,3315,1520, # 3142 +3621,3878, 196,1034, 775,7337,7338, 929,1815, 249, 439, 38,7339,1063,7340, 794, # 3158 +3879,1435,2296, 46, 178,3245,2065,7341,2376,7342, 214,1709,4307, 804, 35, 707, # 3174 + 324,3622,1601,2546, 140, 459,4068,7343,7344,1365, 839, 272, 978,2257,2572,3409, # 3190 +2128,1363,3623,1423, 697, 100,3071, 48, 70,1231, 495,3114,2193,7345,1294,7346, # 3206 +2079, 462, 586,1042,3246, 853, 256, 988, 185,2377,3410,1698, 434,1084,7347,3411, # 3222 + 314,2615,2775,4308,2330,2331, 569,2280, 637,1816,2518, 757,1162,1878,1616,3412, # 3238 + 287,1577,2115, 768,4309,1671,2854,3511,2519,1321,3737, 909,2413,7348,4069, 933, # 3254 +3738,7349,2052,2356,1222,4310, 765,2414,1322, 786,4311,7350,1919,1462,1677,2895, # 3270 +1699,7351,4312,1424,2437,3115,3624,2590,3316,1774,1940,3413,3880,4070, 309,1369, # 3286 +1130,2812, 364,2230,1653,1299,3881,3512,3882,3883,2646, 525,1085,3021, 902,2000, # 3302 +1475, 964,4313, 421,1844,1415,1057,2281, 940,1364,3116, 376,4314,4315,1381, 7, # 3318 +2520, 983,2378, 336,1710,2675,1845, 321,3414, 559,1131,3022,2742,1808,1132,1313, # 3334 + 265,1481,1857,7352, 352,1203,2813,3247, 167,1089, 420,2814, 776, 792,1724,3513, # 3350 +4071,2438,3248,7353,4072,7354, 446, 229, 333,2743, 901,3739,1200,1557,4316,2647, # 3366 +1920, 395,2744,2676,3740,4073,1835, 125, 916,3178,2616,4317,7355,7356,3741,7357, # 3382 +7358,7359,4318,3117,3625,1133,2547,1757,3415,1510,2313,1409,3514,7360,2145, 438, # 3398 +2591,2896,2379,3317,1068, 958,3023, 461, 311,2855,2677,4074,1915,3179,4075,1978, # 3414 + 383, 750,2745,2617,4076, 274, 539, 385,1278,1442,7361,1154,1964, 384, 561, 210, # 3430 + 98,1295,2548,3515,7362,1711,2415,1482,3416,3884,2897,1257, 129,7363,3742, 642, # 3446 + 523,2776,2777,2648,7364, 141,2231,1333, 68, 176, 441, 876, 907,4077, 603,2592, # 3462 + 710, 171,3417, 404, 549, 18,3118,2393,1410,3626,1666,7365,3516,4319,2898,4320, # 3478 +7366,2973, 368,7367, 146, 366, 99, 871,3627,1543, 748, 807,1586,1185, 22,2258, # 3494 + 379,3743,3180,7368,3181, 505,1941,2618,1991,1382,2314,7369, 380,2357, 218, 702, # 3510 +1817,1248,3418,3024,3517,3318,3249,7370,2974,3628, 930,3250,3744,7371, 59,7372, # 3526 + 585, 601,4078, 497,3419,1112,1314,4321,1801,7373,1223,1472,2174,7374, 749,1836, # 3542 + 690,1899,3745,1772,3885,1476, 429,1043,1790,2232,2116, 917,4079, 447,1086,1629, # 3558 +7375, 556,7376,7377,2020,1654, 844,1090, 105, 550, 966,1758,2815,1008,1782, 686, # 3574 +1095,7378,2282, 793,1602,7379,3518,2593,4322,4080,2933,2297,4323,3746, 980,2496, # 3590 + 544, 353, 527,4324, 908,2678,2899,7380, 381,2619,1942,1348,7381,1341,1252, 560, # 3606 +3072,7382,3420,2856,7383,2053, 973, 886,2080, 143,4325,7384,7385, 157,3886, 496, # 3622 +4081, 57, 840, 540,2038,4326,4327,3421,2117,1445, 970,2259,1748,1965,2081,4082, # 3638 +3119,1234,1775,3251,2816,3629, 773,1206,2129,1066,2039,1326,3887,1738,1725,4083, # 3654 + 279,3120, 51,1544,2594, 423,1578,2130,2066, 173,4328,1879,7386,7387,1583, 264, # 3670 + 610,3630,4329,2439, 280, 154,7388,7389,7390,1739, 338,1282,3073, 693,2857,1411, # 3686 +1074,3747,2440,7391,4330,7392,7393,1240, 952,2394,7394,2900,1538,2679, 685,1483, # 3702 +4084,2468,1436, 953,4085,2054,4331, 671,2395, 79,4086,2441,3252, 608, 567,2680, # 3718 +3422,4087,4088,1691, 393,1261,1791,2396,7395,4332,7396,7397,7398,7399,1383,1672, # 3734 +3748,3182,1464, 522,1119, 661,1150, 216, 675,4333,3888,1432,3519, 609,4334,2681, # 3750 +2397,7400,7401,7402,4089,3025, 0,7403,2469, 315, 231,2442, 301,3319,4335,2380, # 3766 +7404, 233,4090,3631,1818,4336,4337,7405, 96,1776,1315,2082,7406, 257,7407,1809, # 3782 +3632,2709,1139,1819,4091,2021,1124,2163,2778,1777,2649,7408,3074, 363,1655,3183, # 3798 +7409,2975,7410,7411,7412,3889,1567,3890, 718, 103,3184, 849,1443, 341,3320,2934, # 3814 +1484,7413,1712, 127, 67, 339,4092,2398, 679,1412, 821,7414,7415, 834, 738, 351, # 3830 +2976,2146, 846, 235,1497,1880, 418,1992,3749,2710, 186,1100,2147,2746,3520,1545, # 3846 +1355,2935,2858,1377, 583,3891,4093,2573,2977,7416,1298,3633,1078,2549,3634,2358, # 3862 + 78,3750,3751, 267,1289,2099,2001,1594,4094, 348, 369,1274,2194,2175,1837,4338, # 3878 +1820,2817,3635,2747,2283,2002,4339,2936,2748, 144,3321, 882,4340,3892,2749,3423, # 3894 +4341,2901,7417,4095,1726, 320,7418,3893,3026, 788,2978,7419,2818,1773,1327,2859, # 3910 +3894,2819,7420,1306,4342,2003,1700,3752,3521,2359,2650, 787,2022, 506, 824,3636, # 3926 + 534, 323,4343,1044,3322,2023,1900, 946,3424,7421,1778,1500,1678,7422,1881,4344, # 3942 + 165, 243,4345,3637,2521, 123, 683,4096, 764,4346, 36,3895,1792, 589,2902, 816, # 3958 + 626,1667,3027,2233,1639,1555,1622,3753,3896,7423,3897,2860,1370,1228,1932, 891, # 3974 +2083,2903, 304,4097,7424, 292,2979,2711,3522, 691,2100,4098,1115,4347, 118, 662, # 3990 +7425, 611,1156, 854,2381,1316,2861, 2, 386, 515,2904,7426,7427,3253, 868,2234, # 4006 +1486, 855,2651, 785,2212,3028,7428,1040,3185,3523,7429,3121, 448,7430,1525,7431, # 4022 +2164,4348,7432,3754,7433,4099,2820,3524,3122, 503, 818,3898,3123,1568, 814, 676, # 4038 +1444, 306,1749,7434,3755,1416,1030, 197,1428, 805,2821,1501,4349,7435,7436,7437, # 4054 +1993,7438,4350,7439,7440,2195, 13,2779,3638,2980,3124,1229,1916,7441,3756,2131, # 4070 +7442,4100,4351,2399,3525,7443,2213,1511,1727,1120,7444,7445, 646,3757,2443, 307, # 4086 +7446,7447,1595,3186,7448,7449,7450,3639,1113,1356,3899,1465,2522,2523,7451, 519, # 4102 +7452, 128,2132, 92,2284,1979,7453,3900,1512, 342,3125,2196,7454,2780,2214,1980, # 4118 +3323,7455, 290,1656,1317, 789, 827,2360,7456,3758,4352, 562, 581,3901,7457, 401, # 4134 +4353,2248, 94,4354,1399,2781,7458,1463,2024,4355,3187,1943,7459, 828,1105,4101, # 4150 +1262,1394,7460,4102, 605,4356,7461,1783,2862,7462,2822, 819,2101, 578,2197,2937, # 4166 +7463,1502, 436,3254,4103,3255,2823,3902,2905,3425,3426,7464,2712,2315,7465,7466, # 4182 +2332,2067, 23,4357, 193, 826,3759,2102, 699,1630,4104,3075, 390,1793,1064,3526, # 4198 +7467,1579,3076,3077,1400,7468,4105,1838,1640,2863,7469,4358,4359, 137,4106, 598, # 4214 +3078,1966, 780, 104, 974,2938,7470, 278, 899, 253, 402, 572, 504, 493,1339,7471, # 4230 +3903,1275,4360,2574,2550,7472,3640,3029,3079,2249, 565,1334,2713, 863, 41,7473, # 4246 +7474,4361,7475,1657,2333, 19, 463,2750,4107, 606,7476,2981,3256,1087,2084,1323, # 4262 +2652,2982,7477,1631,1623,1750,4108,2682,7478,2864, 791,2714,2653,2334, 232,2416, # 4278 +7479,2983,1498,7480,2654,2620, 755,1366,3641,3257,3126,2025,1609, 119,1917,3427, # 4294 + 862,1026,4109,7481,3904,3760,4362,3905,4363,2260,1951,2470,7482,1125, 817,4110, # 4310 +4111,3906,1513,1766,2040,1487,4112,3030,3258,2824,3761,3127,7483,7484,1507,7485, # 4326 +2683, 733, 40,1632,1106,2865, 345,4113, 841,2524, 230,4364,2984,1846,3259,3428, # 4342 +7486,1263, 986,3429,7487, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562,3907, # 4358 +3908,2939, 967,2751,2655,1349, 592,2133,1692,3324,2985,1994,4114,1679,3909,1901, # 4374 +2185,7488, 739,3642,2715,1296,1290,7489,4115,2198,2199,1921,1563,2595,2551,1870, # 4390 +2752,2986,7490, 435,7491, 343,1108, 596, 17,1751,4365,2235,3430,3643,7492,4366, # 4406 + 294,3527,2940,1693, 477, 979, 281,2041,3528, 643,2042,3644,2621,2782,2261,1031, # 4422 +2335,2134,2298,3529,4367, 367,1249,2552,7493,3530,7494,4368,1283,3325,2004, 240, # 4438 +1762,3326,4369,4370, 836,1069,3128, 474,7495,2148,2525, 268,3531,7496,3188,1521, # 4454 +1284,7497,1658,1546,4116,7498,3532,3533,7499,4117,3327,2684,1685,4118, 961,1673, # 4470 +2622, 190,2005,2200,3762,4371,4372,7500, 570,2497,3645,1490,7501,4373,2623,3260, # 4486 +1956,4374, 584,1514, 396,1045,1944,7502,4375,1967,2444,7503,7504,4376,3910, 619, # 4502 +7505,3129,3261, 215,2006,2783,2553,3189,4377,3190,4378, 763,4119,3763,4379,7506, # 4518 +7507,1957,1767,2941,3328,3646,1174, 452,1477,4380,3329,3130,7508,2825,1253,2382, # 4534 +2186,1091,2285,4120, 492,7509, 638,1169,1824,2135,1752,3911, 648, 926,1021,1324, # 4550 +4381, 520,4382, 997, 847,1007, 892,4383,3764,2262,1871,3647,7510,2400,1784,4384, # 4566 +1952,2942,3080,3191,1728,4121,2043,3648,4385,2007,1701,3131,1551, 30,2263,4122, # 4582 +7511,2026,4386,3534,7512, 501,7513,4123, 594,3431,2165,1821,3535,3432,3536,3192, # 4598 + 829,2826,4124,7514,1680,3132,1225,4125,7515,3262,4387,4126,3133,2336,7516,4388, # 4614 +4127,7517,3912,3913,7518,1847,2383,2596,3330,7519,4389, 374,3914, 652,4128,4129, # 4630 + 375,1140, 798,7520,7521,7522,2361,4390,2264, 546,1659, 138,3031,2445,4391,7523, # 4646 +2250, 612,1848, 910, 796,3765,1740,1371, 825,3766,3767,7524,2906,2554,7525, 692, # 4662 + 444,3032,2624, 801,4392,4130,7526,1491, 244,1053,3033,4131,4132, 340,7527,3915, # 4678 +1041,2987, 293,1168, 87,1357,7528,1539, 959,7529,2236, 721, 694,4133,3768, 219, # 4694 +1478, 644,1417,3331,2656,1413,1401,1335,1389,3916,7530,7531,2988,2362,3134,1825, # 4710 + 730,1515, 184,2827, 66,4393,7532,1660,2943, 246,3332, 378,1457, 226,3433, 975, # 4726 +3917,2944,1264,3537, 674, 696,7533, 163,7534,1141,2417,2166, 713,3538,3333,4394, # 4742 +3918,7535,7536,1186, 15,7537,1079,1070,7538,1522,3193,3539, 276,1050,2716, 758, # 4758 +1126, 653,2945,3263,7539,2337, 889,3540,3919,3081,2989, 903,1250,4395,3920,3434, # 4774 +3541,1342,1681,1718, 766,3264, 286, 89,2946,3649,7540,1713,7541,2597,3334,2990, # 4790 +7542,2947,2215,3194,2866,7543,4396,2498,2526, 181, 387,1075,3921, 731,2187,3335, # 4806 +7544,3265, 310, 313,3435,2299, 770,4134, 54,3034, 189,4397,3082,3769,3922,7545, # 4822 +1230,1617,1849, 355,3542,4135,4398,3336, 111,4136,3650,1350,3135,3436,3035,4137, # 4838 +2149,3266,3543,7546,2784,3923,3924,2991, 722,2008,7547,1071, 247,1207,2338,2471, # 4854 +1378,4399,2009, 864,1437,1214,4400, 373,3770,1142,2216, 667,4401, 442,2753,2555, # 4870 +3771,3925,1968,4138,3267,1839, 837, 170,1107, 934,1336,1882,7548,7549,2118,4139, # 4886 +2828, 743,1569,7550,4402,4140, 582,2384,1418,3437,7551,1802,7552, 357,1395,1729, # 4902 +3651,3268,2418,1564,2237,7553,3083,3772,1633,4403,1114,2085,4141,1532,7554, 482, # 4918 +2446,4404,7555,7556,1492, 833,1466,7557,2717,3544,1641,2829,7558,1526,1272,3652, # 4934 +4142,1686,1794, 416,2556,1902,1953,1803,7559,3773,2785,3774,1159,2316,7560,2867, # 4950 +4405,1610,1584,3036,2419,2754, 443,3269,1163,3136,7561,7562,3926,7563,4143,2499, # 4966 +3037,4406,3927,3137,2103,1647,3545,2010,1872,4144,7564,4145, 431,3438,7565, 250, # 4982 + 97, 81,4146,7566,1648,1850,1558, 160, 848,7567, 866, 740,1694,7568,2201,2830, # 4998 +3195,4147,4407,3653,1687, 950,2472, 426, 469,3196,3654,3655,3928,7569,7570,1188, # 5014 + 424,1995, 861,3546,4148,3775,2202,2685, 168,1235,3547,4149,7571,2086,1674,4408, # 5030 +3337,3270, 220,2557,1009,7572,3776, 670,2992, 332,1208, 717,7573,7574,3548,2447, # 5046 +3929,3338,7575, 513,7576,1209,2868,3339,3138,4409,1080,7577,7578,7579,7580,2527, # 5062 +3656,3549, 815,1587,3930,3931,7581,3550,3439,3777,1254,4410,1328,3038,1390,3932, # 5078 +1741,3933,3778,3934,7582, 236,3779,2448,3271,7583,7584,3657,3780,1273,3781,4411, # 5094 +7585, 308,7586,4412, 245,4413,1851,2473,1307,2575, 430, 715,2136,2449,7587, 270, # 5110 + 199,2869,3935,7588,3551,2718,1753, 761,1754, 725,1661,1840,4414,3440,3658,7589, # 5126 +7590, 587, 14,3272, 227,2598, 326, 480,2265, 943,2755,3552, 291, 650,1883,7591, # 5142 +1702,1226, 102,1547, 62,3441, 904,4415,3442,1164,4150,7592,7593,1224,1548,2756, # 5158 + 391, 498,1493,7594,1386,1419,7595,2055,1177,4416, 813, 880,1081,2363, 566,1145, # 5174 +4417,2286,1001,1035,2558,2599,2238, 394,1286,7596,7597,2068,7598, 86,1494,1730, # 5190 +3936, 491,1588, 745, 897,2948, 843,3340,3937,2757,2870,3273,1768, 998,2217,2069, # 5206 + 397,1826,1195,1969,3659,2993,3341, 284,7599,3782,2500,2137,2119,1903,7600,3938, # 5222 +2150,3939,4151,1036,3443,1904, 114,2559,4152, 209,1527,7601,7602,2949,2831,2625, # 5238 +2385,2719,3139, 812,2560,7603,3274,7604,1559, 737,1884,3660,1210, 885, 28,2686, # 5254 +3553,3783,7605,4153,1004,1779,4418,7606, 346,1981,2218,2687,4419,3784,1742, 797, # 5270 +1642,3940,1933,1072,1384,2151, 896,3941,3275,3661,3197,2871,3554,7607,2561,1958, # 5286 +4420,2450,1785,7608,7609,7610,3942,4154,1005,1308,3662,4155,2720,4421,4422,1528, # 5302 +2600, 161,1178,4156,1982, 987,4423,1101,4157, 631,3943,1157,3198,2420,1343,1241, # 5318 +1016,2239,2562, 372, 877,2339,2501,1160, 555,1934, 911,3944,7611, 466,1170, 169, # 5334 +1051,2907,2688,3663,2474,2994,1182,2011,2563,1251,2626,7612, 992,2340,3444,1540, # 5350 +2721,1201,2070,2401,1996,2475,7613,4424, 528,1922,2188,1503,1873,1570,2364,3342, # 5366 +3276,7614, 557,1073,7615,1827,3445,2087,2266,3140,3039,3084, 767,3085,2786,4425, # 5382 +1006,4158,4426,2341,1267,2176,3664,3199, 778,3945,3200,2722,1597,2657,7616,4427, # 5398 +7617,3446,7618,7619,7620,3277,2689,1433,3278, 131, 95,1504,3946, 723,4159,3141, # 5414 +1841,3555,2758,2189,3947,2027,2104,3665,7621,2995,3948,1218,7622,3343,3201,3949, # 5430 +4160,2576, 248,1634,3785, 912,7623,2832,3666,3040,3786, 654, 53,7624,2996,7625, # 5446 +1688,4428, 777,3447,1032,3950,1425,7626, 191, 820,2120,2833, 971,4429, 931,3202, # 5462 + 135, 664, 783,3787,1997, 772,2908,1935,3951,3788,4430,2909,3203, 282,2723, 640, # 5478 +1372,3448,1127, 922, 325,3344,7627,7628, 711,2044,7629,7630,3952,2219,2787,1936, # 5494 +3953,3345,2220,2251,3789,2300,7631,4431,3790,1258,3279,3954,3204,2138,2950,3955, # 5510 +3956,7632,2221, 258,3205,4432, 101,1227,7633,3280,1755,7634,1391,3281,7635,2910, # 5526 +2056, 893,7636,7637,7638,1402,4161,2342,7639,7640,3206,3556,7641,7642, 878,1325, # 5542 +1780,2788,4433, 259,1385,2577, 744,1183,2267,4434,7643,3957,2502,7644, 684,1024, # 5558 +4162,7645, 472,3557,3449,1165,3282,3958,3959, 322,2152, 881, 455,1695,1152,1340, # 5574 + 660, 554,2153,4435,1058,4436,4163, 830,1065,3346,3960,4437,1923,7646,1703,1918, # 5590 +7647, 932,2268, 122,7648,4438, 947, 677,7649,3791,2627, 297,1905,1924,2269,4439, # 5606 +2317,3283,7650,7651,4164,7652,4165, 84,4166, 112, 989,7653, 547,1059,3961, 701, # 5622 +3558,1019,7654,4167,7655,3450, 942, 639, 457,2301,2451, 993,2951, 407, 851, 494, # 5638 +4440,3347, 927,7656,1237,7657,2421,3348, 573,4168, 680, 921,2911,1279,1874, 285, # 5654 + 790,1448,1983, 719,2167,7658,7659,4441,3962,3963,1649,7660,1541, 563,7661,1077, # 5670 +7662,3349,3041,3451, 511,2997,3964,3965,3667,3966,1268,2564,3350,3207,4442,4443, # 5686 +7663, 535,1048,1276,1189,2912,2028,3142,1438,1373,2834,2952,1134,2012,7664,4169, # 5702 +1238,2578,3086,1259,7665, 700,7666,2953,3143,3668,4170,7667,4171,1146,1875,1906, # 5718 +4444,2601,3967, 781,2422, 132,1589, 203, 147, 273,2789,2402, 898,1786,2154,3968, # 5734 +3969,7668,3792,2790,7669,7670,4445,4446,7671,3208,7672,1635,3793, 965,7673,1804, # 5750 +2690,1516,3559,1121,1082,1329,3284,3970,1449,3794, 65,1128,2835,2913,2759,1590, # 5766 +3795,7674,7675, 12,2658, 45, 976,2579,3144,4447, 517,2528,1013,1037,3209,7676, # 5782 +3796,2836,7677,3797,7678,3452,7679,2602, 614,1998,2318,3798,3087,2724,2628,7680, # 5798 +2580,4172, 599,1269,7681,1810,3669,7682,2691,3088, 759,1060, 489,1805,3351,3285, # 5814 +1358,7683,7684,2386,1387,1215,2629,2252, 490,7685,7686,4173,1759,2387,2343,7687, # 5830 +4448,3799,1907,3971,2630,1806,3210,4449,3453,3286,2760,2344, 874,7688,7689,3454, # 5846 +3670,1858, 91,2914,3671,3042,3800,4450,7690,3145,3972,2659,7691,3455,1202,1403, # 5862 +3801,2954,2529,1517,2503,4451,3456,2504,7692,4452,7693,2692,1885,1495,1731,3973, # 5878 +2365,4453,7694,2029,7695,7696,3974,2693,1216, 237,2581,4174,2319,3975,3802,4454, # 5894 +4455,2694,3560,3457, 445,4456,7697,7698,7699,7700,2761, 61,3976,3672,1822,3977, # 5910 +7701, 687,2045, 935, 925, 405,2660, 703,1096,1859,2725,4457,3978,1876,1367,2695, # 5926 +3352, 918,2105,1781,2476, 334,3287,1611,1093,4458, 564,3146,3458,3673,3353, 945, # 5942 +2631,2057,4459,7702,1925, 872,4175,7703,3459,2696,3089, 349,4176,3674,3979,4460, # 5958 +3803,4177,3675,2155,3980,4461,4462,4178,4463,2403,2046, 782,3981, 400, 251,4179, # 5974 +1624,7704,7705, 277,3676, 299,1265, 476,1191,3804,2121,4180,4181,1109, 205,7706, # 5990 +2582,1000,2156,3561,1860,7707,7708,7709,4464,7710,4465,2565, 107,2477,2157,3982, # 6006 +3460,3147,7711,1533, 541,1301, 158, 753,4182,2872,3562,7712,1696, 370,1088,4183, # 6022 +4466,3563, 579, 327, 440, 162,2240, 269,1937,1374,3461, 968,3043, 56,1396,3090, # 6038 +2106,3288,3354,7713,1926,2158,4467,2998,7714,3564,7715,7716,3677,4468,2478,7717, # 6054 +2791,7718,1650,4469,7719,2603,7720,7721,3983,2661,3355,1149,3356,3984,3805,3985, # 6070 +7722,1076, 49,7723, 951,3211,3289,3290, 450,2837, 920,7724,1811,2792,2366,4184, # 6086 +1908,1138,2367,3806,3462,7725,3212,4470,1909,1147,1518,2423,4471,3807,7726,4472, # 6102 +2388,2604, 260,1795,3213,7727,7728,3808,3291, 708,7729,3565,1704,7730,3566,1351, # 6118 +1618,3357,2999,1886, 944,4185,3358,4186,3044,3359,4187,7731,3678, 422, 413,1714, # 6134 +3292, 500,2058,2345,4188,2479,7732,1344,1910, 954,7733,1668,7734,7735,3986,2404, # 6150 +4189,3567,3809,4190,7736,2302,1318,2505,3091, 133,3092,2873,4473, 629, 31,2838, # 6166 +2697,3810,4474, 850, 949,4475,3987,2955,1732,2088,4191,1496,1852,7737,3988, 620, # 6182 +3214, 981,1242,3679,3360,1619,3680,1643,3293,2139,2452,1970,1719,3463,2168,7738, # 6198 +3215,7739,7740,3361,1828,7741,1277,4476,1565,2047,7742,1636,3568,3093,7743, 869, # 6214 +2839, 655,3811,3812,3094,3989,3000,3813,1310,3569,4477,7744,7745,7746,1733, 558, # 6230 +4478,3681, 335,1549,3045,1756,4192,3682,1945,3464,1829,1291,1192, 470,2726,2107, # 6246 +2793, 913,1054,3990,7747,1027,7748,3046,3991,4479, 982,2662,3362,3148,3465,3216, # 6262 +3217,1946,2794,7749, 571,4480,7750,1830,7751,3570,2583,1523,2424,7752,2089, 984, # 6278 +4481,3683,1959,7753,3684, 852, 923,2795,3466,3685, 969,1519, 999,2048,2320,1705, # 6294 +7754,3095, 615,1662, 151, 597,3992,2405,2321,1049, 275,4482,3686,4193, 568,3687, # 6310 +3571,2480,4194,3688,7755,2425,2270, 409,3218,7756,1566,2874,3467,1002, 769,2840, # 6326 + 194,2090,3149,3689,2222,3294,4195, 628,1505,7757,7758,1763,2177,3001,3993, 521, # 6342 +1161,2584,1787,2203,2406,4483,3994,1625,4196,4197, 412, 42,3096, 464,7759,2632, # 6358 +4484,3363,1760,1571,2875,3468,2530,1219,2204,3814,2633,2140,2368,4485,4486,3295, # 6374 +1651,3364,3572,7760,7761,3573,2481,3469,7762,3690,7763,7764,2271,2091, 460,7765, # 6390 +4487,7766,3002, 962, 588,3574, 289,3219,2634,1116, 52,7767,3047,1796,7768,7769, # 6406 +7770,1467,7771,1598,1143,3691,4198,1984,1734,1067,4488,1280,3365, 465,4489,1572, # 6422 + 510,7772,1927,2241,1812,1644,3575,7773,4490,3692,7774,7775,2663,1573,1534,7776, # 6438 +7777,4199, 536,1807,1761,3470,3815,3150,2635,7778,7779,7780,4491,3471,2915,1911, # 6454 +2796,7781,3296,1122, 377,3220,7782, 360,7783,7784,4200,1529, 551,7785,2059,3693, # 6470 +1769,2426,7786,2916,4201,3297,3097,2322,2108,2030,4492,1404, 136,1468,1479, 672, # 6486 +1171,3221,2303, 271,3151,7787,2762,7788,2049, 678,2727, 865,1947,4493,7789,2013, # 6502 +3995,2956,7790,2728,2223,1397,3048,3694,4494,4495,1735,2917,3366,3576,7791,3816, # 6518 + 509,2841,2453,2876,3817,7792,7793,3152,3153,4496,4202,2531,4497,2304,1166,1010, # 6534 + 552, 681,1887,7794,7795,2957,2958,3996,1287,1596,1861,3154, 358, 453, 736, 175, # 6550 + 478,1117, 905,1167,1097,7796,1853,1530,7797,1706,7798,2178,3472,2287,3695,3473, # 6566 +3577,4203,2092,4204,7799,3367,1193,2482,4205,1458,2190,2205,1862,1888,1421,3298, # 6582 +2918,3049,2179,3474, 595,2122,7800,3997,7801,7802,4206,1707,2636, 223,3696,1359, # 6598 + 751,3098, 183,3475,7803,2797,3003, 419,2369, 633, 704,3818,2389, 241,7804,7805, # 6614 +7806, 838,3004,3697,2272,2763,2454,3819,1938,2050,3998,1309,3099,2242,1181,7807, # 6630 +1136,2206,3820,2370,1446,4207,2305,4498,7808,7809,4208,1055,2605, 484,3698,7810, # 6646 +3999, 625,4209,2273,3368,1499,4210,4000,7811,4001,4211,3222,2274,2275,3476,7812, # 6662 +7813,2764, 808,2606,3699,3369,4002,4212,3100,2532, 526,3370,3821,4213, 955,7814, # 6678 +1620,4214,2637,2427,7815,1429,3700,1669,1831, 994, 928,7816,3578,1260,7817,7818, # 6694 +7819,1948,2288, 741,2919,1626,4215,2729,2455, 867,1184, 362,3371,1392,7820,7821, # 6710 +4003,4216,1770,1736,3223,2920,4499,4500,1928,2698,1459,1158,7822,3050,3372,2877, # 6726 +1292,1929,2506,2842,3701,1985,1187,2071,2014,2607,4217,7823,2566,2507,2169,3702, # 6742 +2483,3299,7824,3703,4501,7825,7826, 666,1003,3005,1022,3579,4218,7827,4502,1813, # 6758 +2253, 574,3822,1603, 295,1535, 705,3823,4219, 283, 858, 417,7828,7829,3224,4503, # 6774 +4504,3051,1220,1889,1046,2276,2456,4004,1393,1599, 689,2567, 388,4220,7830,2484, # 6790 + 802,7831,2798,3824,2060,1405,2254,7832,4505,3825,2109,1052,1345,3225,1585,7833, # 6806 + 809,7834,7835,7836, 575,2730,3477, 956,1552,1469,1144,2323,7837,2324,1560,2457, # 6822 +3580,3226,4005, 616,2207,3155,2180,2289,7838,1832,7839,3478,4506,7840,1319,3704, # 6838 +3705,1211,3581,1023,3227,1293,2799,7841,7842,7843,3826, 607,2306,3827, 762,2878, # 6854 +1439,4221,1360,7844,1485,3052,7845,4507,1038,4222,1450,2061,2638,4223,1379,4508, # 6870 +2585,7846,7847,4224,1352,1414,2325,2921,1172,7848,7849,3828,3829,7850,1797,1451, # 6886 +7851,7852,7853,7854,2922,4006,4007,2485,2346, 411,4008,4009,3582,3300,3101,4509, # 6902 +1561,2664,1452,4010,1375,7855,7856, 47,2959, 316,7857,1406,1591,2923,3156,7858, # 6918 +1025,2141,3102,3157, 354,2731, 884,2224,4225,2407, 508,3706, 726,3583, 996,2428, # 6934 +3584, 729,7859, 392,2191,1453,4011,4510,3707,7860,7861,2458,3585,2608,1675,2800, # 6950 + 919,2347,2960,2348,1270,4511,4012, 73,7862,7863, 647,7864,3228,2843,2255,1550, # 6966 +1346,3006,7865,1332, 883,3479,7866,7867,7868,7869,3301,2765,7870,1212, 831,1347, # 6982 +4226,4512,2326,3830,1863,3053, 720,3831,4513,4514,3832,7871,4227,7872,7873,4515, # 6998 +7874,7875,1798,4516,3708,2609,4517,3586,1645,2371,7876,7877,2924, 669,2208,2665, # 7014 +2429,7878,2879,7879,7880,1028,3229,7881,4228,2408,7882,2256,1353,7883,7884,4518, # 7030 +3158, 518,7885,4013,7886,4229,1960,7887,2142,4230,7888,7889,3007,2349,2350,3833, # 7046 + 516,1833,1454,4014,2699,4231,4519,2225,2610,1971,1129,3587,7890,2766,7891,2961, # 7062 +1422, 577,1470,3008,1524,3373,7892,7893, 432,4232,3054,3480,7894,2586,1455,2508, # 7078 +2226,1972,1175,7895,1020,2732,4015,3481,4520,7896,2733,7897,1743,1361,3055,3482, # 7094 +2639,4016,4233,4521,2290, 895, 924,4234,2170, 331,2243,3056, 166,1627,3057,1098, # 7110 +7898,1232,2880,2227,3374,4522, 657, 403,1196,2372, 542,3709,3375,1600,4235,3483, # 7126 +7899,4523,2767,3230, 576, 530,1362,7900,4524,2533,2666,3710,4017,7901, 842,3834, # 7142 +7902,2801,2031,1014,4018, 213,2700,3376, 665, 621,4236,7903,3711,2925,2430,7904, # 7158 +2431,3302,3588,3377,7905,4237,2534,4238,4525,3589,1682,4239,3484,1380,7906, 724, # 7174 +2277, 600,1670,7907,1337,1233,4526,3103,2244,7908,1621,4527,7909, 651,4240,7910, # 7190 +1612,4241,2611,7911,2844,7912,2734,2307,3058,7913, 716,2459,3059, 174,1255,2701, # 7206 +4019,3590, 548,1320,1398, 728,4020,1574,7914,1890,1197,3060,4021,7915,3061,3062, # 7222 +3712,3591,3713, 747,7916, 635,4242,4528,7917,7918,7919,4243,7920,7921,4529,7922, # 7238 +3378,4530,2432, 451,7923,3714,2535,2072,4244,2735,4245,4022,7924,1764,4531,7925, # 7254 +4246, 350,7926,2278,2390,2486,7927,4247,4023,2245,1434,4024, 488,4532, 458,4248, # 7270 +4025,3715, 771,1330,2391,3835,2568,3159,2159,2409,1553,2667,3160,4249,7928,2487, # 7286 +2881,2612,1720,2702,4250,3379,4533,7929,2536,4251,7930,3231,4252,2768,7931,2015, # 7302 +2736,7932,1155,1017,3716,3836,7933,3303,2308, 201,1864,4253,1430,7934,4026,7935, # 7318 +7936,7937,7938,7939,4254,1604,7940, 414,1865, 371,2587,4534,4535,3485,2016,3104, # 7334 +4536,1708, 960,4255, 887, 389,2171,1536,1663,1721,7941,2228,4027,2351,2926,1580, # 7350 +7942,7943,7944,1744,7945,2537,4537,4538,7946,4539,7947,2073,7948,7949,3592,3380, # 7366 +2882,4256,7950,4257,2640,3381,2802, 673,2703,2460, 709,3486,4028,3593,4258,7951, # 7382 +1148, 502, 634,7952,7953,1204,4540,3594,1575,4541,2613,3717,7954,3718,3105, 948, # 7398 +3232, 121,1745,3837,1110,7955,4259,3063,2509,3009,4029,3719,1151,1771,3838,1488, # 7414 +4030,1986,7956,2433,3487,7957,7958,2093,7959,4260,3839,1213,1407,2803, 531,2737, # 7430 +2538,3233,1011,1537,7960,2769,4261,3106,1061,7961,3720,3721,1866,2883,7962,2017, # 7446 + 120,4262,4263,2062,3595,3234,2309,3840,2668,3382,1954,4542,7963,7964,3488,1047, # 7462 +2704,1266,7965,1368,4543,2845, 649,3383,3841,2539,2738,1102,2846,2669,7966,7967, # 7478 +1999,7968,1111,3596,2962,7969,2488,3842,3597,2804,1854,3384,3722,7970,7971,3385, # 7494 +2410,2884,3304,3235,3598,7972,2569,7973,3599,2805,4031,1460, 856,7974,3600,7975, # 7510 +2885,2963,7976,2886,3843,7977,4264, 632,2510, 875,3844,1697,3845,2291,7978,7979, # 7526 +4544,3010,1239, 580,4545,4265,7980, 914, 936,2074,1190,4032,1039,2123,7981,7982, # 7542 +7983,3386,1473,7984,1354,4266,3846,7985,2172,3064,4033, 915,3305,4267,4268,3306, # 7558 +1605,1834,7986,2739, 398,3601,4269,3847,4034, 328,1912,2847,4035,3848,1331,4270, # 7574 +3011, 937,4271,7987,3602,4036,4037,3387,2160,4546,3388, 524, 742, 538,3065,1012, # 7590 +7988,7989,3849,2461,7990, 658,1103, 225,3850,7991,7992,4547,7993,4548,7994,3236, # 7606 +1243,7995,4038, 963,2246,4549,7996,2705,3603,3161,7997,7998,2588,2327,7999,4550, # 7622 +8000,8001,8002,3489,3307, 957,3389,2540,2032,1930,2927,2462, 870,2018,3604,1746, # 7638 +2770,2771,2434,2463,8003,3851,8004,3723,3107,3724,3490,3390,3725,8005,1179,3066, # 7654 +8006,3162,2373,4272,3726,2541,3163,3108,2740,4039,8007,3391,1556,2542,2292, 977, # 7670 +2887,2033,4040,1205,3392,8008,1765,3393,3164,2124,1271,1689, 714,4551,3491,8009, # 7686 +2328,3852, 533,4273,3605,2181, 617,8010,2464,3308,3492,2310,8011,8012,3165,8013, # 7702 +8014,3853,1987, 618, 427,2641,3493,3394,8015,8016,1244,1690,8017,2806,4274,4552, # 7718 +8018,3494,8019,8020,2279,1576, 473,3606,4275,3395, 972,8021,3607,8022,3067,8023, # 7734 +8024,4553,4554,8025,3727,4041,4042,8026, 153,4555, 356,8027,1891,2888,4276,2143, # 7750 + 408, 803,2352,8028,3854,8029,4277,1646,2570,2511,4556,4557,3855,8030,3856,4278, # 7766 +8031,2411,3396, 752,8032,8033,1961,2964,8034, 746,3012,2465,8035,4279,3728, 698, # 7782 +4558,1892,4280,3608,2543,4559,3609,3857,8036,3166,3397,8037,1823,1302,4043,2706, # 7798 +3858,1973,4281,8038,4282,3167, 823,1303,1288,1236,2848,3495,4044,3398, 774,3859, # 7814 +8039,1581,4560,1304,2849,3860,4561,8040,2435,2161,1083,3237,4283,4045,4284, 344, # 7830 +1173, 288,2311, 454,1683,8041,8042,1461,4562,4046,2589,8043,8044,4563, 985, 894, # 7846 +8045,3399,3168,8046,1913,2928,3729,1988,8047,2110,1974,8048,4047,8049,2571,1194, # 7862 + 425,8050,4564,3169,1245,3730,4285,8051,8052,2850,8053, 636,4565,1855,3861, 760, # 7878 +1799,8054,4286,2209,1508,4566,4048,1893,1684,2293,8055,8056,8057,4287,4288,2210, # 7894 + 479,8058,8059, 832,8060,4049,2489,8061,2965,2490,3731, 990,3109, 627,1814,2642, # 7910 +4289,1582,4290,2125,2111,3496,4567,8062, 799,4291,3170,8063,4568,2112,1737,3013, # 7926 +1018, 543, 754,4292,3309,1676,4569,4570,4050,8064,1489,8065,3497,8066,2614,2889, # 7942 +4051,8067,8068,2966,8069,8070,8071,8072,3171,4571,4572,2182,1722,8073,3238,3239, # 7958 +1842,3610,1715, 481, 365,1975,1856,8074,8075,1962,2491,4573,8076,2126,3611,3240, # 7974 + 433,1894,2063,2075,8077, 602,2741,8078,8079,8080,8081,8082,3014,1628,3400,8083, # 7990 +3172,4574,4052,2890,4575,2512,8084,2544,2772,8085,8086,8087,3310,4576,2891,8088, # 8006 +4577,8089,2851,4578,4579,1221,2967,4053,2513,8090,8091,8092,1867,1989,8093,8094, # 8022 +8095,1895,8096,8097,4580,1896,4054, 318,8098,2094,4055,4293,8099,8100, 485,8101, # 8038 + 938,3862, 553,2670, 116,8102,3863,3612,8103,3498,2671,2773,3401,3311,2807,8104, # 8054 +3613,2929,4056,1747,2930,2968,8105,8106, 207,8107,8108,2672,4581,2514,8109,3015, # 8070 + 890,3614,3864,8110,1877,3732,3402,8111,2183,2353,3403,1652,8112,8113,8114, 941, # 8086 +2294, 208,3499,4057,2019, 330,4294,3865,2892,2492,3733,4295,8115,8116,8117,8118, # 8102 +#Everything below is of no interest for detection purpose +2515,1613,4582,8119,3312,3866,2516,8120,4058,8121,1637,4059,2466,4583,3867,8122, # 8118 +2493,3016,3734,8123,8124,2192,8125,8126,2162,8127,8128,8129,8130,8131,8132,8133, # 8134 +8134,8135,8136,8137,8138,8139,8140,8141,8142,8143,8144,8145,8146,8147,8148,8149, # 8150 +8150,8151,8152,8153,8154,8155,8156,8157,8158,8159,8160,8161,8162,8163,8164,8165, # 8166 +8166,8167,8168,8169,8170,8171,8172,8173,8174,8175,8176,8177,8178,8179,8180,8181, # 8182 +8182,8183,8184,8185,8186,8187,8188,8189,8190,8191,8192,8193,8194,8195,8196,8197, # 8198 +8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8208,8209,8210,8211,8212,8213, # 8214 +8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,8224,8225,8226,8227,8228,8229, # 8230 +8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,8240,8241,8242,8243,8244,8245, # 8246 +8246,8247,8248,8249,8250,8251,8252,8253,8254,8255,8256,8257,8258,8259,8260,8261, # 8262 +8262,8263,8264,8265,8266,8267,8268,8269,8270,8271,8272,8273,8274,8275,8276,8277, # 8278 +8278,8279,8280,8281,8282,8283,8284,8285,8286,8287,8288,8289,8290,8291,8292,8293, # 8294 +8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,8304,8305,8306,8307,8308,8309, # 8310 +8310,8311,8312,8313,8314,8315,8316,8317,8318,8319,8320,8321,8322,8323,8324,8325, # 8326 +8326,8327,8328,8329,8330,8331,8332,8333,8334,8335,8336,8337,8338,8339,8340,8341, # 8342 +8342,8343,8344,8345,8346,8347,8348,8349,8350,8351,8352,8353,8354,8355,8356,8357, # 8358 +8358,8359,8360,8361,8362,8363,8364,8365,8366,8367,8368,8369,8370,8371,8372,8373, # 8374 +8374,8375,8376,8377,8378,8379,8380,8381,8382,8383,8384,8385,8386,8387,8388,8389, # 8390 +8390,8391,8392,8393,8394,8395,8396,8397,8398,8399,8400,8401,8402,8403,8404,8405, # 8406 +8406,8407,8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,8420,8421, # 8422 +8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,8433,8434,8435,8436,8437, # 8438 +8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,8448,8449,8450,8451,8452,8453, # 8454 +8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,8464,8465,8466,8467,8468,8469, # 8470 +8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,8480,8481,8482,8483,8484,8485, # 8486 +8486,8487,8488,8489,8490,8491,8492,8493,8494,8495,8496,8497,8498,8499,8500,8501, # 8502 +8502,8503,8504,8505,8506,8507,8508,8509,8510,8511,8512,8513,8514,8515,8516,8517, # 8518 +8518,8519,8520,8521,8522,8523,8524,8525,8526,8527,8528,8529,8530,8531,8532,8533, # 8534 +8534,8535,8536,8537,8538,8539,8540,8541,8542,8543,8544,8545,8546,8547,8548,8549, # 8550 +8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,8560,8561,8562,8563,8564,8565, # 8566 +8566,8567,8568,8569,8570,8571,8572,8573,8574,8575,8576,8577,8578,8579,8580,8581, # 8582 +8582,8583,8584,8585,8586,8587,8588,8589,8590,8591,8592,8593,8594,8595,8596,8597, # 8598 +8598,8599,8600,8601,8602,8603,8604,8605,8606,8607,8608,8609,8610,8611,8612,8613, # 8614 +8614,8615,8616,8617,8618,8619,8620,8621,8622,8623,8624,8625,8626,8627,8628,8629, # 8630 +8630,8631,8632,8633,8634,8635,8636,8637,8638,8639,8640,8641,8642,8643,8644,8645, # 8646 +8646,8647,8648,8649,8650,8651,8652,8653,8654,8655,8656,8657,8658,8659,8660,8661, # 8662 +8662,8663,8664,8665,8666,8667,8668,8669,8670,8671,8672,8673,8674,8675,8676,8677, # 8678 +8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,8688,8689,8690,8691,8692,8693, # 8694 +8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,8704,8705,8706,8707,8708,8709, # 8710 +8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,8720,8721,8722,8723,8724,8725, # 8726 +8726,8727,8728,8729,8730,8731,8732,8733,8734,8735,8736,8737,8738,8739,8740,8741) # 8742 + +# flake8: noqa diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/euctwprober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/euctwprober.py new file mode 100644 index 0000000000..e601adfdc6 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/euctwprober.py @@ -0,0 +1,41 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCTWDistributionAnalysis +from .mbcssm import EUCTWSMModel + +class EUCTWProber(MultiByteCharSetProber): + def __init__(self): + MultiByteCharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(EUCTWSMModel) + self._mDistributionAnalyzer = EUCTWDistributionAnalysis() + self.reset() + + def get_charset_name(self): + return "EUC-TW" diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/gb2312freq.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/gb2312freq.py new file mode 100644 index 0000000000..1238f510fc --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/gb2312freq.py @@ -0,0 +1,472 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# GB2312 most frequently used character table +# +# Char to FreqOrder table , from hz6763 + +# 512 --> 0.79 -- 0.79 +# 1024 --> 0.92 -- 0.13 +# 2048 --> 0.98 -- 0.06 +# 6768 --> 1.00 -- 0.02 +# +# Ideal Distribution Ratio = 0.79135/(1-0.79135) = 3.79 +# Random Distribution Ration = 512 / (3755 - 512) = 0.157 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher that RDR + +GB2312_TYPICAL_DISTRIBUTION_RATIO = 0.9 + +GB2312_TABLE_SIZE = 3760 + +GB2312CharToFreqOrder = ( +1671, 749,1443,2364,3924,3807,2330,3921,1704,3463,2691,1511,1515, 572,3191,2205, +2361, 224,2558, 479,1711, 963,3162, 440,4060,1905,2966,2947,3580,2647,3961,3842, +2204, 869,4207, 970,2678,5626,2944,2956,1479,4048, 514,3595, 588,1346,2820,3409, + 249,4088,1746,1873,2047,1774, 581,1813, 358,1174,3590,1014,1561,4844,2245, 670, +1636,3112, 889,1286, 953, 556,2327,3060,1290,3141, 613, 185,3477,1367, 850,3820, +1715,2428,2642,2303,2732,3041,2562,2648,3566,3946,1349, 388,3098,2091,1360,3585, + 152,1687,1539, 738,1559, 59,1232,2925,2267,1388,1249,1741,1679,2960, 151,1566, +1125,1352,4271, 924,4296, 385,3166,4459, 310,1245,2850, 70,3285,2729,3534,3575, +2398,3298,3466,1960,2265, 217,3647, 864,1909,2084,4401,2773,1010,3269,5152, 853, +3051,3121,1244,4251,1895, 364,1499,1540,2313,1180,3655,2268, 562, 715,2417,3061, + 544, 336,3768,2380,1752,4075, 950, 280,2425,4382, 183,2759,3272, 333,4297,2155, +1688,2356,1444,1039,4540, 736,1177,3349,2443,2368,2144,2225, 565, 196,1482,3406, + 927,1335,4147, 692, 878,1311,1653,3911,3622,1378,4200,1840,2969,3149,2126,1816, +2534,1546,2393,2760, 737,2494, 13, 447, 245,2747, 38,2765,2129,2589,1079, 606, + 360, 471,3755,2890, 404, 848, 699,1785,1236, 370,2221,1023,3746,2074,2026,2023, +2388,1581,2119, 812,1141,3091,2536,1519, 804,2053, 406,1596,1090, 784, 548,4414, +1806,2264,2936,1100, 343,4114,5096, 622,3358, 743,3668,1510,1626,5020,3567,2513, +3195,4115,5627,2489,2991, 24,2065,2697,1087,2719, 48,1634, 315, 68, 985,2052, + 198,2239,1347,1107,1439, 597,2366,2172, 871,3307, 919,2487,2790,1867, 236,2570, +1413,3794, 906,3365,3381,1701,1982,1818,1524,2924,1205, 616,2586,2072,2004, 575, + 253,3099, 32,1365,1182, 197,1714,2454,1201, 554,3388,3224,2748, 756,2587, 250, +2567,1507,1517,3529,1922,2761,2337,3416,1961,1677,2452,2238,3153, 615, 911,1506, +1474,2495,1265,1906,2749,3756,3280,2161, 898,2714,1759,3450,2243,2444, 563, 26, +3286,2266,3769,3344,2707,3677, 611,1402, 531,1028,2871,4548,1375, 261,2948, 835, +1190,4134, 353, 840,2684,1900,3082,1435,2109,1207,1674, 329,1872,2781,4055,2686, +2104, 608,3318,2423,2957,2768,1108,3739,3512,3271,3985,2203,1771,3520,1418,2054, +1681,1153, 225,1627,2929, 162,2050,2511,3687,1954, 124,1859,2431,1684,3032,2894, + 585,4805,3969,2869,2704,2088,2032,2095,3656,2635,4362,2209, 256, 518,2042,2105, +3777,3657, 643,2298,1148,1779, 190, 989,3544, 414, 11,2135,2063,2979,1471, 403, +3678, 126, 770,1563, 671,2499,3216,2877, 600,1179, 307,2805,4937,1268,1297,2694, + 252,4032,1448,1494,1331,1394, 127,2256, 222,1647,1035,1481,3056,1915,1048, 873, +3651, 210, 33,1608,2516, 200,1520, 415, 102, 0,3389,1287, 817, 91,3299,2940, + 836,1814, 549,2197,1396,1669,2987,3582,2297,2848,4528,1070, 687, 20,1819, 121, +1552,1364,1461,1968,2617,3540,2824,2083, 177, 948,4938,2291, 110,4549,2066, 648, +3359,1755,2110,2114,4642,4845,1693,3937,3308,1257,1869,2123, 208,1804,3159,2992, +2531,2549,3361,2418,1350,2347,2800,2568,1291,2036,2680, 72, 842,1990, 212,1233, +1154,1586, 75,2027,3410,4900,1823,1337,2710,2676, 728,2810,1522,3026,4995, 157, + 755,1050,4022, 710, 785,1936,2194,2085,1406,2777,2400, 150,1250,4049,1206, 807, +1910, 534, 529,3309,1721,1660, 274, 39,2827, 661,2670,1578, 925,3248,3815,1094, +4278,4901,4252, 41,1150,3747,2572,2227,4501,3658,4902,3813,3357,3617,2884,2258, + 887, 538,4187,3199,1294,2439,3042,2329,2343,2497,1255, 107, 543,1527, 521,3478, +3568, 194,5062, 15, 961,3870,1241,1192,2664, 66,5215,3260,2111,1295,1127,2152, +3805,4135, 901,1164,1976, 398,1278, 530,1460, 748, 904,1054,1966,1426, 53,2909, + 509, 523,2279,1534, 536,1019, 239,1685, 460,2353, 673,1065,2401,3600,4298,2272, +1272,2363, 284,1753,3679,4064,1695, 81, 815,2677,2757,2731,1386, 859, 500,4221, +2190,2566, 757,1006,2519,2068,1166,1455, 337,2654,3203,1863,1682,1914,3025,1252, +1409,1366, 847, 714,2834,2038,3209, 964,2970,1901, 885,2553,1078,1756,3049, 301, +1572,3326, 688,2130,1996,2429,1805,1648,2930,3421,2750,3652,3088, 262,1158,1254, + 389,1641,1812, 526,1719, 923,2073,1073,1902, 468, 489,4625,1140, 857,2375,3070, +3319,2863, 380, 116,1328,2693,1161,2244, 273,1212,1884,2769,3011,1775,1142, 461, +3066,1200,2147,2212, 790, 702,2695,4222,1601,1058, 434,2338,5153,3640, 67,2360, +4099,2502, 618,3472,1329, 416,1132, 830,2782,1807,2653,3211,3510,1662, 192,2124, + 296,3979,1739,1611,3684, 23, 118, 324, 446,1239,1225, 293,2520,3814,3795,2535, +3116, 17,1074, 467,2692,2201, 387,2922, 45,1326,3055,1645,3659,2817, 958, 243, +1903,2320,1339,2825,1784,3289, 356, 576, 865,2315,2381,3377,3916,1088,3122,1713, +1655, 935, 628,4689,1034,1327, 441, 800, 720, 894,1979,2183,1528,5289,2702,1071, +4046,3572,2399,1571,3281, 79, 761,1103, 327, 134, 758,1899,1371,1615, 879, 442, + 215,2605,2579, 173,2048,2485,1057,2975,3317,1097,2253,3801,4263,1403,1650,2946, + 814,4968,3487,1548,2644,1567,1285, 2, 295,2636, 97, 946,3576, 832, 141,4257, +3273, 760,3821,3521,3156,2607, 949,1024,1733,1516,1803,1920,2125,2283,2665,3180, +1501,2064,3560,2171,1592, 803,3518,1416, 732,3897,4258,1363,1362,2458, 119,1427, + 602,1525,2608,1605,1639,3175, 694,3064, 10, 465, 76,2000,4846,4208, 444,3781, +1619,3353,2206,1273,3796, 740,2483, 320,1723,2377,3660,2619,1359,1137,1762,1724, +2345,2842,1850,1862, 912, 821,1866, 612,2625,1735,2573,3369,1093, 844, 89, 937, + 930,1424,3564,2413,2972,1004,3046,3019,2011, 711,3171,1452,4178, 428, 801,1943, + 432, 445,2811, 206,4136,1472, 730, 349, 73, 397,2802,2547, 998,1637,1167, 789, + 396,3217, 154,1218, 716,1120,1780,2819,4826,1931,3334,3762,2139,1215,2627, 552, +3664,3628,3232,1405,2383,3111,1356,2652,3577,3320,3101,1703, 640,1045,1370,1246, +4996, 371,1575,2436,1621,2210, 984,4033,1734,2638, 16,4529, 663,2755,3255,1451, +3917,2257,1253,1955,2234,1263,2951, 214,1229, 617, 485, 359,1831,1969, 473,2310, + 750,2058, 165, 80,2864,2419, 361,4344,2416,2479,1134, 796,3726,1266,2943, 860, +2715, 938, 390,2734,1313,1384, 248, 202, 877,1064,2854, 522,3907, 279,1602, 297, +2357, 395,3740, 137,2075, 944,4089,2584,1267,3802, 62,1533,2285, 178, 176, 780, +2440, 201,3707, 590, 478,1560,4354,2117,1075, 30, 74,4643,4004,1635,1441,2745, + 776,2596, 238,1077,1692,1912,2844, 605, 499,1742,3947, 241,3053, 980,1749, 936, +2640,4511,2582, 515,1543,2162,5322,2892,2993, 890,2148,1924, 665,1827,3581,1032, + 968,3163, 339,1044,1896, 270, 583,1791,1720,4367,1194,3488,3669, 43,2523,1657, + 163,2167, 290,1209,1622,3378, 550, 634,2508,2510, 695,2634,2384,2512,1476,1414, + 220,1469,2341,2138,2852,3183,2900,4939,2865,3502,1211,3680, 854,3227,1299,2976, +3172, 186,2998,1459, 443,1067,3251,1495, 321,1932,3054, 909, 753,1410,1828, 436, +2441,1119,1587,3164,2186,1258, 227, 231,1425,1890,3200,3942, 247, 959, 725,5254, +2741, 577,2158,2079, 929, 120, 174, 838,2813, 591,1115, 417,2024, 40,3240,1536, +1037, 291,4151,2354, 632,1298,2406,2500,3535,1825,1846,3451, 205,1171, 345,4238, + 18,1163, 811, 685,2208,1217, 425,1312,1508,1175,4308,2552,1033, 587,1381,3059, +2984,3482, 340,1316,4023,3972, 792,3176, 519, 777,4690, 918, 933,4130,2981,3741, + 90,3360,2911,2200,5184,4550, 609,3079,2030, 272,3379,2736, 363,3881,1130,1447, + 286, 779, 357,1169,3350,3137,1630,1220,2687,2391, 747,1277,3688,2618,2682,2601, +1156,3196,5290,4034,3102,1689,3596,3128, 874, 219,2783, 798, 508,1843,2461, 269, +1658,1776,1392,1913,2983,3287,2866,2159,2372, 829,4076, 46,4253,2873,1889,1894, + 915,1834,1631,2181,2318, 298, 664,2818,3555,2735, 954,3228,3117, 527,3511,2173, + 681,2712,3033,2247,2346,3467,1652, 155,2164,3382, 113,1994, 450, 899, 494, 994, +1237,2958,1875,2336,1926,3727, 545,1577,1550, 633,3473, 204,1305,3072,2410,1956, +2471, 707,2134, 841,2195,2196,2663,3843,1026,4940, 990,3252,4997, 368,1092, 437, +3212,3258,1933,1829, 675,2977,2893, 412, 943,3723,4644,3294,3283,2230,2373,5154, +2389,2241,2661,2323,1404,2524, 593, 787, 677,3008,1275,2059, 438,2709,2609,2240, +2269,2246,1446, 36,1568,1373,3892,1574,2301,1456,3962, 693,2276,5216,2035,1143, +2720,1919,1797,1811,2763,4137,2597,1830,1699,1488,1198,2090, 424,1694, 312,3634, +3390,4179,3335,2252,1214, 561,1059,3243,2295,2561, 975,5155,2321,2751,3772, 472, +1537,3282,3398,1047,2077,2348,2878,1323,3340,3076, 690,2906, 51, 369, 170,3541, +1060,2187,2688,3670,2541,1083,1683, 928,3918, 459, 109,4427, 599,3744,4286, 143, +2101,2730,2490, 82,1588,3036,2121, 281,1860, 477,4035,1238,2812,3020,2716,3312, +1530,2188,2055,1317, 843, 636,1808,1173,3495, 649, 181,1002, 147,3641,1159,2414, +3750,2289,2795, 813,3123,2610,1136,4368, 5,3391,4541,2174, 420, 429,1728, 754, +1228,2115,2219, 347,2223,2733, 735,1518,3003,2355,3134,1764,3948,3329,1888,2424, +1001,1234,1972,3321,3363,1672,1021,1450,1584, 226, 765, 655,2526,3404,3244,2302, +3665, 731, 594,2184, 319,1576, 621, 658,2656,4299,2099,3864,1279,2071,2598,2739, + 795,3086,3699,3908,1707,2352,2402,1382,3136,2475,1465,4847,3496,3865,1085,3004, +2591,1084, 213,2287,1963,3565,2250, 822, 793,4574,3187,1772,1789,3050, 595,1484, +1959,2770,1080,2650, 456, 422,2996, 940,3322,4328,4345,3092,2742, 965,2784, 739, +4124, 952,1358,2498,2949,2565, 332,2698,2378, 660,2260,2473,4194,3856,2919, 535, +1260,2651,1208,1428,1300,1949,1303,2942, 433,2455,2450,1251,1946, 614,1269, 641, +1306,1810,2737,3078,2912, 564,2365,1419,1415,1497,4460,2367,2185,1379,3005,1307, +3218,2175,1897,3063, 682,1157,4040,4005,1712,1160,1941,1399, 394, 402,2952,1573, +1151,2986,2404, 862, 299,2033,1489,3006, 346, 171,2886,3401,1726,2932, 168,2533, + 47,2507,1030,3735,1145,3370,1395,1318,1579,3609,4560,2857,4116,1457,2529,1965, + 504,1036,2690,2988,2405, 745,5871, 849,2397,2056,3081, 863,2359,3857,2096, 99, +1397,1769,2300,4428,1643,3455,1978,1757,3718,1440, 35,4879,3742,1296,4228,2280, + 160,5063,1599,2013, 166, 520,3479,1646,3345,3012, 490,1937,1545,1264,2182,2505, +1096,1188,1369,1436,2421,1667,2792,2460,1270,2122, 727,3167,2143, 806,1706,1012, +1800,3037, 960,2218,1882, 805, 139,2456,1139,1521, 851,1052,3093,3089, 342,2039, + 744,5097,1468,1502,1585,2087, 223, 939, 326,2140,2577, 892,2481,1623,4077, 982, +3708, 135,2131, 87,2503,3114,2326,1106, 876,1616, 547,2997,2831,2093,3441,4530, +4314, 9,3256,4229,4148, 659,1462,1986,1710,2046,2913,2231,4090,4880,5255,3392, +3274,1368,3689,4645,1477, 705,3384,3635,1068,1529,2941,1458,3782,1509, 100,1656, +2548, 718,2339, 408,1590,2780,3548,1838,4117,3719,1345,3530, 717,3442,2778,3220, +2898,1892,4590,3614,3371,2043,1998,1224,3483, 891, 635, 584,2559,3355, 733,1766, +1729,1172,3789,1891,2307, 781,2982,2271,1957,1580,5773,2633,2005,4195,3097,1535, +3213,1189,1934,5693,3262, 586,3118,1324,1598, 517,1564,2217,1868,1893,4445,3728, +2703,3139,1526,1787,1992,3882,2875,1549,1199,1056,2224,1904,2711,5098,4287, 338, +1993,3129,3489,2689,1809,2815,1997, 957,1855,3898,2550,3275,3057,1105,1319, 627, +1505,1911,1883,3526, 698,3629,3456,1833,1431, 746, 77,1261,2017,2296,1977,1885, + 125,1334,1600, 525,1798,1109,2222,1470,1945, 559,2236,1186,3443,2476,1929,1411, +2411,3135,1777,3372,2621,1841,1613,3229, 668,1430,1839,2643,2916, 195,1989,2671, +2358,1387, 629,3205,2293,5256,4439, 123,1310, 888,1879,4300,3021,3605,1003,1162, +3192,2910,2010, 140,2395,2859, 55,1082,2012,2901, 662, 419,2081,1438, 680,2774, +4654,3912,1620,1731,1625,5035,4065,2328, 512,1344, 802,5443,2163,2311,2537, 524, +3399, 98,1155,2103,1918,2606,3925,2816,1393,2465,1504,3773,2177,3963,1478,4346, + 180,1113,4655,3461,2028,1698, 833,2696,1235,1322,1594,4408,3623,3013,3225,2040, +3022, 541,2881, 607,3632,2029,1665,1219, 639,1385,1686,1099,2803,3231,1938,3188, +2858, 427, 676,2772,1168,2025, 454,3253,2486,3556, 230,1950, 580, 791,1991,1280, +1086,1974,2034, 630, 257,3338,2788,4903,1017, 86,4790, 966,2789,1995,1696,1131, + 259,3095,4188,1308, 179,1463,5257, 289,4107,1248, 42,3413,1725,2288, 896,1947, + 774,4474,4254, 604,3430,4264, 392,2514,2588, 452, 237,1408,3018, 988,4531,1970, +3034,3310, 540,2370,1562,1288,2990, 502,4765,1147, 4,1853,2708, 207, 294,2814, +4078,2902,2509, 684, 34,3105,3532,2551, 644, 709,2801,2344, 573,1727,3573,3557, +2021,1081,3100,4315,2100,3681, 199,2263,1837,2385, 146,3484,1195,2776,3949, 997, +1939,3973,1008,1091,1202,1962,1847,1149,4209,5444,1076, 493, 117,5400,2521, 972, +1490,2934,1796,4542,2374,1512,2933,2657, 413,2888,1135,2762,2314,2156,1355,2369, + 766,2007,2527,2170,3124,2491,2593,2632,4757,2437, 234,3125,3591,1898,1750,1376, +1942,3468,3138, 570,2127,2145,3276,4131, 962, 132,1445,4196, 19, 941,3624,3480, +3366,1973,1374,4461,3431,2629, 283,2415,2275, 808,2887,3620,2112,2563,1353,3610, + 955,1089,3103,1053, 96, 88,4097, 823,3808,1583, 399, 292,4091,3313, 421,1128, + 642,4006, 903,2539,1877,2082, 596, 29,4066,1790, 722,2157, 130, 995,1569, 769, +1485, 464, 513,2213, 288,1923,1101,2453,4316, 133, 486,2445, 50, 625, 487,2207, + 57, 423, 481,2962, 159,3729,1558, 491, 303, 482, 501, 240,2837, 112,3648,2392, +1783, 362, 8,3433,3422, 610,2793,3277,1390,1284,1654, 21,3823, 734, 367, 623, + 193, 287, 374,1009,1483, 816, 476, 313,2255,2340,1262,2150,2899,1146,2581, 782, +2116,1659,2018,1880, 255,3586,3314,1110,2867,2137,2564, 986,2767,5185,2006, 650, + 158, 926, 762, 881,3157,2717,2362,3587, 306,3690,3245,1542,3077,2427,1691,2478, +2118,2985,3490,2438, 539,2305, 983, 129,1754, 355,4201,2386, 827,2923, 104,1773, +2838,2771, 411,2905,3919, 376, 767, 122,1114, 828,2422,1817,3506, 266,3460,1007, +1609,4998, 945,2612,4429,2274, 726,1247,1964,2914,2199,2070,4002,4108, 657,3323, +1422, 579, 455,2764,4737,1222,2895,1670, 824,1223,1487,2525, 558, 861,3080, 598, +2659,2515,1967, 752,2583,2376,2214,4180, 977, 704,2464,4999,2622,4109,1210,2961, + 819,1541, 142,2284, 44, 418, 457,1126,3730,4347,4626,1644,1876,3671,1864, 302, +1063,5694, 624, 723,1984,3745,1314,1676,2488,1610,1449,3558,3569,2166,2098, 409, +1011,2325,3704,2306, 818,1732,1383,1824,1844,3757, 999,2705,3497,1216,1423,2683, +2426,2954,2501,2726,2229,1475,2554,5064,1971,1794,1666,2014,1343, 783, 724, 191, +2434,1354,2220,5065,1763,2752,2472,4152, 131, 175,2885,3434, 92,1466,4920,2616, +3871,3872,3866, 128,1551,1632, 669,1854,3682,4691,4125,1230, 188,2973,3290,1302, +1213, 560,3266, 917, 763,3909,3249,1760, 868,1958, 764,1782,2097, 145,2277,3774, +4462, 64,1491,3062, 971,2132,3606,2442, 221,1226,1617, 218, 323,1185,3207,3147, + 571, 619,1473,1005,1744,2281, 449,1887,2396,3685, 275, 375,3816,1743,3844,3731, + 845,1983,2350,4210,1377, 773, 967,3499,3052,3743,2725,4007,1697,1022,3943,1464, +3264,2855,2722,1952,1029,2839,2467, 84,4383,2215, 820,1391,2015,2448,3672, 377, +1948,2168, 797,2545,3536,2578,2645, 94,2874,1678, 405,1259,3071, 771, 546,1315, + 470,1243,3083, 895,2468, 981, 969,2037, 846,4181, 653,1276,2928, 14,2594, 557, +3007,2474, 156, 902,1338,1740,2574, 537,2518, 973,2282,2216,2433,1928, 138,2903, +1293,2631,1612, 646,3457, 839,2935, 111, 496,2191,2847, 589,3186, 149,3994,2060, +4031,2641,4067,3145,1870, 37,3597,2136,1025,2051,3009,3383,3549,1121,1016,3261, +1301, 251,2446,2599,2153, 872,3246, 637, 334,3705, 831, 884, 921,3065,3140,4092, +2198,1944, 246,2964, 108,2045,1152,1921,2308,1031, 203,3173,4170,1907,3890, 810, +1401,2003,1690, 506, 647,1242,2828,1761,1649,3208,2249,1589,3709,2931,5156,1708, + 498, 666,2613, 834,3817,1231, 184,2851,1124, 883,3197,2261,3710,1765,1553,2658, +1178,2639,2351, 93,1193, 942,2538,2141,4402, 235,1821, 870,1591,2192,1709,1871, +3341,1618,4126,2595,2334, 603, 651, 69, 701, 268,2662,3411,2555,1380,1606, 503, + 448, 254,2371,2646, 574,1187,2309,1770, 322,2235,1292,1801, 305, 566,1133, 229, +2067,2057, 706, 167, 483,2002,2672,3295,1820,3561,3067, 316, 378,2746,3452,1112, + 136,1981, 507,1651,2917,1117, 285,4591, 182,2580,3522,1304, 335,3303,1835,2504, +1795,1792,2248, 674,1018,2106,2449,1857,2292,2845, 976,3047,1781,2600,2727,1389, +1281, 52,3152, 153, 265,3950, 672,3485,3951,4463, 430,1183, 365, 278,2169, 27, +1407,1336,2304, 209,1340,1730,2202,1852,2403,2883, 979,1737,1062, 631,2829,2542, +3876,2592, 825,2086,2226,3048,3625, 352,1417,3724, 542, 991, 431,1351,3938,1861, +2294, 826,1361,2927,3142,3503,1738, 463,2462,2723, 582,1916,1595,2808, 400,3845, +3891,2868,3621,2254, 58,2492,1123, 910,2160,2614,1372,1603,1196,1072,3385,1700, +3267,1980, 696, 480,2430, 920, 799,1570,2920,1951,2041,4047,2540,1321,4223,2469, +3562,2228,1271,2602, 401,2833,3351,2575,5157, 907,2312,1256, 410, 263,3507,1582, + 996, 678,1849,2316,1480, 908,3545,2237, 703,2322, 667,1826,2849,1531,2604,2999, +2407,3146,2151,2630,1786,3711, 469,3542, 497,3899,2409, 858, 837,4446,3393,1274, + 786, 620,1845,2001,3311, 484, 308,3367,1204,1815,3691,2332,1532,2557,1842,2020, +2724,1927,2333,4440, 567, 22,1673,2728,4475,1987,1858,1144,1597, 101,1832,3601, + 12, 974,3783,4391, 951,1412, 1,3720, 453,4608,4041, 528,1041,1027,3230,2628, +1129, 875,1051,3291,1203,2262,1069,2860,2799,2149,2615,3278, 144,1758,3040, 31, + 475,1680, 366,2685,3184, 311,1642,4008,2466,5036,1593,1493,2809, 216,1420,1668, + 233, 304,2128,3284, 232,1429,1768,1040,2008,3407,2740,2967,2543, 242,2133, 778, +1565,2022,2620, 505,2189,2756,1098,2273, 372,1614, 708, 553,2846,2094,2278, 169, +3626,2835,4161, 228,2674,3165, 809,1454,1309, 466,1705,1095, 900,3423, 880,2667, +3751,5258,2317,3109,2571,4317,2766,1503,1342, 866,4447,1118, 63,2076, 314,1881, +1348,1061, 172, 978,3515,1747, 532, 511,3970, 6, 601, 905,2699,3300,1751, 276, +1467,3725,2668, 65,4239,2544,2779,2556,1604, 578,2451,1802, 992,2331,2624,1320, +3446, 713,1513,1013, 103,2786,2447,1661, 886,1702, 916, 654,3574,2031,1556, 751, +2178,2821,2179,1498,1538,2176, 271, 914,2251,2080,1325, 638,1953,2937,3877,2432, +2754, 95,3265,1716, 260,1227,4083, 775, 106,1357,3254, 426,1607, 555,2480, 772, +1985, 244,2546, 474, 495,1046,2611,1851,2061, 71,2089,1675,2590, 742,3758,2843, +3222,1433, 267,2180,2576,2826,2233,2092,3913,2435, 956,1745,3075, 856,2113,1116, + 451, 3,1988,2896,1398, 993,2463,1878,2049,1341,2718,2721,2870,2108, 712,2904, +4363,2753,2324, 277,2872,2349,2649, 384, 987, 435, 691,3000, 922, 164,3939, 652, +1500,1184,4153,2482,3373,2165,4848,2335,3775,3508,3154,2806,2830,1554,2102,1664, +2530,1434,2408, 893,1547,2623,3447,2832,2242,2532,3169,2856,3223,2078, 49,3770, +3469, 462, 318, 656,2259,3250,3069, 679,1629,2758, 344,1138,1104,3120,1836,1283, +3115,2154,1437,4448, 934, 759,1999, 794,2862,1038, 533,2560,1722,2342, 855,2626, +1197,1663,4476,3127, 85,4240,2528, 25,1111,1181,3673, 407,3470,4561,2679,2713, + 768,1925,2841,3986,1544,1165, 932, 373,1240,2146,1930,2673, 721,4766, 354,4333, + 391,2963, 187, 61,3364,1442,1102, 330,1940,1767, 341,3809,4118, 393,2496,2062, +2211, 105, 331, 300, 439, 913,1332, 626, 379,3304,1557, 328, 689,3952, 309,1555, + 931, 317,2517,3027, 325, 569, 686,2107,3084, 60,1042,1333,2794, 264,3177,4014, +1628, 258,3712, 7,4464,1176,1043,1778, 683, 114,1975, 78,1492, 383,1886, 510, + 386, 645,5291,2891,2069,3305,4138,3867,2939,2603,2493,1935,1066,1848,3588,1015, +1282,1289,4609, 697,1453,3044,2666,3611,1856,2412, 54, 719,1330, 568,3778,2459, +1748, 788, 492, 551,1191,1000, 488,3394,3763, 282,1799, 348,2016,1523,3155,2390, +1049, 382,2019,1788,1170, 729,2968,3523, 897,3926,2785,2938,3292, 350,2319,3238, +1718,1717,2655,3453,3143,4465, 161,2889,2980,2009,1421, 56,1908,1640,2387,2232, +1917,1874,2477,4921, 148, 83,3438, 592,4245,2882,1822,1055, 741, 115,1496,1624, + 381,1638,4592,1020, 516,3214, 458, 947,4575,1432, 211,1514,2926,1865,2142, 189, + 852,1221,1400,1486, 882,2299,4036, 351, 28,1122, 700,6479,6480,6481,6482,6483, # last 512 +#Everything below is of no interest for detection purpose +5508,6484,3900,3414,3974,4441,4024,3537,4037,5628,5099,3633,6485,3148,6486,3636, +5509,3257,5510,5973,5445,5872,4941,4403,3174,4627,5873,6276,2286,4230,5446,5874, +5122,6102,6103,4162,5447,5123,5323,4849,6277,3980,3851,5066,4246,5774,5067,6278, +3001,2807,5695,3346,5775,5974,5158,5448,6487,5975,5976,5776,3598,6279,5696,4806, +4211,4154,6280,6488,6489,6490,6281,4212,5037,3374,4171,6491,4562,4807,4722,4827, +5977,6104,4532,4079,5159,5324,5160,4404,3858,5359,5875,3975,4288,4610,3486,4512, +5325,3893,5360,6282,6283,5560,2522,4231,5978,5186,5449,2569,3878,6284,5401,3578, +4415,6285,4656,5124,5979,2506,4247,4449,3219,3417,4334,4969,4329,6492,4576,4828, +4172,4416,4829,5402,6286,3927,3852,5361,4369,4830,4477,4867,5876,4173,6493,6105, +4657,6287,6106,5877,5450,6494,4155,4868,5451,3700,5629,4384,6288,6289,5878,3189, +4881,6107,6290,6495,4513,6496,4692,4515,4723,5100,3356,6497,6291,3810,4080,5561, +3570,4430,5980,6498,4355,5697,6499,4724,6108,6109,3764,4050,5038,5879,4093,3226, +6292,5068,5217,4693,3342,5630,3504,4831,4377,4466,4309,5698,4431,5777,6293,5778, +4272,3706,6110,5326,3752,4676,5327,4273,5403,4767,5631,6500,5699,5880,3475,5039, +6294,5562,5125,4348,4301,4482,4068,5126,4593,5700,3380,3462,5981,5563,3824,5404, +4970,5511,3825,4738,6295,6501,5452,4516,6111,5881,5564,6502,6296,5982,6503,4213, +4163,3454,6504,6112,4009,4450,6113,4658,6297,6114,3035,6505,6115,3995,4904,4739, +4563,4942,4110,5040,3661,3928,5362,3674,6506,5292,3612,4791,5565,4149,5983,5328, +5259,5021,4725,4577,4564,4517,4364,6298,5405,4578,5260,4594,4156,4157,5453,3592, +3491,6507,5127,5512,4709,4922,5984,5701,4726,4289,6508,4015,6116,5128,4628,3424, +4241,5779,6299,4905,6509,6510,5454,5702,5780,6300,4365,4923,3971,6511,5161,3270, +3158,5985,4100, 867,5129,5703,6117,5363,3695,3301,5513,4467,6118,6512,5455,4232, +4242,4629,6513,3959,4478,6514,5514,5329,5986,4850,5162,5566,3846,4694,6119,5456, +4869,5781,3779,6301,5704,5987,5515,4710,6302,5882,6120,4392,5364,5705,6515,6121, +6516,6517,3736,5988,5457,5989,4695,2457,5883,4551,5782,6303,6304,6305,5130,4971, +6122,5163,6123,4870,3263,5365,3150,4871,6518,6306,5783,5069,5706,3513,3498,4409, +5330,5632,5366,5458,5459,3991,5990,4502,3324,5991,5784,3696,4518,5633,4119,6519, +4630,5634,4417,5707,4832,5992,3418,6124,5993,5567,4768,5218,6520,4595,3458,5367, +6125,5635,6126,4202,6521,4740,4924,6307,3981,4069,4385,6308,3883,2675,4051,3834, +4302,4483,5568,5994,4972,4101,5368,6309,5164,5884,3922,6127,6522,6523,5261,5460, +5187,4164,5219,3538,5516,4111,3524,5995,6310,6311,5369,3181,3386,2484,5188,3464, +5569,3627,5708,6524,5406,5165,4677,4492,6312,4872,4851,5885,4468,5996,6313,5709, +5710,6128,2470,5886,6314,5293,4882,5785,3325,5461,5101,6129,5711,5786,6525,4906, +6526,6527,4418,5887,5712,4808,2907,3701,5713,5888,6528,3765,5636,5331,6529,6530, +3593,5889,3637,4943,3692,5714,5787,4925,6315,6130,5462,4405,6131,6132,6316,5262, +6531,6532,5715,3859,5716,5070,4696,5102,3929,5788,3987,4792,5997,6533,6534,3920, +4809,5000,5998,6535,2974,5370,6317,5189,5263,5717,3826,6536,3953,5001,4883,3190, +5463,5890,4973,5999,4741,6133,6134,3607,5570,6000,4711,3362,3630,4552,5041,6318, +6001,2950,2953,5637,4646,5371,4944,6002,2044,4120,3429,6319,6537,5103,4833,6538, +6539,4884,4647,3884,6003,6004,4758,3835,5220,5789,4565,5407,6540,6135,5294,4697, +4852,6320,6321,3206,4907,6541,6322,4945,6542,6136,6543,6323,6005,4631,3519,6544, +5891,6545,5464,3784,5221,6546,5571,4659,6547,6324,6137,5190,6548,3853,6549,4016, +4834,3954,6138,5332,3827,4017,3210,3546,4469,5408,5718,3505,4648,5790,5131,5638, +5791,5465,4727,4318,6325,6326,5792,4553,4010,4698,3439,4974,3638,4335,3085,6006, +5104,5042,5166,5892,5572,6327,4356,4519,5222,5573,5333,5793,5043,6550,5639,5071, +4503,6328,6139,6551,6140,3914,3901,5372,6007,5640,4728,4793,3976,3836,4885,6552, +4127,6553,4451,4102,5002,6554,3686,5105,6555,5191,5072,5295,4611,5794,5296,6556, +5893,5264,5894,4975,5466,5265,4699,4976,4370,4056,3492,5044,4886,6557,5795,4432, +4769,4357,5467,3940,4660,4290,6141,4484,4770,4661,3992,6329,4025,4662,5022,4632, +4835,4070,5297,4663,4596,5574,5132,5409,5895,6142,4504,5192,4664,5796,5896,3885, +5575,5797,5023,4810,5798,3732,5223,4712,5298,4084,5334,5468,6143,4052,4053,4336, +4977,4794,6558,5335,4908,5576,5224,4233,5024,4128,5469,5225,4873,6008,5045,4729, +4742,4633,3675,4597,6559,5897,5133,5577,5003,5641,5719,6330,6560,3017,2382,3854, +4406,4811,6331,4393,3964,4946,6561,2420,3722,6562,4926,4378,3247,1736,4442,6332, +5134,6333,5226,3996,2918,5470,4319,4003,4598,4743,4744,4485,3785,3902,5167,5004, +5373,4394,5898,6144,4874,1793,3997,6334,4085,4214,5106,5642,4909,5799,6009,4419, +4189,3330,5899,4165,4420,5299,5720,5227,3347,6145,4081,6335,2876,3930,6146,3293, +3786,3910,3998,5900,5300,5578,2840,6563,5901,5579,6147,3531,5374,6564,6565,5580, +4759,5375,6566,6148,3559,5643,6336,6010,5517,6337,6338,5721,5902,3873,6011,6339, +6567,5518,3868,3649,5722,6568,4771,4947,6569,6149,4812,6570,2853,5471,6340,6341, +5644,4795,6342,6012,5723,6343,5724,6013,4349,6344,3160,6150,5193,4599,4514,4493, +5168,4320,6345,4927,3666,4745,5169,5903,5005,4928,6346,5725,6014,4730,4203,5046, +4948,3395,5170,6015,4150,6016,5726,5519,6347,5047,3550,6151,6348,4197,4310,5904, +6571,5581,2965,6152,4978,3960,4291,5135,6572,5301,5727,4129,4026,5905,4853,5728, +5472,6153,6349,4533,2700,4505,5336,4678,3583,5073,2994,4486,3043,4554,5520,6350, +6017,5800,4487,6351,3931,4103,5376,6352,4011,4321,4311,4190,5136,6018,3988,3233, +4350,5906,5645,4198,6573,5107,3432,4191,3435,5582,6574,4139,5410,6353,5411,3944, +5583,5074,3198,6575,6354,4358,6576,5302,4600,5584,5194,5412,6577,6578,5585,5413, +5303,4248,5414,3879,4433,6579,4479,5025,4854,5415,6355,4760,4772,3683,2978,4700, +3797,4452,3965,3932,3721,4910,5801,6580,5195,3551,5907,3221,3471,3029,6019,3999, +5908,5909,5266,5267,3444,3023,3828,3170,4796,5646,4979,4259,6356,5647,5337,3694, +6357,5648,5338,4520,4322,5802,3031,3759,4071,6020,5586,4836,4386,5048,6581,3571, +4679,4174,4949,6154,4813,3787,3402,3822,3958,3215,3552,5268,4387,3933,4950,4359, +6021,5910,5075,3579,6358,4234,4566,5521,6359,3613,5049,6022,5911,3375,3702,3178, +4911,5339,4521,6582,6583,4395,3087,3811,5377,6023,6360,6155,4027,5171,5649,4421, +4249,2804,6584,2270,6585,4000,4235,3045,6156,5137,5729,4140,4312,3886,6361,4330, +6157,4215,6158,3500,3676,4929,4331,3713,4930,5912,4265,3776,3368,5587,4470,4855, +3038,4980,3631,6159,6160,4132,4680,6161,6362,3923,4379,5588,4255,6586,4121,6587, +6363,4649,6364,3288,4773,4774,6162,6024,6365,3543,6588,4274,3107,3737,5050,5803, +4797,4522,5589,5051,5730,3714,4887,5378,4001,4523,6163,5026,5522,4701,4175,2791, +3760,6589,5473,4224,4133,3847,4814,4815,4775,3259,5416,6590,2738,6164,6025,5304, +3733,5076,5650,4816,5590,6591,6165,6592,3934,5269,6593,3396,5340,6594,5804,3445, +3602,4042,4488,5731,5732,3525,5591,4601,5196,6166,6026,5172,3642,4612,3202,4506, +4798,6366,3818,5108,4303,5138,5139,4776,3332,4304,2915,3415,4434,5077,5109,4856, +2879,5305,4817,6595,5913,3104,3144,3903,4634,5341,3133,5110,5651,5805,6167,4057, +5592,2945,4371,5593,6596,3474,4182,6367,6597,6168,4507,4279,6598,2822,6599,4777, +4713,5594,3829,6169,3887,5417,6170,3653,5474,6368,4216,2971,5228,3790,4579,6369, +5733,6600,6601,4951,4746,4555,6602,5418,5475,6027,3400,4665,5806,6171,4799,6028, +5052,6172,3343,4800,4747,5006,6370,4556,4217,5476,4396,5229,5379,5477,3839,5914, +5652,5807,4714,3068,4635,5808,6173,5342,4192,5078,5419,5523,5734,6174,4557,6175, +4602,6371,6176,6603,5809,6372,5735,4260,3869,5111,5230,6029,5112,6177,3126,4681, +5524,5915,2706,3563,4748,3130,6178,4018,5525,6604,6605,5478,4012,4837,6606,4534, +4193,5810,4857,3615,5479,6030,4082,3697,3539,4086,5270,3662,4508,4931,5916,4912, +5811,5027,3888,6607,4397,3527,3302,3798,2775,2921,2637,3966,4122,4388,4028,4054, +1633,4858,5079,3024,5007,3982,3412,5736,6608,3426,3236,5595,3030,6179,3427,3336, +3279,3110,6373,3874,3039,5080,5917,5140,4489,3119,6374,5812,3405,4494,6031,4666, +4141,6180,4166,6032,5813,4981,6609,5081,4422,4982,4112,3915,5653,3296,3983,6375, +4266,4410,5654,6610,6181,3436,5082,6611,5380,6033,3819,5596,4535,5231,5306,5113, +6612,4952,5918,4275,3113,6613,6376,6182,6183,5814,3073,4731,4838,5008,3831,6614, +4888,3090,3848,4280,5526,5232,3014,5655,5009,5737,5420,5527,6615,5815,5343,5173, +5381,4818,6616,3151,4953,6617,5738,2796,3204,4360,2989,4281,5739,5174,5421,5197, +3132,5141,3849,5142,5528,5083,3799,3904,4839,5480,2880,4495,3448,6377,6184,5271, +5919,3771,3193,6034,6035,5920,5010,6036,5597,6037,6378,6038,3106,5422,6618,5423, +5424,4142,6619,4889,5084,4890,4313,5740,6620,3437,5175,5307,5816,4199,5198,5529, +5817,5199,5656,4913,5028,5344,3850,6185,2955,5272,5011,5818,4567,4580,5029,5921, +3616,5233,6621,6622,6186,4176,6039,6379,6380,3352,5200,5273,2908,5598,5234,3837, +5308,6623,6624,5819,4496,4323,5309,5201,6625,6626,4983,3194,3838,4167,5530,5922, +5274,6381,6382,3860,3861,5599,3333,4292,4509,6383,3553,5481,5820,5531,4778,6187, +3955,3956,4324,4389,4218,3945,4325,3397,2681,5923,4779,5085,4019,5482,4891,5382, +5383,6040,4682,3425,5275,4094,6627,5310,3015,5483,5657,4398,5924,3168,4819,6628, +5925,6629,5532,4932,4613,6041,6630,4636,6384,4780,4204,5658,4423,5821,3989,4683, +5822,6385,4954,6631,5345,6188,5425,5012,5384,3894,6386,4490,4104,6632,5741,5053, +6633,5823,5926,5659,5660,5927,6634,5235,5742,5824,4840,4933,4820,6387,4859,5928, +4955,6388,4143,3584,5825,5346,5013,6635,5661,6389,5014,5484,5743,4337,5176,5662, +6390,2836,6391,3268,6392,6636,6042,5236,6637,4158,6638,5744,5663,4471,5347,3663, +4123,5143,4293,3895,6639,6640,5311,5929,5826,3800,6189,6393,6190,5664,5348,3554, +3594,4749,4603,6641,5385,4801,6043,5827,4183,6642,5312,5426,4761,6394,5665,6191, +4715,2669,6643,6644,5533,3185,5427,5086,5930,5931,5386,6192,6044,6645,4781,4013, +5745,4282,4435,5534,4390,4267,6045,5746,4984,6046,2743,6193,3501,4087,5485,5932, +5428,4184,4095,5747,4061,5054,3058,3862,5933,5600,6646,5144,3618,6395,3131,5055, +5313,6396,4650,4956,3855,6194,3896,5202,4985,4029,4225,6195,6647,5828,5486,5829, +3589,3002,6648,6397,4782,5276,6649,6196,6650,4105,3803,4043,5237,5830,6398,4096, +3643,6399,3528,6651,4453,3315,4637,6652,3984,6197,5535,3182,3339,6653,3096,2660, +6400,6654,3449,5934,4250,4236,6047,6401,5831,6655,5487,3753,4062,5832,6198,6199, +6656,3766,6657,3403,4667,6048,6658,4338,2897,5833,3880,2797,3780,4326,6659,5748, +5015,6660,5387,4351,5601,4411,6661,3654,4424,5935,4339,4072,5277,4568,5536,6402, +6662,5238,6663,5349,5203,6200,5204,6201,5145,4536,5016,5056,4762,5834,4399,4957, +6202,6403,5666,5749,6664,4340,6665,5936,5177,5667,6666,6667,3459,4668,6404,6668, +6669,4543,6203,6670,4276,6405,4480,5537,6671,4614,5205,5668,6672,3348,2193,4763, +6406,6204,5937,5602,4177,5669,3419,6673,4020,6205,4443,4569,5388,3715,3639,6407, +6049,4058,6206,6674,5938,4544,6050,4185,4294,4841,4651,4615,5488,6207,6408,6051, +5178,3241,3509,5835,6208,4958,5836,4341,5489,5278,6209,2823,5538,5350,5206,5429, +6675,4638,4875,4073,3516,4684,4914,4860,5939,5603,5389,6052,5057,3237,5490,3791, +6676,6409,6677,4821,4915,4106,5351,5058,4243,5539,4244,5604,4842,4916,5239,3028, +3716,5837,5114,5605,5390,5940,5430,6210,4332,6678,5540,4732,3667,3840,6053,4305, +3408,5670,5541,6410,2744,5240,5750,6679,3234,5606,6680,5607,5671,3608,4283,4159, +4400,5352,4783,6681,6411,6682,4491,4802,6211,6412,5941,6413,6414,5542,5751,6683, +4669,3734,5942,6684,6415,5943,5059,3328,4670,4144,4268,6685,6686,6687,6688,4372, +3603,6689,5944,5491,4373,3440,6416,5543,4784,4822,5608,3792,4616,5838,5672,3514, +5391,6417,4892,6690,4639,6691,6054,5673,5839,6055,6692,6056,5392,6212,4038,5544, +5674,4497,6057,6693,5840,4284,5675,4021,4545,5609,6418,4454,6419,6213,4113,4472, +5314,3738,5087,5279,4074,5610,4959,4063,3179,4750,6058,6420,6214,3476,4498,4716, +5431,4960,4685,6215,5241,6694,6421,6216,6695,5841,5945,6422,3748,5946,5179,3905, +5752,5545,5947,4374,6217,4455,6423,4412,6218,4803,5353,6696,3832,5280,6219,4327, +4702,6220,6221,6059,4652,5432,6424,3749,4751,6425,5753,4986,5393,4917,5948,5030, +5754,4861,4733,6426,4703,6697,6222,4671,5949,4546,4961,5180,6223,5031,3316,5281, +6698,4862,4295,4934,5207,3644,6427,5842,5950,6428,6429,4570,5843,5282,6430,6224, +5088,3239,6060,6699,5844,5755,6061,6431,2701,5546,6432,5115,5676,4039,3993,3327, +4752,4425,5315,6433,3941,6434,5677,4617,4604,3074,4581,6225,5433,6435,6226,6062, +4823,5756,5116,6227,3717,5678,4717,5845,6436,5679,5846,6063,5847,6064,3977,3354, +6437,3863,5117,6228,5547,5394,4499,4524,6229,4605,6230,4306,4500,6700,5951,6065, +3693,5952,5089,4366,4918,6701,6231,5548,6232,6702,6438,4704,5434,6703,6704,5953, +4168,6705,5680,3420,6706,5242,4407,6066,3812,5757,5090,5954,4672,4525,3481,5681, +4618,5395,5354,5316,5955,6439,4962,6707,4526,6440,3465,4673,6067,6441,5682,6708, +5435,5492,5758,5683,4619,4571,4674,4804,4893,4686,5493,4753,6233,6068,4269,6442, +6234,5032,4705,5146,5243,5208,5848,6235,6443,4963,5033,4640,4226,6236,5849,3387, +6444,6445,4436,4437,5850,4843,5494,4785,4894,6709,4361,6710,5091,5956,3331,6237, +4987,5549,6069,6711,4342,3517,4473,5317,6070,6712,6071,4706,6446,5017,5355,6713, +6714,4988,5436,6447,4734,5759,6715,4735,4547,4456,4754,6448,5851,6449,6450,3547, +5852,5318,6451,6452,5092,4205,6716,6238,4620,4219,5611,6239,6072,4481,5760,5957, +5958,4059,6240,6453,4227,4537,6241,5761,4030,4186,5244,5209,3761,4457,4876,3337, +5495,5181,6242,5959,5319,5612,5684,5853,3493,5854,6073,4169,5613,5147,4895,6074, +5210,6717,5182,6718,3830,6243,2798,3841,6075,6244,5855,5614,3604,4606,5496,5685, +5118,5356,6719,6454,5960,5357,5961,6720,4145,3935,4621,5119,5962,4261,6721,6455, +4786,5963,4375,4582,6245,6246,6247,6076,5437,4877,5856,3376,4380,6248,4160,6722, +5148,6456,5211,6457,6723,4718,6458,6724,6249,5358,4044,3297,6459,6250,5857,5615, +5497,5245,6460,5498,6725,6251,6252,5550,3793,5499,2959,5396,6461,6462,4572,5093, +5500,5964,3806,4146,6463,4426,5762,5858,6077,6253,4755,3967,4220,5965,6254,4989, +5501,6464,4352,6726,6078,4764,2290,5246,3906,5438,5283,3767,4964,2861,5763,5094, +6255,6256,4622,5616,5859,5860,4707,6727,4285,4708,4824,5617,6257,5551,4787,5212, +4965,4935,4687,6465,6728,6466,5686,6079,3494,4413,2995,5247,5966,5618,6729,5967, +5764,5765,5687,5502,6730,6731,6080,5397,6467,4990,6258,6732,4538,5060,5619,6733, +4719,5688,5439,5018,5149,5284,5503,6734,6081,4607,6259,5120,3645,5861,4583,6260, +4584,4675,5620,4098,5440,6261,4863,2379,3306,4585,5552,5689,4586,5285,6735,4864, +6736,5286,6082,6737,4623,3010,4788,4381,4558,5621,4587,4896,3698,3161,5248,4353, +4045,6262,3754,5183,4588,6738,6263,6739,6740,5622,3936,6741,6468,6742,6264,5095, +6469,4991,5968,6743,4992,6744,6083,4897,6745,4256,5766,4307,3108,3968,4444,5287, +3889,4343,6084,4510,6085,4559,6086,4898,5969,6746,5623,5061,4919,5249,5250,5504, +5441,6265,5320,4878,3242,5862,5251,3428,6087,6747,4237,5624,5442,6266,5553,4539, +6748,2585,3533,5398,4262,6088,5150,4736,4438,6089,6267,5505,4966,6749,6268,6750, +6269,5288,5554,3650,6090,6091,4624,6092,5690,6751,5863,4270,5691,4277,5555,5864, +6752,5692,4720,4865,6470,5151,4688,4825,6753,3094,6754,6471,3235,4653,6755,5213, +5399,6756,3201,4589,5865,4967,6472,5866,6473,5019,3016,6757,5321,4756,3957,4573, +6093,4993,5767,4721,6474,6758,5625,6759,4458,6475,6270,6760,5556,4994,5214,5252, +6271,3875,5768,6094,5034,5506,4376,5769,6761,2120,6476,5253,5770,6762,5771,5970, +3990,5971,5557,5558,5772,6477,6095,2787,4641,5972,5121,6096,6097,6272,6763,3703, +5867,5507,6273,4206,6274,4789,6098,6764,3619,3646,3833,3804,2394,3788,4936,3978, +4866,4899,6099,6100,5559,6478,6765,3599,5868,6101,5869,5870,6275,6766,4527,6767) + +# flake8: noqa diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/gb2312prober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/gb2312prober.py new file mode 100644 index 0000000000..643fe2519e --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/gb2312prober.py @@ -0,0 +1,41 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import GB2312DistributionAnalysis +from .mbcssm import GB2312SMModel + +class GB2312Prober(MultiByteCharSetProber): + def __init__(self): + MultiByteCharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(GB2312SMModel) + self._mDistributionAnalyzer = GB2312DistributionAnalysis() + self.reset() + + def get_charset_name(self): + return "GB2312" diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/hebrewprober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/hebrewprober.py new file mode 100644 index 0000000000..90d171f302 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/hebrewprober.py @@ -0,0 +1,283 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Shy Shalom +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .constants import eNotMe, eDetecting +from .compat import wrap_ord + +# This prober doesn't actually recognize a language or a charset. +# It is a helper prober for the use of the Hebrew model probers + +### General ideas of the Hebrew charset recognition ### +# +# Four main charsets exist in Hebrew: +# "ISO-8859-8" - Visual Hebrew +# "windows-1255" - Logical Hebrew +# "ISO-8859-8-I" - Logical Hebrew +# "x-mac-hebrew" - ?? Logical Hebrew ?? +# +# Both "ISO" charsets use a completely identical set of code points, whereas +# "windows-1255" and "x-mac-hebrew" are two different proper supersets of +# these code points. windows-1255 defines additional characters in the range +# 0x80-0x9F as some misc punctuation marks as well as some Hebrew-specific +# diacritics and additional 'Yiddish' ligature letters in the range 0xc0-0xd6. +# x-mac-hebrew defines similar additional code points but with a different +# mapping. +# +# As far as an average Hebrew text with no diacritics is concerned, all four +# charsets are identical with respect to code points. Meaning that for the +# main Hebrew alphabet, all four map the same values to all 27 Hebrew letters +# (including final letters). +# +# The dominant difference between these charsets is their directionality. +# "Visual" directionality means that the text is ordered as if the renderer is +# not aware of a BIDI rendering algorithm. The renderer sees the text and +# draws it from left to right. The text itself when ordered naturally is read +# backwards. A buffer of Visual Hebrew generally looks like so: +# "[last word of first line spelled backwards] [whole line ordered backwards +# and spelled backwards] [first word of first line spelled backwards] +# [end of line] [last word of second line] ... etc' " +# adding punctuation marks, numbers and English text to visual text is +# naturally also "visual" and from left to right. +# +# "Logical" directionality means the text is ordered "naturally" according to +# the order it is read. It is the responsibility of the renderer to display +# the text from right to left. A BIDI algorithm is used to place general +# punctuation marks, numbers and English text in the text. +# +# Texts in x-mac-hebrew are almost impossible to find on the Internet. From +# what little evidence I could find, it seems that its general directionality +# is Logical. +# +# To sum up all of the above, the Hebrew probing mechanism knows about two +# charsets: +# Visual Hebrew - "ISO-8859-8" - backwards text - Words and sentences are +# backwards while line order is natural. For charset recognition purposes +# the line order is unimportant (In fact, for this implementation, even +# word order is unimportant). +# Logical Hebrew - "windows-1255" - normal, naturally ordered text. +# +# "ISO-8859-8-I" is a subset of windows-1255 and doesn't need to be +# specifically identified. +# "x-mac-hebrew" is also identified as windows-1255. A text in x-mac-hebrew +# that contain special punctuation marks or diacritics is displayed with +# some unconverted characters showing as question marks. This problem might +# be corrected using another model prober for x-mac-hebrew. Due to the fact +# that x-mac-hebrew texts are so rare, writing another model prober isn't +# worth the effort and performance hit. +# +#### The Prober #### +# +# The prober is divided between two SBCharSetProbers and a HebrewProber, +# all of which are managed, created, fed data, inquired and deleted by the +# SBCSGroupProber. The two SBCharSetProbers identify that the text is in +# fact some kind of Hebrew, Logical or Visual. The final decision about which +# one is it is made by the HebrewProber by combining final-letter scores +# with the scores of the two SBCharSetProbers to produce a final answer. +# +# The SBCSGroupProber is responsible for stripping the original text of HTML +# tags, English characters, numbers, low-ASCII punctuation characters, spaces +# and new lines. It reduces any sequence of such characters to a single space. +# The buffer fed to each prober in the SBCS group prober is pure text in +# high-ASCII. +# The two SBCharSetProbers (model probers) share the same language model: +# Win1255Model. +# The first SBCharSetProber uses the model normally as any other +# SBCharSetProber does, to recognize windows-1255, upon which this model was +# built. The second SBCharSetProber is told to make the pair-of-letter +# lookup in the language model backwards. This in practice exactly simulates +# a visual Hebrew model using the windows-1255 logical Hebrew model. +# +# The HebrewProber is not using any language model. All it does is look for +# final-letter evidence suggesting the text is either logical Hebrew or visual +# Hebrew. Disjointed from the model probers, the results of the HebrewProber +# alone are meaningless. HebrewProber always returns 0.00 as confidence +# since it never identifies a charset by itself. Instead, the pointer to the +# HebrewProber is passed to the model probers as a helper "Name Prober". +# When the Group prober receives a positive identification from any prober, +# it asks for the name of the charset identified. If the prober queried is a +# Hebrew model prober, the model prober forwards the call to the +# HebrewProber to make the final decision. In the HebrewProber, the +# decision is made according to the final-letters scores maintained and Both +# model probers scores. The answer is returned in the form of the name of the +# charset identified, either "windows-1255" or "ISO-8859-8". + +# windows-1255 / ISO-8859-8 code points of interest +FINAL_KAF = 0xea +NORMAL_KAF = 0xeb +FINAL_MEM = 0xed +NORMAL_MEM = 0xee +FINAL_NUN = 0xef +NORMAL_NUN = 0xf0 +FINAL_PE = 0xf3 +NORMAL_PE = 0xf4 +FINAL_TSADI = 0xf5 +NORMAL_TSADI = 0xf6 + +# Minimum Visual vs Logical final letter score difference. +# If the difference is below this, don't rely solely on the final letter score +# distance. +MIN_FINAL_CHAR_DISTANCE = 5 + +# Minimum Visual vs Logical model score difference. +# If the difference is below this, don't rely at all on the model score +# distance. +MIN_MODEL_DISTANCE = 0.01 + +VISUAL_HEBREW_NAME = "ISO-8859-8" +LOGICAL_HEBREW_NAME = "windows-1255" + + +class HebrewProber(CharSetProber): + def __init__(self): + CharSetProber.__init__(self) + self._mLogicalProber = None + self._mVisualProber = None + self.reset() + + def reset(self): + self._mFinalCharLogicalScore = 0 + self._mFinalCharVisualScore = 0 + # The two last characters seen in the previous buffer, + # mPrev and mBeforePrev are initialized to space in order to simulate + # a word delimiter at the beginning of the data + self._mPrev = ' ' + self._mBeforePrev = ' ' + # These probers are owned by the group prober. + + def set_model_probers(self, logicalProber, visualProber): + self._mLogicalProber = logicalProber + self._mVisualProber = visualProber + + def is_final(self, c): + return wrap_ord(c) in [FINAL_KAF, FINAL_MEM, FINAL_NUN, FINAL_PE, + FINAL_TSADI] + + def is_non_final(self, c): + # The normal Tsadi is not a good Non-Final letter due to words like + # 'lechotet' (to chat) containing an apostrophe after the tsadi. This + # apostrophe is converted to a space in FilterWithoutEnglishLetters + # causing the Non-Final tsadi to appear at an end of a word even + # though this is not the case in the original text. + # The letters Pe and Kaf rarely display a related behavior of not being + # a good Non-Final letter. Words like 'Pop', 'Winamp' and 'Mubarak' + # for example legally end with a Non-Final Pe or Kaf. However, the + # benefit of these letters as Non-Final letters outweighs the damage + # since these words are quite rare. + return wrap_ord(c) in [NORMAL_KAF, NORMAL_MEM, NORMAL_NUN, NORMAL_PE] + + def feed(self, aBuf): + # Final letter analysis for logical-visual decision. + # Look for evidence that the received buffer is either logical Hebrew + # or visual Hebrew. + # The following cases are checked: + # 1) A word longer than 1 letter, ending with a final letter. This is + # an indication that the text is laid out "naturally" since the + # final letter really appears at the end. +1 for logical score. + # 2) A word longer than 1 letter, ending with a Non-Final letter. In + # normal Hebrew, words ending with Kaf, Mem, Nun, Pe or Tsadi, + # should not end with the Non-Final form of that letter. Exceptions + # to this rule are mentioned above in isNonFinal(). This is an + # indication that the text is laid out backwards. +1 for visual + # score + # 3) A word longer than 1 letter, starting with a final letter. Final + # letters should not appear at the beginning of a word. This is an + # indication that the text is laid out backwards. +1 for visual + # score. + # + # The visual score and logical score are accumulated throughout the + # text and are finally checked against each other in GetCharSetName(). + # No checking for final letters in the middle of words is done since + # that case is not an indication for either Logical or Visual text. + # + # We automatically filter out all 7-bit characters (replace them with + # spaces) so the word boundary detection works properly. [MAP] + + if self.get_state() == eNotMe: + # Both model probers say it's not them. No reason to continue. + return eNotMe + + aBuf = self.filter_high_bit_only(aBuf) + + for cur in aBuf: + if cur == ' ': + # We stand on a space - a word just ended + if self._mBeforePrev != ' ': + # next-to-last char was not a space so self._mPrev is not a + # 1 letter word + if self.is_final(self._mPrev): + # case (1) [-2:not space][-1:final letter][cur:space] + self._mFinalCharLogicalScore += 1 + elif self.is_non_final(self._mPrev): + # case (2) [-2:not space][-1:Non-Final letter][ + # cur:space] + self._mFinalCharVisualScore += 1 + else: + # Not standing on a space + if ((self._mBeforePrev == ' ') and + (self.is_final(self._mPrev)) and (cur != ' ')): + # case (3) [-2:space][-1:final letter][cur:not space] + self._mFinalCharVisualScore += 1 + self._mBeforePrev = self._mPrev + self._mPrev = cur + + # Forever detecting, till the end or until both model probers return + # eNotMe (handled above) + return eDetecting + + def get_charset_name(self): + # Make the decision: is it Logical or Visual? + # If the final letter score distance is dominant enough, rely on it. + finalsub = self._mFinalCharLogicalScore - self._mFinalCharVisualScore + if finalsub >= MIN_FINAL_CHAR_DISTANCE: + return LOGICAL_HEBREW_NAME + if finalsub <= -MIN_FINAL_CHAR_DISTANCE: + return VISUAL_HEBREW_NAME + + # It's not dominant enough, try to rely on the model scores instead. + modelsub = (self._mLogicalProber.get_confidence() + - self._mVisualProber.get_confidence()) + if modelsub > MIN_MODEL_DISTANCE: + return LOGICAL_HEBREW_NAME + if modelsub < -MIN_MODEL_DISTANCE: + return VISUAL_HEBREW_NAME + + # Still no good, back to final letter distance, maybe it'll save the + # day. + if finalsub < 0.0: + return VISUAL_HEBREW_NAME + + # (finalsub > 0 - Logical) or (don't know what to do) default to + # Logical. + return LOGICAL_HEBREW_NAME + + def get_state(self): + # Remain active as long as any of the model probers are active. + if (self._mLogicalProber.get_state() == eNotMe) and \ + (self._mVisualProber.get_state() == eNotMe): + return eNotMe + return eDetecting diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/jisfreq.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/jisfreq.py new file mode 100644 index 0000000000..064345b086 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/jisfreq.py @@ -0,0 +1,569 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Sampling from about 20M text materials include literature and computer technology +# +# Japanese frequency table, applied to both S-JIS and EUC-JP +# They are sorted in order. + +# 128 --> 0.77094 +# 256 --> 0.85710 +# 512 --> 0.92635 +# 1024 --> 0.97130 +# 2048 --> 0.99431 +# +# Ideal Distribution Ratio = 0.92635 / (1-0.92635) = 12.58 +# Random Distribution Ration = 512 / (2965+62+83+86-512) = 0.191 +# +# Typical Distribution Ratio, 25% of IDR + +JIS_TYPICAL_DISTRIBUTION_RATIO = 3.0 + +# Char to FreqOrder table , +JIS_TABLE_SIZE = 4368 + +JISCharToFreqOrder = ( + 40, 1, 6, 182, 152, 180, 295,2127, 285, 381,3295,4304,3068,4606,3165,3510, # 16 +3511,1822,2785,4607,1193,2226,5070,4608, 171,2996,1247, 18, 179,5071, 856,1661, # 32 +1262,5072, 619, 127,3431,3512,3230,1899,1700, 232, 228,1294,1298, 284, 283,2041, # 48 +2042,1061,1062, 48, 49, 44, 45, 433, 434,1040,1041, 996, 787,2997,1255,4305, # 64 +2108,4609,1684,1648,5073,5074,5075,5076,5077,5078,3687,5079,4610,5080,3927,3928, # 80 +5081,3296,3432, 290,2285,1471,2187,5082,2580,2825,1303,2140,1739,1445,2691,3375, # 96 +1691,3297,4306,4307,4611, 452,3376,1182,2713,3688,3069,4308,5083,5084,5085,5086, # 112 +5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102, # 128 +5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,4097,5113,5114,5115,5116,5117, # 144 +5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133, # 160 +5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149, # 176 +5150,5151,5152,4612,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164, # 192 +5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,1472, 598, 618, 820,1205, # 208 +1309,1412,1858,1307,1692,5176,5177,5178,5179,5180,5181,5182,1142,1452,1234,1172, # 224 +1875,2043,2149,1793,1382,2973, 925,2404,1067,1241, 960,1377,2935,1491, 919,1217, # 240 +1865,2030,1406,1499,2749,4098,5183,5184,5185,5186,5187,5188,2561,4099,3117,1804, # 256 +2049,3689,4309,3513,1663,5189,3166,3118,3298,1587,1561,3433,5190,3119,1625,2998, # 272 +3299,4613,1766,3690,2786,4614,5191,5192,5193,5194,2161, 26,3377, 2,3929, 20, # 288 +3691, 47,4100, 50, 17, 16, 35, 268, 27, 243, 42, 155, 24, 154, 29, 184, # 304 + 4, 91, 14, 92, 53, 396, 33, 289, 9, 37, 64, 620, 21, 39, 321, 5, # 320 + 12, 11, 52, 13, 3, 208, 138, 0, 7, 60, 526, 141, 151,1069, 181, 275, # 336 +1591, 83, 132,1475, 126, 331, 829, 15, 69, 160, 59, 22, 157, 55,1079, 312, # 352 + 109, 38, 23, 25, 10, 19, 79,5195, 61, 382,1124, 8, 30,5196,5197,5198, # 368 +5199,5200,5201,5202,5203,5204,5205,5206, 89, 62, 74, 34,2416, 112, 139, 196, # 384 + 271, 149, 84, 607, 131, 765, 46, 88, 153, 683, 76, 874, 101, 258, 57, 80, # 400 + 32, 364, 121,1508, 169,1547, 68, 235, 145,2999, 41, 360,3027, 70, 63, 31, # 416 + 43, 259, 262,1383, 99, 533, 194, 66, 93, 846, 217, 192, 56, 106, 58, 565, # 432 + 280, 272, 311, 256, 146, 82, 308, 71, 100, 128, 214, 655, 110, 261, 104,1140, # 448 + 54, 51, 36, 87, 67,3070, 185,2618,2936,2020, 28,1066,2390,2059,5207,5208, # 464 +5209,5210,5211,5212,5213,5214,5215,5216,4615,5217,5218,5219,5220,5221,5222,5223, # 480 +5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,3514,5237,5238, # 496 +5239,5240,5241,5242,5243,5244,2297,2031,4616,4310,3692,5245,3071,5246,3598,5247, # 512 +4617,3231,3515,5248,4101,4311,4618,3808,4312,4102,5249,4103,4104,3599,5250,5251, # 528 +5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267, # 544 +5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283, # 560 +5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299, # 576 +5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315, # 592 +5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331, # 608 +5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347, # 624 +5348,5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363, # 640 +5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379, # 656 +5380,5381, 363, 642,2787,2878,2788,2789,2316,3232,2317,3434,2011, 165,1942,3930, # 672 +3931,3932,3933,5382,4619,5383,4620,5384,5385,5386,5387,5388,5389,5390,5391,5392, # 688 +5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408, # 704 +5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424, # 720 +5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440, # 736 +5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456, # 752 +5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472, # 768 +5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488, # 784 +5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504, # 800 +5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520, # 816 +5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536, # 832 +5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552, # 848 +5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568, # 864 +5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584, # 880 +5585,5586,5587,5588,5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600, # 896 +5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616, # 912 +5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632, # 928 +5633,5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648, # 944 +5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664, # 960 +5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680, # 976 +5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696, # 992 +5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712, # 1008 +5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728, # 1024 +5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,5744, # 1040 +5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,5759,5760, # 1056 +5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,5774,5775,5776, # 1072 +5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,5789,5790,5791,5792, # 1088 +5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,5804,5805,5806,5807,5808, # 1104 +5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824, # 1120 +5825,5826,5827,5828,5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840, # 1136 +5841,5842,5843,5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856, # 1152 +5857,5858,5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872, # 1168 +5873,5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888, # 1184 +5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904, # 1200 +5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920, # 1216 +5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936, # 1232 +5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952, # 1248 +5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968, # 1264 +5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,5984, # 1280 +5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,5999,6000, # 1296 +6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016, # 1312 +6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032, # 1328 +6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048, # 1344 +6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064, # 1360 +6065,6066,6067,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080, # 1376 +6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096, # 1392 +6097,6098,6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112, # 1408 +6113,6114,2044,2060,4621, 997,1235, 473,1186,4622, 920,3378,6115,6116, 379,1108, # 1424 +4313,2657,2735,3934,6117,3809, 636,3233, 573,1026,3693,3435,2974,3300,2298,4105, # 1440 + 854,2937,2463, 393,2581,2417, 539, 752,1280,2750,2480, 140,1161, 440, 708,1569, # 1456 + 665,2497,1746,1291,1523,3000, 164,1603, 847,1331, 537,1997, 486, 508,1693,2418, # 1472 +1970,2227, 878,1220, 299,1030, 969, 652,2751, 624,1137,3301,2619, 65,3302,2045, # 1488 +1761,1859,3120,1930,3694,3516, 663,1767, 852, 835,3695, 269, 767,2826,2339,1305, # 1504 + 896,1150, 770,1616,6118, 506,1502,2075,1012,2519, 775,2520,2975,2340,2938,4314, # 1520 +3028,2086,1224,1943,2286,6119,3072,4315,2240,1273,1987,3935,1557, 175, 597, 985, # 1536 +3517,2419,2521,1416,3029, 585, 938,1931,1007,1052,1932,1685,6120,3379,4316,4623, # 1552 + 804, 599,3121,1333,2128,2539,1159,1554,2032,3810, 687,2033,2904, 952, 675,1467, # 1568 +3436,6121,2241,1096,1786,2440,1543,1924, 980,1813,2228, 781,2692,1879, 728,1918, # 1584 +3696,4624, 548,1950,4625,1809,1088,1356,3303,2522,1944, 502, 972, 373, 513,2827, # 1600 + 586,2377,2391,1003,1976,1631,6122,2464,1084, 648,1776,4626,2141, 324, 962,2012, # 1616 +2177,2076,1384, 742,2178,1448,1173,1810, 222, 102, 301, 445, 125,2420, 662,2498, # 1632 + 277, 200,1476,1165,1068, 224,2562,1378,1446, 450,1880, 659, 791, 582,4627,2939, # 1648 +3936,1516,1274, 555,2099,3697,1020,1389,1526,3380,1762,1723,1787,2229, 412,2114, # 1664 +1900,2392,3518, 512,2597, 427,1925,2341,3122,1653,1686,2465,2499, 697, 330, 273, # 1680 + 380,2162, 951, 832, 780, 991,1301,3073, 965,2270,3519, 668,2523,2636,1286, 535, # 1696 +1407, 518, 671, 957,2658,2378, 267, 611,2197,3030,6123, 248,2299, 967,1799,2356, # 1712 + 850,1418,3437,1876,1256,1480,2828,1718,6124,6125,1755,1664,2405,6126,4628,2879, # 1728 +2829, 499,2179, 676,4629, 557,2329,2214,2090, 325,3234, 464, 811,3001, 992,2342, # 1744 +2481,1232,1469, 303,2242, 466,1070,2163, 603,1777,2091,4630,2752,4631,2714, 322, # 1760 +2659,1964,1768, 481,2188,1463,2330,2857,3600,2092,3031,2421,4632,2318,2070,1849, # 1776 +2598,4633,1302,2254,1668,1701,2422,3811,2905,3032,3123,2046,4106,1763,1694,4634, # 1792 +1604, 943,1724,1454, 917, 868,2215,1169,2940, 552,1145,1800,1228,1823,1955, 316, # 1808 +1080,2510, 361,1807,2830,4107,2660,3381,1346,1423,1134,4108,6127, 541,1263,1229, # 1824 +1148,2540, 545, 465,1833,2880,3438,1901,3074,2482, 816,3937, 713,1788,2500, 122, # 1840 +1575, 195,1451,2501,1111,6128, 859, 374,1225,2243,2483,4317, 390,1033,3439,3075, # 1856 +2524,1687, 266, 793,1440,2599, 946, 779, 802, 507, 897,1081, 528,2189,1292, 711, # 1872 +1866,1725,1167,1640, 753, 398,2661,1053, 246, 348,4318, 137,1024,3440,1600,2077, # 1888 +2129, 825,4319, 698, 238, 521, 187,2300,1157,2423,1641,1605,1464,1610,1097,2541, # 1904 +1260,1436, 759,2255,1814,2150, 705,3235, 409,2563,3304, 561,3033,2005,2564, 726, # 1920 +1956,2343,3698,4109, 949,3812,3813,3520,1669, 653,1379,2525, 881,2198, 632,2256, # 1936 +1027, 778,1074, 733,1957, 514,1481,2466, 554,2180, 702,3938,1606,1017,1398,6129, # 1952 +1380,3521, 921, 993,1313, 594, 449,1489,1617,1166, 768,1426,1360, 495,1794,3601, # 1968 +1177,3602,1170,4320,2344, 476, 425,3167,4635,3168,1424, 401,2662,1171,3382,1998, # 1984 +1089,4110, 477,3169, 474,6130,1909, 596,2831,1842, 494, 693,1051,1028,1207,3076, # 2000 + 606,2115, 727,2790,1473,1115, 743,3522, 630, 805,1532,4321,2021, 366,1057, 838, # 2016 + 684,1114,2142,4322,2050,1492,1892,1808,2271,3814,2424,1971,1447,1373,3305,1090, # 2032 +1536,3939,3523,3306,1455,2199, 336, 369,2331,1035, 584,2393, 902, 718,2600,6131, # 2048 +2753, 463,2151,1149,1611,2467, 715,1308,3124,1268, 343,1413,3236,1517,1347,2663, # 2064 +2093,3940,2022,1131,1553,2100,2941,1427,3441,2942,1323,2484,6132,1980, 872,2368, # 2080 +2441,2943, 320,2369,2116,1082, 679,1933,3941,2791,3815, 625,1143,2023, 422,2200, # 2096 +3816,6133, 730,1695, 356,2257,1626,2301,2858,2637,1627,1778, 937, 883,2906,2693, # 2112 +3002,1769,1086, 400,1063,1325,3307,2792,4111,3077, 456,2345,1046, 747,6134,1524, # 2128 + 884,1094,3383,1474,2164,1059, 974,1688,2181,2258,1047, 345,1665,1187, 358, 875, # 2144 +3170, 305, 660,3524,2190,1334,1135,3171,1540,1649,2542,1527, 927, 968,2793, 885, # 2160 +1972,1850, 482, 500,2638,1218,1109,1085,2543,1654,2034, 876, 78,2287,1482,1277, # 2176 + 861,1675,1083,1779, 724,2754, 454, 397,1132,1612,2332, 893, 672,1237, 257,2259, # 2192 +2370, 135,3384, 337,2244, 547, 352, 340, 709,2485,1400, 788,1138,2511, 540, 772, # 2208 +1682,2260,2272,2544,2013,1843,1902,4636,1999,1562,2288,4637,2201,1403,1533, 407, # 2224 + 576,3308,1254,2071, 978,3385, 170, 136,1201,3125,2664,3172,2394, 213, 912, 873, # 2240 +3603,1713,2202, 699,3604,3699, 813,3442, 493, 531,1054, 468,2907,1483, 304, 281, # 2256 +4112,1726,1252,2094, 339,2319,2130,2639, 756,1563,2944, 748, 571,2976,1588,2425, # 2272 +2715,1851,1460,2426,1528,1392,1973,3237, 288,3309, 685,3386, 296, 892,2716,2216, # 2288 +1570,2245, 722,1747,2217, 905,3238,1103,6135,1893,1441,1965, 251,1805,2371,3700, # 2304 +2601,1919,1078, 75,2182,1509,1592,1270,2640,4638,2152,6136,3310,3817, 524, 706, # 2320 +1075, 292,3818,1756,2602, 317, 98,3173,3605,3525,1844,2218,3819,2502, 814, 567, # 2336 + 385,2908,1534,6137, 534,1642,3239, 797,6138,1670,1529, 953,4323, 188,1071, 538, # 2352 + 178, 729,3240,2109,1226,1374,2000,2357,2977, 731,2468,1116,2014,2051,6139,1261, # 2368 +1593, 803,2859,2736,3443, 556, 682, 823,1541,6140,1369,2289,1706,2794, 845, 462, # 2384 +2603,2665,1361, 387, 162,2358,1740, 739,1770,1720,1304,1401,3241,1049, 627,1571, # 2400 +2427,3526,1877,3942,1852,1500, 431,1910,1503, 677, 297,2795, 286,1433,1038,1198, # 2416 +2290,1133,1596,4113,4639,2469,1510,1484,3943,6141,2442, 108, 712,4640,2372, 866, # 2432 +3701,2755,3242,1348, 834,1945,1408,3527,2395,3243,1811, 824, 994,1179,2110,1548, # 2448 +1453, 790,3003, 690,4324,4325,2832,2909,3820,1860,3821, 225,1748, 310, 346,1780, # 2464 +2470, 821,1993,2717,2796, 828, 877,3528,2860,2471,1702,2165,2910,2486,1789, 453, # 2480 + 359,2291,1676, 73,1164,1461,1127,3311, 421, 604, 314,1037, 589, 116,2487, 737, # 2496 + 837,1180, 111, 244, 735,6142,2261,1861,1362, 986, 523, 418, 581,2666,3822, 103, # 2512 + 855, 503,1414,1867,2488,1091, 657,1597, 979, 605,1316,4641,1021,2443,2078,2001, # 2528 +1209, 96, 587,2166,1032, 260,1072,2153, 173, 94, 226,3244, 819,2006,4642,4114, # 2544 +2203, 231,1744, 782, 97,2667, 786,3387, 887, 391, 442,2219,4326,1425,6143,2694, # 2560 + 633,1544,1202, 483,2015, 592,2052,1958,2472,1655, 419, 129,4327,3444,3312,1714, # 2576 +1257,3078,4328,1518,1098, 865,1310,1019,1885,1512,1734, 469,2444, 148, 773, 436, # 2592 +1815,1868,1128,1055,4329,1245,2756,3445,2154,1934,1039,4643, 579,1238, 932,2320, # 2608 + 353, 205, 801, 115,2428, 944,2321,1881, 399,2565,1211, 678, 766,3944, 335,2101, # 2624 +1459,1781,1402,3945,2737,2131,1010, 844, 981,1326,1013, 550,1816,1545,2620,1335, # 2640 +1008, 371,2881, 936,1419,1613,3529,1456,1395,2273,1834,2604,1317,2738,2503, 416, # 2656 +1643,4330, 806,1126, 229, 591,3946,1314,1981,1576,1837,1666, 347,1790, 977,3313, # 2672 + 764,2861,1853, 688,2429,1920,1462, 77, 595, 415,2002,3034, 798,1192,4115,6144, # 2688 +2978,4331,3035,2695,2582,2072,2566, 430,2430,1727, 842,1396,3947,3702, 613, 377, # 2704 + 278, 236,1417,3388,3314,3174, 757,1869, 107,3530,6145,1194, 623,2262, 207,1253, # 2720 +2167,3446,3948, 492,1117,1935, 536,1838,2757,1246,4332, 696,2095,2406,1393,1572, # 2736 +3175,1782, 583, 190, 253,1390,2230, 830,3126,3389, 934,3245,1703,1749,2979,1870, # 2752 +2545,1656,2204, 869,2346,4116,3176,1817, 496,1764,4644, 942,1504, 404,1903,1122, # 2768 +1580,3606,2945,1022, 515, 372,1735, 955,2431,3036,6146,2797,1110,2302,2798, 617, # 2784 +6147, 441, 762,1771,3447,3607,3608,1904, 840,3037, 86, 939,1385, 572,1370,2445, # 2800 +1336, 114,3703, 898, 294, 203,3315, 703,1583,2274, 429, 961,4333,1854,1951,3390, # 2816 +2373,3704,4334,1318,1381, 966,1911,2322,1006,1155, 309, 989, 458,2718,1795,1372, # 2832 +1203, 252,1689,1363,3177, 517,1936, 168,1490, 562, 193,3823,1042,4117,1835, 551, # 2848 + 470,4645, 395, 489,3448,1871,1465,2583,2641, 417,1493, 279,1295, 511,1236,1119, # 2864 + 72,1231,1982,1812,3004, 871,1564, 984,3449,1667,2696,2096,4646,2347,2833,1673, # 2880 +3609, 695,3246,2668, 807,1183,4647, 890, 388,2333,1801,1457,2911,1765,1477,1031, # 2896 +3316,3317,1278,3391,2799,2292,2526, 163,3450,4335,2669,1404,1802,6148,2323,2407, # 2912 +1584,1728,1494,1824,1269, 298, 909,3318,1034,1632, 375, 776,1683,2061, 291, 210, # 2928 +1123, 809,1249,1002,2642,3038, 206,1011,2132, 144, 975, 882,1565, 342, 667, 754, # 2944 +1442,2143,1299,2303,2062, 447, 626,2205,1221,2739,2912,1144,1214,2206,2584, 760, # 2960 +1715, 614, 950,1281,2670,2621, 810, 577,1287,2546,4648, 242,2168, 250,2643, 691, # 2976 + 123,2644, 647, 313,1029, 689,1357,2946,1650, 216, 771,1339,1306, 808,2063, 549, # 2992 + 913,1371,2913,2914,6149,1466,1092,1174,1196,1311,2605,2396,1783,1796,3079, 406, # 3008 +2671,2117,3949,4649, 487,1825,2220,6150,2915, 448,2348,1073,6151,2397,1707, 130, # 3024 + 900,1598, 329, 176,1959,2527,1620,6152,2275,4336,3319,1983,2191,3705,3610,2155, # 3040 +3706,1912,1513,1614,6153,1988, 646, 392,2304,1589,3320,3039,1826,1239,1352,1340, # 3056 +2916, 505,2567,1709,1437,2408,2547, 906,6154,2672, 384,1458,1594,1100,1329, 710, # 3072 + 423,3531,2064,2231,2622,1989,2673,1087,1882, 333, 841,3005,1296,2882,2379, 580, # 3088 +1937,1827,1293,2585, 601, 574, 249,1772,4118,2079,1120, 645, 901,1176,1690, 795, # 3104 +2207, 478,1434, 516,1190,1530, 761,2080, 930,1264, 355, 435,1552, 644,1791, 987, # 3120 + 220,1364,1163,1121,1538, 306,2169,1327,1222, 546,2645, 218, 241, 610,1704,3321, # 3136 +1984,1839,1966,2528, 451,6155,2586,3707,2568, 907,3178, 254,2947, 186,1845,4650, # 3152 + 745, 432,1757, 428,1633, 888,2246,2221,2489,3611,2118,1258,1265, 956,3127,1784, # 3168 +4337,2490, 319, 510, 119, 457,3612, 274,2035,2007,4651,1409,3128, 970,2758, 590, # 3184 +2800, 661,2247,4652,2008,3950,1420,1549,3080,3322,3951,1651,1375,2111, 485,2491, # 3200 +1429,1156,6156,2548,2183,1495, 831,1840,2529,2446, 501,1657, 307,1894,3247,1341, # 3216 + 666, 899,2156,1539,2549,1559, 886, 349,2208,3081,2305,1736,3824,2170,2759,1014, # 3232 +1913,1386, 542,1397,2948, 490, 368, 716, 362, 159, 282,2569,1129,1658,1288,1750, # 3248 +2674, 276, 649,2016, 751,1496, 658,1818,1284,1862,2209,2087,2512,3451, 622,2834, # 3264 + 376, 117,1060,2053,1208,1721,1101,1443, 247,1250,3179,1792,3952,2760,2398,3953, # 3280 +6157,2144,3708, 446,2432,1151,2570,3452,2447,2761,2835,1210,2448,3082, 424,2222, # 3296 +1251,2449,2119,2836, 504,1581,4338, 602, 817, 857,3825,2349,2306, 357,3826,1470, # 3312 +1883,2883, 255, 958, 929,2917,3248, 302,4653,1050,1271,1751,2307,1952,1430,2697, # 3328 +2719,2359, 354,3180, 777, 158,2036,4339,1659,4340,4654,2308,2949,2248,1146,2232, # 3344 +3532,2720,1696,2623,3827,6158,3129,1550,2698,1485,1297,1428, 637, 931,2721,2145, # 3360 + 914,2550,2587, 81,2450, 612, 827,2646,1242,4655,1118,2884, 472,1855,3181,3533, # 3376 +3534, 569,1353,2699,1244,1758,2588,4119,2009,2762,2171,3709,1312,1531,6159,1152, # 3392 +1938, 134,1830, 471,3710,2276,1112,1535,3323,3453,3535, 982,1337,2950, 488, 826, # 3408 + 674,1058,1628,4120,2017, 522,2399, 211, 568,1367,3454, 350, 293,1872,1139,3249, # 3424 +1399,1946,3006,1300,2360,3324, 588, 736,6160,2606, 744, 669,3536,3828,6161,1358, # 3440 + 199, 723, 848, 933, 851,1939,1505,1514,1338,1618,1831,4656,1634,3613, 443,2740, # 3456 +3829, 717,1947, 491,1914,6162,2551,1542,4121,1025,6163,1099,1223, 198,3040,2722, # 3472 + 370, 410,1905,2589, 998,1248,3182,2380, 519,1449,4122,1710, 947, 928,1153,4341, # 3488 +2277, 344,2624,1511, 615, 105, 161,1212,1076,1960,3130,2054,1926,1175,1906,2473, # 3504 + 414,1873,2801,6164,2309, 315,1319,3325, 318,2018,2146,2157, 963, 631, 223,4342, # 3520 +4343,2675, 479,3711,1197,2625,3712,2676,2361,6165,4344,4123,6166,2451,3183,1886, # 3536 +2184,1674,1330,1711,1635,1506, 799, 219,3250,3083,3954,1677,3713,3326,2081,3614, # 3552 +1652,2073,4657,1147,3041,1752, 643,1961, 147,1974,3955,6167,1716,2037, 918,3007, # 3568 +1994, 120,1537, 118, 609,3184,4345, 740,3455,1219, 332,1615,3830,6168,1621,2980, # 3584 +1582, 783, 212, 553,2350,3714,1349,2433,2082,4124, 889,6169,2310,1275,1410, 973, # 3600 + 166,1320,3456,1797,1215,3185,2885,1846,2590,2763,4658, 629, 822,3008, 763, 940, # 3616 +1990,2862, 439,2409,1566,1240,1622, 926,1282,1907,2764, 654,2210,1607, 327,1130, # 3632 +3956,1678,1623,6170,2434,2192, 686, 608,3831,3715, 903,3957,3042,6171,2741,1522, # 3648 +1915,1105,1555,2552,1359, 323,3251,4346,3457, 738,1354,2553,2311,2334,1828,2003, # 3664 +3832,1753,2351,1227,6172,1887,4125,1478,6173,2410,1874,1712,1847, 520,1204,2607, # 3680 + 264,4659, 836,2677,2102, 600,4660,3833,2278,3084,6174,4347,3615,1342, 640, 532, # 3696 + 543,2608,1888,2400,2591,1009,4348,1497, 341,1737,3616,2723,1394, 529,3252,1321, # 3712 + 983,4661,1515,2120, 971,2592, 924, 287,1662,3186,4349,2700,4350,1519, 908,1948, # 3728 +2452, 156, 796,1629,1486,2223,2055, 694,4126,1259,1036,3392,1213,2249,2742,1889, # 3744 +1230,3958,1015, 910, 408, 559,3617,4662, 746, 725, 935,4663,3959,3009,1289, 563, # 3760 + 867,4664,3960,1567,2981,2038,2626, 988,2263,2381,4351, 143,2374, 704,1895,6175, # 3776 +1188,3716,2088, 673,3085,2362,4352, 484,1608,1921,2765,2918, 215, 904,3618,3537, # 3792 + 894, 509, 976,3043,2701,3961,4353,2837,2982, 498,6176,6177,1102,3538,1332,3393, # 3808 +1487,1636,1637, 233, 245,3962, 383, 650, 995,3044, 460,1520,1206,2352, 749,3327, # 3824 + 530, 700, 389,1438,1560,1773,3963,2264, 719,2951,2724,3834, 870,1832,1644,1000, # 3840 + 839,2474,3717, 197,1630,3394, 365,2886,3964,1285,2133, 734, 922, 818,1106, 732, # 3856 + 480,2083,1774,3458, 923,2279,1350, 221,3086, 85,2233,2234,3835,1585,3010,2147, # 3872 +1387,1705,2382,1619,2475, 133, 239,2802,1991,1016,2084,2383, 411,2838,1113, 651, # 3888 +1985,1160,3328, 990,1863,3087,1048,1276,2647, 265,2627,1599,3253,2056, 150, 638, # 3904 +2019, 656, 853, 326,1479, 680,1439,4354,1001,1759, 413,3459,3395,2492,1431, 459, # 3920 +4355,1125,3329,2265,1953,1450,2065,2863, 849, 351,2678,3131,3254,3255,1104,1577, # 3936 + 227,1351,1645,2453,2193,1421,2887, 812,2121, 634, 95,2435, 201,2312,4665,1646, # 3952 +1671,2743,1601,2554,2702,2648,2280,1315,1366,2089,3132,1573,3718,3965,1729,1189, # 3968 + 328,2679,1077,1940,1136, 558,1283, 964,1195, 621,2074,1199,1743,3460,3619,1896, # 3984 +1916,1890,3836,2952,1154,2112,1064, 862, 378,3011,2066,2113,2803,1568,2839,6178, # 4000 +3088,2919,1941,1660,2004,1992,2194, 142, 707,1590,1708,1624,1922,1023,1836,1233, # 4016 +1004,2313, 789, 741,3620,6179,1609,2411,1200,4127,3719,3720,4666,2057,3721, 593, # 4032 +2840, 367,2920,1878,6180,3461,1521, 628,1168, 692,2211,2649, 300, 720,2067,2571, # 4048 +2953,3396, 959,2504,3966,3539,3462,1977, 701,6181, 954,1043, 800, 681, 183,3722, # 4064 +1803,1730,3540,4128,2103, 815,2314, 174, 467, 230,2454,1093,2134, 755,3541,3397, # 4080 +1141,1162,6182,1738,2039, 270,3256,2513,1005,1647,2185,3837, 858,1679,1897,1719, # 4096 +2954,2324,1806, 402, 670, 167,4129,1498,2158,2104, 750,6183, 915, 189,1680,1551, # 4112 + 455,4356,1501,2455, 405,1095,2955, 338,1586,1266,1819, 570, 641,1324, 237,1556, # 4128 +2650,1388,3723,6184,1368,2384,1343,1978,3089,2436, 879,3724, 792,1191, 758,3012, # 4144 +1411,2135,1322,4357, 240,4667,1848,3725,1574,6185, 420,3045,1546,1391, 714,4358, # 4160 +1967, 941,1864, 863, 664, 426, 560,1731,2680,1785,2864,1949,2363, 403,3330,1415, # 4176 +1279,2136,1697,2335, 204, 721,2097,3838, 90,6186,2085,2505, 191,3967, 124,2148, # 4192 +1376,1798,1178,1107,1898,1405, 860,4359,1243,1272,2375,2983,1558,2456,1638, 113, # 4208 +3621, 578,1923,2609, 880, 386,4130, 784,2186,2266,1422,2956,2172,1722, 497, 263, # 4224 +2514,1267,2412,2610, 177,2703,3542, 774,1927,1344, 616,1432,1595,1018, 172,4360, # 4240 +2325, 911,4361, 438,1468,3622, 794,3968,2024,2173,1681,1829,2957, 945, 895,3090, # 4256 + 575,2212,2476, 475,2401,2681, 785,2744,1745,2293,2555,1975,3133,2865, 394,4668, # 4272 +3839, 635,4131, 639, 202,1507,2195,2766,1345,1435,2572,3726,1908,1184,1181,2457, # 4288 +3727,3134,4362, 843,2611, 437, 916,4669, 234, 769,1884,3046,3047,3623, 833,6187, # 4304 +1639,2250,2402,1355,1185,2010,2047, 999, 525,1732,1290,1488,2612, 948,1578,3728, # 4320 +2413,2477,1216,2725,2159, 334,3840,1328,3624,2921,1525,4132, 564,1056, 891,4363, # 4336 +1444,1698,2385,2251,3729,1365,2281,2235,1717,6188, 864,3841,2515, 444, 527,2767, # 4352 +2922,3625, 544, 461,6189, 566, 209,2437,3398,2098,1065,2068,3331,3626,3257,2137, # 4368 #last 512 +#Everything below is of no interest for detection purpose +2138,2122,3730,2888,1995,1820,1044,6190,6191,6192,6193,6194,6195,6196,6197,6198, # 4384 +6199,6200,6201,6202,6203,6204,6205,4670,6206,6207,6208,6209,6210,6211,6212,6213, # 4400 +6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,6224,6225,6226,6227,6228,6229, # 4416 +6230,6231,6232,6233,6234,6235,6236,6237,3187,6238,6239,3969,6240,6241,6242,6243, # 4432 +6244,4671,6245,6246,4672,6247,6248,4133,6249,6250,4364,6251,2923,2556,2613,4673, # 4448 +4365,3970,6252,6253,6254,6255,4674,6256,6257,6258,2768,2353,4366,4675,4676,3188, # 4464 +4367,3463,6259,4134,4677,4678,6260,2267,6261,3842,3332,4368,3543,6262,6263,6264, # 4480 +3013,1954,1928,4135,4679,6265,6266,2478,3091,6267,4680,4369,6268,6269,1699,6270, # 4496 +3544,4136,4681,6271,4137,6272,4370,2804,6273,6274,2593,3971,3972,4682,6275,2236, # 4512 +4683,6276,6277,4684,6278,6279,4138,3973,4685,6280,6281,3258,6282,6283,6284,6285, # 4528 +3974,4686,2841,3975,6286,6287,3545,6288,6289,4139,4687,4140,6290,4141,6291,4142, # 4544 +6292,6293,3333,6294,6295,6296,4371,6297,3399,6298,6299,4372,3976,6300,6301,6302, # 4560 +4373,6303,6304,3843,3731,6305,4688,4374,6306,6307,3259,2294,6308,3732,2530,4143, # 4576 +6309,4689,6310,6311,6312,3048,6313,6314,4690,3733,2237,6315,6316,2282,3334,6317, # 4592 +6318,3844,6319,6320,4691,6321,3400,4692,6322,4693,6323,3049,6324,4375,6325,3977, # 4608 +6326,6327,6328,3546,6329,4694,3335,6330,4695,4696,6331,6332,6333,6334,4376,3978, # 4624 +6335,4697,3979,4144,6336,3980,4698,6337,6338,6339,6340,6341,4699,4700,4701,6342, # 4640 +6343,4702,6344,6345,4703,6346,6347,4704,6348,4705,4706,3135,6349,4707,6350,4708, # 4656 +6351,4377,6352,4709,3734,4145,6353,2506,4710,3189,6354,3050,4711,3981,6355,3547, # 4672 +3014,4146,4378,3735,2651,3845,3260,3136,2224,1986,6356,3401,6357,4712,2594,3627, # 4688 +3137,2573,3736,3982,4713,3628,4714,4715,2682,3629,4716,6358,3630,4379,3631,6359, # 4704 +6360,6361,3983,6362,6363,6364,6365,4147,3846,4717,6366,6367,3737,2842,6368,4718, # 4720 +2628,6369,3261,6370,2386,6371,6372,3738,3984,4719,3464,4720,3402,6373,2924,3336, # 4736 +4148,2866,6374,2805,3262,4380,2704,2069,2531,3138,2806,2984,6375,2769,6376,4721, # 4752 +4722,3403,6377,6378,3548,6379,6380,2705,3092,1979,4149,2629,3337,2889,6381,3338, # 4768 +4150,2557,3339,4381,6382,3190,3263,3739,6383,4151,4723,4152,2558,2574,3404,3191, # 4784 +6384,6385,4153,6386,4724,4382,6387,6388,4383,6389,6390,4154,6391,4725,3985,6392, # 4800 +3847,4155,6393,6394,6395,6396,6397,3465,6398,4384,6399,6400,6401,6402,6403,6404, # 4816 +4156,6405,6406,6407,6408,2123,6409,6410,2326,3192,4726,6411,6412,6413,6414,4385, # 4832 +4157,6415,6416,4158,6417,3093,3848,6418,3986,6419,6420,3849,6421,6422,6423,4159, # 4848 +6424,6425,4160,6426,3740,6427,6428,6429,6430,3987,6431,4727,6432,2238,6433,6434, # 4864 +4386,3988,6435,6436,3632,6437,6438,2843,6439,6440,6441,6442,3633,6443,2958,6444, # 4880 +6445,3466,6446,2364,4387,3850,6447,4388,2959,3340,6448,3851,6449,4728,6450,6451, # 4896 +3264,4729,6452,3193,6453,4389,4390,2706,3341,4730,6454,3139,6455,3194,6456,3051, # 4912 +2124,3852,1602,4391,4161,3853,1158,3854,4162,3989,4392,3990,4731,4732,4393,2040, # 4928 +4163,4394,3265,6457,2807,3467,3855,6458,6459,6460,3991,3468,4733,4734,6461,3140, # 4944 +2960,6462,4735,6463,6464,6465,6466,4736,4737,4738,4739,6467,6468,4164,2403,3856, # 4960 +6469,6470,2770,2844,6471,4740,6472,6473,6474,6475,6476,6477,6478,3195,6479,4741, # 4976 +4395,6480,2867,6481,4742,2808,6482,2493,4165,6483,6484,6485,6486,2295,4743,6487, # 4992 +6488,6489,3634,6490,6491,6492,6493,6494,6495,6496,2985,4744,6497,6498,4745,6499, # 5008 +6500,2925,3141,4166,6501,6502,4746,6503,6504,4747,6505,6506,6507,2890,6508,6509, # 5024 +6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,3469,4167,6520,6521,6522,4748, # 5040 +4396,3741,4397,4749,4398,3342,2125,4750,6523,4751,4752,4753,3052,6524,2961,4168, # 5056 +6525,4754,6526,4755,4399,2926,4169,6527,3857,6528,4400,4170,6529,4171,6530,6531, # 5072 +2595,6532,6533,6534,6535,3635,6536,6537,6538,6539,6540,6541,6542,4756,6543,6544, # 5088 +6545,6546,6547,6548,4401,6549,6550,6551,6552,4402,3405,4757,4403,6553,6554,6555, # 5104 +4172,3742,6556,6557,6558,3992,3636,6559,6560,3053,2726,6561,3549,4173,3054,4404, # 5120 +6562,6563,3993,4405,3266,3550,2809,4406,6564,6565,6566,4758,4759,6567,3743,6568, # 5136 +4760,3744,4761,3470,6569,6570,6571,4407,6572,3745,4174,6573,4175,2810,4176,3196, # 5152 +4762,6574,4177,6575,6576,2494,2891,3551,6577,6578,3471,6579,4408,6580,3015,3197, # 5168 +6581,3343,2532,3994,3858,6582,3094,3406,4409,6583,2892,4178,4763,4410,3016,4411, # 5184 +6584,3995,3142,3017,2683,6585,4179,6586,6587,4764,4412,6588,6589,4413,6590,2986, # 5200 +6591,2962,3552,6592,2963,3472,6593,6594,4180,4765,6595,6596,2225,3267,4414,6597, # 5216 +3407,3637,4766,6598,6599,3198,6600,4415,6601,3859,3199,6602,3473,4767,2811,4416, # 5232 +1856,3268,3200,2575,3996,3997,3201,4417,6603,3095,2927,6604,3143,6605,2268,6606, # 5248 +3998,3860,3096,2771,6607,6608,3638,2495,4768,6609,3861,6610,3269,2745,4769,4181, # 5264 +3553,6611,2845,3270,6612,6613,6614,3862,6615,6616,4770,4771,6617,3474,3999,4418, # 5280 +4419,6618,3639,3344,6619,4772,4182,6620,2126,6621,6622,6623,4420,4773,6624,3018, # 5296 +6625,4774,3554,6626,4183,2025,3746,6627,4184,2707,6628,4421,4422,3097,1775,4185, # 5312 +3555,6629,6630,2868,6631,6632,4423,6633,6634,4424,2414,2533,2928,6635,4186,2387, # 5328 +6636,4775,6637,4187,6638,1891,4425,3202,3203,6639,6640,4776,6641,3345,6642,6643, # 5344 +3640,6644,3475,3346,3641,4000,6645,3144,6646,3098,2812,4188,3642,3204,6647,3863, # 5360 +3476,6648,3864,6649,4426,4001,6650,6651,6652,2576,6653,4189,4777,6654,6655,6656, # 5376 +2846,6657,3477,3205,4002,6658,4003,6659,3347,2252,6660,6661,6662,4778,6663,6664, # 5392 +6665,6666,6667,6668,6669,4779,4780,2048,6670,3478,3099,6671,3556,3747,4004,6672, # 5408 +6673,6674,3145,4005,3748,6675,6676,6677,6678,6679,3408,6680,6681,6682,6683,3206, # 5424 +3207,6684,6685,4781,4427,6686,4782,4783,4784,6687,6688,6689,4190,6690,6691,3479, # 5440 +6692,2746,6693,4428,6694,6695,6696,6697,6698,6699,4785,6700,6701,3208,2727,6702, # 5456 +3146,6703,6704,3409,2196,6705,4429,6706,6707,6708,2534,1996,6709,6710,6711,2747, # 5472 +6712,6713,6714,4786,3643,6715,4430,4431,6716,3557,6717,4432,4433,6718,6719,6720, # 5488 +6721,3749,6722,4006,4787,6723,6724,3644,4788,4434,6725,6726,4789,2772,6727,6728, # 5504 +6729,6730,6731,2708,3865,2813,4435,6732,6733,4790,4791,3480,6734,6735,6736,6737, # 5520 +4436,3348,6738,3410,4007,6739,6740,4008,6741,6742,4792,3411,4191,6743,6744,6745, # 5536 +6746,6747,3866,6748,3750,6749,6750,6751,6752,6753,6754,6755,3867,6756,4009,6757, # 5552 +4793,4794,6758,2814,2987,6759,6760,6761,4437,6762,6763,6764,6765,3645,6766,6767, # 5568 +3481,4192,6768,3751,6769,6770,2174,6771,3868,3752,6772,6773,6774,4193,4795,4438, # 5584 +3558,4796,4439,6775,4797,6776,6777,4798,6778,4799,3559,4800,6779,6780,6781,3482, # 5600 +6782,2893,6783,6784,4194,4801,4010,6785,6786,4440,6787,4011,6788,6789,6790,6791, # 5616 +6792,6793,4802,6794,6795,6796,4012,6797,6798,6799,6800,3349,4803,3483,6801,4804, # 5632 +4195,6802,4013,6803,6804,4196,6805,4014,4015,6806,2847,3271,2848,6807,3484,6808, # 5648 +6809,6810,4441,6811,4442,4197,4443,3272,4805,6812,3412,4016,1579,6813,6814,4017, # 5664 +6815,3869,6816,2964,6817,4806,6818,6819,4018,3646,6820,6821,4807,4019,4020,6822, # 5680 +6823,3560,6824,6825,4021,4444,6826,4198,6827,6828,4445,6829,6830,4199,4808,6831, # 5696 +6832,6833,3870,3019,2458,6834,3753,3413,3350,6835,4809,3871,4810,3561,4446,6836, # 5712 +6837,4447,4811,4812,6838,2459,4448,6839,4449,6840,6841,4022,3872,6842,4813,4814, # 5728 +6843,6844,4815,4200,4201,4202,6845,4023,6846,6847,4450,3562,3873,6848,6849,4816, # 5744 +4817,6850,4451,4818,2139,6851,3563,6852,6853,3351,6854,6855,3352,4024,2709,3414, # 5760 +4203,4452,6856,4204,6857,6858,3874,3875,6859,6860,4819,6861,6862,6863,6864,4453, # 5776 +3647,6865,6866,4820,6867,6868,6869,6870,4454,6871,2869,6872,6873,4821,6874,3754, # 5792 +6875,4822,4205,6876,6877,6878,3648,4206,4455,6879,4823,6880,4824,3876,6881,3055, # 5808 +4207,6882,3415,6883,6884,6885,4208,4209,6886,4210,3353,6887,3354,3564,3209,3485, # 5824 +2652,6888,2728,6889,3210,3755,6890,4025,4456,6891,4825,6892,6893,6894,6895,4211, # 5840 +6896,6897,6898,4826,6899,6900,4212,6901,4827,6902,2773,3565,6903,4828,6904,6905, # 5856 +6906,6907,3649,3650,6908,2849,3566,6909,3567,3100,6910,6911,6912,6913,6914,6915, # 5872 +4026,6916,3355,4829,3056,4457,3756,6917,3651,6918,4213,3652,2870,6919,4458,6920, # 5888 +2438,6921,6922,3757,2774,4830,6923,3356,4831,4832,6924,4833,4459,3653,2507,6925, # 5904 +4834,2535,6926,6927,3273,4027,3147,6928,3568,6929,6930,6931,4460,6932,3877,4461, # 5920 +2729,3654,6933,6934,6935,6936,2175,4835,2630,4214,4028,4462,4836,4215,6937,3148, # 5936 +4216,4463,4837,4838,4217,6938,6939,2850,4839,6940,4464,6941,6942,6943,4840,6944, # 5952 +4218,3274,4465,6945,6946,2710,6947,4841,4466,6948,6949,2894,6950,6951,4842,6952, # 5968 +4219,3057,2871,6953,6954,6955,6956,4467,6957,2711,6958,6959,6960,3275,3101,4843, # 5984 +6961,3357,3569,6962,4844,6963,6964,4468,4845,3570,6965,3102,4846,3758,6966,4847, # 6000 +3878,4848,4849,4029,6967,2929,3879,4850,4851,6968,6969,1733,6970,4220,6971,6972, # 6016 +6973,6974,6975,6976,4852,6977,6978,6979,6980,6981,6982,3759,6983,6984,6985,3486, # 6032 +3487,6986,3488,3416,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,4853, # 6048 +6998,6999,4030,7000,7001,3211,7002,7003,4221,7004,7005,3571,4031,7006,3572,7007, # 6064 +2614,4854,2577,7008,7009,2965,3655,3656,4855,2775,3489,3880,4222,4856,3881,4032, # 6080 +3882,3657,2730,3490,4857,7010,3149,7011,4469,4858,2496,3491,4859,2283,7012,7013, # 6096 +7014,2365,4860,4470,7015,7016,3760,7017,7018,4223,1917,7019,7020,7021,4471,7022, # 6112 +2776,4472,7023,7024,7025,7026,4033,7027,3573,4224,4861,4034,4862,7028,7029,1929, # 6128 +3883,4035,7030,4473,3058,7031,2536,3761,3884,7032,4036,7033,2966,2895,1968,4474, # 6144 +3276,4225,3417,3492,4226,2105,7034,7035,1754,2596,3762,4227,4863,4475,3763,4864, # 6160 +3764,2615,2777,3103,3765,3658,3418,4865,2296,3766,2815,7036,7037,7038,3574,2872, # 6176 +3277,4476,7039,4037,4477,7040,7041,4038,7042,7043,7044,7045,7046,7047,2537,7048, # 6192 +7049,7050,7051,7052,7053,7054,4478,7055,7056,3767,3659,4228,3575,7057,7058,4229, # 6208 +7059,7060,7061,3660,7062,3212,7063,3885,4039,2460,7064,7065,7066,7067,7068,7069, # 6224 +7070,7071,7072,7073,7074,4866,3768,4867,7075,7076,7077,7078,4868,3358,3278,2653, # 6240 +7079,7080,4479,3886,7081,7082,4869,7083,7084,7085,7086,7087,7088,2538,7089,7090, # 6256 +7091,4040,3150,3769,4870,4041,2896,3359,4230,2930,7092,3279,7093,2967,4480,3213, # 6272 +4481,3661,7094,7095,7096,7097,7098,7099,7100,7101,7102,2461,3770,7103,7104,4231, # 6288 +3151,7105,7106,7107,4042,3662,7108,7109,4871,3663,4872,4043,3059,7110,7111,7112, # 6304 +3493,2988,7113,4873,7114,7115,7116,3771,4874,7117,7118,4232,4875,7119,3576,2336, # 6320 +4876,7120,4233,3419,4044,4877,4878,4482,4483,4879,4484,4234,7121,3772,4880,1045, # 6336 +3280,3664,4881,4882,7122,7123,7124,7125,4883,7126,2778,7127,4485,4486,7128,4884, # 6352 +3214,3887,7129,7130,3215,7131,4885,4045,7132,7133,4046,7134,7135,7136,7137,7138, # 6368 +7139,7140,7141,7142,7143,4235,7144,4886,7145,7146,7147,4887,7148,7149,7150,4487, # 6384 +4047,4488,7151,7152,4888,4048,2989,3888,7153,3665,7154,4049,7155,7156,7157,7158, # 6400 +7159,7160,2931,4889,4890,4489,7161,2631,3889,4236,2779,7162,7163,4891,7164,3060, # 6416 +7165,1672,4892,7166,4893,4237,3281,4894,7167,7168,3666,7169,3494,7170,7171,4050, # 6432 +7172,7173,3104,3360,3420,4490,4051,2684,4052,7174,4053,7175,7176,7177,2253,4054, # 6448 +7178,7179,4895,7180,3152,3890,3153,4491,3216,7181,7182,7183,2968,4238,4492,4055, # 6464 +7184,2990,7185,2479,7186,7187,4493,7188,7189,7190,7191,7192,4896,7193,4897,2969, # 6480 +4494,4898,7194,3495,7195,7196,4899,4495,7197,3105,2731,7198,4900,7199,7200,7201, # 6496 +4056,7202,3361,7203,7204,4496,4901,4902,7205,4497,7206,7207,2315,4903,7208,4904, # 6512 +7209,4905,2851,7210,7211,3577,7212,3578,4906,7213,4057,3667,4907,7214,4058,2354, # 6528 +3891,2376,3217,3773,7215,7216,7217,7218,7219,4498,7220,4908,3282,2685,7221,3496, # 6544 +4909,2632,3154,4910,7222,2337,7223,4911,7224,7225,7226,4912,4913,3283,4239,4499, # 6560 +7227,2816,7228,7229,7230,7231,7232,7233,7234,4914,4500,4501,7235,7236,7237,2686, # 6576 +7238,4915,7239,2897,4502,7240,4503,7241,2516,7242,4504,3362,3218,7243,7244,7245, # 6592 +4916,7246,7247,4505,3363,7248,7249,7250,7251,3774,4506,7252,7253,4917,7254,7255, # 6608 +3284,2991,4918,4919,3219,3892,4920,3106,3497,4921,7256,7257,7258,4922,7259,4923, # 6624 +3364,4507,4508,4059,7260,4240,3498,7261,7262,4924,7263,2992,3893,4060,3220,7264, # 6640 +7265,7266,7267,7268,7269,4509,3775,7270,2817,7271,4061,4925,4510,3776,7272,4241, # 6656 +4511,3285,7273,7274,3499,7275,7276,7277,4062,4512,4926,7278,3107,3894,7279,7280, # 6672 +4927,7281,4513,7282,7283,3668,7284,7285,4242,4514,4243,7286,2058,4515,4928,4929, # 6688 +4516,7287,3286,4244,7288,4517,7289,7290,7291,3669,7292,7293,4930,4931,4932,2355, # 6704 +4933,7294,2633,4518,7295,4245,7296,7297,4519,7298,7299,4520,4521,4934,7300,4246, # 6720 +4522,7301,7302,7303,3579,7304,4247,4935,7305,4936,7306,7307,7308,7309,3777,7310, # 6736 +4523,7311,7312,7313,4248,3580,7314,4524,3778,4249,7315,3581,7316,3287,7317,3221, # 6752 +7318,4937,7319,7320,7321,7322,7323,7324,4938,4939,7325,4525,7326,7327,7328,4063, # 6768 +7329,7330,4940,7331,7332,4941,7333,4526,7334,3500,2780,1741,4942,2026,1742,7335, # 6784 +7336,3582,4527,2388,7337,7338,7339,4528,7340,4250,4943,7341,7342,7343,4944,7344, # 6800 +7345,7346,3020,7347,4945,7348,7349,7350,7351,3895,7352,3896,4064,3897,7353,7354, # 6816 +7355,4251,7356,7357,3898,7358,3779,7359,3780,3288,7360,7361,4529,7362,4946,4530, # 6832 +2027,7363,3899,4531,4947,3222,3583,7364,4948,7365,7366,7367,7368,4949,3501,4950, # 6848 +3781,4951,4532,7369,2517,4952,4252,4953,3155,7370,4954,4955,4253,2518,4533,7371, # 6864 +7372,2712,4254,7373,7374,7375,3670,4956,3671,7376,2389,3502,4065,7377,2338,7378, # 6880 +7379,7380,7381,3061,7382,4957,7383,7384,7385,7386,4958,4534,7387,7388,2993,7389, # 6896 +3062,7390,4959,7391,7392,7393,4960,3108,4961,7394,4535,7395,4962,3421,4536,7396, # 6912 +4963,7397,4964,1857,7398,4965,7399,7400,2176,3584,4966,7401,7402,3422,4537,3900, # 6928 +3585,7403,3782,7404,2852,7405,7406,7407,4538,3783,2654,3423,4967,4539,7408,3784, # 6944 +3586,2853,4540,4541,7409,3901,7410,3902,7411,7412,3785,3109,2327,3903,7413,7414, # 6960 +2970,4066,2932,7415,7416,7417,3904,3672,3424,7418,4542,4543,4544,7419,4968,7420, # 6976 +7421,4255,7422,7423,7424,7425,7426,4067,7427,3673,3365,4545,7428,3110,2559,3674, # 6992 +7429,7430,3156,7431,7432,3503,7433,3425,4546,7434,3063,2873,7435,3223,4969,4547, # 7008 +4548,2898,4256,4068,7436,4069,3587,3786,2933,3787,4257,4970,4971,3788,7437,4972, # 7024 +3064,7438,4549,7439,7440,7441,7442,7443,4973,3905,7444,2874,7445,7446,7447,7448, # 7040 +3021,7449,4550,3906,3588,4974,7450,7451,3789,3675,7452,2578,7453,4070,7454,7455, # 7056 +7456,4258,3676,7457,4975,7458,4976,4259,3790,3504,2634,4977,3677,4551,4260,7459, # 7072 +7460,7461,7462,3907,4261,4978,7463,7464,7465,7466,4979,4980,7467,7468,2213,4262, # 7088 +7469,7470,7471,3678,4981,7472,2439,7473,4263,3224,3289,7474,3908,2415,4982,7475, # 7104 +4264,7476,4983,2655,7477,7478,2732,4552,2854,2875,7479,7480,4265,7481,4553,4984, # 7120 +7482,7483,4266,7484,3679,3366,3680,2818,2781,2782,3367,3589,4554,3065,7485,4071, # 7136 +2899,7486,7487,3157,2462,4072,4555,4073,4985,4986,3111,4267,2687,3368,4556,4074, # 7152 +3791,4268,7488,3909,2783,7489,2656,1962,3158,4557,4987,1963,3159,3160,7490,3112, # 7168 +4988,4989,3022,4990,4991,3792,2855,7491,7492,2971,4558,7493,7494,4992,7495,7496, # 7184 +7497,7498,4993,7499,3426,4559,4994,7500,3681,4560,4269,4270,3910,7501,4075,4995, # 7200 +4271,7502,7503,4076,7504,4996,7505,3225,4997,4272,4077,2819,3023,7506,7507,2733, # 7216 +4561,7508,4562,7509,3369,3793,7510,3590,2508,7511,7512,4273,3113,2994,2616,7513, # 7232 +7514,7515,7516,7517,7518,2820,3911,4078,2748,7519,7520,4563,4998,7521,7522,7523, # 7248 +7524,4999,4274,7525,4564,3682,2239,4079,4565,7526,7527,7528,7529,5000,7530,7531, # 7264 +5001,4275,3794,7532,7533,7534,3066,5002,4566,3161,7535,7536,4080,7537,3162,7538, # 7280 +7539,4567,7540,7541,7542,7543,7544,7545,5003,7546,4568,7547,7548,7549,7550,7551, # 7296 +7552,7553,7554,7555,7556,5004,7557,7558,7559,5005,7560,3795,7561,4569,7562,7563, # 7312 +7564,2821,3796,4276,4277,4081,7565,2876,7566,5006,7567,7568,2900,7569,3797,3912, # 7328 +7570,7571,7572,4278,7573,7574,7575,5007,7576,7577,5008,7578,7579,4279,2934,7580, # 7344 +7581,5009,7582,4570,7583,4280,7584,7585,7586,4571,4572,3913,7587,4573,3505,7588, # 7360 +5010,7589,7590,7591,7592,3798,4574,7593,7594,5011,7595,4281,7596,7597,7598,4282, # 7376 +5012,7599,7600,5013,3163,7601,5014,7602,3914,7603,7604,2734,4575,4576,4577,7605, # 7392 +7606,7607,7608,7609,3506,5015,4578,7610,4082,7611,2822,2901,2579,3683,3024,4579, # 7408 +3507,7612,4580,7613,3226,3799,5016,7614,7615,7616,7617,7618,7619,7620,2995,3290, # 7424 +7621,4083,7622,5017,7623,7624,7625,7626,7627,4581,3915,7628,3291,7629,5018,7630, # 7440 +7631,7632,7633,4084,7634,7635,3427,3800,7636,7637,4582,7638,5019,4583,5020,7639, # 7456 +3916,7640,3801,5021,4584,4283,7641,7642,3428,3591,2269,7643,2617,7644,4585,3592, # 7472 +7645,4586,2902,7646,7647,3227,5022,7648,4587,7649,4284,7650,7651,7652,4588,2284, # 7488 +7653,5023,7654,7655,7656,4589,5024,3802,7657,7658,5025,3508,4590,7659,7660,7661, # 7504 +1969,5026,7662,7663,3684,1821,2688,7664,2028,2509,4285,7665,2823,1841,7666,2689, # 7520 +3114,7667,3917,4085,2160,5027,5028,2972,7668,5029,7669,7670,7671,3593,4086,7672, # 7536 +4591,4087,5030,3803,7673,7674,7675,7676,7677,7678,7679,4286,2366,4592,4593,3067, # 7552 +2328,7680,7681,4594,3594,3918,2029,4287,7682,5031,3919,3370,4288,4595,2856,7683, # 7568 +3509,7684,7685,5032,5033,7686,7687,3804,2784,7688,7689,7690,7691,3371,7692,7693, # 7584 +2877,5034,7694,7695,3920,4289,4088,7696,7697,7698,5035,7699,5036,4290,5037,5038, # 7600 +5039,7700,7701,7702,5040,5041,3228,7703,1760,7704,5042,3229,4596,2106,4089,7705, # 7616 +4597,2824,5043,2107,3372,7706,4291,4090,5044,7707,4091,7708,5045,3025,3805,4598, # 7632 +4292,4293,4294,3373,7709,4599,7710,5046,7711,7712,5047,5048,3806,7713,7714,7715, # 7648 +5049,7716,7717,7718,7719,4600,5050,7720,7721,7722,5051,7723,4295,3429,7724,7725, # 7664 +7726,7727,3921,7728,3292,5052,4092,7729,7730,7731,7732,7733,7734,7735,5053,5054, # 7680 +7736,7737,7738,7739,3922,3685,7740,7741,7742,7743,2635,5055,7744,5056,4601,7745, # 7696 +7746,2560,7747,7748,7749,7750,3923,7751,7752,7753,7754,7755,4296,2903,7756,7757, # 7712 +7758,7759,7760,3924,7761,5057,4297,7762,7763,5058,4298,7764,4093,7765,7766,5059, # 7728 +3925,7767,7768,7769,7770,7771,7772,7773,7774,7775,7776,3595,7777,4299,5060,4094, # 7744 +7778,3293,5061,7779,7780,4300,7781,7782,4602,7783,3596,7784,7785,3430,2367,7786, # 7760 +3164,5062,5063,4301,7787,7788,4095,5064,5065,7789,3374,3115,7790,7791,7792,7793, # 7776 +7794,7795,7796,3597,4603,7797,7798,3686,3116,3807,5066,7799,7800,5067,7801,7802, # 7792 +4604,4302,5068,4303,4096,7803,7804,3294,7805,7806,5069,4605,2690,7807,3026,7808, # 7808 +7809,7810,7811,7812,7813,7814,7815,7816,7817,7818,7819,7820,7821,7822,7823,7824, # 7824 +7825,7826,7827,7828,7829,7830,7831,7832,7833,7834,7835,7836,7837,7838,7839,7840, # 7840 +7841,7842,7843,7844,7845,7846,7847,7848,7849,7850,7851,7852,7853,7854,7855,7856, # 7856 +7857,7858,7859,7860,7861,7862,7863,7864,7865,7866,7867,7868,7869,7870,7871,7872, # 7872 +7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886,7887,7888, # 7888 +7889,7890,7891,7892,7893,7894,7895,7896,7897,7898,7899,7900,7901,7902,7903,7904, # 7904 +7905,7906,7907,7908,7909,7910,7911,7912,7913,7914,7915,7916,7917,7918,7919,7920, # 7920 +7921,7922,7923,7924,3926,7925,7926,7927,7928,7929,7930,7931,7932,7933,7934,7935, # 7936 +7936,7937,7938,7939,7940,7941,7942,7943,7944,7945,7946,7947,7948,7949,7950,7951, # 7952 +7952,7953,7954,7955,7956,7957,7958,7959,7960,7961,7962,7963,7964,7965,7966,7967, # 7968 +7968,7969,7970,7971,7972,7973,7974,7975,7976,7977,7978,7979,7980,7981,7982,7983, # 7984 +7984,7985,7986,7987,7988,7989,7990,7991,7992,7993,7994,7995,7996,7997,7998,7999, # 8000 +8000,8001,8002,8003,8004,8005,8006,8007,8008,8009,8010,8011,8012,8013,8014,8015, # 8016 +8016,8017,8018,8019,8020,8021,8022,8023,8024,8025,8026,8027,8028,8029,8030,8031, # 8032 +8032,8033,8034,8035,8036,8037,8038,8039,8040,8041,8042,8043,8044,8045,8046,8047, # 8048 +8048,8049,8050,8051,8052,8053,8054,8055,8056,8057,8058,8059,8060,8061,8062,8063, # 8064 +8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079, # 8080 +8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095, # 8096 +8096,8097,8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110,8111, # 8112 +8112,8113,8114,8115,8116,8117,8118,8119,8120,8121,8122,8123,8124,8125,8126,8127, # 8128 +8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,8138,8139,8140,8141,8142,8143, # 8144 +8144,8145,8146,8147,8148,8149,8150,8151,8152,8153,8154,8155,8156,8157,8158,8159, # 8160 +8160,8161,8162,8163,8164,8165,8166,8167,8168,8169,8170,8171,8172,8173,8174,8175, # 8176 +8176,8177,8178,8179,8180,8181,8182,8183,8184,8185,8186,8187,8188,8189,8190,8191, # 8192 +8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207, # 8208 +8208,8209,8210,8211,8212,8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223, # 8224 +8224,8225,8226,8227,8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239, # 8240 +8240,8241,8242,8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,8255, # 8256 +8256,8257,8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,8270,8271) # 8272 + +# flake8: noqa diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/jpcntx.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/jpcntx.py new file mode 100644 index 0000000000..e4e9e4da51 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/jpcntx.py @@ -0,0 +1,219 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .compat import wrap_ord + +NUM_OF_CATEGORY = 6 +DONT_KNOW = -1 +ENOUGH_REL_THRESHOLD = 100 +MAX_REL_THRESHOLD = 1000 +MINIMUM_DATA_THRESHOLD = 4 + +# This is hiragana 2-char sequence table, the number in each cell represents its frequency category +jp2CharContext = ( +(0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1), +(2,4,0,4,0,3,0,4,0,3,4,4,4,2,4,3,3,4,3,2,3,3,4,2,3,3,3,2,4,1,4,3,3,1,5,4,3,4,3,4,3,5,3,0,3,5,4,2,0,3,1,0,3,3,0,3,3,0,1,1,0,4,3,0,3,3,0,4,0,2,0,3,5,5,5,5,4,0,4,1,0,3,4), +(0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2), +(0,4,0,5,0,5,0,4,0,4,5,4,4,3,5,3,5,1,5,3,4,3,4,4,3,4,3,3,4,3,5,4,4,3,5,5,3,5,5,5,3,5,5,3,4,5,5,3,1,3,2,0,3,4,0,4,2,0,4,2,1,5,3,2,3,5,0,4,0,2,0,5,4,4,5,4,5,0,4,0,0,4,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,4,0,3,0,3,0,4,5,4,3,3,3,3,4,3,5,4,4,3,5,4,4,3,4,3,4,4,4,4,5,3,4,4,3,4,5,5,4,5,5,1,4,5,4,3,0,3,3,1,3,3,0,4,4,0,3,3,1,5,3,3,3,5,0,4,0,3,0,4,4,3,4,3,3,0,4,1,1,3,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,4,0,3,0,3,0,4,0,3,4,4,3,2,2,1,2,1,3,1,3,3,3,3,3,4,3,1,3,3,5,3,3,0,4,3,0,5,4,3,3,5,4,4,3,4,4,5,0,1,2,0,1,2,0,2,2,0,1,0,0,5,2,2,1,4,0,3,0,1,0,4,4,3,5,4,3,0,2,1,0,4,3), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,5,0,4,0,2,1,4,4,2,4,1,4,2,4,2,4,3,3,3,4,3,3,3,3,1,4,2,3,3,3,1,4,4,1,1,1,4,3,3,2,0,2,4,3,2,0,3,3,0,3,1,1,0,0,0,3,3,0,4,2,2,3,4,0,4,0,3,0,4,4,5,3,4,4,0,3,0,0,1,4), +(1,4,0,4,0,4,0,4,0,3,5,4,4,3,4,3,5,4,3,3,4,3,5,4,4,4,4,3,4,2,4,3,3,1,5,4,3,2,4,5,4,5,5,4,4,5,4,4,0,3,2,2,3,3,0,4,3,1,3,2,1,4,3,3,4,5,0,3,0,2,0,4,5,5,4,5,4,0,4,0,0,5,4), +(0,5,0,5,0,4,0,3,0,4,4,3,4,3,3,3,4,0,4,4,4,3,4,3,4,3,3,1,4,2,4,3,4,0,5,4,1,4,5,4,4,5,3,2,4,3,4,3,2,4,1,3,3,3,2,3,2,0,4,3,3,4,3,3,3,4,0,4,0,3,0,4,5,4,4,4,3,0,4,1,0,1,3), +(0,3,1,4,0,3,0,2,0,3,4,4,3,1,4,2,3,3,4,3,4,3,4,3,4,4,3,2,3,1,5,4,4,1,4,4,3,5,4,4,3,5,5,4,3,4,4,3,1,2,3,1,2,2,0,3,2,0,3,1,0,5,3,3,3,4,3,3,3,3,4,4,4,4,5,4,2,0,3,3,2,4,3), +(0,2,0,3,0,1,0,1,0,0,3,2,0,0,2,0,1,0,2,1,3,3,3,1,2,3,1,0,1,0,4,2,1,1,3,3,0,4,3,3,1,4,3,3,0,3,3,2,0,0,0,0,1,0,0,2,0,0,0,0,0,4,1,0,2,3,2,2,2,1,3,3,3,4,4,3,2,0,3,1,0,3,3), +(0,4,0,4,0,3,0,3,0,4,4,4,3,3,3,3,3,3,4,3,4,2,4,3,4,3,3,2,4,3,4,5,4,1,4,5,3,5,4,5,3,5,4,0,3,5,5,3,1,3,3,2,2,3,0,3,4,1,3,3,2,4,3,3,3,4,0,4,0,3,0,4,5,4,4,5,3,0,4,1,0,3,4), +(0,2,0,3,0,3,0,0,0,2,2,2,1,0,1,0,0,0,3,0,3,0,3,0,1,3,1,0,3,1,3,3,3,1,3,3,3,0,1,3,1,3,4,0,0,3,1,1,0,3,2,0,0,0,0,1,3,0,1,0,0,3,3,2,0,3,0,0,0,0,0,3,4,3,4,3,3,0,3,0,0,2,3), +(2,3,0,3,0,2,0,1,0,3,3,4,3,1,3,1,1,1,3,1,4,3,4,3,3,3,0,0,3,1,5,4,3,1,4,3,2,5,5,4,4,4,4,3,3,4,4,4,0,2,1,1,3,2,0,1,2,0,0,1,0,4,1,3,3,3,0,3,0,1,0,4,4,4,5,5,3,0,2,0,0,4,4), +(0,2,0,1,0,3,1,3,0,2,3,3,3,0,3,1,0,0,3,0,3,2,3,1,3,2,1,1,0,0,4,2,1,0,2,3,1,4,3,2,0,4,4,3,1,3,1,3,0,1,0,0,1,0,0,0,1,0,0,0,0,4,1,1,1,2,0,3,0,0,0,3,4,2,4,3,2,0,1,0,0,3,3), +(0,1,0,4,0,5,0,4,0,2,4,4,2,3,3,2,3,3,5,3,3,3,4,3,4,2,3,0,4,3,3,3,4,1,4,3,2,1,5,5,3,4,5,1,3,5,4,2,0,3,3,0,1,3,0,4,2,0,1,3,1,4,3,3,3,3,0,3,0,1,0,3,4,4,4,5,5,0,3,0,1,4,5), +(0,2,0,3,0,3,0,0,0,2,3,1,3,0,4,0,1,1,3,0,3,4,3,2,3,1,0,3,3,2,3,1,3,0,2,3,0,2,1,4,1,2,2,0,0,3,3,0,0,2,0,0,0,1,0,0,0,0,2,2,0,3,2,1,3,3,0,2,0,2,0,0,3,3,1,2,4,0,3,0,2,2,3), +(2,4,0,5,0,4,0,4,0,2,4,4,4,3,4,3,3,3,1,2,4,3,4,3,4,4,5,0,3,3,3,3,2,0,4,3,1,4,3,4,1,4,4,3,3,4,4,3,1,2,3,0,4,2,0,4,1,0,3,3,0,4,3,3,3,4,0,4,0,2,0,3,5,3,4,5,2,0,3,0,0,4,5), +(0,3,0,4,0,1,0,1,0,1,3,2,2,1,3,0,3,0,2,0,2,0,3,0,2,0,0,0,1,0,1,1,0,0,3,1,0,0,0,4,0,3,1,0,2,1,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,4,2,2,3,1,0,3,0,0,0,1,4,4,4,3,0,0,4,0,0,1,4), +(1,4,1,5,0,3,0,3,0,4,5,4,4,3,5,3,3,4,4,3,4,1,3,3,3,3,2,1,4,1,5,4,3,1,4,4,3,5,4,4,3,5,4,3,3,4,4,4,0,3,3,1,2,3,0,3,1,0,3,3,0,5,4,4,4,4,4,4,3,3,5,4,4,3,3,5,4,0,3,2,0,4,4), +(0,2,0,3,0,1,0,0,0,1,3,3,3,2,4,1,3,0,3,1,3,0,2,2,1,1,0,0,2,0,4,3,1,0,4,3,0,4,4,4,1,4,3,1,1,3,3,1,0,2,0,0,1,3,0,0,0,0,2,0,0,4,3,2,4,3,5,4,3,3,3,4,3,3,4,3,3,0,2,1,0,3,3), +(0,2,0,4,0,3,0,2,0,2,5,5,3,4,4,4,4,1,4,3,3,0,4,3,4,3,1,3,3,2,4,3,0,3,4,3,0,3,4,4,2,4,4,0,4,5,3,3,2,2,1,1,1,2,0,1,5,0,3,3,2,4,3,3,3,4,0,3,0,2,0,4,4,3,5,5,0,0,3,0,2,3,3), +(0,3,0,4,0,3,0,1,0,3,4,3,3,1,3,3,3,0,3,1,3,0,4,3,3,1,1,0,3,0,3,3,0,0,4,4,0,1,5,4,3,3,5,0,3,3,4,3,0,2,0,1,1,1,0,1,3,0,1,2,1,3,3,2,3,3,0,3,0,1,0,1,3,3,4,4,1,0,1,2,2,1,3), +(0,1,0,4,0,4,0,3,0,1,3,3,3,2,3,1,1,0,3,0,3,3,4,3,2,4,2,0,1,0,4,3,2,0,4,3,0,5,3,3,2,4,4,4,3,3,3,4,0,1,3,0,0,1,0,0,1,0,0,0,0,4,2,3,3,3,0,3,0,0,0,4,4,4,5,3,2,0,3,3,0,3,5), +(0,2,0,3,0,0,0,3,0,1,3,0,2,0,0,0,1,0,3,1,1,3,3,0,0,3,0,0,3,0,2,3,1,0,3,1,0,3,3,2,0,4,2,2,0,2,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,2,1,2,0,1,0,1,0,0,0,1,3,1,2,0,0,0,1,0,0,1,4), +(0,3,0,3,0,5,0,1,0,2,4,3,1,3,3,2,1,1,5,2,1,0,5,1,2,0,0,0,3,3,2,2,3,2,4,3,0,0,3,3,1,3,3,0,2,5,3,4,0,3,3,0,1,2,0,2,2,0,3,2,0,2,2,3,3,3,0,2,0,1,0,3,4,4,2,5,4,0,3,0,0,3,5), +(0,3,0,3,0,3,0,1,0,3,3,3,3,0,3,0,2,0,2,1,1,0,2,0,1,0,0,0,2,1,0,0,1,0,3,2,0,0,3,3,1,2,3,1,0,3,3,0,0,1,0,0,0,0,0,2,0,0,0,0,0,2,3,1,2,3,0,3,0,1,0,3,2,1,0,4,3,0,1,1,0,3,3), +(0,4,0,5,0,3,0,3,0,4,5,5,4,3,5,3,4,3,5,3,3,2,5,3,4,4,4,3,4,3,4,5,5,3,4,4,3,4,4,5,4,4,4,3,4,5,5,4,2,3,4,2,3,4,0,3,3,1,4,3,2,4,3,3,5,5,0,3,0,3,0,5,5,5,5,4,4,0,4,0,1,4,4), +(0,4,0,4,0,3,0,3,0,3,5,4,4,2,3,2,5,1,3,2,5,1,4,2,3,2,3,3,4,3,3,3,3,2,5,4,1,3,3,5,3,4,4,0,4,4,3,1,1,3,1,0,2,3,0,2,3,0,3,0,0,4,3,1,3,4,0,3,0,2,0,4,4,4,3,4,5,0,4,0,0,3,4), +(0,3,0,3,0,3,1,2,0,3,4,4,3,3,3,0,2,2,4,3,3,1,3,3,3,1,1,0,3,1,4,3,2,3,4,4,2,4,4,4,3,4,4,3,2,4,4,3,1,3,3,1,3,3,0,4,1,0,2,2,1,4,3,2,3,3,5,4,3,3,5,4,4,3,3,0,4,0,3,2,2,4,4), +(0,2,0,1,0,0,0,0,0,1,2,1,3,0,0,0,0,0,2,0,1,2,1,0,0,1,0,0,0,0,3,0,0,1,0,1,1,3,1,0,0,0,1,1,0,1,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,1,2,2,0,3,4,0,0,0,1,1,0,0,1,0,0,0,0,0,1,1), +(0,1,0,0,0,1,0,0,0,0,4,0,4,1,4,0,3,0,4,0,3,0,4,0,3,0,3,0,4,1,5,1,4,0,0,3,0,5,0,5,2,0,1,0,0,0,2,1,4,0,1,3,0,0,3,0,0,3,1,1,4,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0), +(1,4,0,5,0,3,0,2,0,3,5,4,4,3,4,3,5,3,4,3,3,0,4,3,3,3,3,3,3,2,4,4,3,1,3,4,4,5,4,4,3,4,4,1,3,5,4,3,3,3,1,2,2,3,3,1,3,1,3,3,3,5,3,3,4,5,0,3,0,3,0,3,4,3,4,4,3,0,3,0,2,4,3), +(0,1,0,4,0,0,0,0,0,1,4,0,4,1,4,2,4,0,3,0,1,0,1,0,0,0,0,0,2,0,3,1,1,1,0,3,0,0,0,1,2,1,0,0,1,1,1,1,0,1,0,0,0,1,0,0,3,0,0,0,0,3,2,0,2,2,0,1,0,0,0,2,3,2,3,3,0,0,0,0,2,1,0), +(0,5,1,5,0,3,0,3,0,5,4,4,5,1,5,3,3,0,4,3,4,3,5,3,4,3,3,2,4,3,4,3,3,0,3,3,1,4,4,3,4,4,4,3,4,5,5,3,2,3,1,1,3,3,1,3,1,1,3,3,2,4,5,3,3,5,0,4,0,3,0,4,4,3,5,3,3,0,3,4,0,4,3), +(0,5,0,5,0,3,0,2,0,4,4,3,5,2,4,3,3,3,4,4,4,3,5,3,5,3,3,1,4,0,4,3,3,0,3,3,0,4,4,4,4,5,4,3,3,5,5,3,2,3,1,2,3,2,0,1,0,0,3,2,2,4,4,3,1,5,0,4,0,3,0,4,3,1,3,2,1,0,3,3,0,3,3), +(0,4,0,5,0,5,0,4,0,4,5,5,5,3,4,3,3,2,5,4,4,3,5,3,5,3,4,0,4,3,4,4,3,2,4,4,3,4,5,4,4,5,5,0,3,5,5,4,1,3,3,2,3,3,1,3,1,0,4,3,1,4,4,3,4,5,0,4,0,2,0,4,3,4,4,3,3,0,4,0,0,5,5), +(0,4,0,4,0,5,0,1,1,3,3,4,4,3,4,1,3,0,5,1,3,0,3,1,3,1,1,0,3,0,3,3,4,0,4,3,0,4,4,4,3,4,4,0,3,5,4,1,0,3,0,0,2,3,0,3,1,0,3,1,0,3,2,1,3,5,0,3,0,1,0,3,2,3,3,4,4,0,2,2,0,4,4), +(2,4,0,5,0,4,0,3,0,4,5,5,4,3,5,3,5,3,5,3,5,2,5,3,4,3,3,4,3,4,5,3,2,1,5,4,3,2,3,4,5,3,4,1,2,5,4,3,0,3,3,0,3,2,0,2,3,0,4,1,0,3,4,3,3,5,0,3,0,1,0,4,5,5,5,4,3,0,4,2,0,3,5), +(0,5,0,4,0,4,0,2,0,5,4,3,4,3,4,3,3,3,4,3,4,2,5,3,5,3,4,1,4,3,4,4,4,0,3,5,0,4,4,4,4,5,3,1,3,4,5,3,3,3,3,3,3,3,0,2,2,0,3,3,2,4,3,3,3,5,3,4,1,3,3,5,3,2,0,0,0,0,4,3,1,3,3), +(0,1,0,3,0,3,0,1,0,1,3,3,3,2,3,3,3,0,3,0,0,0,3,1,3,0,0,0,2,2,2,3,0,0,3,2,0,1,2,4,1,3,3,0,0,3,3,3,0,1,0,0,2,1,0,0,3,0,3,1,0,3,0,0,1,3,0,2,0,1,0,3,3,1,3,3,0,0,1,1,0,3,3), +(0,2,0,3,0,2,1,4,0,2,2,3,1,1,3,1,1,0,2,0,3,1,2,3,1,3,0,0,1,0,4,3,2,3,3,3,1,4,2,3,3,3,3,1,0,3,1,4,0,1,1,0,1,2,0,1,1,0,1,1,0,3,1,3,2,2,0,1,0,0,0,2,3,3,3,1,0,0,0,0,0,2,3), +(0,5,0,4,0,5,0,2,0,4,5,5,3,3,4,3,3,1,5,4,4,2,4,4,4,3,4,2,4,3,5,5,4,3,3,4,3,3,5,5,4,5,5,1,3,4,5,3,1,4,3,1,3,3,0,3,3,1,4,3,1,4,5,3,3,5,0,4,0,3,0,5,3,3,1,4,3,0,4,0,1,5,3), +(0,5,0,5,0,4,0,2,0,4,4,3,4,3,3,3,3,3,5,4,4,4,4,4,4,5,3,3,5,2,4,4,4,3,4,4,3,3,4,4,5,5,3,3,4,3,4,3,3,4,3,3,3,3,1,2,2,1,4,3,3,5,4,4,3,4,0,4,0,3,0,4,4,4,4,4,1,0,4,2,0,2,4), +(0,4,0,4,0,3,0,1,0,3,5,2,3,0,3,0,2,1,4,2,3,3,4,1,4,3,3,2,4,1,3,3,3,0,3,3,0,0,3,3,3,5,3,3,3,3,3,2,0,2,0,0,2,0,0,2,0,0,1,0,0,3,1,2,2,3,0,3,0,2,0,4,4,3,3,4,1,0,3,0,0,2,4), +(0,0,0,4,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,1,0,2,0,1,0,0,0,0,0,3,1,3,0,3,2,0,0,0,1,0,3,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,4,0,2,0,0,0,0,0,0,2), +(0,2,1,3,0,2,0,2,0,3,3,3,3,1,3,1,3,3,3,3,3,3,4,2,2,1,2,1,4,0,4,3,1,3,3,3,2,4,3,5,4,3,3,3,3,3,3,3,0,1,3,0,2,0,0,1,0,0,1,0,0,4,2,0,2,3,0,3,3,0,3,3,4,2,3,1,4,0,1,2,0,2,3), +(0,3,0,3,0,1,0,3,0,2,3,3,3,0,3,1,2,0,3,3,2,3,3,2,3,2,3,1,3,0,4,3,2,0,3,3,1,4,3,3,2,3,4,3,1,3,3,1,1,0,1,1,0,1,0,1,0,1,0,0,0,4,1,1,0,3,0,3,1,0,2,3,3,3,3,3,1,0,0,2,0,3,3), +(0,0,0,0,0,0,0,0,0,0,3,0,2,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,3,0,3,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,2,0,2,3,0,0,0,0,0,0,0,0,3), +(0,2,0,3,1,3,0,3,0,2,3,3,3,1,3,1,3,1,3,1,3,3,3,1,3,0,2,3,1,1,4,3,3,2,3,3,1,2,2,4,1,3,3,0,1,4,2,3,0,1,3,0,3,0,0,1,3,0,2,0,0,3,3,2,1,3,0,3,0,2,0,3,4,4,4,3,1,0,3,0,0,3,3), +(0,2,0,1,0,2,0,0,0,1,3,2,2,1,3,0,1,1,3,0,3,2,3,1,2,0,2,0,1,1,3,3,3,0,3,3,1,1,2,3,2,3,3,1,2,3,2,0,0,1,0,0,0,0,0,0,3,0,1,0,0,2,1,2,1,3,0,3,0,0,0,3,4,4,4,3,2,0,2,0,0,2,4), +(0,0,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,3,1,0,0,0,0,0,0,0,3), +(0,3,0,3,0,2,0,3,0,3,3,3,2,3,2,2,2,0,3,1,3,3,3,2,3,3,0,0,3,0,3,2,2,0,2,3,1,4,3,4,3,3,2,3,1,5,4,4,0,3,1,2,1,3,0,3,1,1,2,0,2,3,1,3,1,3,0,3,0,1,0,3,3,4,4,2,1,0,2,1,0,2,4), +(0,1,0,3,0,1,0,2,0,1,4,2,5,1,4,0,2,0,2,1,3,1,4,0,2,1,0,0,2,1,4,1,1,0,3,3,0,5,1,3,2,3,3,1,0,3,2,3,0,1,0,0,0,0,0,0,1,0,0,0,0,4,0,1,0,3,0,2,0,1,0,3,3,3,4,3,3,0,0,0,0,2,3), +(0,0,0,1,0,0,0,0,0,0,2,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,0,0,1,0,0,0,0,0,3), +(0,1,0,3,0,4,0,3,0,2,4,3,1,0,3,2,2,1,3,1,2,2,3,1,1,1,2,1,3,0,1,2,0,1,3,2,1,3,0,5,5,1,0,0,1,3,2,1,0,3,0,0,1,0,0,0,0,0,3,4,0,1,1,1,3,2,0,2,0,1,0,2,3,3,1,2,3,0,1,0,1,0,4), +(0,0,0,1,0,3,0,3,0,2,2,1,0,0,4,0,3,0,3,1,3,0,3,0,3,0,1,0,3,0,3,1,3,0,3,3,0,0,1,2,1,1,1,0,1,2,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,2,2,1,2,0,0,2,0,0,0,0,2,3,3,3,3,0,0,0,0,1,4), +(0,0,0,3,0,3,0,0,0,0,3,1,1,0,3,0,1,0,2,0,1,0,0,0,0,0,0,0,1,0,3,0,2,0,2,3,0,0,2,2,3,1,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,2,3), +(2,4,0,5,0,5,0,4,0,3,4,3,3,3,4,3,3,3,4,3,4,4,5,4,5,5,5,2,3,0,5,5,4,1,5,4,3,1,5,4,3,4,4,3,3,4,3,3,0,3,2,0,2,3,0,3,0,0,3,3,0,5,3,2,3,3,0,3,0,3,0,3,4,5,4,5,3,0,4,3,0,3,4), +(0,3,0,3,0,3,0,3,0,3,3,4,3,2,3,2,3,0,4,3,3,3,3,3,3,3,3,0,3,2,4,3,3,1,3,4,3,4,4,4,3,4,4,3,2,4,4,1,0,2,0,0,1,1,0,2,0,0,3,1,0,5,3,2,1,3,0,3,0,1,2,4,3,2,4,3,3,0,3,2,0,4,4), +(0,3,0,3,0,1,0,0,0,1,4,3,3,2,3,1,3,1,4,2,3,2,4,2,3,4,3,0,2,2,3,3,3,0,3,3,3,0,3,4,1,3,3,0,3,4,3,3,0,1,1,0,1,0,0,0,4,0,3,0,0,3,1,2,1,3,0,4,0,1,0,4,3,3,4,3,3,0,2,0,0,3,3), +(0,3,0,4,0,1,0,3,0,3,4,3,3,0,3,3,3,1,3,1,3,3,4,3,3,3,0,0,3,1,5,3,3,1,3,3,2,5,4,3,3,4,5,3,2,5,3,4,0,1,0,0,0,0,0,2,0,0,1,1,0,4,2,2,1,3,0,3,0,2,0,4,4,3,5,3,2,0,1,1,0,3,4), +(0,5,0,4,0,5,0,2,0,4,4,3,3,2,3,3,3,1,4,3,4,1,5,3,4,3,4,0,4,2,4,3,4,1,5,4,0,4,4,4,4,5,4,1,3,5,4,2,1,4,1,1,3,2,0,3,1,0,3,2,1,4,3,3,3,4,0,4,0,3,0,4,4,4,3,3,3,0,4,2,0,3,4), +(1,4,0,4,0,3,0,1,0,3,3,3,1,1,3,3,2,2,3,3,1,0,3,2,2,1,2,0,3,1,2,1,2,0,3,2,0,2,2,3,3,4,3,0,3,3,1,2,0,1,1,3,1,2,0,0,3,0,1,1,0,3,2,2,3,3,0,3,0,0,0,2,3,3,4,3,3,0,1,0,0,1,4), +(0,4,0,4,0,4,0,0,0,3,4,4,3,1,4,2,3,2,3,3,3,1,4,3,4,0,3,0,4,2,3,3,2,2,5,4,2,1,3,4,3,4,3,1,3,3,4,2,0,2,1,0,3,3,0,0,2,0,3,1,0,4,4,3,4,3,0,4,0,1,0,2,4,4,4,4,4,0,3,2,0,3,3), +(0,0,0,1,0,4,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,3,2,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2), +(0,2,0,3,0,4,0,4,0,1,3,3,3,0,4,0,2,1,2,1,1,1,2,0,3,1,1,0,1,0,3,1,0,0,3,3,2,0,1,1,0,0,0,0,0,1,0,2,0,2,2,0,3,1,0,0,1,0,1,1,0,1,2,0,3,0,0,0,0,1,0,0,3,3,4,3,1,0,1,0,3,0,2), +(0,0,0,3,0,5,0,0,0,0,1,0,2,0,3,1,0,1,3,0,0,0,2,0,0,0,1,0,0,0,1,1,0,0,4,0,0,0,2,3,0,1,4,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,3,0,0,0,0,0,3), +(0,2,0,5,0,5,0,1,0,2,4,3,3,2,5,1,3,2,3,3,3,0,4,1,2,0,3,0,4,0,2,2,1,1,5,3,0,0,1,4,2,3,2,0,3,3,3,2,0,2,4,1,1,2,0,1,1,0,3,1,0,1,3,1,2,3,0,2,0,0,0,1,3,5,4,4,4,0,3,0,0,1,3), +(0,4,0,5,0,4,0,4,0,4,5,4,3,3,4,3,3,3,4,3,4,4,5,3,4,5,4,2,4,2,3,4,3,1,4,4,1,3,5,4,4,5,5,4,4,5,5,5,2,3,3,1,4,3,1,3,3,0,3,3,1,4,3,4,4,4,0,3,0,4,0,3,3,4,4,5,0,0,4,3,0,4,5), +(0,4,0,4,0,3,0,3,0,3,4,4,4,3,3,2,4,3,4,3,4,3,5,3,4,3,2,1,4,2,4,4,3,1,3,4,2,4,5,5,3,4,5,4,1,5,4,3,0,3,2,2,3,2,1,3,1,0,3,3,3,5,3,3,3,5,4,4,2,3,3,4,3,3,3,2,1,0,3,2,1,4,3), +(0,4,0,5,0,4,0,3,0,3,5,5,3,2,4,3,4,0,5,4,4,1,4,4,4,3,3,3,4,3,5,5,2,3,3,4,1,2,5,5,3,5,5,2,3,5,5,4,0,3,2,0,3,3,1,1,5,1,4,1,0,4,3,2,3,5,0,4,0,3,0,5,4,3,4,3,0,0,4,1,0,4,4), +(1,3,0,4,0,2,0,2,0,2,5,5,3,3,3,3,3,0,4,2,3,4,4,4,3,4,0,0,3,4,5,4,3,3,3,3,2,5,5,4,5,5,5,4,3,5,5,5,1,3,1,0,1,0,0,3,2,0,4,2,0,5,2,3,2,4,1,3,0,3,0,4,5,4,5,4,3,0,4,2,0,5,4), +(0,3,0,4,0,5,0,3,0,3,4,4,3,2,3,2,3,3,3,3,3,2,4,3,3,2,2,0,3,3,3,3,3,1,3,3,3,0,4,4,3,4,4,1,1,4,4,2,0,3,1,0,1,1,0,4,1,0,2,3,1,3,3,1,3,4,0,3,0,1,0,3,1,3,0,0,1,0,2,0,0,4,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,3,0,2,0,3,0,1,5,4,3,3,3,1,4,2,1,2,3,4,4,2,4,4,5,0,3,1,4,3,4,0,4,3,3,3,2,3,2,5,3,4,3,2,2,3,0,0,3,0,2,1,0,1,2,0,0,0,0,2,1,1,3,1,0,2,0,4,0,3,4,4,4,5,2,0,2,0,0,1,3), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,1,0,0,0,4,2,1,1,0,1,0,3,2,0,0,3,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,1,0,0,0,2,0,0,0,1,4,0,4,2,1,0,0,0,0,0,1), +(0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0,3,1,0,0,0,2,0,2,1,0,0,1,2,1,0,1,1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,1,3,1,0,0,0,0,0,1,0,0,2,1,0,0,0,0,0,0,0,0,2), +(0,4,0,4,0,4,0,3,0,4,4,3,4,2,4,3,2,0,4,4,4,3,5,3,5,3,3,2,4,2,4,3,4,3,1,4,0,2,3,4,4,4,3,3,3,4,4,4,3,4,1,3,4,3,2,1,2,1,3,3,3,4,4,3,3,5,0,4,0,3,0,4,3,3,3,2,1,0,3,0,0,3,3), +(0,4,0,3,0,3,0,3,0,3,5,5,3,3,3,3,4,3,4,3,3,3,4,4,4,3,3,3,3,4,3,5,3,3,1,3,2,4,5,5,5,5,4,3,4,5,5,3,2,2,3,3,3,3,2,3,3,1,2,3,2,4,3,3,3,4,0,4,0,2,0,4,3,2,2,1,2,0,3,0,0,4,1), +) + +class JapaneseContextAnalysis: + def __init__(self): + self.reset() + + def reset(self): + self._mTotalRel = 0 # total sequence received + # category counters, each interger counts sequence in its category + self._mRelSample = [0] * NUM_OF_CATEGORY + # if last byte in current buffer is not the last byte of a character, + # we need to know how many bytes to skip in next buffer + self._mNeedToSkipCharNum = 0 + self._mLastCharOrder = -1 # The order of previous char + # If this flag is set to True, detection is done and conclusion has + # been made + self._mDone = False + + def feed(self, aBuf, aLen): + if self._mDone: + return + + # The buffer we got is byte oriented, and a character may span in more than one + # buffers. In case the last one or two byte in last buffer is not + # complete, we record how many byte needed to complete that character + # and skip these bytes here. We can choose to record those bytes as + # well and analyse the character once it is complete, but since a + # character will not make much difference, by simply skipping + # this character will simply our logic and improve performance. + i = self._mNeedToSkipCharNum + while i < aLen: + order, charLen = self.get_order(aBuf[i:i + 2]) + i += charLen + if i > aLen: + self._mNeedToSkipCharNum = i - aLen + self._mLastCharOrder = -1 + else: + if (order != -1) and (self._mLastCharOrder != -1): + self._mTotalRel += 1 + if self._mTotalRel > MAX_REL_THRESHOLD: + self._mDone = True + break + self._mRelSample[jp2CharContext[self._mLastCharOrder][order]] += 1 + self._mLastCharOrder = order + + def got_enough_data(self): + return self._mTotalRel > ENOUGH_REL_THRESHOLD + + def get_confidence(self): + # This is just one way to calculate confidence. It works well for me. + if self._mTotalRel > MINIMUM_DATA_THRESHOLD: + return float(self._mTotalRel - self._mRelSample[0]) / self._mTotalRel + else: + return DONT_KNOW + + def get_order(self, aBuf): + return -1, 1 + +class SJISContextAnalysis(JapaneseContextAnalysis): + def get_order(self, aBuf): + if not aBuf: + return -1, 1 + # find out current char's byte length + first_char = wrap_ord(aBuf[0]) + if ((0x81 <= first_char <= 0x9F) or (0xE0 <= first_char <= 0xFC)): + charLen = 2 + else: + charLen = 1 + + # return its order if it is hiragana + if len(aBuf) > 1: + second_char = wrap_ord(aBuf[1]) + if (first_char == 202) and (0x9F <= second_char <= 0xF1): + return second_char - 0x9F, charLen + + return -1, charLen + +class EUCJPContextAnalysis(JapaneseContextAnalysis): + def get_order(self, aBuf): + if not aBuf: + return -1, 1 + # find out current char's byte length + first_char = wrap_ord(aBuf[0]) + if (first_char == 0x8E) or (0xA1 <= first_char <= 0xFE): + charLen = 2 + elif first_char == 0x8F: + charLen = 3 + else: + charLen = 1 + + # return its order if it is hiragana + if len(aBuf) > 1: + second_char = wrap_ord(aBuf[1]) + if (first_char == 0xA4) and (0xA1 <= second_char <= 0xF3): + return second_char - 0xA1, charLen + + return -1, charLen + +# flake8: noqa diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langbulgarianmodel.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langbulgarianmodel.py new file mode 100644 index 0000000000..ea5a60ba04 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langbulgarianmodel.py @@ -0,0 +1,229 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +# this table is modified base on win1251BulgarianCharToOrderMap, so +# only number <64 is sure valid + +Latin5_BulgarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 +110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 +253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 +116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 +194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209, # 80 +210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225, # 90 + 81,226,227,228,229,230,105,231,232,233,234,235,236, 45,237,238, # a0 + 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # b0 + 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,239, 67,240, 60, 56, # c0 + 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # d0 + 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,241, 42, 16, # e0 + 62,242,243,244, 58,245, 98,246,247,248,249,250,251, 91,252,253, # f0 +) + +win1251BulgarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 +110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 +253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 +116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 +206,207,208,209,210,211,212,213,120,214,215,216,217,218,219,220, # 80 +221, 78, 64, 83,121, 98,117,105,222,223,224,225,226,227,228,229, # 90 + 88,230,231,232,233,122, 89,106,234,235,236,237,238, 45,239,240, # a0 + 73, 80,118,114,241,242,243,244,245, 62, 58,246,247,248,249,250, # b0 + 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # c0 + 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,251, 67,252, 60, 56, # d0 + 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # e0 + 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,253, 42, 16, # f0 +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 96.9392% +# first 1024 sequences:3.0618% +# rest sequences: 0.2992% +# negative sequences: 0.0020% +BulgarianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,2,2,1,2,2, +3,1,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,0,1, +0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,3,3,0,3,1,0, +0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,2,2,1,3,3,3,3,2,2,2,1,1,2,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,2,3,2,2,3,3,1,1,2,3,3,2,3,3,3,3,2,1,2,0,2,0,3,0,0, +0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,1,3,3,3,3,3,2,3,2,3,3,3,3,3,2,3,3,1,3,0,3,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,1,3,3,2,3,3,3,1,3,3,2,3,2,2,2,0,0,2,0,2,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,3,3,1,2,2,3,2,1,1,2,0,2,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,2,3,3,1,2,3,2,2,2,3,3,3,3,3,2,2,3,1,2,0,2,1,2,0,0, +0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,1,3,3,3,3,3,2,3,3,3,2,3,3,2,3,2,2,2,3,1,2,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,1,1,1,2,2,1,3,1,3,2,2,3,0,0,1,0,1,0,1,0,0, +0,0,0,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,2,2,3,2,2,3,1,2,1,1,1,2,3,1,3,1,2,2,0,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,1,3,2,2,3,3,1,2,3,1,1,3,3,3,3,1,2,2,1,1,1,0,2,0,2,0,1, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,2,2,3,3,3,2,2,1,1,2,0,2,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,0,1,2,1,3,3,2,3,3,3,3,3,2,3,2,1,0,3,1,2,1,2,1,2,3,2,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,2,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,1,3,3,2,3,3,2,2,2,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,0,3,3,3,3,3,2,1,1,2,1,3,3,0,3,1,1,1,1,3,2,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,1,1,3,1,3,3,2,3,2,2,2,3,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,3,2,2,3,2,1,1,1,1,1,3,1,3,1,1,0,0,0,1,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,2,0,3,2,0,3,0,2,0,0,2,1,3,1,0,0,1,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,2,1,1,1,1,2,1,1,2,1,1,1,2,2,1,2,1,1,1,0,1,1,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,2,1,3,1,1,2,1,3,2,1,1,0,1,2,3,2,1,1,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,2,2,1,0,1,0,0,1,0,0,0,2,1,0,3,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,2,3,2,3,3,1,3,2,1,1,1,2,1,1,2,1,3,0,1,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,2,2,3,3,2,3,2,2,2,3,1,2,2,1,1,2,1,1,2,2,0,1,1,0,1,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,3,1,0,2,2,1,3,2,1,0,0,2,0,2,0,1,0,0,0,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,1,2,0,2,3,1,2,3,2,0,1,3,1,2,1,1,1,0,0,1,0,0,2,2,2,3, +2,2,2,2,1,2,1,1,2,2,1,1,2,0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,1, +3,3,3,3,3,2,1,2,2,1,2,0,2,0,1,0,1,2,1,2,1,1,0,0,0,1,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,2,3,3,1,1,3,1,0,3,2,1,0,0,0,1,2,0,2,0,1,0,0,0,1,0,1,2,1,2,2, +1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,0,1,2,1,1,1,0,0,0,0,0,1,1,0,0, +3,1,0,1,0,2,3,2,2,2,3,2,2,2,2,2,1,0,2,1,2,1,1,1,0,1,2,1,2,2,2,1, +1,1,2,2,2,2,1,2,1,1,0,1,2,1,2,2,2,1,1,1,0,1,1,1,1,2,0,1,0,0,0,0, +2,3,2,3,3,0,0,2,1,0,2,1,0,0,0,0,2,3,0,2,0,0,0,0,0,1,0,0,2,0,1,2, +2,1,2,1,2,2,1,1,1,2,1,1,1,0,1,2,2,1,1,1,1,1,0,1,1,1,0,0,1,2,0,0, +3,3,2,2,3,0,2,3,1,1,2,0,0,0,1,0,0,2,0,2,0,0,0,1,0,1,0,1,2,0,2,2, +1,1,1,1,2,1,0,1,2,2,2,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,1,0,0, +2,3,2,3,3,0,0,3,0,1,1,0,1,0,0,0,2,2,1,2,0,0,0,0,0,0,0,0,2,0,1,2, +2,2,1,1,1,1,1,2,2,2,1,0,2,0,1,0,1,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0, +3,3,3,3,2,2,2,2,2,0,2,1,1,1,1,2,1,2,1,1,0,2,0,1,0,1,0,0,2,0,1,2, +1,1,1,1,1,1,1,2,2,1,1,0,2,0,1,0,2,0,0,1,1,1,0,0,2,0,0,0,1,1,0,0, +2,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0,0,0,0,1,2,0,1,2, +2,2,2,1,1,2,1,1,2,2,2,1,2,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,1,1,0,0, +2,3,3,3,3,0,2,2,0,2,1,0,0,0,1,1,1,2,0,2,0,0,0,3,0,0,0,0,2,0,2,2, +1,1,1,2,1,2,1,1,2,2,2,1,2,0,1,1,1,0,1,1,1,1,0,2,1,0,0,0,1,1,0,0, +2,3,3,3,3,0,2,1,0,0,2,0,0,0,0,0,1,2,0,2,0,0,0,0,0,0,0,0,2,0,1,2, +1,1,1,2,1,1,1,1,2,2,2,0,1,0,1,1,1,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0, +3,3,2,2,3,0,1,0,1,0,0,0,0,0,0,0,1,1,0,3,0,0,0,0,0,0,0,0,1,0,2,2, +1,1,1,1,1,2,1,1,2,2,1,2,2,1,0,1,1,1,1,1,0,1,0,0,1,0,0,0,1,1,0,0, +3,1,0,1,0,2,2,2,2,3,2,1,1,1,2,3,0,0,1,0,2,1,1,0,1,1,1,1,2,1,1,1, +1,2,2,1,2,1,2,2,1,1,0,1,2,1,2,2,1,1,1,0,0,1,1,1,2,1,0,1,0,0,0,0, +2,1,0,1,0,3,1,2,2,2,2,1,2,2,1,1,1,0,2,1,2,2,1,1,2,1,1,0,2,1,1,1, +1,2,2,2,2,2,2,2,1,2,0,1,1,0,2,1,1,1,1,1,0,0,1,1,1,1,0,1,0,0,0,0, +2,1,1,1,1,2,2,2,2,1,2,2,2,1,2,2,1,1,2,1,2,3,2,2,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,3,2,0,1,2,0,1,2,1,1,0,1,0,1,2,1,2,0,0,0,1,1,0,0,0,1,0,0,2, +1,1,0,0,1,1,0,1,1,1,1,0,2,0,1,1,1,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0, +2,0,0,0,0,1,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,2,1,1,1, +1,2,2,2,2,1,1,2,1,2,1,1,1,0,2,1,2,1,1,1,0,2,1,1,1,1,0,1,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, +1,1,0,1,0,1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,3,2,0,0,0,0,1,0,0,0,0,0,0,1,1,0,2,0,0,0,0,0,0,0,0,1,0,1,2, +1,1,1,1,1,1,0,0,2,2,2,2,2,0,1,1,0,1,1,1,1,1,0,0,1,0,0,0,1,1,0,1, +2,3,1,2,1,0,1,1,0,2,2,2,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,1,2, +1,1,1,1,2,1,1,1,1,1,1,1,1,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0, +2,2,2,2,2,0,0,2,0,0,2,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,0,2,2, +1,1,1,1,1,0,0,1,2,1,1,0,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,2,0,1,1,0,0,0,1,0,0,2,0,2,0,0,0,0,0,0,0,0,0,0,1,1, +0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,3,2,0,0,1,0,0,1,0,0,0,0,0,0,1,0,2,0,0,0,1,0,0,0,0,0,0,0,2, +1,1,0,0,1,0,0,0,1,1,0,0,1,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,1,2,2,2,1,2,1,2,2,1,1,2,1,1,1,0,1,1,1,1,2,0,1,0,1,1,1,1,0,1,1, +1,1,2,1,1,1,1,1,1,0,0,1,2,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0, +1,0,0,1,3,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,1,0,0,1,0,2,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,2,0,0,1, +0,2,0,1,0,0,1,1,2,0,1,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,1,1,0,2,1,0,1,1,1,0,0,1,0,2,0,1,0,0,0,0,0,0,0,0,0,1, +0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,2,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, +0,1,0,1,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,0,1,2,1,1,1,1,1,1,2,2,1,0,0,1,0,1,0,0,0,0,1,1,1,1,0,0,0, +1,1,2,1,1,1,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,1,2,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +0,1,1,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, +1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,2,0,0,2,0,1,0,0,1,0,0,1, +1,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, +1,1,1,1,1,1,1,2,0,0,0,0,0,0,2,1,0,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +) + +Latin5BulgarianModel = { + 'charToOrderMap': Latin5_BulgarianCharToOrderMap, + 'precedenceMatrix': BulgarianLangModel, + 'mTypicalPositiveRatio': 0.969392, + 'keepEnglishLetter': False, + 'charsetName': "ISO-8859-5" +} + +Win1251BulgarianModel = { + 'charToOrderMap': win1251BulgarianCharToOrderMap, + 'precedenceMatrix': BulgarianLangModel, + 'mTypicalPositiveRatio': 0.969392, + 'keepEnglishLetter': False, + 'charsetName': "windows-1251" +} + + +# flake8: noqa diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langcyrillicmodel.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langcyrillicmodel.py new file mode 100644 index 0000000000..15e338fc11 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langcyrillicmodel.py @@ -0,0 +1,329 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# KOI8-R language model +# Character Mapping Table: +KOI8R_CharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, # 80 +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, # 90 +223,224,225, 68,226,227,228,229,230,231,232,233,234,235,236,237, # a0 +238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, # b0 + 27, 3, 21, 28, 13, 2, 39, 19, 26, 4, 23, 11, 8, 12, 5, 1, # c0 + 15, 16, 9, 7, 6, 14, 24, 10, 17, 18, 20, 25, 30, 29, 22, 54, # d0 + 59, 37, 44, 58, 41, 48, 53, 46, 55, 42, 60, 36, 49, 38, 31, 34, # e0 + 35, 43, 45, 32, 40, 52, 56, 33, 61, 62, 51, 57, 47, 63, 50, 70, # f0 +) + +win1251_CharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, +239,240,241,242,243,244,245,246, 68,247,248,249,250,251,252,253, + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +) + +latin5_CharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, +) + +macCyrillic_CharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, +239,240,241,242,243,244,245,246,247,248,249,250,251,252, 68, 16, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27,255, +) + +IBM855_CharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194, 68,195,196,197,198,199,200,201,202,203,204,205, +206,207,208,209,210,211,212,213,214,215,216,217, 27, 59, 54, 70, + 3, 37, 21, 44, 28, 58, 13, 41, 2, 48, 39, 53, 19, 46,218,219, +220,221,222,223,224, 26, 55, 4, 42,225,226,227,228, 23, 60,229, +230,231,232,233,234,235, 11, 36,236,237,238,239,240,241,242,243, + 8, 49, 12, 38, 5, 31, 1, 34, 15,244,245,246,247, 35, 16,248, + 43, 9, 45, 7, 32, 6, 40, 14, 52, 24, 56, 10, 33, 17, 61,249, +250, 18, 62, 20, 51, 25, 57, 30, 47, 29, 63, 22, 50,251,252,255, +) + +IBM866_CharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 97.6601% +# first 1024 sequences: 2.3389% +# rest sequences: 0.1237% +# negative sequences: 0.0009% +RussianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,3,3,3,3,1,3,3,3,2,3,2,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,2,2,2,2,2,0,0,2, +3,3,3,2,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,2,3,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,2,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,2,3,3,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, +0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, +0,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,2,2,2,3,1,3,3,1,3,3,3,3,2,2,3,0,2,2,2,3,3,2,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,3,3,2,2,3,2,3,3,3,2,1,2,2,0,1,2,2,2,2,2,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,3,0,2,2,3,3,2,1,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,1,2,3,2,2,3,2,3,3,3,3,2,2,3,0,3,2,2,3,1,1,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,3,3,3,3,2,2,2,0,3,3,3,2,2,2,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,2,3,2,2,0,1,3,2,1,2,2,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,2,1,1,3,0,1,1,1,1,2,1,1,0,2,2,2,1,2,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,2,2,2,2,1,3,2,3,2,3,2,1,2,2,0,1,1,2,1,2,1,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,2,3,3,3,2,2,2,2,0,2,2,2,2,3,1,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,2,3,2,2,3,3,3,3,3,3,3,3,3,1,3,2,0,0,3,3,3,3,2,3,3,3,3,2,3,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,3,2,2,3,3,0,2,1,0,3,2,3,2,3,0,0,1,2,0,0,1,0,1,2,1,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,3,0,2,3,3,3,3,2,3,3,3,3,1,2,2,0,0,2,3,2,2,2,3,2,3,2,2,3,0,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,0,2,3,2,3,0,1,2,3,3,2,0,2,3,0,0,2,3,2,2,0,1,3,1,3,2,2,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,3,0,2,3,3,3,3,3,3,3,3,2,1,3,2,0,0,2,2,3,3,3,2,3,3,0,2,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,2,2,2,3,3,0,0,1,1,1,1,1,2,0,0,1,1,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,3,3,3,3,3,0,3,2,3,3,2,3,2,0,2,1,0,1,1,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,2,2,2,2,3,1,3,2,3,1,1,2,1,0,2,2,2,2,1,3,1,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +2,2,3,3,3,3,3,1,2,2,1,3,1,0,3,0,0,3,0,0,0,1,1,0,1,2,1,0,0,0,0,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,2,1,1,3,3,3,2,2,1,2,2,3,1,1,2,0,0,2,2,1,3,0,0,2,1,1,2,1,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,3,3,3,1,2,2,2,1,2,1,3,3,1,1,2,1,2,1,2,2,0,2,0,0,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,3,2,1,3,2,2,3,2,0,3,2,0,3,0,1,0,1,1,0,0,1,1,1,1,0,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,3,3,3,2,2,2,3,3,1,2,1,2,1,0,1,0,1,1,0,1,0,0,2,1,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,1,1,2,1,2,3,3,2,2,1,2,2,3,0,2,1,0,0,2,2,3,2,1,2,2,2,2,2,3,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,1,1,0,1,1,2,2,1,1,3,0,0,1,3,1,1,1,0,0,0,1,0,1,1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,3,3,3,2,0,0,0,2,1,0,1,0,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,0,2,3,2,2,2,1,2,2,2,1,2,1,0,0,1,1,1,0,2,0,1,1,1,0,0,1,1, +1,0,0,0,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,0,0,0,0,1,0,0,0,0,3,0,1,2,1,0,0,0,0,0,0,0,1,1,0,0,1,1, +1,0,1,0,1,2,0,0,1,1,2,1,0,1,1,1,1,0,1,1,1,1,0,1,0,0,1,0,0,1,1,0, +2,2,3,2,2,2,3,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,0,1,0,1,1,1,0,2,1, +1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,0,1,1,0, +3,3,3,2,2,2,2,3,2,2,1,1,2,2,2,2,1,1,3,1,2,1,2,0,0,1,1,0,1,0,2,1, +1,1,1,1,1,2,1,0,1,1,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,1,0, +2,0,0,1,0,3,2,2,2,2,1,2,1,2,1,2,0,0,0,2,1,2,2,1,1,2,2,0,1,1,0,2, +1,1,1,1,1,0,1,1,1,2,1,1,1,2,1,0,1,2,1,1,1,1,0,1,1,1,0,0,1,0,0,1, +1,3,2,2,2,1,1,1,2,3,0,0,0,0,2,0,2,2,1,0,0,0,0,0,0,1,0,0,0,0,1,1, +1,0,1,1,0,1,0,1,1,0,1,1,0,2,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, +2,3,2,3,2,1,2,2,2,2,1,0,0,0,2,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,2,1, +1,1,2,1,0,2,0,0,1,0,1,0,0,1,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,0, +3,0,0,1,0,2,2,2,3,2,2,2,2,2,2,2,0,0,0,2,1,2,1,1,1,2,2,0,0,0,1,2, +1,1,1,1,1,0,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,1, +2,3,2,3,3,2,0,1,1,1,0,0,1,0,2,0,1,1,3,1,0,0,0,0,0,0,0,1,0,0,2,1, +1,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,0,0,1,1,0,1,0,0,0,0,0,0,1,0, +2,3,3,3,3,1,2,2,2,2,0,1,1,0,2,1,1,1,2,1,0,1,1,0,0,1,0,1,0,0,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,2,0,0,1,1,2,2,1,0,0,2,0,1,1,3,0,0,1,0,0,0,0,0,1,0,1,2,1, +1,1,2,0,1,1,1,0,1,0,1,1,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,1,0,1,1,0, +1,3,2,3,2,1,0,0,2,2,2,0,1,0,2,0,1,1,1,0,1,0,0,0,3,0,1,1,0,0,2,1, +1,1,1,0,1,1,0,0,0,0,1,1,0,1,0,0,2,1,1,0,1,0,0,0,1,0,1,0,0,1,1,0, +3,1,2,1,1,2,2,2,2,2,2,1,2,2,1,1,0,0,0,2,2,2,0,0,0,1,2,1,0,1,0,1, +2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,1,1,1,0,1,0,1,1,0,1,1,1,0,0,1, +3,0,0,0,0,2,0,1,1,1,1,1,1,1,0,1,0,0,0,1,1,1,0,1,0,1,1,0,0,1,0,1, +1,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1, +1,3,3,2,2,0,0,0,2,2,0,0,0,1,2,0,1,1,2,0,0,0,0,0,0,0,0,1,0,0,2,1, +0,1,1,0,0,1,1,0,0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +2,3,2,3,2,0,0,0,0,1,1,0,0,0,2,0,2,0,2,0,0,0,0,0,1,0,0,1,0,0,1,1, +1,1,2,0,1,2,1,0,1,1,2,1,1,1,1,1,2,1,1,0,1,0,0,1,1,1,1,1,0,1,1,0, +1,3,2,2,2,1,0,0,2,2,1,0,1,2,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1, +0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,0,2,3,1,2,2,2,2,2,2,1,1,0,0,0,1,0,1,0,2,1,1,1,0,0,0,0,1, +1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +2,0,2,0,0,1,0,3,2,1,2,1,2,2,0,1,0,0,0,2,1,0,0,2,1,1,1,1,0,2,0,2, +2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,0,0,0,1,1,1,1,0,1,0,0,1, +1,2,2,2,2,1,0,0,1,0,0,0,0,0,2,0,1,1,1,1,0,0,0,0,1,0,1,2,0,0,2,0, +1,0,1,1,1,2,1,0,1,0,1,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0, +2,1,2,2,2,0,3,0,1,1,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0, +1,2,2,3,2,2,0,0,1,1,2,0,1,2,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1, +0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, +2,2,1,1,2,1,2,2,2,2,2,1,2,2,0,1,0,0,0,1,2,2,2,1,2,1,1,1,1,1,2,1, +1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,0,1, +1,2,2,2,2,0,1,0,2,2,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +0,0,1,0,0,1,0,0,0,0,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,0,2,2,2,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1, +0,1,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,0,0,1,0,0,1,1,2,0,0,0,0,1,0,1,0,0,1,0,0,2,0,0,0,1, +0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,1,1,2,0,2,1,1,1,1,0,2,2,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1, +0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,0,2,1,2,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0, +0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +1,0,0,0,0,2,0,1,2,1,0,1,1,1,0,1,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1, +0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1, +2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,1,1,0,1,0,1,0,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,1,0,1,1,0,1,0,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0, +0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, +) + +Koi8rModel = { + 'charToOrderMap': KOI8R_CharToOrderMap, + 'precedenceMatrix': RussianLangModel, + 'mTypicalPositiveRatio': 0.976601, + 'keepEnglishLetter': False, + 'charsetName': "KOI8-R" +} + +Win1251CyrillicModel = { + 'charToOrderMap': win1251_CharToOrderMap, + 'precedenceMatrix': RussianLangModel, + 'mTypicalPositiveRatio': 0.976601, + 'keepEnglishLetter': False, + 'charsetName': "windows-1251" +} + +Latin5CyrillicModel = { + 'charToOrderMap': latin5_CharToOrderMap, + 'precedenceMatrix': RussianLangModel, + 'mTypicalPositiveRatio': 0.976601, + 'keepEnglishLetter': False, + 'charsetName': "ISO-8859-5" +} + +MacCyrillicModel = { + 'charToOrderMap': macCyrillic_CharToOrderMap, + 'precedenceMatrix': RussianLangModel, + 'mTypicalPositiveRatio': 0.976601, + 'keepEnglishLetter': False, + 'charsetName': "MacCyrillic" +}; + +Ibm866Model = { + 'charToOrderMap': IBM866_CharToOrderMap, + 'precedenceMatrix': RussianLangModel, + 'mTypicalPositiveRatio': 0.976601, + 'keepEnglishLetter': False, + 'charsetName': "IBM866" +} + +Ibm855Model = { + 'charToOrderMap': IBM855_CharToOrderMap, + 'precedenceMatrix': RussianLangModel, + 'mTypicalPositiveRatio': 0.976601, + 'keepEnglishLetter': False, + 'charsetName': "IBM855" +} + +# flake8: noqa diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langgreekmodel.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langgreekmodel.py new file mode 100644 index 0000000000..93241ce26b --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langgreekmodel.py @@ -0,0 +1,225 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin7_CharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 + 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 +253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 + 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 +253,233, 90,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 +253,253,253,253,247,248, 61, 36, 46, 71, 73,253, 54,253,108,123, # b0 +110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 + 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 +124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 + 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 +) + +win1253_CharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 + 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 +253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 + 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 +253,233, 61,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 +253,253,253,253,247,253,253, 36, 46, 71, 73,253, 54,253,108,123, # b0 +110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 + 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 +124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 + 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 98.2851% +# first 1024 sequences:1.7001% +# rest sequences: 0.0359% +# negative sequences: 0.0148% +GreekLangModel = ( +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,2,2,3,3,3,3,3,3,3,3,1,3,3,3,0,2,2,3,3,0,3,0,3,2,0,3,3,3,0, +3,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,0,3,3,0,3,2,3,3,0,3,2,3,3,3,0,0,3,0,3,0,3,3,2,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,2,3,2,2,3,3,3,3,3,3,3,3,0,3,3,3,3,0,2,3,3,0,3,3,3,3,2,3,3,3,0, +2,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,2,1,3,3,3,3,2,3,3,2,3,3,2,0, +0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,2,3,3,0, +2,0,1,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,3,0,0,0,0,3,3,0,3,1,3,3,3,0,3,3,0,3,3,3,3,0,0,0,0, +2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,0,3,0,3,3,3,3,3,0,3,2,2,2,3,0,2,3,3,3,3,3,2,3,3,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,3,2,2,2,3,3,3,3,0,3,1,3,3,3,3,2,3,3,3,3,3,3,3,2,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,3,0,0,0,3,3,2,3,3,3,3,3,0,0,3,2,3,0,2,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,3,0,0,3,3,0,2,3,0,3,0,3,3,3,0,0,3,0,3,0,2,2,3,3,0,0, +0,0,1,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,3,2,3,3,3,3,0,3,3,3,3,3,0,3,3,2,3,2,3,3,2,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,2,3,2,3,3,3,3,3,3,0,2,3,2,3,2,2,2,3,2,3,3,2,3,0,2,2,2,3,0, +2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,0,3,3,3,2,3,3,0,0,3,0,3,0,0,0,3,2,0,3,0,3,0,0,2,0,2,0, +0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,0,0,0,3,3,0,3,3,3,0,0,1,2,3,0, +3,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,0,3,2,2,3,3,0,3,3,3,3,3,2,1,3,0,3,2,3,3,2,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,3,0,2,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,3,0,3,2,3,0,0,3,3,3,0, +3,0,0,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,2,0,3,2,3,0,0,3,2,3,0, +2,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,1,2,2,3,3,3,3,3,3,0,2,3,0,3,0,0,0,3,3,0,3,0,2,0,0,2,3,1,0, +2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,3,0,3,0,3,3,2,3,0,3,3,3,3,3,3,0,3,3,3,0,2,3,0,0,3,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,0,0,3,0,0,0,3,3,0,3,0,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,0,3,3,3,3,3,3,0,0,3,0,2,0,0,0,3,3,0,3,0,3,0,0,2,0,2,0, +0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,3,0,3,0,2,0,3,2,0,3,2,3,2,3,0,0,3,2,3,2,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,2,3,3,3,3,3,0,0,0,3,0,2,1,0,0,3,2,2,2,0,3,0,0,2,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,2,0,3,0,3,0,3,3,0,2,1,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,3,0,3,3,3,3,3,3,0,2,3,0,3,0,0,0,2,1,0,2,2,3,0,0,2,2,2,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,2,3,3,3,2,3,0,0,1,3,0,2,0,0,0,0,3,0,1,0,2,0,0,1,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,1,0,3,0,0,0,3,2,0,3,2,3,3,3,0,0,3,0,3,2,2,2,1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,0,0,3,0,0,0,0,2,0,2,3,3,2,2,2,2,3,0,2,0,2,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,2,0,0,0,0,0,0,2,3,0,2,0,2,3,2,0,0,3,0,3,0,3,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,2,3,3,2,2,3,0,2,0,3,0,0,0,2,0,0,0,0,1,2,0,2,0,2,0, +0,2,0,2,0,2,2,0,0,1,0,2,2,2,0,2,2,2,0,2,2,2,0,0,2,0,0,1,0,0,0,0, +0,2,0,3,3,2,0,0,0,0,0,0,1,3,0,2,0,2,2,2,0,0,2,0,3,0,0,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,2,3,2,0,2,2,0,2,0,2,2,0,2,0,2,2,2,0,0,0,0,0,0,2,3,0,0,0,2, +0,1,2,0,0,0,0,2,2,0,0,0,2,1,0,2,2,0,0,0,0,0,0,1,0,2,0,0,0,0,0,0, +0,0,2,1,0,2,3,2,2,3,2,3,2,0,0,3,3,3,0,0,3,2,0,0,0,1,1,0,2,0,2,2, +0,2,0,2,0,2,2,0,0,2,0,2,2,2,0,2,2,2,2,0,0,2,0,0,0,2,0,1,0,0,0,0, +0,3,0,3,3,2,2,0,3,0,0,0,2,2,0,2,2,2,1,2,0,0,1,2,2,0,0,3,0,0,0,2, +0,1,2,0,0,0,1,2,0,0,0,0,0,0,0,2,2,0,1,0,0,2,0,0,0,2,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,2,2,0,0,0,2,0,2,3,3,0,2,0,0,0,0,0,0,2,2,2,0,2,2,0,2,0,2, +0,2,2,0,0,2,2,2,2,1,0,0,2,2,0,2,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0, +0,2,0,3,2,3,0,0,0,3,0,0,2,2,0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,0,2, +0,0,2,2,0,0,2,2,2,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,3,2,0,2,2,2,2,2,0,0,0,2,0,0,0,0,2,0,1,0,0,2,0,1,0,0,0, +0,2,2,2,0,2,2,0,1,2,0,2,2,2,0,2,2,2,2,1,2,2,0,0,2,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,2,0,2,0,2,2,0,0,0,0,1,2,1,0,0,2,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,3,2,3,0,0,2,0,0,0,2,2,0,2,0,0,0,1,0,0,2,0,2,0,2,2,0,0,0,0, +0,0,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0, +0,2,2,3,2,2,0,0,0,0,0,0,1,3,0,2,0,2,2,0,0,0,1,0,2,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,0,2,0,3,2,0,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,2,0,0,0,0,1,1,0,0,2,1,2,0,2,2,0,1,0,0,1,0,0,0,2,0,0,0,0,0,0, +0,3,0,2,2,2,0,0,2,0,0,0,2,0,0,0,2,3,0,2,0,0,0,0,0,0,2,2,0,0,0,2, +0,1,2,0,0,0,1,2,2,1,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,1,2,0,2,2,0,2,0,0,2,0,0,0,0,1,2,1,0,2,1,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,3,1,2,2,0,2,0,0,0,0,2,0,0,0,2,0,0,3,0,0,0,0,2,2,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,1,0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,2, +0,2,2,0,0,2,2,2,2,2,0,1,2,0,0,0,2,2,0,1,0,2,0,0,2,2,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,0,0,0,0,2,0,2,0,0,0,0,2, +0,1,2,0,0,0,0,2,2,1,0,1,0,1,0,2,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,2,0,0,2,2,0,0,0,0,1,0,0,0,0,0,0,2, +0,2,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0, +0,2,2,2,2,0,0,0,3,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,1, +0,0,2,0,0,0,0,1,2,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,2,2,2,0,0,0,2,0,0,0,0,0,0,0,0,2, +0,0,1,0,0,0,0,2,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,3,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,2, +0,0,2,0,0,0,0,2,2,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,0,2,2,1,0,0,0,0,0,0,2,0,0,2,0,2,2,2,0,0,0,0,0,0,2,0,0,0,0,2, +0,0,2,0,0,2,0,2,2,0,0,0,0,2,0,2,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0, +0,0,3,0,0,0,2,2,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0, +0,2,2,2,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1, +0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,2,0,0,0,2,0,0,0,0,0,1,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,2,0,0,0, +0,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,2,0,2,0,0,0, +0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +) + +Latin7GreekModel = { + 'charToOrderMap': Latin7_CharToOrderMap, + 'precedenceMatrix': GreekLangModel, + 'mTypicalPositiveRatio': 0.982851, + 'keepEnglishLetter': False, + 'charsetName': "ISO-8859-7" +} + +Win1253GreekModel = { + 'charToOrderMap': win1253_CharToOrderMap, + 'precedenceMatrix': GreekLangModel, + 'mTypicalPositiveRatio': 0.982851, + 'keepEnglishLetter': False, + 'charsetName': "windows-1253" +} + +# flake8: noqa diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langhebrewmodel.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langhebrewmodel.py new file mode 100644 index 0000000000..d87132446d --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langhebrewmodel.py @@ -0,0 +1,201 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Simon Montagu +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Shoshannah Forbes - original C code (?) +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Windows-1255 language model +# Character Mapping Table: +win1255_CharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 69, 91, 79, 80, 92, 89, 97, 90, 68,111,112, 82, 73, 95, 85, # 40 + 78,121, 86, 71, 67,102,107, 84,114,103,115,253,253,253,253,253, # 50 +253, 50, 74, 60, 61, 42, 76, 70, 64, 53,105, 93, 56, 65, 54, 49, # 60 + 66,110, 51, 43, 44, 63, 81, 77, 98, 75,108,253,253,253,253,253, # 70 +124,202,203,204,205, 40, 58,206,207,208,209,210,211,212,213,214, +215, 83, 52, 47, 46, 72, 32, 94,216,113,217,109,218,219,220,221, + 34,116,222,118,100,223,224,117,119,104,125,225,226, 87, 99,227, +106,122,123,228, 55,229,230,101,231,232,120,233, 48, 39, 57,234, + 30, 59, 41, 88, 33, 37, 36, 31, 29, 35,235, 62, 28,236,126,237, +238, 38, 45,239,240,241,242,243,127,244,245,246,247,248,249,250, + 9, 8, 20, 16, 3, 2, 24, 14, 22, 1, 25, 15, 4, 11, 6, 23, + 12, 19, 13, 26, 18, 27, 21, 17, 7, 10, 5,251,252,128, 96,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 98.4004% +# first 1024 sequences: 1.5981% +# rest sequences: 0.087% +# negative sequences: 0.0015% +HebrewLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,3,2,1,2,0,1,0,0, +3,0,3,1,0,0,1,3,2,0,1,1,2,0,2,2,2,1,1,1,1,2,1,1,1,2,0,0,2,2,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2, +1,2,1,2,1,2,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2, +1,2,1,3,1,1,0,0,2,0,0,0,1,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,1,2,2,1,3, +1,2,1,1,2,2,0,0,2,2,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,1,0,1,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,2,2,2,3,2, +1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,3,2,2,3,2,2,2,1,2,2,2,2, +1,2,1,1,2,2,0,1,2,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,0,2,2,2,2,2, +0,2,0,2,2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,0,2,2,2, +0,2,1,2,2,2,0,0,2,1,0,0,0,0,1,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,2,1,2,3,2,2,2, +1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,2,0,2, +0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,2,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,2,2,3,2,1,2,1,1,1, +0,1,1,1,1,1,3,0,1,0,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,0,1,0,0,1,0,0,0,0, +0,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,2,1,2,3,3,2,3,3,3,3,2,3,2,1,2,0,2,1,2, +0,2,0,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,1,2,2,3,3,2,3,2,3,2,2,3,1,2,2,0,2,2,2, +0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,2,2,3,3,3,3,1,3,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,2,3,2,2,2,1,2,2,0,2,2,2,2, +0,2,0,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,1,3,2,3,3,2,3,3,2,2,1,2,2,2,2,2,2, +0,2,1,2,1,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,2,3,3,2,3,3,3,3,2,3,2,3,3,3,3,3,2,2,2,2,2,2,2,1, +0,2,0,1,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,1,2,3,3,3,3,3,3,3,2,3,2,3,2,1,2,3,0,2,1,2,2, +0,2,1,1,2,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,2,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,3,2,1,3,1,2,2,2,1,2,3,3,1,2,1,2,2,2,2, +0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,0,2,3,3,3,1,3,3,3,1,2,2,2,2,1,1,2,2,2,2,2,2, +0,2,0,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,2,2,3,3,3,2,1,2,3,2,3,2,2,2,2,1,2,1,1,1,2,2, +0,2,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0, +1,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,3,2,3,1,2,2,2,2,3,2,3,1,1,2,2,1,2,2,1,1,0,2,2,2,2, +0,1,0,1,2,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,0,0,1,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,0,1,0,1,1,0,1,1,0,0,0,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +3,2,2,1,2,2,2,2,2,2,2,1,2,2,1,2,2,1,1,1,1,1,1,1,1,2,1,1,0,3,3,3, +0,3,0,2,2,2,2,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,1,2,2,2,1,1,1,2,0,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,0,0,0,0, +0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,0,2,1,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,3,1,1,2,2,2,2,2,1,2,2,2,1,1,2,2,2,2,2,2,2,1,2,2,1,0,1,1,1,1,0, +0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,1,1,1,1,2,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, +0,0,2,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,0,0, +2,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,2,1,2,1,1,1,1,0,0,0,0, +0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,1,2,2,2,2,2,2,2,2,2,2,1,2,1,2,1,1,2,1,1,1,2,1,2,1,2,0,1,0,1, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,1,2,2,2,1,2,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,2,1,2,1,1,0,1,0,1, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,1,1,1,1,1,1,0,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,1,1,1,0,1,0,0,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0, +0,1,1,1,2,1,2,2,2,0,2,0,2,0,1,1,2,1,1,1,1,2,1,0,1,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,1,0,0,0,0,0,1,0,1,2,2,0,1,0,0,1,1,2,2,1,2,0,2,0,0,0,1,2,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,2,1,2,0,2,0,0,1,1,1,1,1,1,0,1,0,0,0,1,0,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,1,2,2,0,0,1,0,0,0,1,0,0,1, +1,1,2,1,0,1,1,1,0,1,0,1,1,1,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,2,1, +0,2,0,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,0,0,1,0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,1,0,0,0,1,1,0,1, +2,0,1,0,1,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,0,1,1,2,1,1,2,0,1,0,0,0,1,1,0,1, +1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,0,0,2,1,1,2,0,2,0,0,0,1,1,0,1, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,2,2,1,2,1,1,0,1,0,0,0,1,1,0,1, +2,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,1,0,1, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,2,1,1,1,0,2,1,1,0,0,0,2,1,0,1, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,0,2,1,1,0,1,0,0,0,1,1,0,1, +2,2,1,1,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,0,1,2,1,0,2,0,0,0,1,1,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0, +0,1,0,0,2,0,2,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,1,0,1,0,0,1,0,0,0,1,0,0,1, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,0,2,1,1,1,1,1,0,1,0,0,0,0,1,0,1, +0,1,1,1,2,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,1,0,0,0,0,0,1,1,1,1,1,0,1,0,0,0,1,1,0,0, +) + +Win1255HebrewModel = { + 'charToOrderMap': win1255_CharToOrderMap, + 'precedenceMatrix': HebrewLangModel, + 'mTypicalPositiveRatio': 0.984004, + 'keepEnglishLetter': False, + 'charsetName': "windows-1255" +} + +# flake8: noqa diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langhungarianmodel.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langhungarianmodel.py new file mode 100644 index 0000000000..6f59c61260 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langhungarianmodel.py @@ -0,0 +1,225 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin2_HungarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, + 46, 71, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, +253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, + 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, +159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174, +175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190, +191,192,193,194,195,196,197, 75,198,199,200,201,202,203,204,205, + 79,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, +221, 51, 81,222, 78,223,224,225,226, 44,227,228,229, 61,230,231, +232,233,234, 58,235, 66, 59,236,237,238, 60, 69, 63,239,240,241, + 82, 14, 74,242, 70, 80,243, 72,244, 15, 83, 77, 84, 30, 76, 85, +245,246,247, 25, 73, 42, 24,248,249,250, 31, 56, 29,251,252,253, +) + +win1250HungarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, + 46, 72, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, +253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, + 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, +161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176, +177,178,179,180, 78,181, 69,182,183,184,185,186,187,188,189,190, +191,192,193,194,195,196,197, 76,198,199,200,201,202,203,204,205, + 81,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, +221, 51, 83,222, 80,223,224,225,226, 44,227,228,229, 61,230,231, +232,233,234, 58,235, 66, 59,236,237,238, 60, 70, 63,239,240,241, + 84, 14, 75,242, 71, 82,243, 73,244, 15, 85, 79, 86, 30, 77, 87, +245,246,247, 25, 74, 42, 24,248,249,250, 31, 56, 29,251,252,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 94.7368% +# first 1024 sequences:5.2623% +# rest sequences: 0.8894% +# negative sequences: 0.0009% +HungarianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,2,3,3,1,1,2,2,2,2,2,1,2, +3,2,2,3,3,3,3,3,2,3,3,3,3,3,3,1,2,3,3,3,3,2,3,3,1,1,3,3,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +3,2,1,3,3,3,3,3,2,3,3,3,3,3,1,1,2,3,3,3,3,3,3,3,1,1,3,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,1,1,2,3,3,3,1,3,3,3,3,3,1,3,3,2,2,0,3,2,3, +0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,3,3,2,3,3,2,2,3,2,3,2,0,3,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,1,2,3,2,2,3,1,2,3,3,2,2,0,3,3,3, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,3,2,3,3,3,3,2,3,3,3,3,0,2,3,2, +0,0,0,1,1,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,1,1,1,3,3,2,1,3,2,2,3,2,1,3,2,2,1,0,3,3,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,2,2,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,3,2,2,3,1,1,3,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,1,3,3,3,3,3,2,2,1,3,3,3,0,1,1,2, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,2,0,3,2,3, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,1,3,2,2,2,3,1,1,3,3,1,1,0,3,3,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,2,3,3,3,3,3,1,2,3,2,2,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,1,3,3,2,2,1,3,3,3,1,1,3,1,2,3,2,3,2,2,2,1,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,2,2,3,2,1,0,3,2,0,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,1,0,3,3,3,3,0,2,3,0,0,2,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,2,2,2,2,3,3,0,1,2,3,2,3,2,2,3,2,1,2,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,3,3,3,3,3,1,2,3,3,3,2,1,2,3,3,2,2,2,3,2,3,3,1,3,3,1,1,0,2,3,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,1,2,2,2,2,3,3,3,1,1,1,3,3,1,1,3,1,1,3,2,1,2,3,1,1,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,1,2,1,1,3,3,1,1,1,1,3,3,1,1,2,2,1,2,1,1,2,2,1,1,0,2,2,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,1,1,2,1,1,3,3,1,0,1,1,3,3,2,0,1,1,2,3,1,0,2,2,1,0,0,1,3,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,2,1,3,3,3,3,3,1,2,3,2,3,3,2,1,1,3,2,3,2,1,2,2,0,1,2,1,0,0,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,2,2,2,2,3,1,2,2,1,1,3,3,0,3,2,1,2,3,2,1,3,3,1,1,0,2,1,3, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,2,3,3,3,2,1,1,3,3,1,1,1,2,2,3,2,3,2,2,2,1,0,2,2,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +1,0,0,3,3,3,3,3,0,0,3,3,2,3,0,0,0,2,3,3,1,0,1,2,0,0,1,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,2,3,3,3,3,3,1,2,3,3,2,2,1,1,0,3,3,2,2,1,2,2,1,0,2,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,2,1,3,1,2,3,3,2,2,1,1,2,2,1,1,1,1,3,2,1,1,1,1,2,1,0,1,2,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +2,3,3,1,1,1,1,1,3,3,3,0,1,1,3,3,1,1,1,1,1,2,2,0,3,1,1,2,0,2,1,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,1,0,1,2,1,2,2,0,1,2,3,1,2,0,0,0,2,1,1,1,1,1,2,0,0,1,1,0,0,0,0, +1,2,1,2,2,2,1,2,1,2,0,2,0,2,2,1,1,2,1,1,2,1,1,1,0,1,0,0,0,1,1,0, +1,1,1,2,3,2,3,3,0,1,2,2,3,1,0,1,0,2,1,2,2,0,1,1,0,0,1,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,3,3,2,2,1,0,0,3,2,3,2,0,0,0,1,1,3,0,0,1,1,0,0,2,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,2,2,3,3,1,0,1,3,2,3,1,1,1,0,1,1,1,1,1,3,1,0,0,2,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,1,2,2,2,1,0,1,2,3,3,2,0,0,0,2,1,1,1,2,1,1,1,0,1,1,1,0,0,0, +1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,2,1,1,1,1,1,1,0,1,1,1,0,0,1,1, +3,2,2,1,0,0,1,1,2,2,0,3,0,1,2,1,1,0,0,1,1,1,0,1,1,1,1,0,2,1,1,1, +2,2,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,2,3,1,1,1,1,1,1,1,1,1,0,1, +2,3,3,0,1,0,0,0,3,3,1,0,0,1,2,2,1,0,0,0,0,2,0,0,1,1,1,0,2,1,1,1, +2,1,1,1,1,1,1,2,1,1,0,1,1,0,1,1,1,0,1,2,1,1,0,1,1,1,1,1,1,1,0,1, +2,3,3,0,1,0,0,0,2,2,0,0,0,0,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,1,0, +2,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, +3,2,2,0,1,0,1,0,2,3,2,0,0,1,2,2,1,0,0,1,1,1,0,0,2,1,0,1,2,2,1,1, +2,1,1,1,1,1,1,2,1,1,1,1,1,1,0,2,1,0,1,1,0,1,1,1,0,1,1,2,1,1,0,1, +2,2,2,0,0,1,0,0,2,2,1,1,0,0,2,1,1,0,0,0,1,2,0,0,2,1,0,0,2,1,1,1, +2,1,1,1,1,2,1,2,1,1,1,2,2,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1, +1,2,3,0,0,0,1,0,3,2,1,0,0,1,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,2,1, +1,1,0,0,0,1,0,1,1,1,1,1,2,0,0,1,0,0,0,2,0,0,1,1,1,1,1,1,1,1,0,1, +3,0,0,2,1,2,2,1,0,0,2,1,2,2,0,0,0,2,1,1,1,0,1,1,0,0,1,1,2,0,0,0, +1,2,1,2,2,1,1,2,1,2,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,0,0,1, +1,3,2,0,0,0,1,0,2,2,2,0,0,0,2,2,1,0,0,0,0,3,1,1,1,1,0,0,2,1,1,1, +2,1,0,1,1,1,0,1,1,1,1,1,1,1,0,2,1,0,0,1,0,1,1,0,1,1,1,1,1,1,0,1, +2,3,2,0,0,0,1,0,2,2,0,0,0,0,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,1,0, +2,1,1,1,1,2,1,2,1,2,0,1,1,1,0,2,1,1,1,2,1,1,1,1,0,1,1,1,1,1,0,1, +3,1,1,2,2,2,3,2,1,1,2,2,1,1,0,1,0,2,2,1,1,1,1,1,0,0,1,1,0,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,0,0,0,0,0,2,2,0,0,0,0,2,2,1,0,0,0,1,1,0,0,1,2,0,0,2,1,1,1, +2,2,1,1,1,2,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,1,1,0,1,2,1,1,1,0,1, +1,0,0,1,2,3,2,1,0,0,2,0,1,1,0,0,0,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0, +1,2,1,2,1,2,1,1,1,2,0,2,1,1,1,0,1,2,0,0,1,1,1,0,0,0,0,0,0,0,0,0, +2,3,2,0,0,0,0,0,1,1,2,1,0,0,1,1,1,0,0,0,0,2,0,0,1,1,0,0,2,1,1,1, +2,1,1,1,1,1,1,2,1,0,1,1,1,1,0,2,1,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1, +1,2,2,0,1,1,1,0,2,2,2,0,0,0,3,2,1,0,0,0,1,1,0,0,1,1,0,1,1,1,0,0, +1,1,0,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,0,0,1,1,1,0,1,0,1, +2,1,0,2,1,1,2,2,1,1,2,1,1,1,0,0,0,1,1,0,1,1,1,1,0,0,1,1,1,0,0,0, +1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,1,0, +1,2,3,0,0,0,1,0,2,2,0,0,0,0,2,2,0,0,0,0,0,1,0,0,1,0,0,0,2,0,1,0, +2,1,1,1,1,1,0,2,0,0,0,1,2,1,1,1,1,0,1,2,0,1,0,1,0,1,1,1,0,1,0,1, +2,2,2,0,0,0,1,0,2,1,2,0,0,0,1,1,2,0,0,0,0,1,0,0,1,1,0,0,2,1,0,1, +2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, +1,2,2,0,0,0,1,0,2,2,2,0,0,0,1,1,0,0,0,0,0,1,1,0,2,0,0,1,1,1,0,1, +1,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,0,0,1,1,0,1,0,1,1,1,1,1,0,0,0,1, +1,0,0,1,0,1,2,1,0,0,1,1,1,2,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,0,0,0, +0,2,1,2,1,1,1,1,1,2,0,2,0,1,1,0,1,2,1,0,1,1,1,0,0,0,0,0,0,1,0,0, +2,1,1,0,1,2,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,2,1,0,1, +2,2,1,1,1,1,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,0,1,0,1,1,1,1,1,0,1, +1,2,2,0,0,0,0,0,1,1,0,0,0,0,2,1,0,0,0,0,0,2,0,0,2,2,0,0,2,0,0,1, +2,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,1, +1,1,2,0,0,3,1,0,2,1,1,1,0,0,1,1,1,0,0,0,1,1,0,0,0,1,0,0,1,0,1,0, +1,2,1,0,1,1,1,2,1,1,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,0,0, +2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,2,0,0,0, +2,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,1,0,1, +2,1,1,1,2,1,1,1,0,1,1,2,1,0,0,0,0,1,1,1,1,0,1,0,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,0,1,1,1,1,1,0,0,1,1,2,1,0,0,0,1,1,0,0,0,1,1,0,0,1,0,1,0,0,0, +1,2,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0, +2,0,0,0,1,1,1,1,0,0,1,1,0,0,0,0,0,1,1,1,2,0,0,1,0,0,1,0,1,0,0,0, +0,1,1,1,1,1,1,1,1,2,0,1,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,1,0,0,2,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0, +0,1,1,1,1,1,1,0,1,1,0,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +0,1,1,1,1,1,0,0,1,1,0,1,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +0,0,0,1,0,0,0,0,0,0,1,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,1,1,0,1,0,0,1,1,0,1,0,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +2,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,0,1,0,0,1,0,1,0,1,1,1,0,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,1,1,1,1,1,0,1,1,0,1,0,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +) + +Latin2HungarianModel = { + 'charToOrderMap': Latin2_HungarianCharToOrderMap, + 'precedenceMatrix': HungarianLangModel, + 'mTypicalPositiveRatio': 0.947368, + 'keepEnglishLetter': True, + 'charsetName': "ISO-8859-2" +} + +Win1250HungarianModel = { + 'charToOrderMap': win1250HungarianCharToOrderMap, + 'precedenceMatrix': HungarianLangModel, + 'mTypicalPositiveRatio': 0.947368, + 'keepEnglishLetter': True, + 'charsetName': "windows-1250" +} + +# flake8: noqa diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langthaimodel.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langthaimodel.py new file mode 100644 index 0000000000..df343a7473 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/langthaimodel.py @@ -0,0 +1,200 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# The following result for thai was collected from a limited sample (1M). + +# Character Mapping Table: +TIS620CharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,182,106,107,100,183,184,185,101, 94,186,187,108,109,110,111, # 40 +188,189,190, 89, 95,112,113,191,192,193,194,253,253,253,253,253, # 50 +253, 64, 72, 73,114, 74,115,116,102, 81,201,117, 90,103, 78, 82, # 60 + 96,202, 91, 79, 84,104,105, 97, 98, 92,203,253,253,253,253,253, # 70 +209,210,211,212,213, 88,214,215,216,217,218,219,220,118,221,222, +223,224, 99, 85, 83,225,226,227,228,229,230,231,232,233,234,235, +236, 5, 30,237, 24,238, 75, 8, 26, 52, 34, 51,119, 47, 58, 57, + 49, 53, 55, 43, 20, 19, 44, 14, 48, 3, 17, 25, 39, 62, 31, 54, + 45, 9, 16, 2, 61, 15,239, 12, 42, 46, 18, 21, 76, 4, 66, 63, + 22, 10, 1, 36, 23, 13, 40, 27, 32, 35, 86,240,241,242,243,244, + 11, 28, 41, 29, 33,245, 50, 37, 6, 7, 67, 77, 38, 93,246,247, + 68, 56, 59, 65, 69, 60, 70, 80, 71, 87,248,249,250,251,252,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 92.6386% +# first 1024 sequences:7.3177% +# rest sequences: 1.0230% +# negative sequences: 0.0436% +ThaiLangModel = ( +0,1,3,3,3,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,0,0,3,3,3,0,3,3,3,3, +0,3,3,0,0,0,1,3,0,3,3,2,3,3,0,1,2,3,3,3,3,0,2,0,2,0,0,3,2,1,2,2, +3,0,3,3,2,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,0,3,2,3,0,2,2,2,3, +0,2,3,0,0,0,0,1,0,1,2,3,1,1,3,2,2,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1, +3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,3,3,2,3,2,3,3,2,2,2, +3,1,2,3,0,3,3,2,2,1,2,3,3,1,2,0,1,3,0,1,0,0,1,0,0,0,0,0,0,0,1,1, +3,3,2,2,3,3,3,3,1,2,3,3,3,3,3,2,2,2,2,3,3,2,2,3,3,2,2,3,2,3,2,2, +3,3,1,2,3,1,2,2,3,3,1,0,2,1,0,0,3,1,2,1,0,0,1,0,0,0,0,0,0,1,0,1, +3,3,3,3,3,3,2,2,3,3,3,3,2,3,2,2,3,3,2,2,3,2,2,2,2,1,1,3,1,2,1,1, +3,2,1,0,2,1,0,1,0,1,1,0,1,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,3,2,3,2,3,3,2,2,3,2,3,3,2,3,1,1,2,3,2,2,2,3,2,2,2,2,2,1,2,1, +2,2,1,1,3,3,2,1,0,1,2,2,0,1,3,0,0,0,1,1,0,0,0,0,0,2,3,0,0,2,1,1, +3,3,2,3,3,2,0,0,3,3,0,3,3,0,2,2,3,1,2,2,1,1,1,0,2,2,2,0,2,2,1,1, +0,2,1,0,2,0,0,2,0,1,0,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,2,3,3,2,0,0,3,3,0,2,3,0,2,1,2,2,2,2,1,2,0,0,2,2,2,0,2,2,1,1, +0,2,1,0,2,0,0,2,0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,2,3,2,3,2,0,2,2,1,3,2,1,3,2,1,2,3,2,2,3,0,2,3,2,2,1,2,2,2,2, +1,2,2,0,0,0,0,2,0,1,2,0,1,1,1,0,1,0,3,1,1,0,0,0,0,0,0,0,0,0,1,0, +3,3,2,3,3,2,3,2,2,2,3,2,2,3,2,2,1,2,3,2,2,3,1,3,2,2,2,3,2,2,2,3, +3,2,1,3,0,1,1,1,0,2,1,1,1,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,2,0,0, +1,0,0,3,0,3,3,3,3,3,0,0,3,0,2,2,3,3,3,3,3,0,0,0,1,1,3,0,0,0,0,2, +0,0,1,0,0,0,0,0,0,0,2,3,0,0,0,3,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +2,0,3,3,3,3,0,0,2,3,0,0,3,0,3,3,2,3,3,3,3,3,0,0,3,3,3,0,0,0,3,3, +0,0,3,0,0,0,0,2,0,0,2,1,1,3,0,0,1,0,0,2,3,0,1,0,0,0,0,0,0,0,1,0, +3,3,3,3,2,3,3,3,3,3,3,3,1,2,1,3,3,2,2,1,2,2,2,3,1,1,2,0,2,1,2,1, +2,2,1,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0, +3,0,2,1,2,3,3,3,0,2,0,2,2,0,2,1,3,2,2,1,2,1,0,0,2,2,1,0,2,1,2,2, +0,1,1,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,3,3,1,1,3,0,2,3,1,1,3,2,1,1,2,0,2,2,3,2,1,1,1,1,1,2, +3,0,0,1,3,1,2,1,2,0,3,0,0,0,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, +3,3,1,1,3,2,3,3,3,1,3,2,1,3,2,1,3,2,2,2,2,1,3,3,1,2,1,3,1,2,3,0, +2,1,1,3,2,2,2,1,2,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, +3,3,2,3,2,3,3,2,3,2,3,2,3,3,2,1,0,3,2,2,2,1,2,2,2,1,2,2,1,2,1,1, +2,2,2,3,0,1,3,1,1,1,1,0,1,1,0,2,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,3,2,2,1,1,3,2,3,2,3,2,0,3,2,2,1,2,0,2,2,2,1,2,2,2,2,1, +3,2,1,2,2,1,0,2,0,1,0,0,1,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,2,3,1,2,3,3,2,2,3,0,1,1,2,0,3,3,2,2,3,0,1,1,3,0,0,0,0, +3,1,0,3,3,0,2,0,2,1,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,3,2,3,3,0,1,3,1,1,2,1,2,1,1,3,1,1,0,2,3,1,1,1,1,1,1,1,1, +3,1,1,2,2,2,2,1,1,1,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,2,2,1,1,2,1,3,3,2,3,2,2,3,2,2,3,1,2,2,1,2,0,3,2,1,2,2,2,2,2,1, +3,2,1,2,2,2,1,1,1,1,0,0,1,1,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,1,3,3,0,2,1,0,3,2,0,0,3,1,0,1,1,0,1,0,0,0,0,0,1, +1,0,0,1,0,3,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,2,2,2,3,0,0,1,3,0,3,2,0,3,2,2,3,3,3,3,3,1,0,2,2,2,0,2,2,1,2, +0,2,3,0,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,0,2,3,1,3,3,2,3,3,0,3,3,0,3,2,2,3,2,3,3,3,0,0,2,2,3,0,1,1,1,3, +0,0,3,0,0,0,2,2,0,1,3,0,1,2,2,2,3,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1, +3,2,3,3,2,0,3,3,2,2,3,1,3,2,1,3,2,0,1,2,2,0,2,3,2,1,0,3,0,0,0,0, +3,0,0,2,3,1,3,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,3,2,2,2,1,2,0,1,3,1,1,3,1,3,0,0,2,1,1,1,1,2,1,1,1,0,2,1,0,1, +1,2,0,0,0,3,1,1,0,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,3,1,0,0,0,1,0, +3,3,3,3,2,2,2,2,2,1,3,1,1,1,2,0,1,1,2,1,2,1,3,2,0,0,3,1,1,1,1,1, +3,1,0,2,3,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,2,3,0,3,3,0,2,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,3,1,3,0,0,1,2,0,0,2,0,3,3,2,3,3,3,2,3,0,0,2,2,2,0,0,0,2,2, +0,0,1,0,0,0,0,3,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +0,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,1,2,3,1,3,3,0,0,1,0,3,0,0,0,0,0, +0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,1,2,3,1,2,3,1,0,3,0,2,2,1,0,2,1,1,2,0,1,0,0,1,1,1,1,0,1,0,0, +1,0,0,0,0,1,1,0,3,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,0,1,1,1,3,1,2,2,2,2,2,2,1,1,1,1,0,3,1,0,1,3,1,1,1,1, +1,1,0,2,0,1,3,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1, +3,0,2,2,1,3,3,2,3,3,0,1,1,0,2,2,1,2,1,3,3,1,0,0,3,2,0,0,0,0,2,1, +0,1,0,0,0,0,1,2,0,1,1,3,1,1,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,3,0,0,1,0,0,0,3,0,0,3,0,3,1,0,1,1,1,3,2,0,0,0,3,0,0,0,0,2,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,1,3,2,1,3,3,1,2,2,0,1,2,1,0,1,2,0,0,0,0,0,3,0,0,0,3,0,0,0,0, +3,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,2,0,3,3,3,2,2,0,1,1,0,1,3,0,0,0,2,2,0,0,0,0,3,1,0,1,0,0,0, +0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,2,3,1,2,0,0,2,1,0,3,1,0,1,2,0,1,1,1,1,3,0,0,3,1,1,0,2,2,1,1, +0,2,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,3,1,2,0,0,2,2,0,1,2,0,1,0,1,3,1,2,1,0,0,0,2,0,3,0,0,0,1,0, +0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,1,2,2,0,0,0,2,0,2,1,0,1,1,0,1,1,1,2,1,0,0,1,1,1,0,2,1,1,1, +0,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1, +0,0,0,2,0,1,3,1,1,1,1,0,0,0,0,3,2,0,1,0,0,0,1,2,0,0,0,1,0,0,0,0, +0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,2,3,2,2,0,0,0,1,0,0,0,0,2,3,2,1,2,2,3,0,0,0,2,3,1,0,0,0,1,1, +0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0, +3,3,2,2,0,1,0,0,0,0,2,0,2,0,1,0,0,0,1,1,0,0,0,2,1,0,1,0,1,1,0,0, +0,1,0,2,0,0,1,0,3,0,1,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,1,0,0,1,0,0,0,0,0,1,1,2,0,0,0,0,1,0,0,1,3,1,0,0,0,0,1,1,0,0, +0,1,0,0,0,0,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0, +3,3,1,1,1,1,2,3,0,0,2,1,1,1,1,1,0,2,1,1,0,0,0,2,1,0,1,2,1,1,0,1, +2,1,0,3,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,3,1,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1, +0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,0,0,0,0,0,0,1,2,1,0,1,1,0,2,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,2,0,0,0,1,3,0,1,0,0,0,2,0,0,0,0,0,0,0,1,2,0,0,0,0,0, +3,3,0,0,1,1,2,0,0,1,2,1,0,1,1,1,0,1,1,0,0,2,1,1,0,1,0,0,1,1,1,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,1,0,0,0,0,1,0,0,0,0,3,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,0,0,1,1,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,0,1,2,0,1,2,0,0,1,1,0,2,0,1,0,0,1,0,0,0,0,1,0,0,0,2,0,0,0,0, +1,0,0,1,0,1,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,0,0,0,0,0,0,0,1,1,0,1,1,0,2,1,3,0,0,0,0,1,1,0,0,0,0,0,0,0,3, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,1,0,0,2,0,0,2,0,0,1,1,2,0,0,1,1,0,0,0,1,0,0,0,1,1,0,0,0, +1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,3,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0, +1,0,0,0,0,0,0,0,0,1,0,0,0,0,2,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,1,0,0,2,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +) + +TIS620ThaiModel = { + 'charToOrderMap': TIS620CharToOrderMap, + 'precedenceMatrix': ThaiLangModel, + 'mTypicalPositiveRatio': 0.926386, + 'keepEnglishLetter': False, + 'charsetName': "TIS-620" +} + +# flake8: noqa diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/latin1prober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/latin1prober.py new file mode 100644 index 0000000000..18eefd46a5 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/latin1prober.py @@ -0,0 +1,139 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .constants import eNotMe +from .compat import wrap_ord + +FREQ_CAT_NUM = 4 + +UDF = 0 # undefined +OTH = 1 # other +ASC = 2 # ascii capital letter +ASS = 3 # ascii small letter +ACV = 4 # accent capital vowel +ACO = 5 # accent capital other +ASV = 6 # accent small vowel +ASO = 7 # accent small other +CLASS_NUM = 8 # total classes + +Latin1_CharToClass = ( + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 00 - 07 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 08 - 0F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 10 - 17 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 18 - 1F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 20 - 27 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 28 - 2F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 30 - 37 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 38 - 3F + OTH, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 40 - 47 + ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 48 - 4F + ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 50 - 57 + ASC, ASC, ASC, OTH, OTH, OTH, OTH, OTH, # 58 - 5F + OTH, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 60 - 67 + ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 68 - 6F + ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 70 - 77 + ASS, ASS, ASS, OTH, OTH, OTH, OTH, OTH, # 78 - 7F + OTH, UDF, OTH, ASO, OTH, OTH, OTH, OTH, # 80 - 87 + OTH, OTH, ACO, OTH, ACO, UDF, ACO, UDF, # 88 - 8F + UDF, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 90 - 97 + OTH, OTH, ASO, OTH, ASO, UDF, ASO, ACO, # 98 - 9F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A0 - A7 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A8 - AF + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B0 - B7 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B8 - BF + ACV, ACV, ACV, ACV, ACV, ACV, ACO, ACO, # C0 - C7 + ACV, ACV, ACV, ACV, ACV, ACV, ACV, ACV, # C8 - CF + ACO, ACO, ACV, ACV, ACV, ACV, ACV, OTH, # D0 - D7 + ACV, ACV, ACV, ACV, ACV, ACO, ACO, ACO, # D8 - DF + ASV, ASV, ASV, ASV, ASV, ASV, ASO, ASO, # E0 - E7 + ASV, ASV, ASV, ASV, ASV, ASV, ASV, ASV, # E8 - EF + ASO, ASO, ASV, ASV, ASV, ASV, ASV, OTH, # F0 - F7 + ASV, ASV, ASV, ASV, ASV, ASO, ASO, ASO, # F8 - FF +) + +# 0 : illegal +# 1 : very unlikely +# 2 : normal +# 3 : very likely +Latin1ClassModel = ( + # UDF OTH ASC ASS ACV ACO ASV ASO + 0, 0, 0, 0, 0, 0, 0, 0, # UDF + 0, 3, 3, 3, 3, 3, 3, 3, # OTH + 0, 3, 3, 3, 3, 3, 3, 3, # ASC + 0, 3, 3, 3, 1, 1, 3, 3, # ASS + 0, 3, 3, 3, 1, 2, 1, 2, # ACV + 0, 3, 3, 3, 3, 3, 3, 3, # ACO + 0, 3, 1, 3, 1, 1, 1, 3, # ASV + 0, 3, 1, 3, 1, 1, 3, 3, # ASO +) + + +class Latin1Prober(CharSetProber): + def __init__(self): + CharSetProber.__init__(self) + self.reset() + + def reset(self): + self._mLastCharClass = OTH + self._mFreqCounter = [0] * FREQ_CAT_NUM + CharSetProber.reset(self) + + def get_charset_name(self): + return "windows-1252" + + def feed(self, aBuf): + aBuf = self.filter_with_english_letters(aBuf) + for c in aBuf: + charClass = Latin1_CharToClass[wrap_ord(c)] + freq = Latin1ClassModel[(self._mLastCharClass * CLASS_NUM) + + charClass] + if freq == 0: + self._mState = eNotMe + break + self._mFreqCounter[freq] += 1 + self._mLastCharClass = charClass + + return self.get_state() + + def get_confidence(self): + if self.get_state() == eNotMe: + return 0.01 + + total = sum(self._mFreqCounter) + if total < 0.01: + confidence = 0.0 + else: + confidence = ((float(self._mFreqCounter[3]) / total) + - (self._mFreqCounter[1] * 20.0 / total)) + if confidence < 0.0: + confidence = 0.0 + # lower the confidence of latin1 so that other more accurate + # detector can take priority. + confidence = confidence * 0.5 + return confidence diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/mbcharsetprober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/mbcharsetprober.py new file mode 100644 index 0000000000..1eee253c04 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/mbcharsetprober.py @@ -0,0 +1,86 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Proofpoint, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import sys +from . import constants +from .charsetprober import CharSetProber + + +class MultiByteCharSetProber(CharSetProber): + def __init__(self): + CharSetProber.__init__(self) + self._mDistributionAnalyzer = None + self._mCodingSM = None + self._mLastChar = [0, 0] + + def reset(self): + CharSetProber.reset(self) + if self._mCodingSM: + self._mCodingSM.reset() + if self._mDistributionAnalyzer: + self._mDistributionAnalyzer.reset() + self._mLastChar = [0, 0] + + def get_charset_name(self): + pass + + def feed(self, aBuf): + aLen = len(aBuf) + for i in range(0, aLen): + codingState = self._mCodingSM.next_state(aBuf[i]) + if codingState == constants.eError: + if constants._debug: + sys.stderr.write(self.get_charset_name() + + ' prober hit error at byte ' + str(i) + + '\n') + self._mState = constants.eNotMe + break + elif codingState == constants.eItsMe: + self._mState = constants.eFoundIt + break + elif codingState == constants.eStart: + charLen = self._mCodingSM.get_current_charlen() + if i == 0: + self._mLastChar[1] = aBuf[0] + self._mDistributionAnalyzer.feed(self._mLastChar, charLen) + else: + self._mDistributionAnalyzer.feed(aBuf[i - 1:i + 1], + charLen) + + self._mLastChar[0] = aBuf[aLen - 1] + + if self.get_state() == constants.eDetecting: + if (self._mDistributionAnalyzer.got_enough_data() and + (self.get_confidence() > constants.SHORTCUT_THRESHOLD)): + self._mState = constants.eFoundIt + + return self.get_state() + + def get_confidence(self): + return self._mDistributionAnalyzer.get_confidence() diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/mbcsgroupprober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/mbcsgroupprober.py new file mode 100644 index 0000000000..2f6f5e897f --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/mbcsgroupprober.py @@ -0,0 +1,54 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Proofpoint, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetgroupprober import CharSetGroupProber +from .utf8prober import UTF8Prober +from .sjisprober import SJISProber +from .eucjpprober import EUCJPProber +from .gb2312prober import GB2312Prober +from .euckrprober import EUCKRProber +from .cp949prober import CP949Prober +from .big5prober import Big5Prober +from .euctwprober import EUCTWProber + + +class MBCSGroupProber(CharSetGroupProber): + def __init__(self): + CharSetGroupProber.__init__(self) + self._mProbers = [ + UTF8Prober(), + SJISProber(), + EUCJPProber(), + GB2312Prober(), + EUCKRProber(), + CP949Prober(), + Big5Prober(), + EUCTWProber() + ] + self.reset() diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/mbcssm.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/mbcssm.py new file mode 100644 index 0000000000..55c02f0a06 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/mbcssm.py @@ -0,0 +1,575 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .constants import eStart, eError, eItsMe + +# BIG5 + +BIG5_cls = ( + 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as legal value + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,1, # 78 - 7f + 4,4,4,4,4,4,4,4, # 80 - 87 + 4,4,4,4,4,4,4,4, # 88 - 8f + 4,4,4,4,4,4,4,4, # 90 - 97 + 4,4,4,4,4,4,4,4, # 98 - 9f + 4,3,3,3,3,3,3,3, # a0 - a7 + 3,3,3,3,3,3,3,3, # a8 - af + 3,3,3,3,3,3,3,3, # b0 - b7 + 3,3,3,3,3,3,3,3, # b8 - bf + 3,3,3,3,3,3,3,3, # c0 - c7 + 3,3,3,3,3,3,3,3, # c8 - cf + 3,3,3,3,3,3,3,3, # d0 - d7 + 3,3,3,3,3,3,3,3, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,3,3,3, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,3,3,0 # f8 - ff +) + +BIG5_st = ( + eError,eStart,eStart, 3,eError,eError,eError,eError,#00-07 + eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eError,#08-0f + eError,eStart,eStart,eStart,eStart,eStart,eStart,eStart#10-17 +) + +Big5CharLenTable = (0, 1, 1, 2, 0) + +Big5SMModel = {'classTable': BIG5_cls, + 'classFactor': 5, + 'stateTable': BIG5_st, + 'charLenTable': Big5CharLenTable, + 'name': 'Big5'} + +# CP949 + +CP949_cls = ( + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,0,0, # 00 - 0f + 1,1,1,1,1,1,1,1, 1,1,1,0,1,1,1,1, # 10 - 1f + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, # 20 - 2f + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, # 30 - 3f + 1,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4, # 40 - 4f + 4,4,5,5,5,5,5,5, 5,5,5,1,1,1,1,1, # 50 - 5f + 1,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5, # 60 - 6f + 5,5,5,5,5,5,5,5, 5,5,5,1,1,1,1,1, # 70 - 7f + 0,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6, # 80 - 8f + 6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6, # 90 - 9f + 6,7,7,7,7,7,7,7, 7,7,7,7,7,8,8,8, # a0 - af + 7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7, # b0 - bf + 7,7,7,7,7,7,9,2, 2,3,2,2,2,2,2,2, # c0 - cf + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, # d0 - df + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, # e0 - ef + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,0, # f0 - ff +) + +CP949_st = ( +#cls= 0 1 2 3 4 5 6 7 8 9 # previous state = + eError,eStart, 3,eError,eStart,eStart, 4, 5,eError, 6, # eStart + eError,eError,eError,eError,eError,eError,eError,eError,eError,eError, # eError + eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe, # eItsMe + eError,eError,eStart,eStart,eError,eError,eError,eStart,eStart,eStart, # 3 + eError,eError,eStart,eStart,eStart,eStart,eStart,eStart,eStart,eStart, # 4 + eError,eStart,eStart,eStart,eStart,eStart,eStart,eStart,eStart,eStart, # 5 + eError,eStart,eStart,eStart,eStart,eError,eError,eStart,eStart,eStart, # 6 +) + +CP949CharLenTable = (0, 1, 2, 0, 1, 1, 2, 2, 0, 2) + +CP949SMModel = {'classTable': CP949_cls, + 'classFactor': 10, + 'stateTable': CP949_st, + 'charLenTable': CP949CharLenTable, + 'name': 'CP949'} + +# EUC-JP + +EUCJP_cls = ( + 4,4,4,4,4,4,4,4, # 00 - 07 + 4,4,4,4,4,4,5,5, # 08 - 0f + 4,4,4,4,4,4,4,4, # 10 - 17 + 4,4,4,5,4,4,4,4, # 18 - 1f + 4,4,4,4,4,4,4,4, # 20 - 27 + 4,4,4,4,4,4,4,4, # 28 - 2f + 4,4,4,4,4,4,4,4, # 30 - 37 + 4,4,4,4,4,4,4,4, # 38 - 3f + 4,4,4,4,4,4,4,4, # 40 - 47 + 4,4,4,4,4,4,4,4, # 48 - 4f + 4,4,4,4,4,4,4,4, # 50 - 57 + 4,4,4,4,4,4,4,4, # 58 - 5f + 4,4,4,4,4,4,4,4, # 60 - 67 + 4,4,4,4,4,4,4,4, # 68 - 6f + 4,4,4,4,4,4,4,4, # 70 - 77 + 4,4,4,4,4,4,4,4, # 78 - 7f + 5,5,5,5,5,5,5,5, # 80 - 87 + 5,5,5,5,5,5,1,3, # 88 - 8f + 5,5,5,5,5,5,5,5, # 90 - 97 + 5,5,5,5,5,5,5,5, # 98 - 9f + 5,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,2,2,2, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,2,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,0,5 # f8 - ff +) + +EUCJP_st = ( + 3, 4, 3, 5,eStart,eError,eError,eError,#00-07 + eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,#08-0f + eItsMe,eItsMe,eStart,eError,eStart,eError,eError,eError,#10-17 + eError,eError,eStart,eError,eError,eError, 3,eError,#18-1f + 3,eError,eError,eError,eStart,eStart,eStart,eStart#20-27 +) + +EUCJPCharLenTable = (2, 2, 2, 3, 1, 0) + +EUCJPSMModel = {'classTable': EUCJP_cls, + 'classFactor': 6, + 'stateTable': EUCJP_st, + 'charLenTable': EUCJPCharLenTable, + 'name': 'EUC-JP'} + +# EUC-KR + +EUCKR_cls = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 1,1,1,1,1,1,1,1, # 40 - 47 + 1,1,1,1,1,1,1,1, # 48 - 4f + 1,1,1,1,1,1,1,1, # 50 - 57 + 1,1,1,1,1,1,1,1, # 58 - 5f + 1,1,1,1,1,1,1,1, # 60 - 67 + 1,1,1,1,1,1,1,1, # 68 - 6f + 1,1,1,1,1,1,1,1, # 70 - 77 + 1,1,1,1,1,1,1,1, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,3,3,3, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,3,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 2,2,2,2,2,2,2,2, # e0 - e7 + 2,2,2,2,2,2,2,2, # e8 - ef + 2,2,2,2,2,2,2,2, # f0 - f7 + 2,2,2,2,2,2,2,0 # f8 - ff +) + +EUCKR_st = ( + eError,eStart, 3,eError,eError,eError,eError,eError,#00-07 + eItsMe,eItsMe,eItsMe,eItsMe,eError,eError,eStart,eStart #08-0f +) + +EUCKRCharLenTable = (0, 1, 2, 0) + +EUCKRSMModel = {'classTable': EUCKR_cls, + 'classFactor': 4, + 'stateTable': EUCKR_st, + 'charLenTable': EUCKRCharLenTable, + 'name': 'EUC-KR'} + +# EUC-TW + +EUCTW_cls = ( + 2,2,2,2,2,2,2,2, # 00 - 07 + 2,2,2,2,2,2,0,0, # 08 - 0f + 2,2,2,2,2,2,2,2, # 10 - 17 + 2,2,2,0,2,2,2,2, # 18 - 1f + 2,2,2,2,2,2,2,2, # 20 - 27 + 2,2,2,2,2,2,2,2, # 28 - 2f + 2,2,2,2,2,2,2,2, # 30 - 37 + 2,2,2,2,2,2,2,2, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,2, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,6,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,3,4,4,4,4,4,4, # a0 - a7 + 5,5,1,1,1,1,1,1, # a8 - af + 1,1,1,1,1,1,1,1, # b0 - b7 + 1,1,1,1,1,1,1,1, # b8 - bf + 1,1,3,1,3,3,3,3, # c0 - c7 + 3,3,3,3,3,3,3,3, # c8 - cf + 3,3,3,3,3,3,3,3, # d0 - d7 + 3,3,3,3,3,3,3,3, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,3,3,3, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,3,3,0 # f8 - ff +) + +EUCTW_st = ( + eError,eError,eStart, 3, 3, 3, 4,eError,#00-07 + eError,eError,eError,eError,eError,eError,eItsMe,eItsMe,#08-0f + eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eError,eStart,eError,#10-17 + eStart,eStart,eStart,eError,eError,eError,eError,eError,#18-1f + 5,eError,eError,eError,eStart,eError,eStart,eStart,#20-27 + eStart,eError,eStart,eStart,eStart,eStart,eStart,eStart #28-2f +) + +EUCTWCharLenTable = (0, 0, 1, 2, 2, 2, 3) + +EUCTWSMModel = {'classTable': EUCTW_cls, + 'classFactor': 7, + 'stateTable': EUCTW_st, + 'charLenTable': EUCTWCharLenTable, + 'name': 'x-euc-tw'} + +# GB2312 + +GB2312_cls = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 3,3,3,3,3,3,3,3, # 30 - 37 + 3,3,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,4, # 78 - 7f + 5,6,6,6,6,6,6,6, # 80 - 87 + 6,6,6,6,6,6,6,6, # 88 - 8f + 6,6,6,6,6,6,6,6, # 90 - 97 + 6,6,6,6,6,6,6,6, # 98 - 9f + 6,6,6,6,6,6,6,6, # a0 - a7 + 6,6,6,6,6,6,6,6, # a8 - af + 6,6,6,6,6,6,6,6, # b0 - b7 + 6,6,6,6,6,6,6,6, # b8 - bf + 6,6,6,6,6,6,6,6, # c0 - c7 + 6,6,6,6,6,6,6,6, # c8 - cf + 6,6,6,6,6,6,6,6, # d0 - d7 + 6,6,6,6,6,6,6,6, # d8 - df + 6,6,6,6,6,6,6,6, # e0 - e7 + 6,6,6,6,6,6,6,6, # e8 - ef + 6,6,6,6,6,6,6,6, # f0 - f7 + 6,6,6,6,6,6,6,0 # f8 - ff +) + +GB2312_st = ( + eError,eStart,eStart,eStart,eStart,eStart, 3,eError,#00-07 + eError,eError,eError,eError,eError,eError,eItsMe,eItsMe,#08-0f + eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eError,eError,eStart,#10-17 + 4,eError,eStart,eStart,eError,eError,eError,eError,#18-1f + eError,eError, 5,eError,eError,eError,eItsMe,eError,#20-27 + eError,eError,eStart,eStart,eStart,eStart,eStart,eStart #28-2f +) + +# To be accurate, the length of class 6 can be either 2 or 4. +# But it is not necessary to discriminate between the two since +# it is used for frequency analysis only, and we are validing +# each code range there as well. So it is safe to set it to be +# 2 here. +GB2312CharLenTable = (0, 1, 1, 1, 1, 1, 2) + +GB2312SMModel = {'classTable': GB2312_cls, + 'classFactor': 7, + 'stateTable': GB2312_st, + 'charLenTable': GB2312CharLenTable, + 'name': 'GB2312'} + +# Shift_JIS + +SJIS_cls = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,1, # 78 - 7f + 3,3,3,3,3,3,3,3, # 80 - 87 + 3,3,3,3,3,3,3,3, # 88 - 8f + 3,3,3,3,3,3,3,3, # 90 - 97 + 3,3,3,3,3,3,3,3, # 98 - 9f + #0xa0 is illegal in sjis encoding, but some pages does + #contain such byte. We need to be more error forgiven. + 2,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,2,2,2, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,2,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,4,4,4, # e8 - ef + 4,4,4,4,4,4,4,4, # f0 - f7 + 4,4,4,4,4,0,0,0 # f8 - ff +) + + +SJIS_st = ( + eError,eStart,eStart, 3,eError,eError,eError,eError,#00-07 + eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,#08-0f + eItsMe,eItsMe,eError,eError,eStart,eStart,eStart,eStart #10-17 +) + +SJISCharLenTable = (0, 1, 1, 2, 0, 0) + +SJISSMModel = {'classTable': SJIS_cls, + 'classFactor': 6, + 'stateTable': SJIS_st, + 'charLenTable': SJISCharLenTable, + 'name': 'Shift_JIS'} + +# UCS2-BE + +UCS2BE_cls = ( + 0,0,0,0,0,0,0,0, # 00 - 07 + 0,0,1,0,0,2,0,0, # 08 - 0f + 0,0,0,0,0,0,0,0, # 10 - 17 + 0,0,0,3,0,0,0,0, # 18 - 1f + 0,0,0,0,0,0,0,0, # 20 - 27 + 0,3,3,3,3,3,0,0, # 28 - 2f + 0,0,0,0,0,0,0,0, # 30 - 37 + 0,0,0,0,0,0,0,0, # 38 - 3f + 0,0,0,0,0,0,0,0, # 40 - 47 + 0,0,0,0,0,0,0,0, # 48 - 4f + 0,0,0,0,0,0,0,0, # 50 - 57 + 0,0,0,0,0,0,0,0, # 58 - 5f + 0,0,0,0,0,0,0,0, # 60 - 67 + 0,0,0,0,0,0,0,0, # 68 - 6f + 0,0,0,0,0,0,0,0, # 70 - 77 + 0,0,0,0,0,0,0,0, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,0,0,0,0,0,0,0, # a0 - a7 + 0,0,0,0,0,0,0,0, # a8 - af + 0,0,0,0,0,0,0,0, # b0 - b7 + 0,0,0,0,0,0,0,0, # b8 - bf + 0,0,0,0,0,0,0,0, # c0 - c7 + 0,0,0,0,0,0,0,0, # c8 - cf + 0,0,0,0,0,0,0,0, # d0 - d7 + 0,0,0,0,0,0,0,0, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,4,5 # f8 - ff +) + +UCS2BE_st = ( + 5, 7, 7,eError, 4, 3,eError,eError,#00-07 + eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,#08-0f + eItsMe,eItsMe, 6, 6, 6, 6,eError,eError,#10-17 + 6, 6, 6, 6, 6,eItsMe, 6, 6,#18-1f + 6, 6, 6, 6, 5, 7, 7,eError,#20-27 + 5, 8, 6, 6,eError, 6, 6, 6,#28-2f + 6, 6, 6, 6,eError,eError,eStart,eStart #30-37 +) + +UCS2BECharLenTable = (2, 2, 2, 0, 2, 2) + +UCS2BESMModel = {'classTable': UCS2BE_cls, + 'classFactor': 6, + 'stateTable': UCS2BE_st, + 'charLenTable': UCS2BECharLenTable, + 'name': 'UTF-16BE'} + +# UCS2-LE + +UCS2LE_cls = ( + 0,0,0,0,0,0,0,0, # 00 - 07 + 0,0,1,0,0,2,0,0, # 08 - 0f + 0,0,0,0,0,0,0,0, # 10 - 17 + 0,0,0,3,0,0,0,0, # 18 - 1f + 0,0,0,0,0,0,0,0, # 20 - 27 + 0,3,3,3,3,3,0,0, # 28 - 2f + 0,0,0,0,0,0,0,0, # 30 - 37 + 0,0,0,0,0,0,0,0, # 38 - 3f + 0,0,0,0,0,0,0,0, # 40 - 47 + 0,0,0,0,0,0,0,0, # 48 - 4f + 0,0,0,0,0,0,0,0, # 50 - 57 + 0,0,0,0,0,0,0,0, # 58 - 5f + 0,0,0,0,0,0,0,0, # 60 - 67 + 0,0,0,0,0,0,0,0, # 68 - 6f + 0,0,0,0,0,0,0,0, # 70 - 77 + 0,0,0,0,0,0,0,0, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,0,0,0,0,0,0,0, # a0 - a7 + 0,0,0,0,0,0,0,0, # a8 - af + 0,0,0,0,0,0,0,0, # b0 - b7 + 0,0,0,0,0,0,0,0, # b8 - bf + 0,0,0,0,0,0,0,0, # c0 - c7 + 0,0,0,0,0,0,0,0, # c8 - cf + 0,0,0,0,0,0,0,0, # d0 - d7 + 0,0,0,0,0,0,0,0, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,4,5 # f8 - ff +) + +UCS2LE_st = ( + 6, 6, 7, 6, 4, 3,eError,eError,#00-07 + eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe,#08-0f + eItsMe,eItsMe, 5, 5, 5,eError,eItsMe,eError,#10-17 + 5, 5, 5,eError, 5,eError, 6, 6,#18-1f + 7, 6, 8, 8, 5, 5, 5,eError,#20-27 + 5, 5, 5,eError,eError,eError, 5, 5,#28-2f + 5, 5, 5,eError, 5,eError,eStart,eStart #30-37 +) + +UCS2LECharLenTable = (2, 2, 2, 2, 2, 2) + +UCS2LESMModel = {'classTable': UCS2LE_cls, + 'classFactor': 6, + 'stateTable': UCS2LE_st, + 'charLenTable': UCS2LECharLenTable, + 'name': 'UTF-16LE'} + +# UTF-8 + +UTF8_cls = ( + 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as a legal value + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 1,1,1,1,1,1,1,1, # 40 - 47 + 1,1,1,1,1,1,1,1, # 48 - 4f + 1,1,1,1,1,1,1,1, # 50 - 57 + 1,1,1,1,1,1,1,1, # 58 - 5f + 1,1,1,1,1,1,1,1, # 60 - 67 + 1,1,1,1,1,1,1,1, # 68 - 6f + 1,1,1,1,1,1,1,1, # 70 - 77 + 1,1,1,1,1,1,1,1, # 78 - 7f + 2,2,2,2,3,3,3,3, # 80 - 87 + 4,4,4,4,4,4,4,4, # 88 - 8f + 4,4,4,4,4,4,4,4, # 90 - 97 + 4,4,4,4,4,4,4,4, # 98 - 9f + 5,5,5,5,5,5,5,5, # a0 - a7 + 5,5,5,5,5,5,5,5, # a8 - af + 5,5,5,5,5,5,5,5, # b0 - b7 + 5,5,5,5,5,5,5,5, # b8 - bf + 0,0,6,6,6,6,6,6, # c0 - c7 + 6,6,6,6,6,6,6,6, # c8 - cf + 6,6,6,6,6,6,6,6, # d0 - d7 + 6,6,6,6,6,6,6,6, # d8 - df + 7,8,8,8,8,8,8,8, # e0 - e7 + 8,8,8,8,8,9,8,8, # e8 - ef + 10,11,11,11,11,11,11,11, # f0 - f7 + 12,13,13,13,14,15,0,0 # f8 - ff +) + +UTF8_st = ( + eError,eStart,eError,eError,eError,eError, 12, 10,#00-07 + 9, 11, 8, 7, 6, 5, 4, 3,#08-0f + eError,eError,eError,eError,eError,eError,eError,eError,#10-17 + eError,eError,eError,eError,eError,eError,eError,eError,#18-1f + eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,#20-27 + eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,eItsMe,#28-2f + eError,eError, 5, 5, 5, 5,eError,eError,#30-37 + eError,eError,eError,eError,eError,eError,eError,eError,#38-3f + eError,eError,eError, 5, 5, 5,eError,eError,#40-47 + eError,eError,eError,eError,eError,eError,eError,eError,#48-4f + eError,eError, 7, 7, 7, 7,eError,eError,#50-57 + eError,eError,eError,eError,eError,eError,eError,eError,#58-5f + eError,eError,eError,eError, 7, 7,eError,eError,#60-67 + eError,eError,eError,eError,eError,eError,eError,eError,#68-6f + eError,eError, 9, 9, 9, 9,eError,eError,#70-77 + eError,eError,eError,eError,eError,eError,eError,eError,#78-7f + eError,eError,eError,eError,eError, 9,eError,eError,#80-87 + eError,eError,eError,eError,eError,eError,eError,eError,#88-8f + eError,eError, 12, 12, 12, 12,eError,eError,#90-97 + eError,eError,eError,eError,eError,eError,eError,eError,#98-9f + eError,eError,eError,eError,eError, 12,eError,eError,#a0-a7 + eError,eError,eError,eError,eError,eError,eError,eError,#a8-af + eError,eError, 12, 12, 12,eError,eError,eError,#b0-b7 + eError,eError,eError,eError,eError,eError,eError,eError,#b8-bf + eError,eError,eStart,eStart,eStart,eStart,eError,eError,#c0-c7 + eError,eError,eError,eError,eError,eError,eError,eError #c8-cf +) + +UTF8CharLenTable = (0, 1, 0, 0, 0, 0, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6) + +UTF8SMModel = {'classTable': UTF8_cls, + 'classFactor': 16, + 'stateTable': UTF8_st, + 'charLenTable': UTF8CharLenTable, + 'name': 'UTF-8'} + +# flake8: noqa diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/sbcharsetprober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/sbcharsetprober.py new file mode 100644 index 0000000000..da26715cfc --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/sbcharsetprober.py @@ -0,0 +1,120 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import sys +from . import constants +from .charsetprober import CharSetProber +from .compat import wrap_ord + +SAMPLE_SIZE = 64 +SB_ENOUGH_REL_THRESHOLD = 1024 +POSITIVE_SHORTCUT_THRESHOLD = 0.95 +NEGATIVE_SHORTCUT_THRESHOLD = 0.05 +SYMBOL_CAT_ORDER = 250 +NUMBER_OF_SEQ_CAT = 4 +POSITIVE_CAT = NUMBER_OF_SEQ_CAT - 1 +#NEGATIVE_CAT = 0 + + +class SingleByteCharSetProber(CharSetProber): + def __init__(self, model, reversed=False, nameProber=None): + CharSetProber.__init__(self) + self._mModel = model + # TRUE if we need to reverse every pair in the model lookup + self._mReversed = reversed + # Optional auxiliary prober for name decision + self._mNameProber = nameProber + self.reset() + + def reset(self): + CharSetProber.reset(self) + # char order of last character + self._mLastOrder = 255 + self._mSeqCounters = [0] * NUMBER_OF_SEQ_CAT + self._mTotalSeqs = 0 + self._mTotalChar = 0 + # characters that fall in our sampling range + self._mFreqChar = 0 + + def get_charset_name(self): + if self._mNameProber: + return self._mNameProber.get_charset_name() + else: + return self._mModel['charsetName'] + + def feed(self, aBuf): + if not self._mModel['keepEnglishLetter']: + aBuf = self.filter_without_english_letters(aBuf) + aLen = len(aBuf) + if not aLen: + return self.get_state() + for c in aBuf: + order = self._mModel['charToOrderMap'][wrap_ord(c)] + if order < SYMBOL_CAT_ORDER: + self._mTotalChar += 1 + if order < SAMPLE_SIZE: + self._mFreqChar += 1 + if self._mLastOrder < SAMPLE_SIZE: + self._mTotalSeqs += 1 + if not self._mReversed: + i = (self._mLastOrder * SAMPLE_SIZE) + order + model = self._mModel['precedenceMatrix'][i] + else: # reverse the order of the letters in the lookup + i = (order * SAMPLE_SIZE) + self._mLastOrder + model = self._mModel['precedenceMatrix'][i] + self._mSeqCounters[model] += 1 + self._mLastOrder = order + + if self.get_state() == constants.eDetecting: + if self._mTotalSeqs > SB_ENOUGH_REL_THRESHOLD: + cf = self.get_confidence() + if cf > POSITIVE_SHORTCUT_THRESHOLD: + if constants._debug: + sys.stderr.write('%s confidence = %s, we have a' + 'winner\n' % + (self._mModel['charsetName'], cf)) + self._mState = constants.eFoundIt + elif cf < NEGATIVE_SHORTCUT_THRESHOLD: + if constants._debug: + sys.stderr.write('%s confidence = %s, below negative' + 'shortcut threshhold %s\n' % + (self._mModel['charsetName'], cf, + NEGATIVE_SHORTCUT_THRESHOLD)) + self._mState = constants.eNotMe + + return self.get_state() + + def get_confidence(self): + r = 0.01 + if self._mTotalSeqs > 0: + r = ((1.0 * self._mSeqCounters[POSITIVE_CAT]) / self._mTotalSeqs + / self._mModel['mTypicalPositiveRatio']) + r = r * self._mFreqChar / self._mTotalChar + if r >= 1.0: + r = 0.99 + return r diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/sbcsgroupprober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/sbcsgroupprober.py new file mode 100644 index 0000000000..b224814568 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/sbcsgroupprober.py @@ -0,0 +1,69 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetgroupprober import CharSetGroupProber +from .sbcharsetprober import SingleByteCharSetProber +from .langcyrillicmodel import (Win1251CyrillicModel, Koi8rModel, + Latin5CyrillicModel, MacCyrillicModel, + Ibm866Model, Ibm855Model) +from .langgreekmodel import Latin7GreekModel, Win1253GreekModel +from .langbulgarianmodel import Latin5BulgarianModel, Win1251BulgarianModel +from .langhungarianmodel import Latin2HungarianModel, Win1250HungarianModel +from .langthaimodel import TIS620ThaiModel +from .langhebrewmodel import Win1255HebrewModel +from .hebrewprober import HebrewProber + + +class SBCSGroupProber(CharSetGroupProber): + def __init__(self): + CharSetGroupProber.__init__(self) + self._mProbers = [ + SingleByteCharSetProber(Win1251CyrillicModel), + SingleByteCharSetProber(Koi8rModel), + SingleByteCharSetProber(Latin5CyrillicModel), + SingleByteCharSetProber(MacCyrillicModel), + SingleByteCharSetProber(Ibm866Model), + SingleByteCharSetProber(Ibm855Model), + SingleByteCharSetProber(Latin7GreekModel), + SingleByteCharSetProber(Win1253GreekModel), + SingleByteCharSetProber(Latin5BulgarianModel), + SingleByteCharSetProber(Win1251BulgarianModel), + SingleByteCharSetProber(Latin2HungarianModel), + SingleByteCharSetProber(Win1250HungarianModel), + SingleByteCharSetProber(TIS620ThaiModel), + ] + hebrewProber = HebrewProber() + logicalHebrewProber = SingleByteCharSetProber(Win1255HebrewModel, + False, hebrewProber) + visualHebrewProber = SingleByteCharSetProber(Win1255HebrewModel, True, + hebrewProber) + hebrewProber.set_model_probers(logicalHebrewProber, visualHebrewProber) + self._mProbers.extend([hebrewProber, logicalHebrewProber, + visualHebrewProber]) + + self.reset() diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/sjisprober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/sjisprober.py new file mode 100644 index 0000000000..9bb0cdcf1f --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/sjisprober.py @@ -0,0 +1,91 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import sys +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import SJISDistributionAnalysis +from .jpcntx import SJISContextAnalysis +from .mbcssm import SJISSMModel +from . import constants + + +class SJISProber(MultiByteCharSetProber): + def __init__(self): + MultiByteCharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(SJISSMModel) + self._mDistributionAnalyzer = SJISDistributionAnalysis() + self._mContextAnalyzer = SJISContextAnalysis() + self.reset() + + def reset(self): + MultiByteCharSetProber.reset(self) + self._mContextAnalyzer.reset() + + def get_charset_name(self): + return "SHIFT_JIS" + + def feed(self, aBuf): + aLen = len(aBuf) + for i in range(0, aLen): + codingState = self._mCodingSM.next_state(aBuf[i]) + if codingState == constants.eError: + if constants._debug: + sys.stderr.write(self.get_charset_name() + + ' prober hit error at byte ' + str(i) + + '\n') + self._mState = constants.eNotMe + break + elif codingState == constants.eItsMe: + self._mState = constants.eFoundIt + break + elif codingState == constants.eStart: + charLen = self._mCodingSM.get_current_charlen() + if i == 0: + self._mLastChar[1] = aBuf[0] + self._mContextAnalyzer.feed(self._mLastChar[2 - charLen:], + charLen) + self._mDistributionAnalyzer.feed(self._mLastChar, charLen) + else: + self._mContextAnalyzer.feed(aBuf[i + 1 - charLen:i + 3 + - charLen], charLen) + self._mDistributionAnalyzer.feed(aBuf[i - 1:i + 1], + charLen) + + self._mLastChar[0] = aBuf[aLen - 1] + + if self.get_state() == constants.eDetecting: + if (self._mContextAnalyzer.got_enough_data() and + (self.get_confidence() > constants.SHORTCUT_THRESHOLD)): + self._mState = constants.eFoundIt + + return self.get_state() + + def get_confidence(self): + contxtCf = self._mContextAnalyzer.get_confidence() + distribCf = self._mDistributionAnalyzer.get_confidence() + return max(contxtCf, distribCf) diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/universaldetector.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/universaldetector.py new file mode 100644 index 0000000000..6a8e68a8a7 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/universaldetector.py @@ -0,0 +1,168 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from . import constants +import sys +import codecs +from .latin1prober import Latin1Prober # windows-1252 +from .mbcsgroupprober import MBCSGroupProber # multi-byte character sets +from .sbcsgroupprober import SBCSGroupProber # single-byte character sets +from .escprober import EscCharSetProber # ISO-2122, etc. +import re + +MINIMUM_THRESHOLD = 0.20 +ePureAscii = 0 +eEscAscii = 1 +eHighbyte = 2 + + +class UniversalDetector: + def __init__(self): + self._highBitDetector = re.compile(b'[\x80-\xFF]') + self._escDetector = re.compile(b'(\033|~{)') + self._mEscCharSetProber = None + self._mCharSetProbers = [] + self.reset() + + def reset(self): + self.result = {'encoding': None, 'confidence': 0.0} + self.done = False + self._mStart = True + self._mGotData = False + self._mInputState = ePureAscii + self._mLastChar = b'' + if self._mEscCharSetProber: + self._mEscCharSetProber.reset() + for prober in self._mCharSetProbers: + prober.reset() + + def feed(self, aBuf): + if self.done: + return + + aLen = len(aBuf) + if not aLen: + return + + if not self._mGotData: + # If the data starts with BOM, we know it is UTF + if aBuf[:3] == codecs.BOM: + # EF BB BF UTF-8 with BOM + self.result = {'encoding': "UTF-8", 'confidence': 1.0} + elif aBuf[:4] in (codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE): + # FF FE 00 00 UTF-32, little-endian BOM + # 00 00 FE FF UTF-32, big-endian BOM + self.result = {'encoding': "UTF-32", 'confidence': 1.0} + elif aBuf[:4] == b'\xFE\xFF\x00\x00': + # FE FF 00 00 UCS-4, unusual octet order BOM (3412) + self.result = { + 'encoding': "X-ISO-10646-UCS-4-3412", + 'confidence': 1.0 + } + elif aBuf[:4] == b'\x00\x00\xFF\xFE': + # 00 00 FF FE UCS-4, unusual octet order BOM (2143) + self.result = { + 'encoding': "X-ISO-10646-UCS-4-2143", + 'confidence': 1.0 + } + elif aBuf[:2] == codecs.BOM_LE or aBuf[:2] == codecs.BOM_BE: + # FF FE UTF-16, little endian BOM + # FE FF UTF-16, big endian BOM + self.result = {'encoding': "UTF-16", 'confidence': 1.0} + + self._mGotData = True + if self.result['encoding'] and (self.result['confidence'] > 0.0): + self.done = True + return + + if self._mInputState == ePureAscii: + if self._highBitDetector.search(aBuf): + self._mInputState = eHighbyte + elif ((self._mInputState == ePureAscii) and + self._escDetector.search(self._mLastChar + aBuf)): + self._mInputState = eEscAscii + + self._mLastChar = aBuf[-1:] + + if self._mInputState == eEscAscii: + if not self._mEscCharSetProber: + self._mEscCharSetProber = EscCharSetProber() + if self._mEscCharSetProber.feed(aBuf) == constants.eFoundIt: + self.result = { + 'encoding': self._mEscCharSetProber.get_charset_name(), + 'confidence': self._mEscCharSetProber.get_confidence() + } + self.done = True + elif self._mInputState == eHighbyte: + if not self._mCharSetProbers: + self._mCharSetProbers = [MBCSGroupProber(), SBCSGroupProber(), + Latin1Prober()] + for prober in self._mCharSetProbers: + if prober.feed(aBuf) == constants.eFoundIt: + self.result = {'encoding': prober.get_charset_name(), + 'confidence': prober.get_confidence()} + self.done = True + break + + def close(self): + if self.done: + return + if not self._mGotData: + if constants._debug: + sys.stderr.write('no data received!\n') + return + self.done = True + + if self._mInputState == ePureAscii: + self.result = {'encoding': 'ascii', 'confidence': 1.0} + return self.result + + if self._mInputState == eHighbyte: + proberConfidence = None + maxProberConfidence = 0.0 + maxProber = None + for prober in self._mCharSetProbers: + if not prober: + continue + proberConfidence = prober.get_confidence() + if proberConfidence > maxProberConfidence: + maxProberConfidence = proberConfidence + maxProber = prober + if maxProber and (maxProberConfidence > MINIMUM_THRESHOLD): + self.result = {'encoding': maxProber.get_charset_name(), + 'confidence': maxProber.get_confidence()} + return self.result + + if constants._debug: + sys.stderr.write('no probers hit minimum threshhold\n') + for prober in self._mCharSetProbers[0].mProbers: + if not prober: + continue + sys.stderr.write('%s confidence = %s\n' % + (prober.get_charset_name(), + prober.get_confidence())) diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/charade/utf8prober.py b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/utf8prober.py new file mode 100644 index 0000000000..72c8d3d6a9 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/charade/utf8prober.py @@ -0,0 +1,76 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from . import constants +from .charsetprober import CharSetProber +from .codingstatemachine import CodingStateMachine +from .mbcssm import UTF8SMModel + +ONE_CHAR_PROB = 0.5 + + +class UTF8Prober(CharSetProber): + def __init__(self): + CharSetProber.__init__(self) + self._mCodingSM = CodingStateMachine(UTF8SMModel) + self.reset() + + def reset(self): + CharSetProber.reset(self) + self._mCodingSM.reset() + self._mNumOfMBChar = 0 + + def get_charset_name(self): + return "utf-8" + + def feed(self, aBuf): + for c in aBuf: + codingState = self._mCodingSM.next_state(c) + if codingState == constants.eError: + self._mState = constants.eNotMe + break + elif codingState == constants.eItsMe: + self._mState = constants.eFoundIt + break + elif codingState == constants.eStart: + if self._mCodingSM.get_current_charlen() >= 2: + self._mNumOfMBChar += 1 + + if self.get_state() == constants.eDetecting: + if self.get_confidence() > constants.SHORTCUT_THRESHOLD: + self._mState = constants.eFoundIt + + return self.get_state() + + def get_confidence(self): + unlike = 0.99 + if self._mNumOfMBChar < 6: + for i in range(0, self._mNumOfMBChar): + unlike = unlike * ONE_CHAR_PROB + return 1.0 - unlike + else: + return unlike diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/__init__.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/__init__.py new file mode 100644 index 0000000000..73071f7001 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/__init__.py @@ -0,0 +1,58 @@ +# urllib3/__init__.py +# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) +# +# This module is part of urllib3 and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + +""" +urllib3 - Thread-safe connection pooling and re-using. +""" + +__author__ = 'Andrey Petrov (andrey.petrov@shazow.net)' +__license__ = 'MIT' +__version__ = 'dev' + + +from .connectionpool import ( + HTTPConnectionPool, + HTTPSConnectionPool, + connection_from_url +) + +from . import exceptions +from .filepost import encode_multipart_formdata +from .poolmanager import PoolManager, ProxyManager, proxy_from_url +from .response import HTTPResponse +from .util import make_headers, get_host, Timeout + + +# Set default logging handler to avoid "No handler found" warnings. +import logging +try: # Python 2.7+ + from logging import NullHandler +except ImportError: + class NullHandler(logging.Handler): + def emit(self, record): + pass + +logging.getLogger(__name__).addHandler(NullHandler()) + +def add_stderr_logger(level=logging.DEBUG): + """ + Helper for quickly adding a StreamHandler to the logger. Useful for + debugging. + + Returns the handler after adding it. + """ + # This method needs to be in this __init__.py to get the __name__ correct + # even if urllib3 is vendored within another package. + logger = logging.getLogger(__name__) + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s')) + logger.addHandler(handler) + logger.setLevel(level) + logger.debug('Added an stderr logging handler to logger: %s' % __name__) + return handler + +# ... Clean up. +del NullHandler diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/_collections.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/_collections.py new file mode 100644 index 0000000000..5907b0dc7c --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/_collections.py @@ -0,0 +1,103 @@ +# urllib3/_collections.py +# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) +# +# This module is part of urllib3 and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + +from collections import MutableMapping +try: + from threading import RLock +except ImportError: # Platform-specific: No threads available + class RLock: + def __enter__(self): + pass + + def __exit__(self, exc_type, exc_value, traceback): + pass + + +try: # Python 2.7+ + from collections import OrderedDict +except ImportError: + from .packages.ordered_dict import OrderedDict + + +__all__ = ['RecentlyUsedContainer'] + + +_Null = object() + + +class RecentlyUsedContainer(MutableMapping): + """ + Provides a thread-safe dict-like container which maintains up to + ``maxsize`` keys while throwing away the least-recently-used keys beyond + ``maxsize``. + + :param maxsize: + Maximum number of recent elements to retain. + + :param dispose_func: + Every time an item is evicted from the container, + ``dispose_func(value)`` is called. Callback which will get called + """ + + ContainerCls = OrderedDict + + def __init__(self, maxsize=10, dispose_func=None): + self._maxsize = maxsize + self.dispose_func = dispose_func + + self._container = self.ContainerCls() + self.lock = RLock() + + def __getitem__(self, key): + # Re-insert the item, moving it to the end of the eviction line. + with self.lock: + item = self._container.pop(key) + self._container[key] = item + return item + + def __setitem__(self, key, value): + evicted_value = _Null + with self.lock: + # Possibly evict the existing value of 'key' + evicted_value = self._container.get(key, _Null) + self._container[key] = value + + # If we didn't evict an existing value, we might have to evict the + # least recently used item from the beginning of the container. + if len(self._container) > self._maxsize: + _key, evicted_value = self._container.popitem(last=False) + + if self.dispose_func and evicted_value is not _Null: + self.dispose_func(evicted_value) + + def __delitem__(self, key): + with self.lock: + value = self._container.pop(key) + + if self.dispose_func: + self.dispose_func(value) + + def __len__(self): + with self.lock: + return len(self._container) + + def __iter__(self): + raise NotImplementedError('Iteration over this class is unlikely to be threadsafe.') + + def clear(self): + with self.lock: + # Copy pointers to all values, then wipe the mapping + # under Python 2, this copies the list of values twice :-| + values = list(self._container.values()) + self._container.clear() + + if self.dispose_func: + for value in values: + self.dispose_func(value) + + def keys(self): + with self.lock: + return self._container.keys() diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/connection.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/connection.py new file mode 100644 index 0000000000..e240786a67 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/connection.py @@ -0,0 +1,107 @@ +# urllib3/connection.py +# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) +# +# This module is part of urllib3 and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + +import socket +from socket import timeout as SocketTimeout + +try: # Python 3 + from http.client import HTTPConnection, HTTPException +except ImportError: + from httplib import HTTPConnection, HTTPException + +class DummyConnection(object): + "Used to detect a failed ConnectionCls import." + pass + +try: # Compiled with SSL? + ssl = None + HTTPSConnection = DummyConnection + + class BaseSSLError(BaseException): + pass + + try: # Python 3 + from http.client import HTTPSConnection + except ImportError: + from httplib import HTTPSConnection + + import ssl + BaseSSLError = ssl.SSLError + +except (ImportError, AttributeError): # Platform-specific: No SSL. + pass + +from .exceptions import ( + ConnectTimeoutError, +) +from .packages.ssl_match_hostname import match_hostname +from .util import ( + assert_fingerprint, + resolve_cert_reqs, + resolve_ssl_version, + ssl_wrap_socket, +) + +class VerifiedHTTPSConnection(HTTPSConnection): + """ + Based on httplib.HTTPSConnection but wraps the socket with + SSL certification. + """ + cert_reqs = None + ca_certs = None + ssl_version = None + + def set_cert(self, key_file=None, cert_file=None, + cert_reqs=None, ca_certs=None, + assert_hostname=None, assert_fingerprint=None): + + self.key_file = key_file + self.cert_file = cert_file + self.cert_reqs = cert_reqs + self.ca_certs = ca_certs + self.assert_hostname = assert_hostname + self.assert_fingerprint = assert_fingerprint + + def connect(self): + # Add certificate verification + try: + sock = socket.create_connection( + address=(self.host, self.port), + timeout=self.timeout, + ) + except SocketTimeout: + raise ConnectTimeoutError( + self, "Connection to %s timed out. (connect timeout=%s)" % + (self.host, self.timeout)) + + resolved_cert_reqs = resolve_cert_reqs(self.cert_reqs) + resolved_ssl_version = resolve_ssl_version(self.ssl_version) + + if self._tunnel_host: + self.sock = sock + # Calls self._set_hostport(), so self.host is + # self._tunnel_host below. + self._tunnel() + + # Wrap socket using verification with the root certs in + # trusted_root_certs + self.sock = ssl_wrap_socket(sock, self.key_file, self.cert_file, + cert_reqs=resolved_cert_reqs, + ca_certs=self.ca_certs, + server_hostname=self.host, + ssl_version=resolved_ssl_version) + + if resolved_cert_reqs != ssl.CERT_NONE: + if self.assert_fingerprint: + assert_fingerprint(self.sock.getpeercert(binary_form=True), + self.assert_fingerprint) + elif self.assert_hostname is not False: + match_hostname(self.sock.getpeercert(), + self.assert_hostname or self.host) + + +if ssl: + HTTPSConnection = VerifiedHTTPSConnection diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/connectionpool.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/connectionpool.py new file mode 100644 index 0000000000..72011b5a33 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/connectionpool.py @@ -0,0 +1,681 @@ +# urllib3/connectionpool.py +# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) +# +# This module is part of urllib3 and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + +import errno +import logging + +from socket import error as SocketError, timeout as SocketTimeout +import socket + +try: # Python 3 + from queue import LifoQueue, Empty, Full +except ImportError: + from Queue import LifoQueue, Empty, Full + import Queue as _ # Platform-specific: Windows + + +from .exceptions import ( + ClosedPoolError, + ConnectTimeoutError, + EmptyPoolError, + HostChangedError, + MaxRetryError, + SSLError, + TimeoutError, + ReadTimeoutError, + ProxyError, +) +from .packages.ssl_match_hostname import CertificateError +from .packages import six +from .connection import ( + DummyConnection, + HTTPConnection, HTTPSConnection, VerifiedHTTPSConnection, + HTTPException, BaseSSLError, +) +from .request import RequestMethods +from .response import HTTPResponse +from .util import ( + assert_fingerprint, + get_host, + is_connection_dropped, + Timeout, +) + + +xrange = six.moves.xrange + +log = logging.getLogger(__name__) + +_Default = object() + +port_by_scheme = { + 'http': 80, + 'https': 443, +} + + +## Pool objects + +class ConnectionPool(object): + """ + Base class for all connection pools, such as + :class:`.HTTPConnectionPool` and :class:`.HTTPSConnectionPool`. + """ + + scheme = None + QueueCls = LifoQueue + + def __init__(self, host, port=None): + # httplib doesn't like it when we include brackets in ipv6 addresses + host = host.strip('[]') + + self.host = host + self.port = port + + def __str__(self): + return '%s(host=%r, port=%r)' % (type(self).__name__, + self.host, self.port) + +# This is taken from http://hg.python.org/cpython/file/7aaba721ebc0/Lib/socket.py#l252 +_blocking_errnos = set([errno.EAGAIN, errno.EWOULDBLOCK]) + +class HTTPConnectionPool(ConnectionPool, RequestMethods): + """ + Thread-safe connection pool for one host. + + :param host: + Host used for this HTTP Connection (e.g. "localhost"), passed into + :class:`httplib.HTTPConnection`. + + :param port: + Port used for this HTTP Connection (None is equivalent to 80), passed + into :class:`httplib.HTTPConnection`. + + :param strict: + Causes BadStatusLine to be raised if the status line can't be parsed + as a valid HTTP/1.0 or 1.1 status line, passed into + :class:`httplib.HTTPConnection`. + + .. note:: + Only works in Python 2. This parameter is ignored in Python 3. + + :param timeout: + Socket timeout in seconds for each individual connection. This can + be a float or integer, which sets the timeout for the HTTP request, + or an instance of :class:`urllib3.util.Timeout` which gives you more + fine-grained control over request timeouts. After the constructor has + been parsed, this is always a `urllib3.util.Timeout` object. + + :param maxsize: + Number of connections to save that can be reused. More than 1 is useful + in multithreaded situations. If ``block`` is set to false, more + connections will be created but they will not be saved once they've + been used. + + :param block: + If set to True, no more than ``maxsize`` connections will be used at + a time. When no free connections are available, the call will block + until a connection has been released. This is a useful side effect for + particular multithreaded situations where one does not want to use more + than maxsize connections per host to prevent flooding. + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + + :param _proxy: + Parsed proxy URL, should not be used directly, instead, see + :class:`urllib3.connectionpool.ProxyManager`" + + :param _proxy_headers: + A dictionary with proxy headers, should not be used directly, + instead, see :class:`urllib3.connectionpool.ProxyManager`" + """ + + scheme = 'http' + ConnectionCls = HTTPConnection + + def __init__(self, host, port=None, strict=False, + timeout=Timeout.DEFAULT_TIMEOUT, maxsize=1, block=False, + headers=None, _proxy=None, _proxy_headers=None): + ConnectionPool.__init__(self, host, port) + RequestMethods.__init__(self, headers) + + self.strict = strict + + # This is for backwards compatibility and can be removed once a timeout + # can only be set to a Timeout object + if not isinstance(timeout, Timeout): + timeout = Timeout.from_float(timeout) + + self.timeout = timeout + + self.pool = self.QueueCls(maxsize) + self.block = block + + self.proxy = _proxy + self.proxy_headers = _proxy_headers or {} + + # Fill the queue up so that doing get() on it will block properly + for _ in xrange(maxsize): + self.pool.put(None) + + # These are mostly for testing and debugging purposes. + self.num_connections = 0 + self.num_requests = 0 + + def _new_conn(self): + """ + Return a fresh :class:`httplib.HTTPConnection`. + """ + self.num_connections += 1 + log.info("Starting new HTTP connection (%d): %s" % + (self.num_connections, self.host)) + + extra_params = {} + if not six.PY3: # Python 2 + extra_params['strict'] = self.strict + + return self.ConnectionCls(host=self.host, port=self.port, + timeout=self.timeout.connect_timeout, + **extra_params) + + def _get_conn(self, timeout=None): + """ + Get a connection. Will return a pooled connection if one is available. + + If no connections are available and :prop:`.block` is ``False``, then a + fresh connection is returned. + + :param timeout: + Seconds to wait before giving up and raising + :class:`urllib3.exceptions.EmptyPoolError` if the pool is empty and + :prop:`.block` is ``True``. + """ + conn = None + try: + conn = self.pool.get(block=self.block, timeout=timeout) + + except AttributeError: # self.pool is None + raise ClosedPoolError(self, "Pool is closed.") + + except Empty: + if self.block: + raise EmptyPoolError(self, + "Pool reached maximum size and no more " + "connections are allowed.") + pass # Oh well, we'll create a new connection then + + # If this is a persistent connection, check if it got disconnected + if conn and is_connection_dropped(conn): + log.info("Resetting dropped connection: %s" % self.host) + conn.close() + + return conn or self._new_conn() + + def _put_conn(self, conn): + """ + Put a connection back into the pool. + + :param conn: + Connection object for the current host and port as returned by + :meth:`._new_conn` or :meth:`._get_conn`. + + If the pool is already full, the connection is closed and discarded + because we exceeded maxsize. If connections are discarded frequently, + then maxsize should be increased. + + If the pool is closed, then the connection will be closed and discarded. + """ + try: + self.pool.put(conn, block=False) + return # Everything is dandy, done. + except AttributeError: + # self.pool is None. + pass + except Full: + # This should never happen if self.block == True + log.warning("HttpConnectionPool is full, discarding connection: %s" + % self.host) + + # Connection never got put back into the pool, close it. + if conn: + conn.close() + + def _get_timeout(self, timeout): + """ Helper that always returns a :class:`urllib3.util.Timeout` """ + if timeout is _Default: + return self.timeout.clone() + + if isinstance(timeout, Timeout): + return timeout.clone() + else: + # User passed us an int/float. This is for backwards compatibility, + # can be removed later + return Timeout.from_float(timeout) + + def _make_request(self, conn, method, url, timeout=_Default, + **httplib_request_kw): + """ + Perform a request on a given httplib connection object taken from our + pool. + + :param conn: + a connection from one of our connection pools + + :param timeout: + Socket timeout in seconds for the request. This can be a + float or integer, which will set the same timeout value for + the socket connect and the socket read, or an instance of + :class:`urllib3.util.Timeout`, which gives you more fine-grained + control over your timeouts. + """ + self.num_requests += 1 + + timeout_obj = self._get_timeout(timeout) + + try: + timeout_obj.start_connect() + conn.timeout = timeout_obj.connect_timeout + # conn.request() calls httplib.*.request, not the method in + # urllib3.request. It also calls makefile (recv) on the socket. + conn.request(method, url, **httplib_request_kw) + except SocketTimeout: + raise ConnectTimeoutError( + self, "Connection to %s timed out. (connect timeout=%s)" % + (self.host, timeout_obj.connect_timeout)) + + # Reset the timeout for the recv() on the socket + read_timeout = timeout_obj.read_timeout + + # App Engine doesn't have a sock attr + if hasattr(conn, 'sock'): + # In Python 3 socket.py will catch EAGAIN and return None when you + # try and read into the file pointer created by http.client, which + # instead raises a BadStatusLine exception. Instead of catching + # the exception and assuming all BadStatusLine exceptions are read + # timeouts, check for a zero timeout before making the request. + if read_timeout == 0: + raise ReadTimeoutError( + self, url, + "Read timed out. (read timeout=%s)" % read_timeout) + if read_timeout is Timeout.DEFAULT_TIMEOUT: + conn.sock.settimeout(socket.getdefaulttimeout()) + else: # None or a value + conn.sock.settimeout(read_timeout) + + # Receive the response from the server + try: + try: # Python 2.7+, use buffering of HTTP responses + httplib_response = conn.getresponse(buffering=True) + except TypeError: # Python 2.6 and older + httplib_response = conn.getresponse() + except SocketTimeout: + raise ReadTimeoutError( + self, url, "Read timed out. (read timeout=%s)" % read_timeout) + + except BaseSSLError as e: + # Catch possible read timeouts thrown as SSL errors. If not the + # case, rethrow the original. We need to do this because of: + # http://bugs.python.org/issue10272 + if 'timed out' in str(e) or \ + 'did not complete (read)' in str(e): # Python 2.6 + raise ReadTimeoutError(self, url, "Read timed out.") + + raise + + except SocketError as e: # Platform-specific: Python 2 + # See the above comment about EAGAIN in Python 3. In Python 2 we + # have to specifically catch it and throw the timeout error + if e.errno in _blocking_errnos: + raise ReadTimeoutError( + self, url, + "Read timed out. (read timeout=%s)" % read_timeout) + + raise + + # AppEngine doesn't have a version attr. + http_version = getattr(conn, '_http_vsn_str', 'HTTP/?') + log.debug("\"%s %s %s\" %s %s" % (method, url, http_version, + httplib_response.status, + httplib_response.length)) + return httplib_response + + def close(self): + """ + Close all pooled connections and disable the pool. + """ + # Disable access to the pool + old_pool, self.pool = self.pool, None + + try: + while True: + conn = old_pool.get(block=False) + if conn: + conn.close() + + except Empty: + pass # Done. + + def is_same_host(self, url): + """ + Check if the given ``url`` is a member of the same host as this + connection pool. + """ + if url.startswith('/'): + return True + + # TODO: Add optional support for socket.gethostbyname checking. + scheme, host, port = get_host(url) + + if self.port and not port: + # Use explicit default port for comparison when none is given. + port = port_by_scheme.get(scheme) + + return (scheme, host, port) == (self.scheme, self.host, self.port) + + def urlopen(self, method, url, body=None, headers=None, retries=3, + redirect=True, assert_same_host=True, timeout=_Default, + pool_timeout=None, release_conn=None, **response_kw): + """ + Get a connection from the pool and perform an HTTP request. This is the + lowest level call for making a request, so you'll need to specify all + the raw details. + + .. note:: + + More commonly, it's appropriate to use a convenience method provided + by :class:`.RequestMethods`, such as :meth:`request`. + + .. note:: + + `release_conn` will only behave as expected if + `preload_content=False` because we want to make + `preload_content=False` the default behaviour someday soon without + breaking backwards compatibility. + + :param method: + HTTP request method (such as GET, POST, PUT, etc.) + + :param body: + Data to send in the request body (useful for creating + POST requests, see HTTPConnectionPool.post_url for + more convenience). + + :param headers: + Dictionary of custom headers to send, such as User-Agent, + If-None-Match, etc. If None, pool headers are used. If provided, + these headers completely replace any pool-specific headers. + + :param retries: + Number of retries to allow before raising a MaxRetryError exception. + + :param redirect: + If True, automatically handle redirects (status codes 301, 302, + 303, 307, 308). Each redirect counts as a retry. + + :param assert_same_host: + If ``True``, will make sure that the host of the pool requests is + consistent else will raise HostChangedError. When False, you can + use the pool on an HTTP proxy and request foreign hosts. + + :param timeout: + If specified, overrides the default timeout for this one + request. It may be a float (in seconds) or an instance of + :class:`urllib3.util.Timeout`. + + :param pool_timeout: + If set and the pool is set to block=True, then this method will + block for ``pool_timeout`` seconds and raise EmptyPoolError if no + connection is available within the time period. + + :param release_conn: + If False, then the urlopen call will not release the connection + back into the pool once a response is received (but will release if + you read the entire contents of the response such as when + `preload_content=True`). This is useful if you're not preloading + the response's content immediately. You will need to call + ``r.release_conn()`` on the response ``r`` to return the connection + back into the pool. If None, it takes the value of + ``response_kw.get('preload_content', True)``. + + :param \**response_kw: + Additional parameters are passed to + :meth:`urllib3.response.HTTPResponse.from_httplib` + """ + if headers is None: + headers = self.headers + + if retries < 0: + raise MaxRetryError(self, url) + + if release_conn is None: + release_conn = response_kw.get('preload_content', True) + + # Check host + if assert_same_host and not self.is_same_host(url): + raise HostChangedError(self, url, retries - 1) + + conn = None + + # Merge the proxy headers. Only do this in HTTP. We have to copy the + # headers dict so we can safely change it without those changes being + # reflected in anyone else's copy. + if self.scheme == 'http': + headers = headers.copy() + headers.update(self.proxy_headers) + + try: + # Request a connection from the queue + conn = self._get_conn(timeout=pool_timeout) + + # Make the request on the httplib connection object + httplib_response = self._make_request(conn, method, url, + timeout=timeout, + body=body, headers=headers) + + # If we're going to release the connection in ``finally:``, then + # the request doesn't need to know about the connection. Otherwise + # it will also try to release it and we'll have a double-release + # mess. + response_conn = not release_conn and conn + + # Import httplib's response into our own wrapper object + response = HTTPResponse.from_httplib(httplib_response, + pool=self, + connection=response_conn, + **response_kw) + + # else: + # The connection will be put back into the pool when + # ``response.release_conn()`` is called (implicitly by + # ``response.read()``) + + except Empty: + # Timed out by queue + raise EmptyPoolError(self, "No pool connections are available.") + + except BaseSSLError as e: + raise SSLError(e) + + except CertificateError as e: + # Name mismatch + raise SSLError(e) + + except TimeoutError as e: + # Connection broken, discard. + conn = None + # Save the error off for retry logic. + err = e + + if retries == 0: + raise + + except (HTTPException, SocketError) as e: + if isinstance(e, SocketError) and self.proxy is not None: + raise ProxyError('Cannot connect to proxy. ' + 'Socket error: %s.' % e) + + # Connection broken, discard. It will be replaced next _get_conn(). + conn = None + # This is necessary so we can access e below + err = e + + if retries == 0: + raise MaxRetryError(self, url, e) + + finally: + if release_conn: + # Put the connection back to be reused. If the connection is + # expired then it will be None, which will get replaced with a + # fresh connection during _get_conn. + self._put_conn(conn) + + if not conn: + # Try again + log.warn("Retrying (%d attempts remain) after connection " + "broken by '%r': %s" % (retries, err, url)) + return self.urlopen(method, url, body, headers, retries - 1, + redirect, assert_same_host, + timeout=timeout, pool_timeout=pool_timeout, + release_conn=release_conn, **response_kw) + + # Handle redirect? + redirect_location = redirect and response.get_redirect_location() + if redirect_location: + if response.status == 303: + method = 'GET' + log.info("Redirecting %s -> %s" % (url, redirect_location)) + return self.urlopen(method, redirect_location, body, headers, + retries - 1, redirect, assert_same_host, + timeout=timeout, pool_timeout=pool_timeout, + release_conn=release_conn, **response_kw) + + return response + + +class HTTPSConnectionPool(HTTPConnectionPool): + """ + Same as :class:`.HTTPConnectionPool`, but HTTPS. + + When Python is compiled with the :mod:`ssl` module, then + :class:`.VerifiedHTTPSConnection` is used, which *can* verify certificates, + instead of :class:`httplib.HTTPSConnection`. + + :class:`.VerifiedHTTPSConnection` uses one of ``assert_fingerprint``, + ``assert_hostname`` and ``host`` in this order to verify connections. + If ``assert_hostname`` is False, no verification is done. + + The ``key_file``, ``cert_file``, ``cert_reqs``, ``ca_certs`` and + ``ssl_version`` are only used if :mod:`ssl` is available and are fed into + :meth:`urllib3.util.ssl_wrap_socket` to upgrade the connection socket + into an SSL socket. + """ + + scheme = 'https' + ConnectionCls = HTTPSConnection + + def __init__(self, host, port=None, + strict=False, timeout=None, maxsize=1, + block=False, headers=None, + _proxy=None, _proxy_headers=None, + key_file=None, cert_file=None, cert_reqs=None, + ca_certs=None, ssl_version=None, + assert_hostname=None, assert_fingerprint=None): + + HTTPConnectionPool.__init__(self, host, port, strict, timeout, maxsize, + block, headers, _proxy, _proxy_headers) + self.key_file = key_file + self.cert_file = cert_file + self.cert_reqs = cert_reqs + self.ca_certs = ca_certs + self.ssl_version = ssl_version + self.assert_hostname = assert_hostname + self.assert_fingerprint = assert_fingerprint + + def _prepare_conn(self, conn): + """ + Prepare the ``connection`` for :meth:`urllib3.util.ssl_wrap_socket` + and establish the tunnel if proxy is used. + """ + + if isinstance(conn, VerifiedHTTPSConnection): + conn.set_cert(key_file=self.key_file, + cert_file=self.cert_file, + cert_reqs=self.cert_reqs, + ca_certs=self.ca_certs, + assert_hostname=self.assert_hostname, + assert_fingerprint=self.assert_fingerprint) + conn.ssl_version = self.ssl_version + + if self.proxy is not None: + # Python 2.7+ + try: + set_tunnel = conn.set_tunnel + except AttributeError: # Platform-specific: Python 2.6 + set_tunnel = conn._set_tunnel + set_tunnel(self.host, self.port, self.proxy_headers) + # Establish tunnel connection early, because otherwise httplib + # would improperly set Host: header to proxy's IP:port. + conn.connect() + + return conn + + def _new_conn(self): + """ + Return a fresh :class:`httplib.HTTPSConnection`. + """ + self.num_connections += 1 + log.info("Starting new HTTPS connection (%d): %s" + % (self.num_connections, self.host)) + + if not self.ConnectionCls or self.ConnectionCls is DummyConnection: + # Platform-specific: Python without ssl + raise SSLError("Can't connect to HTTPS URL because the SSL " + "module is not available.") + + actual_host = self.host + actual_port = self.port + if self.proxy is not None: + actual_host = self.proxy.host + actual_port = self.proxy.port + + extra_params = {} + if not six.PY3: # Python 2 + extra_params['strict'] = self.strict + + conn = self.ConnectionCls(host=actual_host, port=actual_port, + timeout=self.timeout.connect_timeout, + **extra_params) + + return self._prepare_conn(conn) + + +def connection_from_url(url, **kw): + """ + Given a url, return an :class:`.ConnectionPool` instance of its host. + + This is a shortcut for not having to parse out the scheme, host, and port + of the url before creating an :class:`.ConnectionPool` instance. + + :param url: + Absolute URL string that must include the scheme. Port is optional. + + :param \**kw: + Passes additional parameters to the constructor of the appropriate + :class:`.ConnectionPool`. Useful for specifying things like + timeout, maxsize, headers, etc. + + Example: :: + + >>> conn = connection_from_url('http://google.com/') + >>> r = conn.request('GET', '/') + """ + scheme, host, port = get_host(url) + if scheme == 'https': + return HTTPSConnectionPool(host, port=port, **kw) + else: + return HTTPConnectionPool(host, port=port, **kw) diff --git a/awx/lib/site-packages/setuptools/_backport/__init__.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/contrib/__init__.py similarity index 100% rename from awx/lib/site-packages/setuptools/_backport/__init__.py rename to awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/contrib/__init__.py diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/contrib/ntlmpool.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/contrib/ntlmpool.py new file mode 100644 index 0000000000..b8cd933034 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/contrib/ntlmpool.py @@ -0,0 +1,120 @@ +# urllib3/contrib/ntlmpool.py +# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) +# +# This module is part of urllib3 and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + +""" +NTLM authenticating pool, contributed by erikcederstran + +Issue #10, see: http://code.google.com/p/urllib3/issues/detail?id=10 +""" + +try: + from http.client import HTTPSConnection +except ImportError: + from httplib import HTTPSConnection +from logging import getLogger +from ntlm import ntlm + +from urllib3 import HTTPSConnectionPool + + +log = getLogger(__name__) + + +class NTLMConnectionPool(HTTPSConnectionPool): + """ + Implements an NTLM authentication version of an urllib3 connection pool + """ + + scheme = 'https' + + def __init__(self, user, pw, authurl, *args, **kwargs): + """ + authurl is a random URL on the server that is protected by NTLM. + user is the Windows user, probably in the DOMAIN\\username format. + pw is the password for the user. + """ + super(NTLMConnectionPool, self).__init__(*args, **kwargs) + self.authurl = authurl + self.rawuser = user + user_parts = user.split('\\', 1) + self.domain = user_parts[0].upper() + self.user = user_parts[1] + self.pw = pw + + def _new_conn(self): + # Performs the NTLM handshake that secures the connection. The socket + # must be kept open while requests are performed. + self.num_connections += 1 + log.debug('Starting NTLM HTTPS connection no. %d: https://%s%s' % + (self.num_connections, self.host, self.authurl)) + + headers = {} + headers['Connection'] = 'Keep-Alive' + req_header = 'Authorization' + resp_header = 'www-authenticate' + + conn = HTTPSConnection(host=self.host, port=self.port) + + # Send negotiation message + headers[req_header] = ( + 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.rawuser)) + log.debug('Request headers: %s' % headers) + conn.request('GET', self.authurl, None, headers) + res = conn.getresponse() + reshdr = dict(res.getheaders()) + log.debug('Response status: %s %s' % (res.status, res.reason)) + log.debug('Response headers: %s' % reshdr) + log.debug('Response data: %s [...]' % res.read(100)) + + # Remove the reference to the socket, so that it can not be closed by + # the response object (we want to keep the socket open) + res.fp = None + + # Server should respond with a challenge message + auth_header_values = reshdr[resp_header].split(', ') + auth_header_value = None + for s in auth_header_values: + if s[:5] == 'NTLM ': + auth_header_value = s[5:] + if auth_header_value is None: + raise Exception('Unexpected %s response header: %s' % + (resp_header, reshdr[resp_header])) + + # Send authentication message + ServerChallenge, NegotiateFlags = \ + ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value) + auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, + self.user, + self.domain, + self.pw, + NegotiateFlags) + headers[req_header] = 'NTLM %s' % auth_msg + log.debug('Request headers: %s' % headers) + conn.request('GET', self.authurl, None, headers) + res = conn.getresponse() + log.debug('Response status: %s %s' % (res.status, res.reason)) + log.debug('Response headers: %s' % dict(res.getheaders())) + log.debug('Response data: %s [...]' % res.read()[:100]) + if res.status != 200: + if res.status == 401: + raise Exception('Server rejected request: wrong ' + 'username or password') + raise Exception('Wrong server response: %s %s' % + (res.status, res.reason)) + + res.fp = None + log.debug('Connection established') + return conn + + def urlopen(self, method, url, body=None, headers=None, retries=3, + redirect=True, assert_same_host=True): + if headers is None: + headers = {} + headers['Connection'] = 'Keep-Alive' + return super(NTLMConnectionPool, self).urlopen(method, url, body, + headers, retries, + redirect, + assert_same_host) diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/contrib/pyopenssl.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/contrib/pyopenssl.py new file mode 100644 index 0000000000..f78e71706e --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/contrib/pyopenssl.py @@ -0,0 +1,346 @@ +'''SSL with SNI-support for Python 2. + +This needs the following packages installed: + +* pyOpenSSL (tested with 0.13) +* ndg-httpsclient (tested with 0.3.2) +* pyasn1 (tested with 0.1.6) + +To activate it call :func:`~urllib3.contrib.pyopenssl.inject_into_urllib3`. +This can be done in a ``sitecustomize`` module, or at any other time before +your application begins using ``urllib3``, like this:: + + try: + import urllib3.contrib.pyopenssl + urllib3.contrib.pyopenssl.inject_into_urllib3() + except ImportError: + pass + +Now you can use :mod:`urllib3` as you normally would, and it will support SNI +when the required modules are installed. +''' + +from ndg.httpsclient.ssl_peer_verification import SUBJ_ALT_NAME_SUPPORT +from ndg.httpsclient.subj_alt_name import SubjectAltName +import OpenSSL.SSL +from pyasn1.codec.der import decoder as der_decoder +from socket import _fileobject +import ssl +import select +from cStringIO import StringIO + +from .. import connection +from .. import util + +__all__ = ['inject_into_urllib3', 'extract_from_urllib3'] + +# SNI only *really* works if we can read the subjectAltName of certificates. +HAS_SNI = SUBJ_ALT_NAME_SUPPORT + +# Map from urllib3 to PyOpenSSL compatible parameter-values. +_openssl_versions = { + ssl.PROTOCOL_SSLv23: OpenSSL.SSL.SSLv23_METHOD, + ssl.PROTOCOL_SSLv3: OpenSSL.SSL.SSLv3_METHOD, + ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD, +} +_openssl_verify = { + ssl.CERT_NONE: OpenSSL.SSL.VERIFY_NONE, + ssl.CERT_OPTIONAL: OpenSSL.SSL.VERIFY_PEER, + ssl.CERT_REQUIRED: OpenSSL.SSL.VERIFY_PEER + + OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT, +} + + +orig_util_HAS_SNI = util.HAS_SNI +orig_connection_ssl_wrap_socket = connection.ssl_wrap_socket + + +def inject_into_urllib3(): + 'Monkey-patch urllib3 with PyOpenSSL-backed SSL-support.' + + connection.ssl_wrap_socket = ssl_wrap_socket + util.HAS_SNI = HAS_SNI + + +def extract_from_urllib3(): + 'Undo monkey-patching by :func:`inject_into_urllib3`.' + + connection.ssl_wrap_socket = orig_connection_ssl_wrap_socket + util.HAS_SNI = orig_util_HAS_SNI + + +### Note: This is a slightly bug-fixed version of same from ndg-httpsclient. +def get_subj_alt_name(peer_cert): + # Search through extensions + dns_name = [] + if not SUBJ_ALT_NAME_SUPPORT: + return dns_name + + general_names = SubjectAltName() + for i in range(peer_cert.get_extension_count()): + ext = peer_cert.get_extension(i) + ext_name = ext.get_short_name() + if ext_name != 'subjectAltName': + continue + + # PyOpenSSL returns extension data in ASN.1 encoded form + ext_dat = ext.get_data() + decoded_dat = der_decoder.decode(ext_dat, + asn1Spec=general_names) + + for name in decoded_dat: + if not isinstance(name, SubjectAltName): + continue + for entry in range(len(name)): + component = name.getComponentByPosition(entry) + if component.getName() != 'dNSName': + continue + dns_name.append(str(component.getComponent())) + + return dns_name + + +class fileobject(_fileobject): + + def read(self, size=-1): + # Use max, disallow tiny reads in a loop as they are very inefficient. + # We never leave read() with any leftover data from a new recv() call + # in our internal buffer. + rbufsize = max(self._rbufsize, self.default_bufsize) + # Our use of StringIO rather than lists of string objects returned by + # recv() minimizes memory usage and fragmentation that occurs when + # rbufsize is large compared to the typical return value of recv(). + buf = self._rbuf + buf.seek(0, 2) # seek end + if size < 0: + # Read until EOF + self._rbuf = StringIO() # reset _rbuf. we consume it via buf. + while True: + try: + data = self._sock.recv(rbufsize) + except OpenSSL.SSL.WantReadError: + continue + if not data: + break + buf.write(data) + return buf.getvalue() + else: + # Read until size bytes or EOF seen, whichever comes first + buf_len = buf.tell() + if buf_len >= size: + # Already have size bytes in our buffer? Extract and return. + buf.seek(0) + rv = buf.read(size) + self._rbuf = StringIO() + self._rbuf.write(buf.read()) + return rv + + self._rbuf = StringIO() # reset _rbuf. we consume it via buf. + while True: + left = size - buf_len + # recv() will malloc the amount of memory given as its + # parameter even though it often returns much less data + # than that. The returned data string is short lived + # as we copy it into a StringIO and free it. This avoids + # fragmentation issues on many platforms. + try: + data = self._sock.recv(left) + except OpenSSL.SSL.WantReadError: + continue + if not data: + break + n = len(data) + if n == size and not buf_len: + # Shortcut. Avoid buffer data copies when: + # - We have no data in our buffer. + # AND + # - Our call to recv returned exactly the + # number of bytes we were asked to read. + return data + if n == left: + buf.write(data) + del data # explicit free + break + assert n <= left, "recv(%d) returned %d bytes" % (left, n) + buf.write(data) + buf_len += n + del data # explicit free + #assert buf_len == buf.tell() + return buf.getvalue() + + def readline(self, size=-1): + buf = self._rbuf + buf.seek(0, 2) # seek end + if buf.tell() > 0: + # check if we already have it in our buffer + buf.seek(0) + bline = buf.readline(size) + if bline.endswith('\n') or len(bline) == size: + self._rbuf = StringIO() + self._rbuf.write(buf.read()) + return bline + del bline + if size < 0: + # Read until \n or EOF, whichever comes first + if self._rbufsize <= 1: + # Speed up unbuffered case + buf.seek(0) + buffers = [buf.read()] + self._rbuf = StringIO() # reset _rbuf. we consume it via buf. + data = None + recv = self._sock.recv + while True: + try: + while data != "\n": + data = recv(1) + if not data: + break + buffers.append(data) + except OpenSSL.SSL.WantReadError: + continue + break + return "".join(buffers) + + buf.seek(0, 2) # seek end + self._rbuf = StringIO() # reset _rbuf. we consume it via buf. + while True: + try: + data = self._sock.recv(self._rbufsize) + except OpenSSL.SSL.WantReadError: + continue + if not data: + break + nl = data.find('\n') + if nl >= 0: + nl += 1 + buf.write(data[:nl]) + self._rbuf.write(data[nl:]) + del data + break + buf.write(data) + return buf.getvalue() + else: + # Read until size bytes or \n or EOF seen, whichever comes first + buf.seek(0, 2) # seek end + buf_len = buf.tell() + if buf_len >= size: + buf.seek(0) + rv = buf.read(size) + self._rbuf = StringIO() + self._rbuf.write(buf.read()) + return rv + self._rbuf = StringIO() # reset _rbuf. we consume it via buf. + while True: + try: + data = self._sock.recv(self._rbufsize) + except OpenSSL.SSL.WantReadError: + continue + if not data: + break + left = size - buf_len + # did we just receive a newline? + nl = data.find('\n', 0, left) + if nl >= 0: + nl += 1 + # save the excess data to _rbuf + self._rbuf.write(data[nl:]) + if buf_len: + buf.write(data[:nl]) + break + else: + # Shortcut. Avoid data copy through buf when returning + # a substring of our first recv(). + return data[:nl] + n = len(data) + if n == size and not buf_len: + # Shortcut. Avoid data copy through buf when + # returning exactly all of our first recv(). + return data + if n >= left: + buf.write(data[:left]) + self._rbuf.write(data[left:]) + break + buf.write(data) + buf_len += n + #assert buf_len == buf.tell() + return buf.getvalue() + + +class WrappedSocket(object): + '''API-compatibility wrapper for Python OpenSSL's Connection-class.''' + + def __init__(self, connection, socket): + self.connection = connection + self.socket = socket + + def fileno(self): + return self.socket.fileno() + + def makefile(self, mode, bufsize=-1): + return fileobject(self.connection, mode, bufsize) + + def settimeout(self, timeout): + return self.socket.settimeout(timeout) + + def sendall(self, data): + return self.connection.sendall(data) + + def close(self): + return self.connection.shutdown() + + def getpeercert(self, binary_form=False): + x509 = self.connection.get_peer_certificate() + + if not x509: + return x509 + + if binary_form: + return OpenSSL.crypto.dump_certificate( + OpenSSL.crypto.FILETYPE_ASN1, + x509) + + return { + 'subject': ( + (('commonName', x509.get_subject().CN),), + ), + 'subjectAltName': [ + ('DNS', value) + for value in get_subj_alt_name(x509) + ] + } + + +def _verify_callback(cnx, x509, err_no, err_depth, return_code): + return err_no == 0 + + +def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None, + ca_certs=None, server_hostname=None, + ssl_version=None): + ctx = OpenSSL.SSL.Context(_openssl_versions[ssl_version]) + if certfile: + ctx.use_certificate_file(certfile) + if keyfile: + ctx.use_privatekey_file(keyfile) + if cert_reqs != ssl.CERT_NONE: + ctx.set_verify(_openssl_verify[cert_reqs], _verify_callback) + if ca_certs: + try: + ctx.load_verify_locations(ca_certs, None) + except OpenSSL.SSL.Error as e: + raise ssl.SSLError('bad ca_certs: %r' % ca_certs, e) + + cnx = OpenSSL.SSL.Connection(ctx, sock) + cnx.set_tlsext_host_name(server_hostname) + cnx.set_connect_state() + while True: + try: + cnx.do_handshake() + except OpenSSL.SSL.WantReadError: + select.select([sock], [], []) + continue + except OpenSSL.SSL.Error as e: + raise ssl.SSLError('bad handshake', e) + break + + return WrappedSocket(cnx, sock) diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/exceptions.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/exceptions.py new file mode 100644 index 0000000000..98ef9abc7f --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/exceptions.py @@ -0,0 +1,121 @@ +# urllib3/exceptions.py +# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) +# +# This module is part of urllib3 and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + + +## Base Exceptions + +class HTTPError(Exception): + "Base exception used by this module." + pass + + +class PoolError(HTTPError): + "Base exception for errors caused within a pool." + def __init__(self, pool, message): + self.pool = pool + HTTPError.__init__(self, "%s: %s" % (pool, message)) + + def __reduce__(self): + # For pickling purposes. + return self.__class__, (None, None) + + +class RequestError(PoolError): + "Base exception for PoolErrors that have associated URLs." + def __init__(self, pool, url, message): + self.url = url + PoolError.__init__(self, pool, message) + + def __reduce__(self): + # For pickling purposes. + return self.__class__, (None, self.url, None) + + +class SSLError(HTTPError): + "Raised when SSL certificate fails in an HTTPS connection." + pass + + +class ProxyError(HTTPError): + "Raised when the connection to a proxy fails." + pass + + +class DecodeError(HTTPError): + "Raised when automatic decoding based on Content-Type fails." + pass + + +## Leaf Exceptions + +class MaxRetryError(RequestError): + "Raised when the maximum number of retries is exceeded." + + def __init__(self, pool, url, reason=None): + self.reason = reason + + message = "Max retries exceeded with url: %s" % url + if reason: + message += " (Caused by %s: %s)" % (type(reason), reason) + else: + message += " (Caused by redirect)" + + RequestError.__init__(self, pool, url, message) + + +class HostChangedError(RequestError): + "Raised when an existing pool gets a request for a foreign host." + + def __init__(self, pool, url, retries=3): + message = "Tried to open a foreign host with url: %s" % url + RequestError.__init__(self, pool, url, message) + self.retries = retries + + +class TimeoutStateError(HTTPError): + """ Raised when passing an invalid state to a timeout """ + pass + + +class TimeoutError(HTTPError): + """ Raised when a socket timeout error occurs. + + Catching this error will catch both :exc:`ReadTimeoutErrors + ` and :exc:`ConnectTimeoutErrors `. + """ + pass + + +class ReadTimeoutError(TimeoutError, RequestError): + "Raised when a socket timeout occurs while receiving data from a server" + pass + + +# This timeout error does not have a URL attached and needs to inherit from the +# base HTTPError +class ConnectTimeoutError(TimeoutError): + "Raised when a socket timeout occurs while connecting to a server" + pass + + +class EmptyPoolError(PoolError): + "Raised when a pool runs out of connections and no more are allowed." + pass + + +class ClosedPoolError(PoolError): + "Raised when a request enters a pool after the pool has been closed." + pass + + +class LocationParseError(ValueError, HTTPError): + "Raised when get_host or similar fails to parse the URL input." + + def __init__(self, location): + message = "Failed to parse: %s" % location + HTTPError.__init__(self, message) + + self.location = location diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/fields.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/fields.py new file mode 100644 index 0000000000..ed017657a2 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/fields.py @@ -0,0 +1,177 @@ +# urllib3/fields.py +# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) +# +# This module is part of urllib3 and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + +import email.utils +import mimetypes + +from .packages import six + + +def guess_content_type(filename, default='application/octet-stream'): + """ + Guess the "Content-Type" of a file. + + :param filename: + The filename to guess the "Content-Type" of using :mod:`mimetimes`. + :param default: + If no "Content-Type" can be guessed, default to `default`. + """ + if filename: + return mimetypes.guess_type(filename)[0] or default + return default + + +def format_header_param(name, value): + """ + Helper function to format and quote a single header parameter. + + Particularly useful for header parameters which might contain + non-ASCII values, like file names. This follows RFC 2231, as + suggested by RFC 2388 Section 4.4. + + :param name: + The name of the parameter, a string expected to be ASCII only. + :param value: + The value of the parameter, provided as a unicode string. + """ + if not any(ch in value for ch in '"\\\r\n'): + result = '%s="%s"' % (name, value) + try: + result.encode('ascii') + except UnicodeEncodeError: + pass + else: + return result + if not six.PY3: # Python 2: + value = value.encode('utf-8') + value = email.utils.encode_rfc2231(value, 'utf-8') + value = '%s*=%s' % (name, value) + return value + + +class RequestField(object): + """ + A data container for request body parameters. + + :param name: + The name of this request field. + :param data: + The data/value body. + :param filename: + An optional filename of the request field. + :param headers: + An optional dict-like object of headers to initially use for the field. + """ + def __init__(self, name, data, filename=None, headers=None): + self._name = name + self._filename = filename + self.data = data + self.headers = {} + if headers: + self.headers = dict(headers) + + @classmethod + def from_tuples(cls, fieldname, value): + """ + A :class:`~urllib3.fields.RequestField` factory from old-style tuple parameters. + + Supports constructing :class:`~urllib3.fields.RequestField` from parameter + of key/value strings AND key/filetuple. A filetuple is a (filename, data, MIME type) + tuple where the MIME type is optional. For example: :: + + 'foo': 'bar', + 'fakefile': ('foofile.txt', 'contents of foofile'), + 'realfile': ('barfile.txt', open('realfile').read()), + 'typedfile': ('bazfile.bin', open('bazfile').read(), 'image/jpeg'), + 'nonamefile': 'contents of nonamefile field', + + Field names and filenames must be unicode. + """ + if isinstance(value, tuple): + if len(value) == 3: + filename, data, content_type = value + else: + filename, data = value + content_type = guess_content_type(filename) + else: + filename = None + content_type = None + data = value + + request_param = cls(fieldname, data, filename=filename) + request_param.make_multipart(content_type=content_type) + + return request_param + + def _render_part(self, name, value): + """ + Overridable helper function to format a single header parameter. + + :param name: + The name of the parameter, a string expected to be ASCII only. + :param value: + The value of the parameter, provided as a unicode string. + """ + return format_header_param(name, value) + + def _render_parts(self, header_parts): + """ + Helper function to format and quote a single header. + + Useful for single headers that are composed of multiple items. E.g., + 'Content-Disposition' fields. + + :param header_parts: + A sequence of (k, v) typles or a :class:`dict` of (k, v) to format as + `k1="v1"; k2="v2"; ...`. + """ + parts = [] + iterable = header_parts + if isinstance(header_parts, dict): + iterable = header_parts.items() + + for name, value in iterable: + if value: + parts.append(self._render_part(name, value)) + + return '; '.join(parts) + + def render_headers(self): + """ + Renders the headers for this request field. + """ + lines = [] + + sort_keys = ['Content-Disposition', 'Content-Type', 'Content-Location'] + for sort_key in sort_keys: + if self.headers.get(sort_key, False): + lines.append('%s: %s' % (sort_key, self.headers[sort_key])) + + for header_name, header_value in self.headers.items(): + if header_name not in sort_keys: + if header_value: + lines.append('%s: %s' % (header_name, header_value)) + + lines.append('\r\n') + return '\r\n'.join(lines) + + def make_multipart(self, content_disposition=None, content_type=None, content_location=None): + """ + Makes this request field into a multipart request field. + + This method overrides "Content-Disposition", "Content-Type" and + "Content-Location" headers to the request parameter. + + :param content_type: + The 'Content-Type' of the request body. + :param content_location: + The 'Content-Location' of the request body. + + """ + self.headers['Content-Disposition'] = content_disposition or 'form-data' + self.headers['Content-Disposition'] += '; '.join(['', self._render_parts((('name', self._name), ('filename', self._filename)))]) + self.headers['Content-Type'] = content_type + self.headers['Content-Location'] = content_location diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/filepost.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/filepost.py new file mode 100644 index 0000000000..4575582e91 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/filepost.py @@ -0,0 +1,101 @@ +# urllib3/filepost.py +# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) +# +# This module is part of urllib3 and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + +import codecs +import mimetypes + +from uuid import uuid4 +from io import BytesIO + +from .packages import six +from .packages.six import b +from .fields import RequestField + +writer = codecs.lookup('utf-8')[3] + + +def choose_boundary(): + """ + Our embarassingly-simple replacement for mimetools.choose_boundary. + """ + return uuid4().hex + + +def iter_field_objects(fields): + """ + Iterate over fields. + + Supports list of (k, v) tuples and dicts, and lists of + :class:`~urllib3.fields.RequestField`. + + """ + if isinstance(fields, dict): + i = six.iteritems(fields) + else: + i = iter(fields) + + for field in i: + if isinstance(field, RequestField): + yield field + else: + yield RequestField.from_tuples(*field) + + +def iter_fields(fields): + """ + Iterate over fields. + + .. deprecated :: + + The addition of `~urllib3.fields.RequestField` makes this function + obsolete. Instead, use :func:`iter_field_objects`, which returns + `~urllib3.fields.RequestField` objects, instead. + + Supports list of (k, v) tuples and dicts. + + """ + if isinstance(fields, dict): + return ((k, v) for k, v in six.iteritems(fields)) + + return ((k, v) for k, v in fields) + + +def encode_multipart_formdata(fields, boundary=None): + """ + Encode a dictionary of ``fields`` using the multipart/form-data MIME format. + + :param fields: + Dictionary of fields or list of (key, :class:`~urllib3.fields.RequestField`). + + :param boundary: + If not specified, then a random boundary will be generated using + :func:`mimetools.choose_boundary`. + """ + body = BytesIO() + if boundary is None: + boundary = choose_boundary() + + for field in iter_field_objects(fields): + body.write(b('--%s\r\n' % (boundary))) + + writer(body).write(field.render_headers()) + data = field.data + + if isinstance(data, int): + data = str(data) # Backwards compatibility + + if isinstance(data, six.text_type): + writer(body).write(data) + else: + body.write(data) + + body.write(b'\r\n') + + body.write(b('--%s--\r\n' % (boundary))) + + content_type = str('multipart/form-data; boundary=%s' % boundary) + + return body.getvalue(), content_type diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/__init__.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/__init__.py new file mode 100644 index 0000000000..37e8351577 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/__init__.py @@ -0,0 +1,4 @@ +from __future__ import absolute_import + +from . import ssl_match_hostname + diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/ordered_dict.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/ordered_dict.py new file mode 100644 index 0000000000..7f8ee15436 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/ordered_dict.py @@ -0,0 +1,260 @@ +# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. +# Passes Python2.7's test suite and incorporates all the latest updates. +# Copyright 2009 Raymond Hettinger, released under the MIT License. +# http://code.activestate.com/recipes/576693/ + +try: + from thread import get_ident as _get_ident +except ImportError: + from dummy_thread import get_ident as _get_ident + +try: + from _abcoll import KeysView, ValuesView, ItemsView +except ImportError: + pass + + +class OrderedDict(dict): + 'Dictionary that remembers insertion order' + # An inherited dict maps keys to values. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-O running times for all methods are the same as for regular dictionaries. + + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # Each link is stored as a list of length three: [PREV, NEXT, KEY]. + + def __init__(self, *args, **kwds): + '''Initialize an ordered dictionary. Signature is the same as for + regular dictionaries, but keyword arguments are not recommended + because their insertion order is arbitrary. + + ''' + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__root + except AttributeError: + self.__root = root = [] # sentinel node + root[:] = [root, root, None] + self.__map = {} + self.__update(*args, **kwds) + + def __setitem__(self, key, value, dict_setitem=dict.__setitem__): + 'od.__setitem__(i, y) <==> od[i]=y' + # Setting a new item creates a new link which goes at the end of the linked + # list, and the inherited dictionary is updated with the new key/value pair. + if key not in self: + root = self.__root + last = root[0] + last[1] = root[0] = self.__map[key] = [last, root, key] + dict_setitem(self, key, value) + + def __delitem__(self, key, dict_delitem=dict.__delitem__): + 'od.__delitem__(y) <==> del od[y]' + # Deleting an existing item uses self.__map to find the link which is + # then removed by updating the links in the predecessor and successor nodes. + dict_delitem(self, key) + link_prev, link_next, key = self.__map.pop(key) + link_prev[1] = link_next + link_next[0] = link_prev + + def __iter__(self): + 'od.__iter__() <==> iter(od)' + root = self.__root + curr = root[1] + while curr is not root: + yield curr[2] + curr = curr[1] + + def __reversed__(self): + 'od.__reversed__() <==> reversed(od)' + root = self.__root + curr = root[0] + while curr is not root: + yield curr[2] + curr = curr[0] + + def clear(self): + 'od.clear() -> None. Remove all items from od.' + try: + for node in self.__map.itervalues(): + del node[:] + root = self.__root + root[:] = [root, root, None] + self.__map.clear() + except AttributeError: + pass + dict.clear(self) + + def popitem(self, last=True): + '''od.popitem() -> (k, v), return and remove a (key, value) pair. + Pairs are returned in LIFO order if last is true or FIFO order if false. + + ''' + if not self: + raise KeyError('dictionary is empty') + root = self.__root + if last: + link = root[0] + link_prev = link[0] + link_prev[1] = root + root[0] = link_prev + else: + link = root[1] + link_next = link[1] + root[1] = link_next + link_next[0] = root + key = link[2] + del self.__map[key] + value = dict.pop(self, key) + return key, value + + # -- the following methods do not depend on the internal structure -- + + def keys(self): + 'od.keys() -> list of keys in od' + return list(self) + + def values(self): + 'od.values() -> list of values in od' + return [self[key] for key in self] + + def items(self): + 'od.items() -> list of (key, value) pairs in od' + return [(key, self[key]) for key in self] + + def iterkeys(self): + 'od.iterkeys() -> an iterator over the keys in od' + return iter(self) + + def itervalues(self): + 'od.itervalues -> an iterator over the values in od' + for k in self: + yield self[k] + + def iteritems(self): + 'od.iteritems -> an iterator over the (key, value) items in od' + for k in self: + yield (k, self[k]) + + def update(*args, **kwds): + '''od.update(E, **F) -> None. Update od from dict/iterable E and F. + + If E is a dict instance, does: for k in E: od[k] = E[k] + If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] + Or if E is an iterable of items, does: for k, v in E: od[k] = v + In either case, this is followed by: for k, v in F.items(): od[k] = v + + ''' + if len(args) > 2: + raise TypeError('update() takes at most 2 positional ' + 'arguments (%d given)' % (len(args),)) + elif not args: + raise TypeError('update() takes at least 1 argument (0 given)') + self = args[0] + # Make progressively weaker assumptions about "other" + other = () + if len(args) == 2: + other = args[1] + if isinstance(other, dict): + for key in other: + self[key] = other[key] + elif hasattr(other, 'keys'): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + __update = update # let subclasses override update without breaking __init__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + + def __repr__(self, _repr_running={}): + 'od.__repr__() <==> repr(od)' + call_key = id(self), _get_ident() + if call_key in _repr_running: + return '...' + _repr_running[call_key] = 1 + try: + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + finally: + del _repr_running[call_key] + + def __reduce__(self): + 'Return state information for pickling' + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S + and values equal to v (which defaults to None). + + ''' + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return len(self)==len(other) and self.items() == other.items() + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other + + # -- the following methods are only used in Python 2.7 -- + + def viewkeys(self): + "od.viewkeys() -> a set-like object providing a view on od's keys" + return KeysView(self) + + def viewvalues(self): + "od.viewvalues() -> an object providing a view on od's values" + return ValuesView(self) + + def viewitems(self): + "od.viewitems() -> a set-like object providing a view on od's items" + return ItemsView(self) diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/six.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/six.py new file mode 100644 index 0000000000..27d80112bf --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/six.py @@ -0,0 +1,385 @@ +"""Utilities for writing code that runs on Python 2 and 3""" + +#Copyright (c) 2010-2011 Benjamin Peterson + +#Permission is hereby granted, free of charge, to any person obtaining a copy of +#this software and associated documentation files (the "Software"), to deal in +#the Software without restriction, including without limitation the rights to +#use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +#the Software, and to permit persons to whom the Software is furnished to do so, +#subject to the following conditions: + +#The above copyright notice and this permission notice shall be included in all +#copies or substantial portions of the Software. + +#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +#FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +#COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +#IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +#CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import operator +import sys +import types + +__author__ = "Benjamin Peterson " +__version__ = "1.2.0" # Revision 41c74fef2ded + + +# True if we are running on Python 3. +PY3 = sys.version_info[0] == 3 + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) + # This is a bit ugly, but it avoids running this again. + delattr(tp, self.name) + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + + +class _MovedItems(types.ModuleType): + """Lazy loading of moved objects""" + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("reload_module", "__builtin__", "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("winreg", "_winreg"), +] +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) +del attr + +moves = sys.modules[__name__ + ".moves"] = _MovedItems("moves") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_code = "__code__" + _func_defaults = "__defaults__" + + _iterkeys = "keys" + _itervalues = "values" + _iteritems = "items" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_code = "func_code" + _func_defaults = "func_defaults" + + _iterkeys = "iterkeys" + _itervalues = "itervalues" + _iteritems = "iteritems" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +if PY3: + def get_unbound_function(unbound): + return unbound + + Iterator = object + + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) +else: + def get_unbound_function(unbound): + return unbound.im_func + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) + + +def iterkeys(d): + """Return an iterator over the keys of a dictionary.""" + return iter(getattr(d, _iterkeys)()) + +def itervalues(d): + """Return an iterator over the values of a dictionary.""" + return iter(getattr(d, _itervalues)()) + +def iteritems(d): + """Return an iterator over the (key, value) pairs of a dictionary.""" + return iter(getattr(d, _iteritems)()) + + +if PY3: + def b(s): + return s.encode("latin-1") + def u(s): + return s + if sys.version_info[1] <= 1: + def int2byte(i): + return bytes((i,)) + else: + # This is about 2x faster than the implementation above on 3.2+ + int2byte = operator.methodcaller("to_bytes", 1, "big") + import io + StringIO = io.StringIO + BytesIO = io.BytesIO +else: + def b(s): + return s + def u(s): + return unicode(s, "unicode_escape") + int2byte = chr + import StringIO + StringIO = BytesIO = StringIO.StringIO +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +if PY3: + import builtins + exec_ = getattr(builtins, "exec") + + + def reraise(tp, value, tb=None): + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + + + print_ = getattr(builtins, "print") + del builtins + +else: + def exec_(code, globs=None, locs=None): + """Execute code in a namespace.""" + if globs is None: + frame = sys._getframe(1) + globs = frame.f_globals + if locs is None: + locs = frame.f_locals + del frame + elif locs is None: + locs = globs + exec("""exec code in globs, locs""") + + + exec_("""def reraise(tp, value, tb=None): + raise tp, value, tb +""") + + + def print_(*args, **kwargs): + """The new-style print function.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + def write(data): + if not isinstance(data, basestring): + data = str(data) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) + +_add_doc(reraise, """Reraise an exception.""") + + +def with_metaclass(meta, base=object): + """Create a base class with a metaclass.""" + return meta("NewBase", (base,), {}) diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py new file mode 100644 index 0000000000..3aa5b2e190 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py @@ -0,0 +1,13 @@ +try: + # Python 3.2+ + from ssl import CertificateError, match_hostname +except ImportError: + try: + # Backport of the function from a pypi module + from backports.ssl_match_hostname import CertificateError, match_hostname + except ImportError: + # Our vendored copy + from _implementation import CertificateError, match_hostname + +# Not needed, but documenting what we provide. +__all__ = ('CertificateError', 'match_hostname') diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py new file mode 100644 index 0000000000..52f428733d --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py @@ -0,0 +1,105 @@ +"""The match_hostname() function from Python 3.3.3, essential when using SSL.""" + +# Note: This file is under the PSF license as the code comes from the python +# stdlib. http://docs.python.org/3/license.html + +import re + +__version__ = '3.4.0.2' + +class CertificateError(ValueError): + pass + + +def _dnsname_match(dn, hostname, max_wildcards=1): + """Matching according to RFC 6125, section 6.4.3 + + http://tools.ietf.org/html/rfc6125#section-6.4.3 + """ + pats = [] + if not dn: + return False + + # Ported from python3-syntax: + # leftmost, *remainder = dn.split(r'.') + parts = dn.split(r'.') + leftmost = parts[0] + remainder = parts[1:] + + wildcards = leftmost.count('*') + if wildcards > max_wildcards: + # Issue #17980: avoid denials of service by refusing more + # than one wildcard per fragment. A survey of established + # policy among SSL implementations showed it to be a + # reasonable choice. + raise CertificateError( + "too many wildcards in certificate DNS name: " + repr(dn)) + + # speed up common case w/o wildcards + if not wildcards: + return dn.lower() == hostname.lower() + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in which + # the wildcard character comprises a label other than the left-most label. + if leftmost == '*': + # When '*' is a fragment by itself, it matches a non-empty dotless + # fragment. + pats.append('[^.]+') + elif leftmost.startswith('xn--') or hostname.startswith('xn--'): + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + pats.append(re.escape(leftmost)) + else: + # Otherwise, '*' matches any dotless string, e.g. www* + pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) + + # add the remaining fragments, ignore any wildcards + for frag in remainder: + pats.append(re.escape(frag)) + + pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) + return pat.match(hostname) + + +def match_hostname(cert, hostname): + """Verify that *cert* (in decoded format as returned by + SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 + rules are followed, but IP addresses are not accepted for *hostname*. + + CertificateError is raised on failure. On success, the function + returns nothing. + """ + if not cert: + raise ValueError("empty or no certificate") + dnsnames = [] + san = cert.get('subjectAltName', ()) + for key, value in san: + if key == 'DNS': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if not dnsnames: + # The subject is only checked when there is no dNSName entry + # in subjectAltName + for sub in cert.get('subject', ()): + for key, value in sub: + # XXX according to RFC 2818, the most specific Common Name + # must be used. + if key == 'commonName': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if len(dnsnames) > 1: + raise CertificateError("hostname %r " + "doesn't match either of %s" + % (hostname, ', '.join(map(repr, dnsnames)))) + elif len(dnsnames) == 1: + raise CertificateError("hostname %r " + "doesn't match %r" + % (hostname, dnsnames[0])) + else: + raise CertificateError("no appropriate commonName or " + "subjectAltName fields were found") diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/poolmanager.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/poolmanager.py new file mode 100644 index 0000000000..c16519f883 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/poolmanager.py @@ -0,0 +1,258 @@ +# urllib3/poolmanager.py +# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) +# +# This module is part of urllib3 and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + +import logging + +try: # Python 3 + from urllib.parse import urljoin +except ImportError: + from urlparse import urljoin + +from ._collections import RecentlyUsedContainer +from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool +from .connectionpool import port_by_scheme +from .request import RequestMethods +from .util import parse_url + + +__all__ = ['PoolManager', 'ProxyManager', 'proxy_from_url'] + + +pool_classes_by_scheme = { + 'http': HTTPConnectionPool, + 'https': HTTPSConnectionPool, +} + +log = logging.getLogger(__name__) + +SSL_KEYWORDS = ('key_file', 'cert_file', 'cert_reqs', 'ca_certs', + 'ssl_version') + + +class PoolManager(RequestMethods): + """ + Allows for arbitrary requests while transparently keeping track of + necessary connection pools for you. + + :param num_pools: + Number of connection pools to cache before discarding the least + recently used pool. + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + + :param \**connection_pool_kw: + Additional parameters are used to create fresh + :class:`urllib3.connectionpool.ConnectionPool` instances. + + Example: :: + + >>> manager = PoolManager(num_pools=2) + >>> r = manager.request('GET', 'http://google.com/') + >>> r = manager.request('GET', 'http://google.com/mail') + >>> r = manager.request('GET', 'http://yahoo.com/') + >>> len(manager.pools) + 2 + + """ + + proxy = None + + def __init__(self, num_pools=10, headers=None, **connection_pool_kw): + RequestMethods.__init__(self, headers) + self.connection_pool_kw = connection_pool_kw + self.pools = RecentlyUsedContainer(num_pools, + dispose_func=lambda p: p.close()) + + def _new_pool(self, scheme, host, port): + """ + Create a new :class:`ConnectionPool` based on host, port and scheme. + + This method is used to actually create the connection pools handed out + by :meth:`connection_from_url` and companion methods. It is intended + to be overridden for customization. + """ + pool_cls = pool_classes_by_scheme[scheme] + kwargs = self.connection_pool_kw + if scheme == 'http': + kwargs = self.connection_pool_kw.copy() + for kw in SSL_KEYWORDS: + kwargs.pop(kw, None) + + return pool_cls(host, port, **kwargs) + + def clear(self): + """ + Empty our store of pools and direct them all to close. + + This will not affect in-flight connections, but they will not be + re-used after completion. + """ + self.pools.clear() + + def connection_from_host(self, host, port=None, scheme='http'): + """ + Get a :class:`ConnectionPool` based on the host, port, and scheme. + + If ``port`` isn't given, it will be derived from the ``scheme`` using + ``urllib3.connectionpool.port_by_scheme``. + """ + + scheme = scheme or 'http' + + port = port or port_by_scheme.get(scheme, 80) + + pool_key = (scheme, host, port) + + with self.pools.lock: + # If the scheme, host, or port doesn't match existing open + # connections, open a new ConnectionPool. + pool = self.pools.get(pool_key) + if pool: + return pool + + # Make a fresh ConnectionPool of the desired type + pool = self._new_pool(scheme, host, port) + self.pools[pool_key] = pool + return pool + + def connection_from_url(self, url): + """ + Similar to :func:`urllib3.connectionpool.connection_from_url` but + doesn't pass any additional parameters to the + :class:`urllib3.connectionpool.ConnectionPool` constructor. + + Additional parameters are taken from the :class:`.PoolManager` + constructor. + """ + u = parse_url(url) + return self.connection_from_host(u.host, port=u.port, scheme=u.scheme) + + def urlopen(self, method, url, redirect=True, **kw): + """ + Same as :meth:`urllib3.connectionpool.HTTPConnectionPool.urlopen` + with custom cross-host redirect logic and only sends the request-uri + portion of the ``url``. + + The given ``url`` parameter must be absolute, such that an appropriate + :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it. + """ + u = parse_url(url) + conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme) + + kw['assert_same_host'] = False + kw['redirect'] = False + if 'headers' not in kw: + kw['headers'] = self.headers + + if self.proxy is not None and u.scheme == "http": + response = conn.urlopen(method, url, **kw) + else: + response = conn.urlopen(method, u.request_uri, **kw) + + redirect_location = redirect and response.get_redirect_location() + if not redirect_location: + return response + + # Support relative URLs for redirecting. + redirect_location = urljoin(url, redirect_location) + + # RFC 2616, Section 10.3.4 + if response.status == 303: + method = 'GET' + + log.info("Redirecting %s -> %s" % (url, redirect_location)) + kw['retries'] = kw.get('retries', 3) - 1 # Persist retries countdown + kw['redirect'] = redirect + return self.urlopen(method, redirect_location, **kw) + + +class ProxyManager(PoolManager): + """ + Behaves just like :class:`PoolManager`, but sends all requests through + the defined proxy, using the CONNECT method for HTTPS URLs. + + :param poxy_url: + The URL of the proxy to be used. + + :param proxy_headers: + A dictionary contaning headers that will be sent to the proxy. In case + of HTTP they are being sent with each request, while in the + HTTPS/CONNECT case they are sent only once. Could be used for proxy + authentication. + + Example: + >>> proxy = urllib3.ProxyManager('http://localhost:3128/') + >>> r1 = proxy.request('GET', 'http://google.com/') + >>> r2 = proxy.request('GET', 'http://httpbin.org/') + >>> len(proxy.pools) + 1 + >>> r3 = proxy.request('GET', 'https://httpbin.org/') + >>> r4 = proxy.request('GET', 'https://twitter.com/') + >>> len(proxy.pools) + 3 + + """ + + def __init__(self, proxy_url, num_pools=10, headers=None, + proxy_headers=None, **connection_pool_kw): + + if isinstance(proxy_url, HTTPConnectionPool): + proxy_url = '%s://%s:%i' % (proxy_url.scheme, proxy_url.host, + proxy_url.port) + proxy = parse_url(proxy_url) + if not proxy.port: + port = port_by_scheme.get(proxy.scheme, 80) + proxy = proxy._replace(port=port) + self.proxy = proxy + self.proxy_headers = proxy_headers or {} + assert self.proxy.scheme in ("http", "https"), \ + 'Not supported proxy scheme %s' % self.proxy.scheme + connection_pool_kw['_proxy'] = self.proxy + connection_pool_kw['_proxy_headers'] = self.proxy_headers + super(ProxyManager, self).__init__( + num_pools, headers, **connection_pool_kw) + + def connection_from_host(self, host, port=None, scheme='http'): + if scheme == "https": + return super(ProxyManager, self).connection_from_host( + host, port, scheme) + + return super(ProxyManager, self).connection_from_host( + self.proxy.host, self.proxy.port, self.proxy.scheme) + + def _set_proxy_headers(self, url, headers=None): + """ + Sets headers needed by proxies: specifically, the Accept and Host + headers. Only sets headers not provided by the user. + """ + headers_ = {'Accept': '*/*'} + + netloc = parse_url(url).netloc + if netloc: + headers_['Host'] = netloc + + if headers: + headers_.update(headers) + return headers_ + + def urlopen(self, method, url, redirect=True, **kw): + "Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute." + u = parse_url(url) + + if u.scheme == "http": + # For proxied HTTPS requests, httplib sets the necessary headers + # on the CONNECT to the proxy. For HTTP, we'll definitely + # need to set 'Host' at the very least. + kw['headers'] = self._set_proxy_headers(url, kw.get('headers', + self.headers)) + + return super(ProxyManager, self).urlopen(method, url, redirect, **kw) + + +def proxy_from_url(url, **kw): + return ProxyManager(proxy_url=url, **kw) diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/request.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/request.py new file mode 100644 index 0000000000..66a9a0e690 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/request.py @@ -0,0 +1,142 @@ +# urllib3/request.py +# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) +# +# This module is part of urllib3 and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + +try: + from urllib.parse import urlencode +except ImportError: + from urllib import urlencode + +from .filepost import encode_multipart_formdata + + +__all__ = ['RequestMethods'] + + +class RequestMethods(object): + """ + Convenience mixin for classes who implement a :meth:`urlopen` method, such + as :class:`~urllib3.connectionpool.HTTPConnectionPool` and + :class:`~urllib3.poolmanager.PoolManager`. + + Provides behavior for making common types of HTTP request methods and + decides which type of request field encoding to use. + + Specifically, + + :meth:`.request_encode_url` is for sending requests whose fields are encoded + in the URL (such as GET, HEAD, DELETE). + + :meth:`.request_encode_body` is for sending requests whose fields are + encoded in the *body* of the request using multipart or www-form-urlencoded + (such as for POST, PUT, PATCH). + + :meth:`.request` is for making any kind of request, it will look up the + appropriate encoding format and use one of the above two methods to make + the request. + + Initializer parameters: + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + """ + + _encode_url_methods = set(['DELETE', 'GET', 'HEAD', 'OPTIONS']) + _encode_body_methods = set(['PATCH', 'POST', 'PUT', 'TRACE']) + + def __init__(self, headers=None): + self.headers = headers or {} + + def urlopen(self, method, url, body=None, headers=None, + encode_multipart=True, multipart_boundary=None, + **kw): # Abstract + raise NotImplemented("Classes extending RequestMethods must implement " + "their own ``urlopen`` method.") + + def request(self, method, url, fields=None, headers=None, **urlopen_kw): + """ + Make a request using :meth:`urlopen` with the appropriate encoding of + ``fields`` based on the ``method`` used. + + This is a convenience method that requires the least amount of manual + effort. It can be used in most situations, while still having the option + to drop down to more specific methods when necessary, such as + :meth:`request_encode_url`, :meth:`request_encode_body`, + or even the lowest level :meth:`urlopen`. + """ + method = method.upper() + + if method in self._encode_url_methods: + return self.request_encode_url(method, url, fields=fields, + headers=headers, + **urlopen_kw) + else: + return self.request_encode_body(method, url, fields=fields, + headers=headers, + **urlopen_kw) + + def request_encode_url(self, method, url, fields=None, **urlopen_kw): + """ + Make a request using :meth:`urlopen` with the ``fields`` encoded in + the url. This is useful for request methods like GET, HEAD, DELETE, etc. + """ + if fields: + url += '?' + urlencode(fields) + return self.urlopen(method, url, **urlopen_kw) + + def request_encode_body(self, method, url, fields=None, headers=None, + encode_multipart=True, multipart_boundary=None, + **urlopen_kw): + """ + Make a request using :meth:`urlopen` with the ``fields`` encoded in + the body. This is useful for request methods like POST, PUT, PATCH, etc. + + When ``encode_multipart=True`` (default), then + :meth:`urllib3.filepost.encode_multipart_formdata` is used to encode the + payload with the appropriate content type. Otherwise + :meth:`urllib.urlencode` is used with the + 'application/x-www-form-urlencoded' content type. + + Multipart encoding must be used when posting files, and it's reasonably + safe to use it in other times too. However, it may break request signing, + such as with OAuth. + + Supports an optional ``fields`` parameter of key/value strings AND + key/filetuple. A filetuple is a (filename, data, MIME type) tuple where + the MIME type is optional. For example: :: + + fields = { + 'foo': 'bar', + 'fakefile': ('foofile.txt', 'contents of foofile'), + 'realfile': ('barfile.txt', open('realfile').read()), + 'typedfile': ('bazfile.bin', open('bazfile').read(), + 'image/jpeg'), + 'nonamefile': 'contents of nonamefile field', + } + + When uploading a file, providing a filename (the first parameter of the + tuple) is optional but recommended to best mimick behavior of browsers. + + Note that if ``headers`` are supplied, the 'Content-Type' header will be + overwritten because it depends on the dynamic random boundary string + which is used to compose the body of the request. The random boundary + string can be explicitly set with the ``multipart_boundary`` parameter. + """ + if encode_multipart: + body, content_type = encode_multipart_formdata(fields or {}, + boundary=multipart_boundary) + else: + body, content_type = (urlencode(fields or {}), + 'application/x-www-form-urlencoded') + + if headers is None: + headers = self.headers + + headers_ = {'Content-Type': content_type} + headers_.update(headers) + + return self.urlopen(method, url, body=body, headers=headers_, + **urlopen_kw) diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/response.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/response.py new file mode 100644 index 0000000000..6a1fe1a77c --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/response.py @@ -0,0 +1,312 @@ +# urllib3/response.py +# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) +# +# This module is part of urllib3 and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + + +import logging +import zlib +import io + +from .exceptions import DecodeError +from .packages.six import string_types as basestring, binary_type +from .util import is_fp_closed + + +log = logging.getLogger(__name__) + + +class DeflateDecoder(object): + + def __init__(self): + self._first_try = True + self._data = binary_type() + self._obj = zlib.decompressobj() + + def __getattr__(self, name): + return getattr(self._obj, name) + + def decompress(self, data): + if not self._first_try: + return self._obj.decompress(data) + + self._data += data + try: + return self._obj.decompress(data) + except zlib.error: + self._first_try = False + self._obj = zlib.decompressobj(-zlib.MAX_WBITS) + try: + return self.decompress(self._data) + finally: + self._data = None + + +def _get_decoder(mode): + if mode == 'gzip': + return zlib.decompressobj(16 + zlib.MAX_WBITS) + + return DeflateDecoder() + + +class HTTPResponse(io.IOBase): + """ + HTTP Response container. + + Backwards-compatible to httplib's HTTPResponse but the response ``body`` is + loaded and decoded on-demand when the ``data`` property is accessed. + + Extra parameters for behaviour not present in httplib.HTTPResponse: + + :param preload_content: + If True, the response's body will be preloaded during construction. + + :param decode_content: + If True, attempts to decode specific content-encoding's based on headers + (like 'gzip' and 'deflate') will be skipped and raw data will be used + instead. + + :param original_response: + When this HTTPResponse wrapper is generated from an httplib.HTTPResponse + object, it's convenient to include the original for debug purposes. It's + otherwise unused. + """ + + CONTENT_DECODERS = ['gzip', 'deflate'] + REDIRECT_STATUSES = [301, 302, 303, 307, 308] + + def __init__(self, body='', headers=None, status=0, version=0, reason=None, + strict=0, preload_content=True, decode_content=True, + original_response=None, pool=None, connection=None): + self.headers = headers or {} + self.status = status + self.version = version + self.reason = reason + self.strict = strict + self.decode_content = decode_content + + self._decoder = None + self._body = body if body and isinstance(body, basestring) else None + self._fp = None + self._original_response = original_response + self._fp_bytes_read = 0 + + self._pool = pool + self._connection = connection + + if hasattr(body, 'read'): + self._fp = body + + if preload_content and not self._body: + self._body = self.read(decode_content=decode_content) + + def get_redirect_location(self): + """ + Should we redirect and where to? + + :returns: Truthy redirect location string if we got a redirect status + code and valid location. ``None`` if redirect status and no + location. ``False`` if not a redirect status code. + """ + if self.status in self.REDIRECT_STATUSES: + return self.headers.get('location') + + return False + + def release_conn(self): + if not self._pool or not self._connection: + return + + self._pool._put_conn(self._connection) + self._connection = None + + @property + def data(self): + # For backwords-compat with earlier urllib3 0.4 and earlier. + if self._body: + return self._body + + if self._fp: + return self.read(cache_content=True) + + def tell(self): + """ + Obtain the number of bytes pulled over the wire so far. May differ from + the amount of content returned by :meth:``HTTPResponse.read`` if bytes + are encoded on the wire (e.g, compressed). + """ + return self._fp_bytes_read + + def read(self, amt=None, decode_content=None, cache_content=False): + """ + Similar to :meth:`httplib.HTTPResponse.read`, but with two additional + parameters: ``decode_content`` and ``cache_content``. + + :param amt: + How much of the content to read. If specified, caching is skipped + because it doesn't make sense to cache partial content as the full + response. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + + :param cache_content: + If True, will save the returned data such that the same result is + returned despite of the state of the underlying file object. This + is useful if you want the ``.data`` property to continue working + after having ``.read()`` the file object. (Overridden if ``amt`` is + set.) + """ + # Note: content-encoding value should be case-insensitive, per RFC 2616 + # Section 3.5 + content_encoding = self.headers.get('content-encoding', '').lower() + if self._decoder is None: + if content_encoding in self.CONTENT_DECODERS: + self._decoder = _get_decoder(content_encoding) + if decode_content is None: + decode_content = self.decode_content + + if self._fp is None: + return + + flush_decoder = False + + try: + if amt is None: + # cStringIO doesn't like amt=None + data = self._fp.read() + flush_decoder = True + else: + cache_content = False + data = self._fp.read(amt) + if amt != 0 and not data: # Platform-specific: Buggy versions of Python. + # Close the connection when no data is returned + # + # This is redundant to what httplib/http.client _should_ + # already do. However, versions of python released before + # December 15, 2012 (http://bugs.python.org/issue16298) do not + # properly close the connection in all cases. There is no harm + # in redundantly calling close. + self._fp.close() + flush_decoder = True + + self._fp_bytes_read += len(data) + + try: + if decode_content and self._decoder: + data = self._decoder.decompress(data) + except (IOError, zlib.error) as e: + raise DecodeError( + "Received response with content-encoding: %s, but " + "failed to decode it." % content_encoding, + e) + + if flush_decoder and decode_content and self._decoder: + buf = self._decoder.decompress(binary_type()) + data += buf + self._decoder.flush() + + if cache_content: + self._body = data + + return data + + finally: + if self._original_response and self._original_response.isclosed(): + self.release_conn() + + def stream(self, amt=2**16, decode_content=None): + """ + A generator wrapper for the read() method. A call will block until + ``amt`` bytes have been read from the connection or until the + connection is closed. + + :param amt: + How much of the content to read. The generator will return up to + much data per iteration, but may return less. This is particularly + likely when using compressed data. However, the empty string will + never be returned. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + """ + while not is_fp_closed(self._fp): + data = self.read(amt=amt, decode_content=decode_content) + + if data: + yield data + + + @classmethod + def from_httplib(ResponseCls, r, **response_kw): + """ + Given an :class:`httplib.HTTPResponse` instance ``r``, return a + corresponding :class:`urllib3.response.HTTPResponse` object. + + Remaining parameters are passed to the HTTPResponse constructor, along + with ``original_response=r``. + """ + + # Normalize headers between different versions of Python + headers = {} + for k, v in r.getheaders(): + # Python 3: Header keys are returned capitalised + k = k.lower() + + has_value = headers.get(k) + if has_value: # Python 3: Repeating header keys are unmerged. + v = ', '.join([has_value, v]) + + headers[k] = v + + # HTTPResponse objects in Python 3 don't have a .strict attribute + strict = getattr(r, 'strict', 0) + return ResponseCls(body=r, + headers=headers, + status=r.status, + version=r.version, + reason=r.reason, + strict=strict, + original_response=r, + **response_kw) + + # Backwards-compatibility methods for httplib.HTTPResponse + def getheaders(self): + return self.headers + + def getheader(self, name, default=None): + return self.headers.get(name, default) + + # Overrides from io.IOBase + def close(self): + if not self.closed: + self._fp.close() + + @property + def closed(self): + if self._fp is None: + return True + elif hasattr(self._fp, 'closed'): + return self._fp.closed + elif hasattr(self._fp, 'isclosed'): # Python 2 + return self._fp.isclosed() + else: + return True + + def fileno(self): + if self._fp is None: + raise IOError("HTTPResponse has no file to get a fileno from") + elif hasattr(self._fp, "fileno"): + return self._fp.fileno() + else: + raise IOError("The file-like object this HTTPResponse is wrapped " + "around has no file descriptor") + + def flush(self): + if self._fp is not None and hasattr(self._fp, 'flush'): + return self._fp.flush() + + def readable(self): + return True diff --git a/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/util.py b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/util.py new file mode 100644 index 0000000000..46a0c48de1 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/packages/urllib3/util.py @@ -0,0 +1,643 @@ +# urllib3/util.py +# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) +# +# This module is part of urllib3 and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + + +from base64 import b64encode +from binascii import hexlify, unhexlify +from collections import namedtuple +from hashlib import md5, sha1 +from socket import error as SocketError, _GLOBAL_DEFAULT_TIMEOUT +import time + +try: + from select import poll, POLLIN +except ImportError: # `poll` doesn't exist on OSX and other platforms + poll = False + try: + from select import select + except ImportError: # `select` doesn't exist on AppEngine. + select = False + +try: # Test for SSL features + SSLContext = None + HAS_SNI = False + + import ssl + from ssl import wrap_socket, CERT_NONE, PROTOCOL_SSLv23 + from ssl import SSLContext # Modern SSL? + from ssl import HAS_SNI # Has SNI? +except ImportError: + pass + +from .packages import six +from .exceptions import LocationParseError, SSLError, TimeoutStateError + + +_Default = object() +# The default timeout to use for socket connections. This is the attribute used +# by httplib to define the default timeout + + +def current_time(): + """ + Retrieve the current time, this function is mocked out in unit testing. + """ + return time.time() + + +class Timeout(object): + """ + Utility object for storing timeout values. + + Example usage: + + .. code-block:: python + + timeout = urllib3.util.Timeout(connect=2.0, read=7.0) + pool = HTTPConnectionPool('www.google.com', 80, timeout=timeout) + pool.request(...) # Etc, etc + + :param connect: + The maximum amount of time to wait for a connection attempt to a server + to succeed. Omitting the parameter will default the connect timeout to + the system default, probably `the global default timeout in socket.py + `_. + None will set an infinite timeout for connection attempts. + + :type connect: integer, float, or None + + :param read: + The maximum amount of time to wait between consecutive + read operations for a response from the server. Omitting + the parameter will default the read timeout to the system + default, probably `the global default timeout in socket.py + `_. + None will set an infinite timeout. + + :type read: integer, float, or None + + :param total: + This combines the connect and read timeouts into one; the read timeout + will be set to the time leftover from the connect attempt. In the + event that both a connect timeout and a total are specified, or a read + timeout and a total are specified, the shorter timeout will be applied. + + Defaults to None. + + :type total: integer, float, or None + + .. note:: + + Many factors can affect the total amount of time for urllib3 to return + an HTTP response. Specifically, Python's DNS resolver does not obey the + timeout specified on the socket. Other factors that can affect total + request time include high CPU load, high swap, the program running at a + low priority level, or other behaviors. The observed running time for + urllib3 to return a response may be greater than the value passed to + `total`. + + In addition, the read and total timeouts only measure the time between + read operations on the socket connecting the client and the server, + not the total amount of time for the request to return a complete + response. For most requests, the timeout is raised because the server + has not sent the first byte in the specified time. This is not always + the case; if a server streams one byte every fifteen seconds, a timeout + of 20 seconds will not ever trigger, even though the request will + take several minutes to complete. + + If your goal is to cut off any request after a set amount of wall clock + time, consider having a second "watcher" thread to cut off a slow + request. + """ + + #: A sentinel object representing the default timeout value + DEFAULT_TIMEOUT = _GLOBAL_DEFAULT_TIMEOUT + + def __init__(self, total=None, connect=_Default, read=_Default): + self._connect = self._validate_timeout(connect, 'connect') + self._read = self._validate_timeout(read, 'read') + self.total = self._validate_timeout(total, 'total') + self._start_connect = None + + def __str__(self): + return '%s(connect=%r, read=%r, total=%r)' % ( + type(self).__name__, self._connect, self._read, self.total) + + + @classmethod + def _validate_timeout(cls, value, name): + """ Check that a timeout attribute is valid + + :param value: The timeout value to validate + :param name: The name of the timeout attribute to validate. This is used + for clear error messages + :return: the value + :raises ValueError: if the type is not an integer or a float, or if it + is a numeric value less than zero + """ + if value is _Default: + return cls.DEFAULT_TIMEOUT + + if value is None or value is cls.DEFAULT_TIMEOUT: + return value + + try: + float(value) + except (TypeError, ValueError): + raise ValueError("Timeout value %s was %s, but it must be an " + "int or float." % (name, value)) + + try: + if value < 0: + raise ValueError("Attempted to set %s timeout to %s, but the " + "timeout cannot be set to a value less " + "than 0." % (name, value)) + except TypeError: # Python 3 + raise ValueError("Timeout value %s was %s, but it must be an " + "int or float." % (name, value)) + + return value + + @classmethod + def from_float(cls, timeout): + """ Create a new Timeout from a legacy timeout value. + + The timeout value used by httplib.py sets the same timeout on the + connect(), and recv() socket requests. This creates a :class:`Timeout` + object that sets the individual timeouts to the ``timeout`` value passed + to this function. + + :param timeout: The legacy timeout value + :type timeout: integer, float, sentinel default object, or None + :return: a Timeout object + :rtype: :class:`Timeout` + """ + return Timeout(read=timeout, connect=timeout) + + def clone(self): + """ Create a copy of the timeout object + + Timeout properties are stored per-pool but each request needs a fresh + Timeout object to ensure each one has its own start/stop configured. + + :return: a copy of the timeout object + :rtype: :class:`Timeout` + """ + # We can't use copy.deepcopy because that will also create a new object + # for _GLOBAL_DEFAULT_TIMEOUT, which socket.py uses as a sentinel to + # detect the user default. + return Timeout(connect=self._connect, read=self._read, + total=self.total) + + def start_connect(self): + """ Start the timeout clock, used during a connect() attempt + + :raises urllib3.exceptions.TimeoutStateError: if you attempt + to start a timer that has been started already. + """ + if self._start_connect is not None: + raise TimeoutStateError("Timeout timer has already been started.") + self._start_connect = current_time() + return self._start_connect + + def get_connect_duration(self): + """ Gets the time elapsed since the call to :meth:`start_connect`. + + :return: the elapsed time + :rtype: float + :raises urllib3.exceptions.TimeoutStateError: if you attempt + to get duration for a timer that hasn't been started. + """ + if self._start_connect is None: + raise TimeoutStateError("Can't get connect duration for timer " + "that has not started.") + return current_time() - self._start_connect + + @property + def connect_timeout(self): + """ Get the value to use when setting a connection timeout. + + This will be a positive float or integer, the value None + (never timeout), or the default system timeout. + + :return: the connect timeout + :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None + """ + if self.total is None: + return self._connect + + if self._connect is None or self._connect is self.DEFAULT_TIMEOUT: + return self.total + + return min(self._connect, self.total) + + @property + def read_timeout(self): + """ Get the value for the read timeout. + + This assumes some time has elapsed in the connection timeout and + computes the read timeout appropriately. + + If self.total is set, the read timeout is dependent on the amount of + time taken by the connect timeout. If the connection time has not been + established, a :exc:`~urllib3.exceptions.TimeoutStateError` will be + raised. + + :return: the value to use for the read timeout + :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None + :raises urllib3.exceptions.TimeoutStateError: If :meth:`start_connect` + has not yet been called on this object. + """ + if (self.total is not None and + self.total is not self.DEFAULT_TIMEOUT and + self._read is not None and + self._read is not self.DEFAULT_TIMEOUT): + # in case the connect timeout has not yet been established. + if self._start_connect is None: + return self._read + return max(0, min(self.total - self.get_connect_duration(), + self._read)) + elif self.total is not None and self.total is not self.DEFAULT_TIMEOUT: + return max(0, self.total - self.get_connect_duration()) + else: + return self._read + + +class Url(namedtuple('Url', ['scheme', 'auth', 'host', 'port', 'path', 'query', 'fragment'])): + """ + Datastructure for representing an HTTP URL. Used as a return value for + :func:`parse_url`. + """ + slots = () + + def __new__(cls, scheme=None, auth=None, host=None, port=None, path=None, query=None, fragment=None): + return super(Url, cls).__new__(cls, scheme, auth, host, port, path, query, fragment) + + @property + def hostname(self): + """For backwards-compatibility with urlparse. We're nice like that.""" + return self.host + + @property + def request_uri(self): + """Absolute path including the query string.""" + uri = self.path or '/' + + if self.query is not None: + uri += '?' + self.query + + return uri + + @property + def netloc(self): + """Network location including host and port""" + if self.port: + return '%s:%d' % (self.host, self.port) + return self.host + + +def split_first(s, delims): + """ + Given a string and an iterable of delimiters, split on the first found + delimiter. Return two split parts and the matched delimiter. + + If not found, then the first part is the full input string. + + Example: :: + + >>> split_first('foo/bar?baz', '?/=') + ('foo', 'bar?baz', '/') + >>> split_first('foo/bar?baz', '123') + ('foo/bar?baz', '', None) + + Scales linearly with number of delims. Not ideal for large number of delims. + """ + min_idx = None + min_delim = None + for d in delims: + idx = s.find(d) + if idx < 0: + continue + + if min_idx is None or idx < min_idx: + min_idx = idx + min_delim = d + + if min_idx is None or min_idx < 0: + return s, '', None + + return s[:min_idx], s[min_idx+1:], min_delim + + +def parse_url(url): + """ + Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is + performed to parse incomplete urls. Fields not provided will be None. + + Partly backwards-compatible with :mod:`urlparse`. + + Example: :: + + >>> parse_url('http://google.com/mail/') + Url(scheme='http', host='google.com', port=None, path='/', ...) + >>> parse_url('google.com:80') + Url(scheme=None, host='google.com', port=80, path=None, ...) + >>> parse_url('/foo?bar') + Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...) + """ + + # While this code has overlap with stdlib's urlparse, it is much + # simplified for our needs and less annoying. + # Additionally, this implementations does silly things to be optimal + # on CPython. + + scheme = None + auth = None + host = None + port = None + path = None + fragment = None + query = None + + # Scheme + if '://' in url: + scheme, url = url.split('://', 1) + + # Find the earliest Authority Terminator + # (http://tools.ietf.org/html/rfc3986#section-3.2) + url, path_, delim = split_first(url, ['/', '?', '#']) + + if delim: + # Reassemble the path + path = delim + path_ + + # Auth + if '@' in url: + # Last '@' denotes end of auth part + auth, url = url.rsplit('@', 1) + + # IPv6 + if url and url[0] == '[': + host, url = url.split(']', 1) + host += ']' + + # Port + if ':' in url: + _host, port = url.split(':', 1) + + if not host: + host = _host + + if port: + # If given, ports must be integers. + if not port.isdigit(): + raise LocationParseError("Failed to parse: %s" % url) + port = int(port) + else: + # Blank ports are cool, too. (rfc3986#section-3.2.3) + port = None + + elif not host and url: + host = url + + if not path: + return Url(scheme, auth, host, port, path, query, fragment) + + # Fragment + if '#' in path: + path, fragment = path.split('#', 1) + + # Query + if '?' in path: + path, query = path.split('?', 1) + + return Url(scheme, auth, host, port, path, query, fragment) + + +def get_host(url): + """ + Deprecated. Use :func:`.parse_url` instead. + """ + p = parse_url(url) + return p.scheme or 'http', p.hostname, p.port + + +def make_headers(keep_alive=None, accept_encoding=None, user_agent=None, + basic_auth=None, proxy_basic_auth=None): + """ + Shortcuts for generating request headers. + + :param keep_alive: + If ``True``, adds 'connection: keep-alive' header. + + :param accept_encoding: + Can be a boolean, list, or string. + ``True`` translates to 'gzip,deflate'. + List will get joined by comma. + String will be used as provided. + + :param user_agent: + String representing the user-agent you want, such as + "python-urllib3/0.6" + + :param basic_auth: + Colon-separated username:password string for 'authorization: basic ...' + auth header. + + :param proxy_basic_auth: + Colon-separated username:password string for 'proxy-authorization: basic ...' + auth header. + + Example: :: + + >>> make_headers(keep_alive=True, user_agent="Batman/1.0") + {'connection': 'keep-alive', 'user-agent': 'Batman/1.0'} + >>> make_headers(accept_encoding=True) + {'accept-encoding': 'gzip,deflate'} + """ + headers = {} + if accept_encoding: + if isinstance(accept_encoding, str): + pass + elif isinstance(accept_encoding, list): + accept_encoding = ','.join(accept_encoding) + else: + accept_encoding = 'gzip,deflate' + headers['accept-encoding'] = accept_encoding + + if user_agent: + headers['user-agent'] = user_agent + + if keep_alive: + headers['connection'] = 'keep-alive' + + if basic_auth: + headers['authorization'] = 'Basic ' + \ + b64encode(six.b(basic_auth)).decode('utf-8') + + if proxy_basic_auth: + headers['proxy-authorization'] = 'Basic ' + \ + b64encode(six.b(proxy_basic_auth)).decode('utf-8') + + return headers + + +def is_connection_dropped(conn): # Platform-specific + """ + Returns True if the connection is dropped and should be closed. + + :param conn: + :class:`httplib.HTTPConnection` object. + + Note: For platforms like AppEngine, this will always return ``False`` to + let the platform handle connection recycling transparently for us. + """ + sock = getattr(conn, 'sock', False) + if not sock: # Platform-specific: AppEngine + return False + + if not poll: + if not select: # Platform-specific: AppEngine + return False + + try: + return select([sock], [], [], 0.0)[0] + except SocketError: + return True + + # This version is better on platforms that support it. + p = poll() + p.register(sock, POLLIN) + for (fno, ev) in p.poll(0.0): + if fno == sock.fileno(): + # Either data is buffered (bad), or the connection is dropped. + return True + + +def resolve_cert_reqs(candidate): + """ + Resolves the argument to a numeric constant, which can be passed to + the wrap_socket function/method from the ssl module. + Defaults to :data:`ssl.CERT_NONE`. + If given a string it is assumed to be the name of the constant in the + :mod:`ssl` module or its abbrevation. + (So you can specify `REQUIRED` instead of `CERT_REQUIRED`. + If it's neither `None` nor a string we assume it is already the numeric + constant which can directly be passed to wrap_socket. + """ + if candidate is None: + return CERT_NONE + + if isinstance(candidate, str): + res = getattr(ssl, candidate, None) + if res is None: + res = getattr(ssl, 'CERT_' + candidate) + return res + + return candidate + + +def resolve_ssl_version(candidate): + """ + like resolve_cert_reqs + """ + if candidate is None: + return PROTOCOL_SSLv23 + + if isinstance(candidate, str): + res = getattr(ssl, candidate, None) + if res is None: + res = getattr(ssl, 'PROTOCOL_' + candidate) + return res + + return candidate + + +def assert_fingerprint(cert, fingerprint): + """ + Checks if given fingerprint matches the supplied certificate. + + :param cert: + Certificate as bytes object. + :param fingerprint: + Fingerprint as string of hexdigits, can be interspersed by colons. + """ + + # Maps the length of a digest to a possible hash function producing + # this digest. + hashfunc_map = { + 16: md5, + 20: sha1 + } + + fingerprint = fingerprint.replace(':', '').lower() + + digest_length, rest = divmod(len(fingerprint), 2) + + if rest or digest_length not in hashfunc_map: + raise SSLError('Fingerprint is of invalid length.') + + # We need encode() here for py32; works on py2 and p33. + fingerprint_bytes = unhexlify(fingerprint.encode()) + + hashfunc = hashfunc_map[digest_length] + + cert_digest = hashfunc(cert).digest() + + if not cert_digest == fingerprint_bytes: + raise SSLError('Fingerprints did not match. Expected "{0}", got "{1}".' + .format(hexlify(fingerprint_bytes), + hexlify(cert_digest))) + +def is_fp_closed(obj): + """ + Checks whether a given file-like object is closed. + + :param obj: + The file-like object to check. + """ + if hasattr(obj, 'fp'): + # Object is a container for another file-like object that gets released + # on exhaustion (e.g. HTTPResponse) + return obj.fp is None + + return obj.closed + + +if SSLContext is not None: # Python 3.2+ + def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None, + ca_certs=None, server_hostname=None, + ssl_version=None): + """ + All arguments except `server_hostname` have the same meaning as for + :func:`ssl.wrap_socket` + + :param server_hostname: + Hostname of the expected certificate + """ + context = SSLContext(ssl_version) + context.verify_mode = cert_reqs + if ca_certs: + try: + context.load_verify_locations(ca_certs) + # Py32 raises IOError + # Py33 raises FileNotFoundError + except Exception as e: # Reraise as SSLError + raise SSLError(e) + if certfile: + # FIXME: This block needs a test. + context.load_cert_chain(certfile, keyfile) + if HAS_SNI: # Platform-specific: OpenSSL with enabled SNI + return context.wrap_socket(sock, server_hostname=server_hostname) + return context.wrap_socket(sock) + +else: # Python 3.1 and earlier + def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None, + ca_certs=None, server_hostname=None, + ssl_version=None): + return wrap_socket(sock, keyfile=keyfile, certfile=certfile, + ca_certs=ca_certs, cert_reqs=cert_reqs, + ssl_version=ssl_version) diff --git a/awx/lib/site-packages/pip/_vendor/requests/sessions.py b/awx/lib/site-packages/pip/_vendor/requests/sessions.py new file mode 100644 index 0000000000..06e17d4b94 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/sessions.py @@ -0,0 +1,552 @@ +# -*- coding: utf-8 -*- + +""" +requests.session +~~~~~~~~~~~~~~~~ + +This module provides a Session object to manage and persist settings across +requests (cookies, auth, proxies). + +""" +import os +from collections import Mapping +from datetime import datetime + +from .compat import cookielib, OrderedDict, urljoin, urlparse, builtin_str +from .cookies import ( + cookiejar_from_dict, extract_cookies_to_jar, RequestsCookieJar, merge_cookies) +from .models import Request, PreparedRequest +from .hooks import default_hooks, dispatch_hook +from .utils import to_key_val_list, default_headers +from .exceptions import TooManyRedirects, InvalidSchema +from .structures import CaseInsensitiveDict + +from .adapters import HTTPAdapter + +from .utils import requote_uri, get_environ_proxies, get_netrc_auth + +from .status_codes import codes +REDIRECT_STATI = ( + codes.moved, # 301 + codes.found, # 302 + codes.other, # 303 + codes.temporary_moved, # 307 +) +DEFAULT_REDIRECT_LIMIT = 30 + + +def merge_setting(request_setting, session_setting, dict_class=OrderedDict): + """ + Determines appropriate setting for a given request, taking into account the + explicit setting on that request, and the setting in the session. If a + setting is a dictionary, they will be merged together using `dict_class` + """ + + if session_setting is None: + return request_setting + + if request_setting is None: + return session_setting + + # Bypass if not a dictionary (e.g. verify) + if not ( + isinstance(session_setting, Mapping) and + isinstance(request_setting, Mapping) + ): + return request_setting + + merged_setting = dict_class(to_key_val_list(session_setting)) + merged_setting.update(to_key_val_list(request_setting)) + + # Remove keys that are set to None. + for (k, v) in request_setting.items(): + if v is None: + del merged_setting[k] + + return merged_setting + + +def merge_hooks(request_hooks, session_hooks, dict_class=OrderedDict): + """ + Properly merges both requests and session hooks. + + This is necessary because when request_hooks == {'response': []}, the + merge breaks Session hooks entirely. + """ + if session_hooks is None or session_hooks.get('response') == []: + return request_hooks + + if request_hooks is None or request_hooks.get('response') == []: + return session_hooks + + return merge_setting(request_hooks, session_hooks, dict_class) + + +class SessionRedirectMixin(object): + def resolve_redirects(self, resp, req, stream=False, timeout=None, + verify=True, cert=None, proxies=None): + """Receives a Response. Returns a generator of Responses.""" + + i = 0 + + # ((resp.status_code is codes.see_other)) + while ('location' in resp.headers and resp.status_code in REDIRECT_STATI): + prepared_request = req.copy() + + resp.content # Consume socket so it can be released + + if i >= self.max_redirects: + raise TooManyRedirects('Exceeded %s redirects.' % self.max_redirects) + + # Release the connection back into the pool. + resp.close() + + url = resp.headers['location'] + method = req.method + + # Handle redirection without scheme (see: RFC 1808 Section 4) + if url.startswith('//'): + parsed_rurl = urlparse(resp.url) + url = '%s:%s' % (parsed_rurl.scheme, url) + + # The scheme should be lower case... + parsed = urlparse(url) + url = parsed.geturl() + + # Facilitate non-RFC2616-compliant 'location' headers + # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource') + # Compliant with RFC3986, we percent encode the url. + if not urlparse(url).netloc: + url = urljoin(resp.url, requote_uri(url)) + else: + url = requote_uri(url) + + prepared_request.url = url + + # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4 + if (resp.status_code == codes.see_other and + method != 'HEAD'): + method = 'GET' + + # Do what the browsers do, despite standards... + # First, turn 302s into GETs. + if resp.status_code == codes.found and method != 'HEAD': + method = 'GET' + + # Second, if a POST is responded to with a 301, turn it into a GET. + # This bizarre behaviour is explained in Issue 1704. + if resp.status_code == codes.moved and method == 'POST': + method = 'GET' + + prepared_request.method = method + + # https://github.com/kennethreitz/requests/issues/1084 + if resp.status_code not in (codes.temporary, codes.resume): + if 'Content-Length' in prepared_request.headers: + del prepared_request.headers['Content-Length'] + + prepared_request.body = None + + headers = prepared_request.headers + try: + del headers['Cookie'] + except KeyError: + pass + + extract_cookies_to_jar(prepared_request._cookies, + prepared_request, resp.raw) + prepared_request.prepare_cookies(prepared_request._cookies) + + resp = self.send( + prepared_request, + stream=stream, + timeout=timeout, + verify=verify, + cert=cert, + proxies=proxies, + allow_redirects=False, + ) + + extract_cookies_to_jar(self.cookies, prepared_request, resp.raw) + + i += 1 + yield resp + + +class Session(SessionRedirectMixin): + """A Requests session. + + Provides cookie persistence, connection-pooling, and configuration. + + Basic Usage:: + + >>> import requests + >>> s = requests.Session() + >>> s.get('http://httpbin.org/get') + 200 + """ + + __attrs__ = [ + 'headers', 'cookies', 'auth', 'timeout', 'proxies', 'hooks', + 'params', 'verify', 'cert', 'prefetch', 'adapters', 'stream', + 'trust_env', 'max_redirects'] + + def __init__(self): + + #: A case-insensitive dictionary of headers to be sent on each + #: :class:`Request ` sent from this + #: :class:`Session `. + self.headers = default_headers() + + #: Default Authentication tuple or object to attach to + #: :class:`Request `. + self.auth = None + + #: Dictionary mapping protocol to the URL of the proxy (e.g. + #: {'http': 'foo.bar:3128'}) to be used on each + #: :class:`Request `. + self.proxies = {} + + #: Event-handling hooks. + self.hooks = default_hooks() + + #: Dictionary of querystring data to attach to each + #: :class:`Request `. The dictionary values may be lists for + #: representing multivalued query parameters. + self.params = {} + + #: Stream response content default. + self.stream = False + + #: SSL Verification default. + self.verify = True + + #: SSL certificate default. + self.cert = None + + #: Maximum number of redirects allowed. If the request exceeds this + #: limit, a :class:`TooManyRedirects` exception is raised. + self.max_redirects = DEFAULT_REDIRECT_LIMIT + + #: Should we trust the environment? + self.trust_env = True + + #: A CookieJar containing all currently outstanding cookies set on this + #: session. By default it is a + #: :class:`RequestsCookieJar `, but + #: may be any other ``cookielib.CookieJar`` compatible object. + self.cookies = cookiejar_from_dict({}) + + # Default connection adapters. + self.adapters = OrderedDict() + self.mount('https://', HTTPAdapter()) + self.mount('http://', HTTPAdapter()) + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + def prepare_request(self, request): + """Constructs a :class:`PreparedRequest ` for + transmission and returns it. The :class:`PreparedRequest` has settings + merged from the :class:`Request ` instance and those of the + :class:`Session`. + + :param request: :class:`Request` instance to prepare with this + session's settings. + """ + cookies = request.cookies or {} + + # Bootstrap CookieJar. + if not isinstance(cookies, cookielib.CookieJar): + cookies = cookiejar_from_dict(cookies) + + # Merge with session cookies + merged_cookies = merge_cookies( + merge_cookies(RequestsCookieJar(), self.cookies), cookies) + + + # Set environment's basic authentication if not explicitly set. + auth = request.auth + if self.trust_env and not auth and not self.auth: + auth = get_netrc_auth(request.url) + + p = PreparedRequest() + p.prepare( + method=request.method.upper(), + url=request.url, + files=request.files, + data=request.data, + headers=merge_setting(request.headers, self.headers, dict_class=CaseInsensitiveDict), + params=merge_setting(request.params, self.params), + auth=merge_setting(auth, self.auth), + cookies=merged_cookies, + hooks=merge_hooks(request.hooks, self.hooks), + ) + return p + + def request(self, method, url, + params=None, + data=None, + headers=None, + cookies=None, + files=None, + auth=None, + timeout=None, + allow_redirects=True, + proxies=None, + hooks=None, + stream=None, + verify=None, + cert=None): + """Constructs a :class:`Request `, prepares it and sends it. + Returns :class:`Response ` object. + + :param method: method for the new :class:`Request` object. + :param url: URL for the new :class:`Request` object. + :param params: (optional) Dictionary or bytes to be sent in the query + string for the :class:`Request`. + :param data: (optional) Dictionary or bytes to send in the body of the + :class:`Request`. + :param headers: (optional) Dictionary of HTTP Headers to send with the + :class:`Request`. + :param cookies: (optional) Dict or CookieJar object to send with the + :class:`Request`. + :param files: (optional) Dictionary of 'filename': file-like-objects + for multipart encoding upload. + :param auth: (optional) Auth tuple or callable to enable + Basic/Digest/Custom HTTP Auth. + :param timeout: (optional) Float describing the timeout of the + request. + :param allow_redirects: (optional) Boolean. Set to True by default. + :param proxies: (optional) Dictionary mapping protocol to the URL of + the proxy. + :param stream: (optional) whether to immediately download the response + content. Defaults to ``False``. + :param verify: (optional) if ``True``, the SSL cert will be verified. + A CA_BUNDLE path can also be provided. + :param cert: (optional) if String, path to ssl client cert file (.pem). + If Tuple, ('cert', 'key') pair. + """ + + method = builtin_str(method) + + # Create the Request. + req = Request( + method = method.upper(), + url = url, + headers = headers, + files = files, + data = data or {}, + params = params or {}, + auth = auth, + cookies = cookies, + hooks = hooks, + ) + prep = self.prepare_request(req) + + proxies = proxies or {} + + # Gather clues from the surrounding environment. + if self.trust_env: + # Set environment's proxies. + env_proxies = get_environ_proxies(url) or {} + for (k, v) in env_proxies.items(): + proxies.setdefault(k, v) + + # Look for configuration. + if not verify and verify is not False: + verify = os.environ.get('REQUESTS_CA_BUNDLE') + + # Curl compatibility. + if not verify and verify is not False: + verify = os.environ.get('CURL_CA_BUNDLE') + + # Merge all the kwargs. + proxies = merge_setting(proxies, self.proxies) + stream = merge_setting(stream, self.stream) + verify = merge_setting(verify, self.verify) + cert = merge_setting(cert, self.cert) + + # Send the request. + send_kwargs = { + 'stream': stream, + 'timeout': timeout, + 'verify': verify, + 'cert': cert, + 'proxies': proxies, + 'allow_redirects': allow_redirects, + } + resp = self.send(prep, **send_kwargs) + + return resp + + def get(self, url, **kwargs): + """Sends a GET request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + """ + + kwargs.setdefault('allow_redirects', True) + return self.request('GET', url, **kwargs) + + def options(self, url, **kwargs): + """Sends a OPTIONS request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + """ + + kwargs.setdefault('allow_redirects', True) + return self.request('OPTIONS', url, **kwargs) + + def head(self, url, **kwargs): + """Sends a HEAD request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + """ + + kwargs.setdefault('allow_redirects', False) + return self.request('HEAD', url, **kwargs) + + def post(self, url, data=None, **kwargs): + """Sends a POST request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + """ + + return self.request('POST', url, data=data, **kwargs) + + def put(self, url, data=None, **kwargs): + """Sends a PUT request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + """ + + return self.request('PUT', url, data=data, **kwargs) + + def patch(self, url, data=None, **kwargs): + """Sends a PATCH request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + """ + + return self.request('PATCH', url, data=data, **kwargs) + + def delete(self, url, **kwargs): + """Sends a DELETE request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + """ + + return self.request('DELETE', url, **kwargs) + + def send(self, request, **kwargs): + """Send a given PreparedRequest.""" + # Set defaults that the hooks can utilize to ensure they always have + # the correct parameters to reproduce the previous request. + kwargs.setdefault('stream', self.stream) + kwargs.setdefault('verify', self.verify) + kwargs.setdefault('cert', self.cert) + kwargs.setdefault('proxies', self.proxies) + + # It's possible that users might accidentally send a Request object. + # Guard against that specific failure case. + if not isinstance(request, PreparedRequest): + raise ValueError('You can only send PreparedRequests.') + + # Set up variables needed for resolve_redirects and dispatching of + # hooks + allow_redirects = kwargs.pop('allow_redirects', True) + stream = kwargs.get('stream') + timeout = kwargs.get('timeout') + verify = kwargs.get('verify') + cert = kwargs.get('cert') + proxies = kwargs.get('proxies') + hooks = request.hooks + + # Get the appropriate adapter to use + adapter = self.get_adapter(url=request.url) + + # Start time (approximately) of the request + start = datetime.utcnow() + # Send the request + r = adapter.send(request, **kwargs) + # Total elapsed time of the request (approximately) + r.elapsed = datetime.utcnow() - start + + # Response manipulation hooks + r = dispatch_hook('response', hooks, r, **kwargs) + + # Persist cookies + if r.history: + # If the hooks create history then we want those cookies too + for resp in r.history: + extract_cookies_to_jar(self.cookies, resp.request, resp.raw) + extract_cookies_to_jar(self.cookies, request, r.raw) + + # Redirect resolving generator. + gen = self.resolve_redirects(r, request, stream=stream, + timeout=timeout, verify=verify, cert=cert, + proxies=proxies) + + # Resolve redirects if allowed. + history = [resp for resp in gen] if allow_redirects else [] + + # Shuffle things around if there's history. + if history: + # Insert the first (original) request at the start + history.insert(0, r) + # Get the last request made + r = history.pop() + r.history = tuple(history) + + return r + + def get_adapter(self, url): + """Returns the appropriate connnection adapter for the given URL.""" + for (prefix, adapter) in self.adapters.items(): + + if url.lower().startswith(prefix): + return adapter + + # Nothing matches :-/ + raise InvalidSchema("No connection adapters were found for '%s'" % url) + + def close(self): + """Closes all adapters and as such the session""" + for v in self.adapters.values(): + v.close() + + def mount(self, prefix, adapter): + """Registers a connection adapter to a prefix. + + Adapters are sorted in descending order by key length.""" + self.adapters[prefix] = adapter + keys_to_move = [k for k in self.adapters if len(k) < len(prefix)] + for key in keys_to_move: + self.adapters[key] = self.adapters.pop(key) + + def __getstate__(self): + return dict((attr, getattr(self, attr, None)) for attr in self.__attrs__) + + def __setstate__(self, state): + for attr, value in state.items(): + setattr(self, attr, value) + + +def session(): + """Returns a :class:`Session` for context-management.""" + + return Session() diff --git a/awx/lib/site-packages/pip/_vendor/requests/status_codes.py b/awx/lib/site-packages/pip/_vendor/requests/status_codes.py new file mode 100644 index 0000000000..ed7a8660a6 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/status_codes.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- + +from .structures import LookupDict + +_codes = { + + # Informational. + 100: ('continue',), + 101: ('switching_protocols',), + 102: ('processing',), + 103: ('checkpoint',), + 122: ('uri_too_long', 'request_uri_too_long'), + 200: ('ok', 'okay', 'all_ok', 'all_okay', 'all_good', '\\o/', '✓'), + 201: ('created',), + 202: ('accepted',), + 203: ('non_authoritative_info', 'non_authoritative_information'), + 204: ('no_content',), + 205: ('reset_content', 'reset'), + 206: ('partial_content', 'partial'), + 207: ('multi_status', 'multiple_status', 'multi_stati', 'multiple_stati'), + 208: ('already_reported',), + 226: ('im_used',), + + # Redirection. + 300: ('multiple_choices',), + 301: ('moved_permanently', 'moved', '\\o-'), + 302: ('found',), + 303: ('see_other', 'other'), + 304: ('not_modified',), + 305: ('use_proxy',), + 306: ('switch_proxy',), + 307: ('temporary_redirect', 'temporary_moved', 'temporary'), + 308: ('resume_incomplete', 'resume'), + + # Client Error. + 400: ('bad_request', 'bad'), + 401: ('unauthorized',), + 402: ('payment_required', 'payment'), + 403: ('forbidden',), + 404: ('not_found', '-o-'), + 405: ('method_not_allowed', 'not_allowed'), + 406: ('not_acceptable',), + 407: ('proxy_authentication_required', 'proxy_auth', 'proxy_authentication'), + 408: ('request_timeout', 'timeout'), + 409: ('conflict',), + 410: ('gone',), + 411: ('length_required',), + 412: ('precondition_failed', 'precondition'), + 413: ('request_entity_too_large',), + 414: ('request_uri_too_large',), + 415: ('unsupported_media_type', 'unsupported_media', 'media_type'), + 416: ('requested_range_not_satisfiable', 'requested_range', 'range_not_satisfiable'), + 417: ('expectation_failed',), + 418: ('im_a_teapot', 'teapot', 'i_am_a_teapot'), + 422: ('unprocessable_entity', 'unprocessable'), + 423: ('locked',), + 424: ('failed_dependency', 'dependency'), + 425: ('unordered_collection', 'unordered'), + 426: ('upgrade_required', 'upgrade'), + 428: ('precondition_required', 'precondition'), + 429: ('too_many_requests', 'too_many'), + 431: ('header_fields_too_large', 'fields_too_large'), + 444: ('no_response', 'none'), + 449: ('retry_with', 'retry'), + 450: ('blocked_by_windows_parental_controls', 'parental_controls'), + 451: ('unavailable_for_legal_reasons', 'legal_reasons'), + 499: ('client_closed_request',), + + # Server Error. + 500: ('internal_server_error', 'server_error', '/o\\', '✗'), + 501: ('not_implemented',), + 502: ('bad_gateway',), + 503: ('service_unavailable', 'unavailable'), + 504: ('gateway_timeout',), + 505: ('http_version_not_supported', 'http_version'), + 506: ('variant_also_negotiates',), + 507: ('insufficient_storage',), + 509: ('bandwidth_limit_exceeded', 'bandwidth'), + 510: ('not_extended',), +} + +codes = LookupDict(name='status_codes') + +for (code, titles) in list(_codes.items()): + for title in titles: + setattr(codes, title, code) + if not title.startswith('\\'): + setattr(codes, title.upper(), code) diff --git a/awx/lib/site-packages/pip/_vendor/requests/structures.py b/awx/lib/site-packages/pip/_vendor/requests/structures.py new file mode 100644 index 0000000000..a1759137aa --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/structures.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- + +""" +requests.structures +~~~~~~~~~~~~~~~~~~~ + +Data structures that power Requests. + +""" + +import os +import collections +from itertools import islice + + +class IteratorProxy(object): + """docstring for IteratorProxy""" + def __init__(self, i): + self.i = i + # self.i = chain.from_iterable(i) + + def __iter__(self): + return self.i + + def __len__(self): + if hasattr(self.i, '__len__'): + return len(self.i) + if hasattr(self.i, 'len'): + return self.i.len + if hasattr(self.i, 'fileno'): + return os.fstat(self.i.fileno()).st_size + + def read(self, n): + return "".join(islice(self.i, None, n)) + + +class CaseInsensitiveDict(collections.MutableMapping): + """ + A case-insensitive ``dict``-like object. + + Implements all methods and operations of + ``collections.MutableMapping`` as well as dict's ``copy``. Also + provides ``lower_items``. + + All keys are expected to be strings. The structure remembers the + case of the last key to be set, and ``iter(instance)``, + ``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()`` + will contain case-sensitive keys. However, querying and contains + testing is case insensitive: + + cid = CaseInsensitiveDict() + cid['Accept'] = 'application/json' + cid['aCCEPT'] == 'application/json' # True + list(cid) == ['Accept'] # True + + For example, ``headers['content-encoding']`` will return the + value of a ``'Content-Encoding'`` response header, regardless + of how the header name was originally stored. + + If the constructor, ``.update``, or equality comparison + operations are given keys that have equal ``.lower()``s, the + behavior is undefined. + + """ + def __init__(self, data=None, **kwargs): + self._store = dict() + if data is None: + data = {} + self.update(data, **kwargs) + + def __setitem__(self, key, value): + # Use the lowercased key for lookups, but store the actual + # key alongside the value. + self._store[key.lower()] = (key, value) + + def __getitem__(self, key): + return self._store[key.lower()][1] + + def __delitem__(self, key): + del self._store[key.lower()] + + def __iter__(self): + return (casedkey for casedkey, mappedvalue in self._store.values()) + + def __len__(self): + return len(self._store) + + def lower_items(self): + """Like iteritems(), but with all lowercase keys.""" + return ( + (lowerkey, keyval[1]) + for (lowerkey, keyval) + in self._store.items() + ) + + def __eq__(self, other): + if isinstance(other, collections.Mapping): + other = CaseInsensitiveDict(other) + else: + return NotImplemented + # Compare insensitively + return dict(self.lower_items()) == dict(other.lower_items()) + + # Copy is required + def copy(self): + return CaseInsensitiveDict(self._store.values()) + + def __repr__(self): + return '%s(%r)' % (self.__class__.__name__, dict(self.items())) + + +class LookupDict(dict): + """Dictionary lookup object.""" + + def __init__(self, name=None): + self.name = name + super(LookupDict, self).__init__() + + def __repr__(self): + return '' % (self.name) + + def __getitem__(self, key): + # We allow fall-through here, so values default to None + + return self.__dict__.get(key, None) + + def get(self, key, default=None): + return self.__dict__.get(key, default) diff --git a/awx/lib/site-packages/pip/_vendor/requests/utils.py b/awx/lib/site-packages/pip/_vendor/requests/utils.py new file mode 100644 index 0000000000..c7e2b08943 --- /dev/null +++ b/awx/lib/site-packages/pip/_vendor/requests/utils.py @@ -0,0 +1,643 @@ +# -*- coding: utf-8 -*- + +""" +requests.utils +~~~~~~~~~~~~~~ + +This module provides utility functions that are used within Requests +that are also useful for external consumption. + +""" + +import cgi +import codecs +import collections +import io +import os +import platform +import re +import sys +import socket +import struct + +from . import __version__ +from . import certs +from .compat import parse_http_list as _parse_list_header +from .compat import (quote, urlparse, bytes, str, OrderedDict, unquote, is_py2, + builtin_str, getproxies, proxy_bypass) +from .cookies import RequestsCookieJar, cookiejar_from_dict +from .structures import CaseInsensitiveDict +from .exceptions import MissingSchema, InvalidURL + +_hush_pyflakes = (RequestsCookieJar,) + +NETRC_FILES = ('.netrc', '_netrc') + +DEFAULT_CA_BUNDLE_PATH = certs.where() + + +def dict_to_sequence(d): + """Returns an internal sequence dictionary update.""" + + if hasattr(d, 'items'): + d = d.items() + + return d + + +def super_len(o): + if hasattr(o, '__len__'): + return len(o) + + if hasattr(o, 'len'): + return o.len + + if hasattr(o, 'fileno'): + try: + fileno = o.fileno() + except io.UnsupportedOperation: + pass + else: + return os.fstat(fileno).st_size + + if hasattr(o, 'getvalue'): + # e.g. BytesIO, cStringIO.StringI + return len(o.getvalue()) + +def get_netrc_auth(url): + """Returns the Requests tuple auth for a given url from netrc.""" + + try: + from netrc import netrc, NetrcParseError + + locations = (os.path.expanduser('~/{0}'.format(f)) for f in NETRC_FILES) + netrc_path = None + + for loc in locations: + if os.path.exists(loc) and not netrc_path: + netrc_path = loc + + # Abort early if there isn't one. + if netrc_path is None: + return netrc_path + + ri = urlparse(url) + + # Strip port numbers from netloc + host = ri.netloc.split(':')[0] + + try: + _netrc = netrc(netrc_path).authenticators(host) + if _netrc: + # Return with login / password + login_i = (0 if _netrc[0] else 1) + return (_netrc[login_i], _netrc[2]) + except (NetrcParseError, IOError): + # If there was a parsing error or a permissions issue reading the file, + # we'll just skip netrc auth + pass + + # AppEngine hackiness. + except (ImportError, AttributeError): + pass + + +def guess_filename(obj): + """Tries to guess the filename of the given object.""" + name = getattr(obj, 'name', None) + if name and name[0] != '<' and name[-1] != '>': + return os.path.basename(name) + + +def from_key_val_list(value): + """Take an object and test to see if it can be represented as a + dictionary. Unless it can not be represented as such, return an + OrderedDict, e.g., + + :: + + >>> from_key_val_list([('key', 'val')]) + OrderedDict([('key', 'val')]) + >>> from_key_val_list('string') + ValueError: need more than 1 value to unpack + >>> from_key_val_list({'key': 'val'}) + OrderedDict([('key', 'val')]) + """ + if value is None: + return None + + if isinstance(value, (str, bytes, bool, int)): + raise ValueError('cannot encode objects that are not 2-tuples') + + return OrderedDict(value) + + +def to_key_val_list(value): + """Take an object and test to see if it can be represented as a + dictionary. If it can be, return a list of tuples, e.g., + + :: + + >>> to_key_val_list([('key', 'val')]) + [('key', 'val')] + >>> to_key_val_list({'key': 'val'}) + [('key', 'val')] + >>> to_key_val_list('string') + ValueError: cannot encode objects that are not 2-tuples. + """ + if value is None: + return None + + if isinstance(value, (str, bytes, bool, int)): + raise ValueError('cannot encode objects that are not 2-tuples') + + if isinstance(value, collections.Mapping): + value = value.items() + + return list(value) + + +# From mitsuhiko/werkzeug (used with permission). +def parse_list_header(value): + """Parse lists as described by RFC 2068 Section 2. + + In particular, parse comma-separated lists where the elements of + the list may include quoted-strings. A quoted-string could + contain a comma. A non-quoted string could have quotes in the + middle. Quotes are removed automatically after parsing. + + It basically works like :func:`parse_set_header` just that items + may appear multiple times and case sensitivity is preserved. + + The return value is a standard :class:`list`: + + >>> parse_list_header('token, "quoted value"') + ['token', 'quoted value'] + + To create a header from the :class:`list` again, use the + :func:`dump_header` function. + + :param value: a string with a list header. + :return: :class:`list` + """ + result = [] + for item in _parse_list_header(value): + if item[:1] == item[-1:] == '"': + item = unquote_header_value(item[1:-1]) + result.append(item) + return result + + +# From mitsuhiko/werkzeug (used with permission). +def parse_dict_header(value): + """Parse lists of key, value pairs as described by RFC 2068 Section 2 and + convert them into a python dict: + + >>> d = parse_dict_header('foo="is a fish", bar="as well"') + >>> type(d) is dict + True + >>> sorted(d.items()) + [('bar', 'as well'), ('foo', 'is a fish')] + + If there is no value for a key it will be `None`: + + >>> parse_dict_header('key_without_value') + {'key_without_value': None} + + To create a header from the :class:`dict` again, use the + :func:`dump_header` function. + + :param value: a string with a dict header. + :return: :class:`dict` + """ + result = {} + for item in _parse_list_header(value): + if '=' not in item: + result[item] = None + continue + name, value = item.split('=', 1) + if value[:1] == value[-1:] == '"': + value = unquote_header_value(value[1:-1]) + result[name] = value + return result + + +# From mitsuhiko/werkzeug (used with permission). +def unquote_header_value(value, is_filename=False): + r"""Unquotes a header value. (Reversal of :func:`quote_header_value`). + This does not use the real unquoting but what browsers are actually + using for quoting. + + :param value: the header value to unquote. + """ + if value and value[0] == value[-1] == '"': + # this is not the real unquoting, but fixing this so that the + # RFC is met will result in bugs with internet explorer and + # probably some other browsers as well. IE for example is + # uploading files with "C:\foo\bar.txt" as filename + value = value[1:-1] + + # if this is a filename and the starting characters look like + # a UNC path, then just return the value without quotes. Using the + # replace sequence below on a UNC path has the effect of turning + # the leading double slash into a single slash and then + # _fix_ie_filename() doesn't work correctly. See #458. + if not is_filename or value[:2] != '\\\\': + return value.replace('\\\\', '\\').replace('\\"', '"') + return value + + +def dict_from_cookiejar(cj): + """Returns a key/value dictionary from a CookieJar. + + :param cj: CookieJar object to extract cookies from. + """ + + cookie_dict = {} + + for cookie in cj: + cookie_dict[cookie.name] = cookie.value + + return cookie_dict + + +def add_dict_to_cookiejar(cj, cookie_dict): + """Returns a CookieJar from a key/value dictionary. + + :param cj: CookieJar to insert cookies into. + :param cookie_dict: Dict of key/values to insert into CookieJar. + """ + + cj2 = cookiejar_from_dict(cookie_dict) + cj.update(cj2) + return cj + + +def get_encodings_from_content(content): + """Returns encodings from given content string. + + :param content: bytestring to extract encodings from. + """ + + charset_re = re.compile(r']', flags=re.I) + pragma_re = re.compile(r']', flags=re.I) + xml_re = re.compile(r'^<\?xml.*?encoding=["\']*(.+?)["\'>]') + + return (charset_re.findall(content) + + pragma_re.findall(content) + + xml_re.findall(content)) + + +def get_encoding_from_headers(headers): + """Returns encodings from given HTTP Header Dict. + + :param headers: dictionary to extract encoding from. + """ + + content_type = headers.get('content-type') + + if not content_type: + return None + + content_type, params = cgi.parse_header(content_type) + + if 'charset' in params: + return params['charset'].strip("'\"") + + if 'text' in content_type: + return 'ISO-8859-1' + + +def stream_decode_response_unicode(iterator, r): + """Stream decodes a iterator.""" + + if r.encoding is None: + for item in iterator: + yield item + return + + decoder = codecs.getincrementaldecoder(r.encoding)(errors='replace') + for chunk in iterator: + rv = decoder.decode(chunk) + if rv: + yield rv + rv = decoder.decode(b'', final=True) + if rv: + yield rv + + +def iter_slices(string, slice_length): + """Iterate over slices of a string.""" + pos = 0 + while pos < len(string): + yield string[pos:pos + slice_length] + pos += slice_length + + +def get_unicode_from_response(r): + """Returns the requested content back in unicode. + + :param r: Response object to get unicode content from. + + Tried: + + 1. charset from content-type + + 2. every encodings from ```` + + 3. fall back and replace all unicode characters + + """ + + tried_encodings = [] + + # Try charset from content-type + encoding = get_encoding_from_headers(r.headers) + + if encoding: + try: + return str(r.content, encoding) + except UnicodeError: + tried_encodings.append(encoding) + + # Fall back: + try: + return str(r.content, encoding, errors='replace') + except TypeError: + return r.content + + +# The unreserved URI characters (RFC 3986) +UNRESERVED_SET = frozenset( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + + "0123456789-._~") + + +def unquote_unreserved(uri): + """Un-escape any percent-escape sequences in a URI that are unreserved + characters. This leaves all reserved, illegal and non-ASCII bytes encoded. + """ + parts = uri.split('%') + for i in range(1, len(parts)): + h = parts[i][0:2] + if len(h) == 2 and h.isalnum(): + try: + c = chr(int(h, 16)) + except ValueError: + raise InvalidURL("Invalid percent-escape sequence: '%s'" % h) + + if c in UNRESERVED_SET: + parts[i] = c + parts[i][2:] + else: + parts[i] = '%' + parts[i] + else: + parts[i] = '%' + parts[i] + return ''.join(parts) + + +def requote_uri(uri): + """Re-quote the given URI. + + This function passes the given URI through an unquote/quote cycle to + ensure that it is fully and consistently quoted. + """ + # Unquote only the unreserved characters + # Then quote only illegal characters (do not quote reserved, unreserved, + # or '%') + return quote(unquote_unreserved(uri), safe="!#$%&'()*+,/:;=?@[]~") + + +def address_in_network(ip, net): + """ + This function allows you to check if on IP belongs to a network subnet + Example: returns True if ip = 192.168.1.1 and net = 192.168.1.0/24 + returns False if ip = 192.168.1.1 and net = 192.168.100.0/24 + """ + ipaddr = struct.unpack('=L', socket.inet_aton(ip))[0] + netaddr, bits = net.split('/') + netmask = struct.unpack('=L', socket.inet_aton(dotted_netmask(int(bits))))[0] + network = struct.unpack('=L', socket.inet_aton(netaddr))[0] & netmask + return (ipaddr & netmask) == (network & netmask) + + +def dotted_netmask(mask): + """ + Converts mask from /xx format to xxx.xxx.xxx.xxx + Example: if mask is 24 function returns 255.255.255.0 + """ + bits = 0xffffffff ^ (1 << 32 - mask) - 1 + return socket.inet_ntoa(struct.pack('>I', bits)) + + +def is_ipv4_address(string_ip): + try: + socket.inet_aton(string_ip) + except socket.error: + return False + return True + + +def is_valid_cidr(string_network): + """Very simple check of the cidr format in no_proxy variable""" + if string_network.count('/') == 1: + try: + mask = int(string_network.split('/')[1]) + except ValueError: + return False + + if mask < 1 or mask > 32: + return False + + try: + socket.inet_aton(string_network.split('/')[0]) + except socket.error: + return False + else: + return False + return True + + +def get_environ_proxies(url): + """Return a dict of environment proxies.""" + + get_proxy = lambda k: os.environ.get(k) or os.environ.get(k.upper()) + + # First check whether no_proxy is defined. If it is, check that the URL + # we're getting isn't in the no_proxy list. + no_proxy = get_proxy('no_proxy') + netloc = urlparse(url).netloc + + if no_proxy: + # We need to check whether we match here. We need to see if we match + # the end of the netloc, both with and without the port. + no_proxy = no_proxy.replace(' ', '').split(',') + + ip = netloc.split(':')[0] + if is_ipv4_address(ip): + for proxy_ip in no_proxy: + if is_valid_cidr(proxy_ip): + if address_in_network(ip, proxy_ip): + return {} + else: + for host in no_proxy: + if netloc.endswith(host) or netloc.split(':')[0].endswith(host): + # The URL does match something in no_proxy, so we don't want + # to apply the proxies on this URL. + return {} + + # If the system proxy settings indicate that this URL should be bypassed, + # don't proxy. + if proxy_bypass(netloc): + return {} + + # If we get here, we either didn't have no_proxy set or we're not going + # anywhere that no_proxy applies to, and the system settings don't require + # bypassing the proxy for the current URL. + return getproxies() + + +def default_user_agent(name="python-requests"): + """Return a string representing the default user agent.""" + _implementation = platform.python_implementation() + + if _implementation == 'CPython': + _implementation_version = platform.python_version() + elif _implementation == 'PyPy': + _implementation_version = '%s.%s.%s' % (sys.pypy_version_info.major, + sys.pypy_version_info.minor, + sys.pypy_version_info.micro) + if sys.pypy_version_info.releaselevel != 'final': + _implementation_version = ''.join([_implementation_version, sys.pypy_version_info.releaselevel]) + elif _implementation == 'Jython': + _implementation_version = platform.python_version() # Complete Guess + elif _implementation == 'IronPython': + _implementation_version = platform.python_version() # Complete Guess + else: + _implementation_version = 'Unknown' + + try: + p_system = platform.system() + p_release = platform.release() + except IOError: + p_system = 'Unknown' + p_release = 'Unknown' + + return " ".join(['%s/%s' % (name, __version__), + '%s/%s' % (_implementation, _implementation_version), + '%s/%s' % (p_system, p_release)]) + + +def default_headers(): + return CaseInsensitiveDict({ + 'User-Agent': default_user_agent(), + 'Accept-Encoding': ', '.join(('gzip', 'deflate', 'compress')), + 'Accept': '*/*' + }) + + +def parse_header_links(value): + """Return a dict of parsed link headers proxies. + + i.e. Link: ; rel=front; type="image/jpeg",; rel=back;type="image/jpeg" + + """ + + links = [] + + replace_chars = " '\"" + + for val in value.split(","): + try: + url, params = val.split(";", 1) + except ValueError: + url, params = val, '' + + link = {} + + link["url"] = url.strip("<> '\"") + + for param in params.split(";"): + try: + key, value = param.split("=") + except ValueError: + break + + link[key.strip(replace_chars)] = value.strip(replace_chars) + + links.append(link) + + return links + + +# Null bytes; no need to recreate these on each call to guess_json_utf +_null = '\x00'.encode('ascii') # encoding to ASCII for Python 3 +_null2 = _null * 2 +_null3 = _null * 3 + + +def guess_json_utf(data): + # JSON always starts with two ASCII characters, so detection is as + # easy as counting the nulls and from their location and count + # determine the encoding. Also detect a BOM, if present. + sample = data[:4] + if sample in (codecs.BOM_UTF32_LE, codecs.BOM32_BE): + return 'utf-32' # BOM included + if sample[:3] == codecs.BOM_UTF8: + return 'utf-8-sig' # BOM included, MS style (discouraged) + if sample[:2] in (codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE): + return 'utf-16' # BOM included + nullcount = sample.count(_null) + if nullcount == 0: + return 'utf-8' + if nullcount == 2: + if sample[::2] == _null2: # 1st and 3rd are null + return 'utf-16-be' + if sample[1::2] == _null2: # 2nd and 4th are null + return 'utf-16-le' + # Did not detect 2 valid UTF-16 ascii-range characters + if nullcount == 3: + if sample[:3] == _null3: + return 'utf-32-be' + if sample[1:] == _null3: + return 'utf-32-le' + # Did not detect a valid UTF-32 ascii-range character + return None + + +def except_on_missing_scheme(url): + """Given a URL, raise a MissingSchema exception if the scheme is missing. + """ + scheme, netloc, path, params, query, fragment = urlparse(url) + + if not scheme: + raise MissingSchema('Proxy URLs must have explicit schemes.') + + +def get_auth_from_url(url): + """Given a url with authentication components, extract them into a tuple of + username,password.""" + if url: + url = unquote(url) + parsed = urlparse(url) + return (parsed.username, parsed.password) + else: + return ('', '') + + +def to_native_string(string, encoding='ascii'): + """ + Given a string object, regardless of type, returns a representation of that + string in the native string type, encoding and decoding where necessary. + This assumes ASCII unless told otherwise. + """ + out = None + + if isinstance(string, builtin_str): + out = string + else: + if is_py2: + out = string.encode(encoding) + else: + out = string.decode(encoding) + + return out diff --git a/awx/lib/site-packages/pip/vendor/six.py b/awx/lib/site-packages/pip/_vendor/six.py similarity index 100% rename from awx/lib/site-packages/pip/vendor/six.py rename to awx/lib/site-packages/pip/_vendor/six.py diff --git a/awx/lib/site-packages/pip/backwardcompat/__init__.py b/awx/lib/site-packages/pip/backwardcompat/__init__.py index 465759d802..c327bbeec1 100644 --- a/awx/lib/site-packages/pip/backwardcompat/__init__.py +++ b/awx/lib/site-packages/pip/backwardcompat/__init__.py @@ -1,4 +1,5 @@ -"""Stuff that differs in different Python versions""" +"""Stuff that differs in different Python versions and platform +distributions.""" import os import imp @@ -30,8 +31,7 @@ if sys.version_info >= (3,): from functools import reduce from urllib.error import URLError, HTTPError from queue import Queue, Empty - from urllib.request import url2pathname - from urllib.request import urlretrieve + from urllib.request import url2pathname, urlretrieve, pathname2url from email import message as emailmessage import urllib.parse as urllib import urllib.request as urllib2 @@ -55,9 +55,6 @@ if sys.version_info >= (3,): except UnicodeDecodeError: return s.decode('utf_8') - def fwrite(f, s): - f.buffer.write(b(s)) - def get_http_message_param(http_message, param, default_value): return http_message.get_param(param, default_value) @@ -68,7 +65,7 @@ else: from cStringIO import StringIO from urllib2 import URLError, HTTPError from Queue import Queue, Empty - from urllib import url2pathname, urlretrieve + from urllib import url2pathname, urlretrieve, pathname2url from email import Message as emailmessage import urllib import urllib2 @@ -86,9 +83,6 @@ else: def console_to_str(s): return s - def fwrite(f, s): - f.write(s) - def get_http_message_param(http_message, param, default_value): result = http_message.getparam(param) return result or default_value @@ -118,8 +112,27 @@ def product(*args, **kwds): yield tuple(prod) -## only >=py32 has ssl.match_hostname and ssl.CertificateError -try: - from ssl import match_hostname, CertificateError -except ImportError: - from ssl_match_hostname import match_hostname, CertificateError +def get_path_uid(path): + """ + Return path's uid. + + Does not follow symlinks: https://github.com/pypa/pip/pull/935#discussion_r5307003 + + Placed this function in backwardcompat due to differences on AIX and Jython, + that should eventually go away. + + :raises OSError: When path is a symlink or can't be read. + """ + if hasattr(os, 'O_NOFOLLOW'): + fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) + file_uid = os.fstat(fd).st_uid + os.close(fd) + else: # AIX and Jython + # WARNING: time of check vulnerabity, but best we can do w/o NOFOLLOW + if not os.path.islink(path): + # older versions of Jython don't have `os.fstat` + file_uid = os.stat(path).st_uid + else: + # raise OSError for parity with os.O_NOFOLLOW above + raise OSError("%s is a symlink; Will not return uid for symlinks" % path) + return file_uid diff --git a/awx/lib/site-packages/pip/backwardcompat/ssl_match_hostname.py b/awx/lib/site-packages/pip/backwardcompat/ssl_match_hostname.py deleted file mode 100644 index a6fadf424b..0000000000 --- a/awx/lib/site-packages/pip/backwardcompat/ssl_match_hostname.py +++ /dev/null @@ -1,68 +0,0 @@ -"""The match_hostname() function from Python 3.2, essential when using SSL.""" - -import re - -__version__ = '3.2a3' - -class CertificateError(ValueError): - pass - -def _dnsname_to_pat(dn, max_wildcards=1): - pats = [] - for frag in dn.split(r'.'): - if frag.count('*') > max_wildcards: - # Issue #17980: avoid denials of service by refusing more - # than one wildcard per fragment. A survery of established - # policy among SSL implementations showed it to be a - # reasonable choice. - raise CertificateError( - "too many wildcards in certificate DNS name: " + repr(dn)) - - if frag == '*': - # When '*' is a fragment by itself, it matches a non-empty dotless - # fragment. - pats.append('[^.]+') - else: - # Otherwise, '*' matches any dotless fragment. - frag = re.escape(frag) - pats.append(frag.replace(r'\*', '[^.]*')) - return re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) - -def match_hostname(cert, hostname): - """Verify that *cert* (in decoded format as returned by - SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 rules - are mostly followed, but IP addresses are not accepted for *hostname*. - - CertificateError is raised on failure. On success, the function - returns nothing. - """ - if not cert: - raise ValueError("empty or no certificate") - dnsnames = [] - san = cert.get('subjectAltName', ()) - for key, value in san: - if key == 'DNS': - if _dnsname_to_pat(value).match(hostname): - return - dnsnames.append(value) - if not san: - # The subject is only checked when subjectAltName is empty - for sub in cert.get('subject', ()): - for key, value in sub: - # XXX according to RFC 2818, the most specific Common Name - # must be used. - if key == 'commonName': - if _dnsname_to_pat(value).match(hostname): - return - dnsnames.append(value) - if len(dnsnames) > 1: - raise CertificateError("hostname %r " - "doesn't match either of %s" - % (hostname, ', '.join(map(repr, dnsnames)))) - elif len(dnsnames) == 1: - raise CertificateError("hostname %r " - "doesn't match %r" - % (hostname, dnsnames[0])) - else: - raise CertificateError("no appropriate commonName or " - "subjectAltName fields were found") diff --git a/awx/lib/site-packages/pip/basecommand.py b/awx/lib/site-packages/pip/basecommand.py index 1a22c47f23..e467019129 100644 --- a/awx/lib/site-packages/pip/basecommand.py +++ b/awx/lib/site-packages/pip/basecommand.py @@ -1,36 +1,34 @@ """Base Command class, and related routines""" import os -import socket import sys import tempfile import traceback import time import optparse +from pip import cmdoptions +from pip.locations import running_under_virtualenv from pip.log import logger -from pip.download import urlopen +from pip.download import PipSession from pip.exceptions import (BadCommand, InstallationError, UninstallationError, - CommandError) + CommandError, PreviousBuildDirError) from pip.backwardcompat import StringIO from pip.baseparser import ConfigOptionParser, UpdatingDefaultsHelpFormatter -from pip.status_codes import SUCCESS, ERROR, UNKNOWN_ERROR, VIRTUALENV_NOT_FOUND +from pip.status_codes import (SUCCESS, ERROR, UNKNOWN_ERROR, VIRTUALENV_NOT_FOUND, + PREVIOUS_BUILD_DIR_ERROR) from pip.util import get_prog __all__ = ['Command'] -# for backwards compatibiliy -get_proxy = urlopen.get_proxy - - class Command(object): name = None usage = None hidden = False - def __init__(self, main_parser): + def __init__(self): parser_kw = { 'usage': self.usage, 'prog': '%s %s' % (get_prog(), self.name), @@ -39,62 +37,59 @@ class Command(object): 'name': self.name, 'description': self.__doc__, } - self.main_parser = main_parser + self.parser = ConfigOptionParser(**parser_kw) # Commands should add options to this option group optgroup_name = '%s Options' % self.name.capitalize() self.cmd_opts = optparse.OptionGroup(self.parser, optgroup_name) - # Re-add all options and option groups. - for group in main_parser.option_groups: - self._copy_option_group(self.parser, group) + # Add the general options + gen_opts = cmdoptions.make_option_group(cmdoptions.general_group, self.parser) + self.parser.add_option_group(gen_opts) - # Copies all general options from the main parser. - self._copy_options(self.parser, main_parser.option_list) + def _build_session(self, options): + session = PipSession() - def _copy_options(self, parser, options): - """Populate an option parser or group with options.""" - for option in options: - if not option.dest: - continue - parser.add_option(option) + # Handle custom ca-bundles from the user + if options.cert: + session.verify = options.cert - def _copy_option_group(self, parser, group): - """Copy option group (including options) to another parser.""" - new_group = optparse.OptionGroup(parser, group.title) - self._copy_options(new_group, group.option_list) + # Handle timeouts + if options.timeout: + session.timeout = options.timeout - parser.add_option_group(new_group) + # Handle configured proxies + if options.proxy: + session.proxies = { + "http": options.proxy, + "https": options.proxy, + } - def merge_options(self, initial_options, options): - # Make sure we have all global options carried over - attrs = ['log', 'proxy', 'require_venv', - 'log_explicit_levels', 'log_file', - 'timeout', 'default_vcs', - 'skip_requirements_regex', - 'no_input', 'exists_action', - 'cert'] - for attr in attrs: - setattr(options, attr, getattr(initial_options, attr) or getattr(options, attr)) - options.quiet += initial_options.quiet - options.verbose += initial_options.verbose + # Determine if we can prompt the user for authentication or not + session.auth.prompting = not options.no_input + + return session def setup_logging(self): pass - def main(self, args, initial_options): - options, args = self.parser.parse_args(args) - self.merge_options(initial_options, options) + def parse_args(self, args): + # factored out for testability + return self.parser.parse_args(args) + + def main(self, args): + options, args = self.parse_args(args) level = 1 # Notify level += options.verbose level -= options.quiet level = logger.level_for_integer(4 - level) complete_log = [] - logger.consumers.extend( - [(level, sys.stdout), - (logger.DEBUG, complete_log.append)]) + logger.add_consumers( + (level, sys.stdout), + (logger.DEBUG, complete_log.append), + ) if options.log_explicit_levels: logger.explicit_levels = True @@ -107,27 +102,20 @@ class Command(object): os.environ['PIP_NO_INPUT'] = '1' if options.exists_action: - os.environ['PIP_EXISTS_ACTION'] = ''.join(options.exists_action) - - if options.cert: - os.environ['PIP_CERT'] = options.cert + os.environ['PIP_EXISTS_ACTION'] = ' '.join(options.exists_action) if options.require_venv: # If a venv is required check if it can really be found - if not os.environ.get('VIRTUAL_ENV'): + if not running_under_virtualenv(): logger.fatal('Could not find an activated virtualenv (required).') sys.exit(VIRTUALENV_NOT_FOUND) if options.log: log_fp = open_logfile(options.log, 'a') - logger.consumers.append((logger.DEBUG, log_fp)) + logger.add_consumers((logger.DEBUG, log_fp)) else: log_fp = None - socket.setdefaulttimeout(options.timeout or None) - - urlopen.setup(proxystr=options.proxy, prompting=not options.no_input) - exit = SUCCESS store_log = False try: @@ -136,6 +124,12 @@ class Command(object): # and when it is done, isinstance is not needed anymore if isinstance(status, int): exit = status + except PreviousBuildDirError: + e = sys.exc_info()[1] + logger.fatal(str(e)) + logger.info('Exception information:\n%s' % format_exc()) + store_log = True + exit = PREVIOUS_BUILD_DIR_ERROR except (InstallationError, UninstallationError): e = sys.exc_info()[1] logger.fatal(str(e)) @@ -162,19 +156,19 @@ class Command(object): logger.fatal('Exception:\n%s' % format_exc()) store_log = True exit = UNKNOWN_ERROR - if log_fp is not None: - log_fp.close() if store_log: - log_fn = options.log_file + log_file_fn = options.log_file text = '\n'.join(complete_log) try: - log_fp = open_logfile(log_fn, 'w') + log_file_fp = open_logfile(log_file_fn, 'w') except IOError: temp = tempfile.NamedTemporaryFile(delete=False) - log_fn = temp.name - log_fp = open_logfile(log_fn, 'w') - logger.fatal('Storing complete log in %s' % log_fn) - log_fp.write(text) + log_file_fn = temp.name + log_file_fp = open_logfile(log_file_fn, 'w') + logger.fatal('Storing debug log for failure in %s' % log_file_fn) + log_file_fp.write(text) + log_file_fp.close() + if log_fp is not None: log_fp.close() return exit diff --git a/awx/lib/site-packages/pip/baseparser.py b/awx/lib/site-packages/pip/baseparser.py index 61a73ce002..ce4016033f 100644 --- a/awx/lib/site-packages/pip/baseparser.py +++ b/awx/lib/site-packages/pip/baseparser.py @@ -7,7 +7,7 @@ import os import textwrap from distutils.util import strtobool from pip.backwardcompat import ConfigParser, string_types -from pip.locations import default_config_file, default_log_file +from pip.locations import default_config_file from pip.util import get_terminal_size, get_prog @@ -122,7 +122,7 @@ class CustomOptionParser(optparse.OptionParser): class ConfigOptionParser(CustomOptionParser): - """Custom option parser which updates its defaults by by checking the + """Custom option parser which updates its defaults by checking the configuration files and environmental variables""" def __init__(self, *args, **kwargs): @@ -139,6 +139,14 @@ class ConfigOptionParser(CustomOptionParser): return [config_file] return [default_config_file] + def check_default(self, option, key, val): + try: + return option.check_value(key, val) + except optparse.OptionValueError: + e = sys.exc_info()[1] + print("An error occurred during configuration: %s" % e) + sys.exit(3) + def update_defaults(self, defaults): """Updates the given defaults with values from the config files and the environ. Does a little special handling for certain types of @@ -157,19 +165,14 @@ class ConfigOptionParser(CustomOptionParser): # ignore empty values if not val: continue - # handle multiline configs - if option.action == 'append': - val = val.split() - else: - option.nargs = 1 if option.action in ('store_true', 'store_false', 'count'): val = strtobool(val) - try: - val = option.convert_value(key, val) - except optparse.OptionValueError: - e = sys.exc_info()[1] - print("An error occurred during configuration: %s" % e) - sys.exit(3) + if option.action == 'append': + val = val.split() + val = [self.check_default(option, key, v) for v in val] + else: + val = self.check_default(option, key, val) + defaults[option.dest] = val return defaults @@ -215,154 +218,3 @@ class ConfigOptionParser(CustomOptionParser): def error(self, msg): self.print_usage(sys.stderr) self.exit(2, "%s\n" % msg) - - -try: - pip_dist = pkg_resources.get_distribution('pip') - version = '%s from %s (python %s)' % ( - pip_dist, pip_dist.location, sys.version[:3]) -except pkg_resources.DistributionNotFound: - # when running pip.py without installing - version = None - - -def create_main_parser(): - parser_kw = { - 'usage': '\n%prog [options]', - 'add_help_option': False, - 'formatter': UpdatingDefaultsHelpFormatter(), - 'name': 'global', - 'prog': get_prog(), - } - - parser = ConfigOptionParser(**parser_kw) - genopt = optparse.OptionGroup(parser, 'General Options') - parser.disable_interspersed_args() - - # having a default version action just causes trouble - parser.version = version - - for opt in standard_options: - genopt.add_option(opt) - parser.add_option_group(genopt) - - return parser - - -standard_options = [ - optparse.make_option( - '-h', '--help', - dest='help', - action='help', - help='Show help.'), - - optparse.make_option( - # Run only if inside a virtualenv, bail if not. - '--require-virtualenv', '--require-venv', - dest='require_venv', - action='store_true', - default=False, - help=optparse.SUPPRESS_HELP), - - optparse.make_option( - '-v', '--verbose', - dest='verbose', - action='count', - default=0, - help='Give more output. Option is additive, and can be used up to 3 times.'), - - optparse.make_option( - '-V', '--version', - dest='version', - action='store_true', - help='Show version and exit.'), - - optparse.make_option( - '-q', '--quiet', - dest='quiet', - action='count', - default=0, - help='Give less output.'), - - optparse.make_option( - '--log', - dest='log', - metavar='file', - help='Log file where a complete (maximum verbosity) record will be kept.'), - - optparse.make_option( - # Writes the log levels explicitely to the log' - '--log-explicit-levels', - dest='log_explicit_levels', - action='store_true', - default=False, - help=optparse.SUPPRESS_HELP), - - optparse.make_option( - # The default log file - '--local-log', '--log-file', - dest='log_file', - metavar='file', - default=default_log_file, - help=optparse.SUPPRESS_HELP), - - optparse.make_option( - # Don't ask for input - '--no-input', - dest='no_input', - action='store_true', - default=False, - help=optparse.SUPPRESS_HELP), - - optparse.make_option( - '--proxy', - dest='proxy', - type='str', - default='', - help="Specify a proxy in the form [user:passwd@]proxy.server:port."), - - optparse.make_option( - '--timeout', '--default-timeout', - metavar='sec', - dest='timeout', - type='float', - default=15, - help='Set the socket timeout (default %default seconds).'), - - optparse.make_option( - # The default version control system for editables, e.g. 'svn' - '--default-vcs', - dest='default_vcs', - type='str', - default='', - help=optparse.SUPPRESS_HELP), - - optparse.make_option( - # A regex to be used to skip requirements - '--skip-requirements-regex', - dest='skip_requirements_regex', - type='str', - default='', - help=optparse.SUPPRESS_HELP), - - optparse.make_option( - # Option when path already exist - '--exists-action', - dest='exists_action', - type='choice', - choices=['s', 'i', 'w', 'b'], - default=[], - action='append', - metavar='action', - help="Default action when a path already exists: " - "(s)witch, (i)gnore, (w)ipe, (b)ackup."), - - optparse.make_option( - '--cert', - dest='cert', - type='str', - default='', - metavar='path', - help = "Path to alternate CA bundle."), - - ] diff --git a/awx/lib/site-packages/pip/cacert.pem b/awx/lib/site-packages/pip/cacert.pem deleted file mode 100644 index 99b310bce9..0000000000 --- a/awx/lib/site-packages/pip/cacert.pem +++ /dev/null @@ -1,3895 +0,0 @@ -## -## ca-bundle.crt -- Bundle of CA Root Certificates -## -## Certificate data from Mozilla as of: Sat Dec 29 20:03:40 2012 -## -## This is a bundle of X.509 certificates of public Certificate Authorities -## (CA). These were automatically extracted from Mozilla's root certificates -## file (certdata.txt). This file can be found in the mozilla source tree: -## http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1 -## -## It contains the certificates in PEM format and therefore -## can be directly used with curl / libcurl / php_curl, or with -## an Apache+mod_ssl webserver for SSL client authentication. -## Just configure this file as the SSLCACertificateFile. -## - -# @(#) $RCSfile: certdata.txt,v $ $Revision: 1.87 $ $Date: 2012/12/29 16:32:45 $ - -GTE CyberTrust Global Root -========================== ------BEGIN CERTIFICATE----- -MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg -Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG -A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz -MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL -Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0 -IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u -sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql -HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID -AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW -M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF -NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ ------END CERTIFICATE----- - -Thawte Server CA -================ ------BEGIN CERTIFICATE----- -MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT -DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs -dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UE -AxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5j -b20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNV -BAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29u -c3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcG -A1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0 -ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl -/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg7 -1CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzAR -MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9J -GubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZ -GCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc= ------END CERTIFICATE----- - -Thawte Premium Server CA -======================== ------BEGIN CERTIFICATE----- -MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT -DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs -dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE -AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl -ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT -AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU -VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2 -aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ -cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2 -aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh -Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/ -qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm -SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf -8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t -UCemDaYj+bvLpgcUQg== ------END CERTIFICATE----- - -Equifax Secure CA -================= ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE -ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 -MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT -B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB -nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR -fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW -8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG -A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE -CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG -A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS -spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB -Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961 -zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB -BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95 -70+sB3c4 ------END CERTIFICATE----- - -Digital Signature Trust Co. Global CA 1 -======================================= ------BEGIN CERTIFICATE----- -MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE -ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMTAeFw05ODEy -MTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs -IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUA -A4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJE -NySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2i -o74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo -BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0 -dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw -IoAPMTk5ODEyMTAxODEwMjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQY -MBaAFGp5fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i+DAM -BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB -ACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lNQseSJqBcNJo4cvj9axY+IO6CizEq -kzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4 -RbyhkwS7hp86W0N6w4pl ------END CERTIFICATE----- - -Digital Signature Trust Co. Global CA 3 -======================================= ------BEGIN CERTIFICATE----- -MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE -ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMjAeFw05ODEy -MDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs -IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUA -A4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGOD -VvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JS -xhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo -BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0 -dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw -IoAPMTk5ODEyMDkxOTE3MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQY -MBaAFB6CTShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5WzAM -BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB -AEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHRxdf0CiUPPXiBng+xZ8SQTGPdXqfi -up/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVLB3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1 -mPnHfxsb1gYgAlihw6ID ------END CERTIFICATE----- - -Verisign Class 3 Public Primary Certification Authority -======================================================= ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMx -FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5 -IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVow -XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz -IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA -A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94 -f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol -hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBAgUAA4GBALtMEivPLCYA -TxQT3ab7/AoRhIzzKBxnki98tsX63/Dolbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59Ah -WM1pF+NEHJwZRDmJXNycAA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2Omuf -Tqj/ZA1k ------END CERTIFICATE----- - -Verisign Class 1 Public Primary Certification Authority - G2 -============================================================ ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT -MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMgUHJpbWFy -eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz -dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT -MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMgUHJpbWFy -eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz -dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgd -k4xWArzZbxpvUjZudVYKVdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIq -WpDBucSmFc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQIDAQAB -MA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0Jh9ZrbWB85a7FkCMM -XErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2uluIncrKTdcu1OofdPvAbT6shkdHvC -lUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68DzFc6PLZ ------END CERTIFICATE----- - -Verisign Class 2 Public Primary Certification Authority - G2 -============================================================ ------BEGIN CERTIFICATE----- -MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1h -cnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNp -Z24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1 -c3QgTmV0d29yazAeFw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1h -cnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNp -Z24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1 -c3QgTmV0d29yazCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjx -nNuX6Zr8wgQGE75fUsjMHiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRC -wiNPStjwDqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cCAwEA -ATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9jinb3/7aHmZuovCfTK -1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAXrXfMSTWqz9iP0b63GJZHc2pUIjRk -LbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnInjBJ7xUS0rg== ------END CERTIFICATE----- - -Verisign Class 3 Public Primary Certification Authority - G2 -============================================================ ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT -MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy -eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz -dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT -MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy -eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz -dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCO -FoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71 -lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQAB -MA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01UbSuvDV1Ai2TT -1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7iF6YM40AIOw7n60RzKprxaZLvcRTD -Oaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpYoJ2daZH9 ------END CERTIFICATE----- - -GlobalSign Root CA -================== ------BEGIN CERTIFICATE----- -MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx -GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds -b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV -BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD -VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa -DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc -THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb -Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP -c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX -gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF -AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj -Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG -j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH -hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC -X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== ------END CERTIFICATE----- - -GlobalSign Root CA - R2 -======================= ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv -YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh -bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT -aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln -bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6 -ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp -s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN -S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL -TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C -ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E -FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i -YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN -BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp -9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu -01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7 -9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 -TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== ------END CERTIFICATE----- - -ValiCert Class 1 VA -=================== ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp -b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh -bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIy -MjM0OFoXDTE5MDYyNTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 -d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEg -UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 -LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA -A4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIi -GQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCm -DuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0LBwG -lN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLWI8sogTLDAHkY7FkX -icnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPwnXS3qT6gpf+2SQMT2iLM7XGCK5nP -Orf1LXLI ------END CERTIFICATE----- - -ValiCert Class 2 VA -=================== ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp -b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh -bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw -MTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 -d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIg -UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 -LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA -A4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVC -CSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7Rf -ZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZ -SWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbV -UjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8 -W9ViH0Pd ------END CERTIFICATE----- - -RSA Root Certificate 1 -====================== ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp -b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh -bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw -MjIzM1oXDTE5MDYyNjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 -d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMg -UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 -LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA -A4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td -3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89H -BFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliEZwgs -3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJn0WuPIqpsHEzXcjF -V9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/APhmcGcwTTYJBtYze4D1gCCAPRX5r -on+jjBXu ------END CERTIFICATE----- - -Verisign Class 1 Public Primary Certification Authority - G3 -============================================================ ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv -cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy -dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv -cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAN2E1Lm0+afY8wR4nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/E -bRrsC+MO8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjVojYJ -rKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjbPG7PoBMAGrgnoeS+ -Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP26KbqxzcSXKMpHgLZ2x87tNcPVkeB -FQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vrn5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA -q2aN17O6x5q25lXQBfGfMY1aqtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/N -y9Sn2WCVhDr4wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 -ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrspSCAaWihT37h -a88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4E1Z5T21Q6huwtVexN2ZYI/Pc -D98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== ------END CERTIFICATE----- - -Verisign Class 2 Public Primary Certification Authority - G3 -============================================================ ------BEGIN CERTIFICATE----- -MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJBgNVBAYTAlVT -MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29y -azE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ug -b25seTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0 -aW9uIEF1dGhvcml0eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1 -c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y -aXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEArwoNwtUs22e5LeWUJ92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6 -tW8UvxDOJxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUYwZF7 -C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9okoqQHgiBVrKtaaNS -0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjNqWm6o+sdDZykIKbBoMXRRkwXbdKs -Zj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/ESrg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0 -JhU8wI1NQ0kdvekhktdmnLfexbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf -0xwLRtxyID+u7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU -sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RIsH/7NiXaldDx -JBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTPcjnhsUPgKM+351psE2tJs//j -GHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q ------END CERTIFICATE----- - -Verisign Class 3 Public Primary Certification Authority - G3 -============================================================ ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv -cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy -dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv -cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1 -EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc -cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw -EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj -055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA -ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f -j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC -/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0 -xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa -t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== ------END CERTIFICATE----- - -Verisign Class 4 Public Primary Certification Authority - G3 -============================================================ ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv -cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy -dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv -cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS -tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM -8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW -Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX -Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA -j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt -mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm -fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd -RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG -UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== ------END CERTIFICATE----- - -Entrust.net Secure Server CA -============================ ------BEGIN CERTIFICATE----- -MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMCVVMxFDASBgNV -BAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5uZXQvQ1BTIGluY29ycC4gYnkg -cmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRl -ZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhv -cml0eTAeFw05OTA1MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIG -A1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBi -eSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1p -dGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQ -aO2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5 -gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OCAdcw -ggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHboIHYpIHVMIHSMQsw -CQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5l -dC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF -bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENl -cnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu -dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0MFqBDzIwMTkw -NTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0Bow -HQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAaMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA -BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyN -Ewr75Ji174z4xRAN95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9 -n9cd2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= ------END CERTIFICATE----- - -Entrust.net Premium 2048 Secure Server CA -========================================= ------BEGIN CERTIFICATE----- -MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u -ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp -bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV -BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx -NzUwNTFaFw0xOTEyMjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 -d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl -MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u -ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL -Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr -hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW -nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi -VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo3QwcjARBglghkgBhvhC -AQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGAvtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdER -gL7YibkIozH5oSQJFrlwMB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0B -AQUFAAOCAQEAWUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo -oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQh7A6tcOdBTcS -o8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18f3v/rxzP5tsHrV7bhZ3QKw0z -2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfNB/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjX -OP/swNlQ8C5LWK5Gb9Auw2DaclVyvUxFnmG6v4SBkgPR0ml8xQ== ------END CERTIFICATE----- - -Baltimore CyberTrust Root -========================= ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE -ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li -ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC -SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs -dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME -uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB -UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C -G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 -XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr -l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI -VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB -BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh -cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 -hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa -Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H -RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE----- - -Equifax Secure Global eBusiness CA -================================== ------BEGIN CERTIFICATE----- -MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT -RXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNp -bmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMx -HDAaBgNVBAoTE0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEds -b2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRV -PEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzN -qfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxn -hcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j -BBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hs -MA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okEN -I7SS+RkAZ70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIY -NMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV ------END CERTIFICATE----- - -Equifax Secure eBusiness CA 1 -============================= ------BEGIN CERTIFICATE----- -MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT -RXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENB -LTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UE -ChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNz -IENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ -1MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBuWqDZQu4a -IZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKwEnv+j6YDAgMBAAGjZjBk -MBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEp4MlIR21kW -Nl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQF -AAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5 -lSE/9dR+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+ -KpYrtWKmpj29f5JZzVoqgrI3eQ== ------END CERTIFICATE----- - -Equifax Secure eBusiness CA 2 -============================= ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEXMBUGA1UE -ChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0y -MB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoT -DkVxdWlmYXggU2VjdXJlMSYwJAYDVQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCB -nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn -2Z0GvxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/BPO3QSQ5 -BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0CAwEAAaOCAQkwggEFMHAG -A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUx -JjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoG -A1UdEAQTMBGBDzIwMTkwNjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9e -uSBIplBqy/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQFMAMB -Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAAyGgq3oThr1 -jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia -78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUm -V+GRMOrN ------END CERTIFICATE----- - -AddTrust Low-Value Services Root -================================ ------BEGIN CERTIFICATE----- -MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU -cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw -CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO -ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6 -54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr -oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1 -Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui -GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w -HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD -AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT -RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw -HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt -ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph -iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY -eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr -mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj -ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= ------END CERTIFICATE----- - -AddTrust External Root -====================== ------BEGIN CERTIFICATE----- -MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD -VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw -NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU -cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg -Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821 -+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw -Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo -aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy -2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7 -7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P -BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL -VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk -VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB -IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl -j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 -6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355 -e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u -G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= ------END CERTIFICATE----- - -AddTrust Public Services Root -============================= ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU -cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ -BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l -dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu -nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i -d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG -Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw -HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G -A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux -FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G -A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4 -JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL -+YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao -GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9 -Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H -EufOX1362KqxMy3ZdvJOOjMMK7MtkAY= ------END CERTIFICATE----- - -AddTrust Qualified Certificates Root -==================================== ------BEGIN CERTIFICATE----- -MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU -cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx -CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ -IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx -64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3 -KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o -L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR -wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU -MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE -BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y -azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD -ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG -GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X -dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze -RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB -iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE= ------END CERTIFICATE----- - -Entrust Root Certification Authority -==================================== ------BEGIN CERTIFICATE----- -MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV -BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw -b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG -A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 -MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu -MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu -Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v -dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz -A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww -Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 -j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN -rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw -DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 -MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH -hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA -A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM -Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa -v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS -W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 -tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 ------END CERTIFICATE----- - -RSA Security 2048 v3 -==================== ------BEGIN CERTIFICATE----- -MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYDVQQK -ExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAy -MjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAb -BgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7 -Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgb -WhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iH -KrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP -+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/ -MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4E -FgQUB8NRMKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmY -v/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj -0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwj -VAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395 -nzIlQnQFgCi/vcEkllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA -pKnXwiJPZ9d37CAFYd4= ------END CERTIFICATE----- - -GeoTrust Global CA -================== ------BEGIN CERTIFICATE----- -MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK -Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw -MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j -LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo -BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet -8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc -T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU -vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD -AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk -DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q -zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4 -d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2 -mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p -XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm -Mw== ------END CERTIFICATE----- - -GeoTrust Global CA 2 -==================== ------BEGIN CERTIFICATE----- -MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN -R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw -MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j -LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/ -NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k -LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA -Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b -HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH -K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7 -srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh -ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL -OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC -x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF -H4z1Ir+rzoPz4iIprn2DQKi6bA== ------END CERTIFICATE----- - -GeoTrust Universal CA -===================== ------BEGIN CERTIFICATE----- -MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN -R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1 -MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu -Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP -ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t -JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e -RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs -7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d -8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V -qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga -Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB -Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu -KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08 -ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0 -XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB -hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc -aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2 -qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL -oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK -xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF -KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2 -DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK -xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU -p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI -P/rmMuGNG2+k5o7Y+SlIis5z/iw= ------END CERTIFICATE----- - -GeoTrust Universal CA 2 -======================= ------BEGIN CERTIFICATE----- -MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN -R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0 -MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg -SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0 -DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17 -j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q -JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a -QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2 -WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP -20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn -ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC -SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG -8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2 -+/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E -BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z -dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ -4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+ -mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq -A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg -Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP -pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d -FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp -gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm -X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS ------END CERTIFICATE----- - -UTN-USER First-Network Applications -=================================== ------BEGIN CERTIFICATE----- -MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCBozELMAkGA1UE -BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl -IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzAp -BgNVBAMTIlVUTi1VU0VSRmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5 -WhcNMTkwNzA5MTg1NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5T -YWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3QtTmV0d29yayBB -cHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz+5Gh5DZVhawGNFug -mliy+LUPBXeDrjKxdpJo7CNKyXY/45y2N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4Cj -DUeJT1FxL+78P/m4FoCHiZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXu -Ozr0hAReYFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1axwi -P8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6gyN7igEL66S/ozjIE -j3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8w -HQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPhahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9j -cmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0G -CSqGSIb3DQEBBQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y -IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6LzsQCv4AdRWOOTK -RIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4ZSfP1FMa8Kxun08FDAOBp4Qp -xFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qMYEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAq -DbUMo2s/rn9X9R+WfN9v3YIwLGUbQErNaLly7HF27FSOH4UMAWr6pjisH8SE ------END CERTIFICATE----- - -America Online Root Certification Authority 1 -============================================= ------BEGIN CERTIFICATE----- -MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT -QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkG -A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg -T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lkhsmj76CG -v2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym1BW32J/X3HGrfpq/m44z -DyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsWOqMFf6Dch9Wc/HKpoH145LcxVR5lu9Rh -sCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP -8c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0T -AQH/BAUwAwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Z -o/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQB8itEf -GDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkFZu90821fnZmv9ov761KyBZiibyrF -VL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft -3OJvx8Fi8eNy1gTIdGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43g -Kd8hdIaC2y+CMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds -sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 ------END CERTIFICATE----- - -America Online Root Certification Authority 2 -============================================= ------BEGIN CERTIFICATE----- -MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT -QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkG -A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg -T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC206B89en -fHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFciKtZHgVdEglZTvYYUAQv8 -f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2JxhP7JsowtS013wMPgwr38oE18aO6lhO -qKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JN -RvCAOVIyD+OEsnpD8l7eXz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0 -gBe4lL8BPeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67Xnfn -6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEqZ8A9W6Wa6897Gqid -FEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZo2C7HK2JNDJiuEMhBnIMoVxtRsX6 -Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnj -B453cMor9H124HhnAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3Op -aaEg5+31IqEjFNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE -AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmnxPBUlgtk87FY -T15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2LHo1YGwRgJfMqZJS5ivmae2p -+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzcccobGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXg -JXUjhx5c3LqdsKyzadsXg8n33gy8CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//Zoy -zH1kUQ7rVyZ2OuMeIjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgO -ZtMADjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2FAjgQ5ANh -1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUXOm/9riW99XJZZLF0Kjhf -GEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPbAZO1XB4Y3WRayhgoPmMEEf0cjQAPuDff -Z4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQlZvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuP -cX/9XhmgD0uRuMRUvAawRY8mkaKO/qk= ------END CERTIFICATE----- - -Visa eCommerce Root -=================== ------BEGIN CERTIFICATE----- -MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG -EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug -QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2 -WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm -VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv -bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL -F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b -RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0 -TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI -/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs -GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG -MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc -CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW -YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz -zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu -YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt -398znM/jra6O1I7mT1GvFpLgXPYHDw== ------END CERTIFICATE----- - -Certum Root CA -============== ------BEGIN CERTIFICATE----- -MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK -ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla -Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u -by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x -wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL -kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ -89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K -Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P -NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq -hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+ -GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg -GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/ -0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS -qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw== ------END CERTIFICATE----- - -Comodo AAA Services root -======================== ------BEGIN CERTIFICATE----- -MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS -R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg -TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw -MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl -c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV -BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG -C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs -i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW -Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH -Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK -Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f -BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl -cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz -LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm -7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz -Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z -8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C -12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== ------END CERTIFICATE----- - -Comodo Secure Services root -=========================== ------BEGIN CERTIFICATE----- -MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS -R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg -TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw -MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu -Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi -BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP -9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc -rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC -oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V -p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E -FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w -gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj -YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm -aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm -4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj -Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL -DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw -pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H -RR3B7Hzs/Sk= ------END CERTIFICATE----- - -Comodo Trusted Services root -============================ ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS -R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg -TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw -MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h -bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw -IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7 -3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y -/9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6 -juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS -ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud -DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp -ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl -cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw -uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 -pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA -BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l -R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O -9y5Xt5hwXsjEeLBi ------END CERTIFICATE----- - -QuoVadis Root CA -================ ------BEGIN CERTIFICATE----- -MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE -ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz -MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp -cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD -EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk -J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL -F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL -YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen -AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w -PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y -ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7 -MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj -YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs -ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh -Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW -Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu -BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw -FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6 -tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo -fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul -LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x -gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi -5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi -5nrQNiOKSnQ2+Q== ------END CERTIFICATE----- - -QuoVadis Root CA 2 -================== ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -QuoVadis Root CA 3 -================== ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -Security Communication Root CA -============================== ------BEGIN CERTIFICATE----- -MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP -U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw -HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP -U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw -8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM -DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX -5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd -DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 -JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw -DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g -0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a -mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ -s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ -6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi -FL39vmwLAw== ------END CERTIFICATE----- - -Sonera Class 1 Root CA -====================== ------BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG -U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAxMDQwNjEwNDkxM1oXDTIxMDQw -NjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh -IENsYXNzMSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H88 -7dF+2rDNbS82rDTG29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9 -EJUkoVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk3w0LBUXl -0fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBLqdReLjVQCfOAl/QMF645 -2F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIINnvmLVz5MxxftLItyM19yejhW1ebZrgUa -HXVFsculJRwSVzb9IjcCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZT -iFIwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE9 -28Jj2VuXZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0HDjxV -yhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VOTzF2nBBhjrZTOqMR -vq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2UvkVrCqIexVmiUefkl98HVrhq4uz2P -qYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4wzMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9Z -IRlXvVWa ------END CERTIFICATE----- - -Sonera Class 2 Root CA -====================== ------BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG -U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw -NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh -IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3 -/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT -dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG -f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P -tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH -nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT -XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt -0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI -cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph -Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx -EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH -llpwrN9M ------END CERTIFICATE----- - -Staat der Nederlanden Root CA -============================= ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE -ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g -Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w -HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh -bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt -vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P -jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca -C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth -vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6 -22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV -HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v -dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN -BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR -EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw -MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y -nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR -iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== ------END CERTIFICATE----- - -TDC Internet Root CA -==================== ------BEGIN CERTIFICATE----- -MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJESzEVMBMGA1UE -ChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTAeFw0wMTA0MDUx -NjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNVBAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJu -ZXQxHTAbBgNVBAsTFFREQyBJbnRlcm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAxLhAvJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20j -xsNuZp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a0vnRrEvL -znWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc14izbSysseLlJ28TQx5yc -5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGNeGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6 -otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcDR0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZI -AYb4QgEBBAQDAgAHMGUGA1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMM -VERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxMEQ1JM -MTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3WjALBgNVHQ8EBAMC -AQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAwHQYDVR0OBBYEFGxkAcf9hW2syNqe -UAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJKoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0G -CSqGSIb3DQEBBQUAA4IBAQBOQ8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540m -gwV5dOy0uaOXwTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ -2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm899qNLPg7kbWzb -O0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0jUNAE4z9mQNUecYu6oah9jrU -Cbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38aQNiuJkFBT1reBK9sG9l ------END CERTIFICATE----- - -TDC OCES Root CA -================ ------BEGIN CERTIFICATE----- -MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJESzEMMAoGA1UE -ChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEwODM5MzBaFw0zNzAyMTEwOTA5 -MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNUREMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuH -nEz9pPPEXyG9VhDr2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0 -zY0s2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItUGBxIYXvV -iGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKjdGqPqcNiKXEx5TukYBde -dObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+rTpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO -3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB -5DCB4TCB3gYIKoFQgSkBAQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5k -ay9yZXBvc2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRlciBm -cmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEuMS4xLiBDZXJ0aWZp -Y2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEuMS4x -LjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1UdHwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEM -MAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYm -aHR0cDovL2NybC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy -MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZJ2cdUBVLc647 -+RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqGSIb2fQdBAAQQMA4bCFY2LjA6 -NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACromJkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4 -A9G28kNBKWKnctj7fAXmMXAnVBhOinxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYsc -A+UYyAFMP8uXBV2YcaaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9 -AOoBmbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQYqbsFbS1 -AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9BKNDLdr8C2LqL19iUw== ------END CERTIFICATE----- - -UTN DATACorp SGC Root CA -======================== ------BEGIN CERTIFICATE----- -MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE -BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl -IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ -BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa -MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w -HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy -dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys -raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo -wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA -9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv -33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud -DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9 -BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD -LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3 -DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0 -I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx -EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP -DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI ------END CERTIFICATE----- - -UTN USERFirst Email Root CA -=========================== ------BEGIN CERTIFICATE----- -MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCBrjELMAkGA1UE -BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl -IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0 -BgNVBAMTLVVUTi1VU0VSRmlyc3QtQ2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05 -OTA3MDkxNzI4NTBaFw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQx -FzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsx -ITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UEAxMtVVROLVVTRVJGaXJz -dC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWlsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3BYHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIx -B8dOtINknS4p1aJkxIW9hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8 -om+rWV6lL8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLmSGHG -TPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM1tZUOt4KpLoDd7Nl -yP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws6wIDAQABo4G5MIG2MAsGA1UdDwQE -AwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNV -HR8EUTBPME2gS6BJhkdodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGll -bnRBdXRoZW50aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH -AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u7mFVbwQ+zzne -xRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0xtcgBEXkzYABurorbs6q15L+ -5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQrfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarV -NZ1yQAOJujEdxRBoUp7fooXFXAimeOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZ -w7JHpsIyYdfHb0gkUSeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ= ------END CERTIFICATE----- - -UTN USERFirst Hardware Root CA -============================== ------BEGIN CERTIFICATE----- -MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE -BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl -IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd -BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx -OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0 -eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz -ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI -wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd -tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8 -i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf -Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw -gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF -lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF -UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF -BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM -//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW -XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2 -lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn -iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67 -nfhmqA== ------END CERTIFICATE----- - -UTN USERFirst Object Root CA -============================ ------BEGIN CERTIFICATE----- -MIIEZjCCA06gAwIBAgIQRL4Mi1AAJLQR0zYt4LNfGzANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UE -BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl -IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAb -BgNVBAMTFFVUTi1VU0VSRmlyc3QtT2JqZWN0MB4XDTk5MDcwOTE4MzEyMFoXDTE5MDcwOTE4NDAz -NlowgZUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkx -HjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3dy51c2Vy -dHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdDCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAM6qgT+jo2F4qjEAVZURnicPHxzfOpuCaDDASmEd8S8O+r5596Uj71VR -loTN2+O5bj4x2AogZ8f02b+U60cEPgLOKqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQ -w5ujm9M89RKZd7G3CeBo5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbHd2pBnqcP1/vu -lBe3/IW+pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh2JU022R5KP+6LhHC5ehbkkj7 -RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzTbafc8H9vg2XiaquHhnUCAwEAAaOBrzCBrDAL -BgNVHQ8EBAMCAcYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU2u1kdBScFDyr3ZmpvVsoTYs8 -ydgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmly -c3QtT2JqZWN0LmNybDApBgNVHSUEIjAgBggrBgEFBQcDAwYIKwYBBQUHAwgGCisGAQQBgjcKAwQw -DQYJKoZIhvcNAQEFBQADggEBAAgfUrE3RHjb/c652pWWmKpVZIC1WkDdIaXFwfNfLEzIR1pp6ujw -NTX00CXzyKakh0q9G7FzCL3Uw8q2NbtZhncxzaeAFK4T7/yxSPlrJSUtUbYsbUXBmMiKVl0+7kNO -PmsnjtA6S4ULX9Ptaqd1y9Fahy85dRNacrACgZ++8A+EVCBibGnU4U3GDZlDAQ0Slox4nb9QorFE -qmrPF3rPbw/U+CRVX/A0FklmPlBGyWNxODFiuGK581OtbLUrohKqGU8J2l7nk8aOFAj+8DCAGKCG -hU3IfdeLA/5u1fedFqySLKAj5ZyRUh+U3xeUc8OzwcFxBSAAeL0TUh2oPs0AH8g= ------END CERTIFICATE----- - -Camerfirma Chambers of Commerce Root -==================================== ------BEGIN CERTIFICATE----- -MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe -QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i -ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx -NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp -cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn -MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC -AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU -xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH -NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW -DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV -d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud -EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v -cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P -AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh -bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD -VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz -aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi -fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD -L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN -UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n -ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1 -erfutGWaIZDgqtCYvDi1czyL+Nw= ------END CERTIFICATE----- - -Camerfirma Global Chambersign Root -================================== ------BEGIN CERTIFICATE----- -MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe -QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i -ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx -NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt -YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg -MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw -ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J -1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O -by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl -6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c -8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/ -BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j -aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B -Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj -aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y -ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh -bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA -PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y -gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ -PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4 -IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes -t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== ------END CERTIFICATE----- - -NetLock Qualified (Class QA) Root -================================= ------BEGIN CERTIFICATE----- -MIIG0TCCBbmgAwIBAgIBezANBgkqhkiG9w0BAQUFADCByTELMAkGA1UEBhMCSFUxETAPBgNVBAcT -CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV -BAsTEVRhbnVzaXR2YW55a2lhZG9rMUIwQAYDVQQDEzlOZXRMb2NrIE1pbm9zaXRldHQgS296amVn -eXpvaSAoQ2xhc3MgUUEpIFRhbnVzaXR2YW55a2lhZG8xHjAcBgkqhkiG9w0BCQEWD2luZm9AbmV0 -bG9jay5odTAeFw0wMzAzMzAwMTQ3MTFaFw0yMjEyMTUwMTQ3MTFaMIHJMQswCQYDVQQGEwJIVTER -MA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNhZ2kgS2Z0 -LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxQjBABgNVBAMTOU5ldExvY2sgTWlub3NpdGV0 -dCBLb3pqZWd5em9pIChDbGFzcyBRQSkgVGFudXNpdHZhbnlraWFkbzEeMBwGCSqGSIb3DQEJARYP -aW5mb0BuZXRsb2NrLmh1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx1Ilstg91IRV -CacbvWy5FPSKAtt2/GoqeKvld/Bu4IwjZ9ulZJm53QE+b+8tmjwi8F3JV6BVQX/yQ15YglMxZc4e -8ia6AFQer7C8HORSjKAyr7c3sVNnaHRnUPYtLmTeriZ539+Zhqurf4XsoPuAzPS4DB6TRWO53Lhb -m+1bOdRfYrCnjnxmOCyqsQhjF2d9zL2z8cM/z1A57dEZgxXbhxInlrfa6uWdvLrqOU+L73Sa58XQ -0uqGURzk/mQIKAR5BevKxXEOC++r6uwSEaEYBTJp0QwsGj0lmT+1fMptsK6ZmfoIYOcZwvK9UdPM -0wKswREMgM6r3JSda6M5UzrWhQIDAMV9o4ICwDCCArwwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV -HQ8BAf8EBAMCAQYwggJ1BglghkgBhvhCAQ0EggJmFoICYkZJR1lFTEVNISBFemVuIHRhbnVzaXR2 -YW55IGEgTmV0TG9jayBLZnQuIE1pbm9zaXRldHQgU3pvbGdhbHRhdGFzaSBTemFiYWx5emF0YWJh -biBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBBIG1pbm9zaXRldHQgZWxla3Ryb25p -a3VzIGFsYWlyYXMgam9naGF0YXMgZXJ2ZW55ZXN1bGVzZW5laywgdmFsYW1pbnQgZWxmb2dhZGFz -YW5hayBmZWx0ZXRlbGUgYSBNaW5vc2l0ZXR0IFN6b2xnYWx0YXRhc2kgU3phYmFseXphdGJhbiwg -YXogQWx0YWxhbm9zIFN6ZXJ6b2Rlc2kgRmVsdGV0ZWxla2JlbiBlbG9pcnQgZWxsZW5vcnplc2kg -ZWxqYXJhcyBtZWd0ZXRlbGUuIEEgZG9rdW1lbnR1bW9rIG1lZ3RhbGFsaGF0b2sgYSBodHRwczov -L3d3dy5uZXRsb2NrLmh1L2RvY3MvIGNpbWVuIHZhZ3kga2VyaGV0b2sgYXogaW5mb0BuZXRsb2Nr -Lm5ldCBlLW1haWwgY2ltZW4uIFdBUk5JTkchIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0 -aGlzIGNlcnRpZmljYXRlIGFyZSBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIFF1YWxpZmllZCBDUFMg -YXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3Lm5ldGxvY2suaHUvZG9jcy8gb3IgYnkgZS1tYWlsIGF0 -IGluZm9AbmV0bG9jay5uZXQwHQYDVR0OBBYEFAlqYhaSsFq7VQ7LdTI6MuWyIckoMA0GCSqGSIb3 -DQEBBQUAA4IBAQCRalCc23iBmz+LQuM7/KbD7kPgz/PigDVJRXYC4uMvBcXxKufAQTPGtpvQMznN -wNuhrWw3AkxYQTvyl5LGSKjN5Yo5iWH5Upfpvfb5lHTocQ68d4bDBsxafEp+NFAwLvt/MpqNPfMg -W/hqyobzMUwsWYACff44yTB1HLdV47yfuqhthCgFdbOLDcCRVCHnpgu0mfVRQdzNo0ci2ccBgcTc -R08m6h/t280NmPSjnLRzMkqWmf68f8glWPhY83ZmiVSkpj7EUFy6iRiCdUgh0k8T6GB+B3bbELVR -5qq5aKrN9p2QdRLqOBrKROi3macqaJVmlaut74nLYKkGEsaUR+ko ------END CERTIFICATE----- - -NetLock Notary (Class A) Root -============================= ------BEGIN CERTIFICATE----- -MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI -EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 -dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j -ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX -DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH -EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD -VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz -cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM -D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ -z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC -/tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7 -tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6 -4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG -A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC -Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv -bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu -IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn -LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0 -ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz -IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh -IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu -b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh -bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg -Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp -bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5 -ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP -ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB -CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr -KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM -8CgHrTwXZoi1/baI ------END CERTIFICATE----- - -NetLock Business (Class B) Root -=============================== ------BEGIN CERTIFICATE----- -MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUxETAPBgNVBAcT -CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV -BAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQDEylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikg -VGFudXNpdHZhbnlraWFkbzAeFw05OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYD -VQQGEwJIVTERMA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRv -bnNhZ2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5ldExvY2sg -VXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB -iQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2S -o/1bXHQawEfKOml2mrriRBf8TKPV/riXiK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr -1nGTLbO/CVRY7QbrqHvcQ7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV -HQ8BAf8EBAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZ -RUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRh -dGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQuIEEgaGl0 -ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRv -c2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUg -YXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh -c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBz -Oi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6ZXNA -bmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhl -IHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2 -YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBj -cHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06sPgzTEdM -43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXan3BukxowOR0w2y7jfLKR -stE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKSNitjrFgBazMpUIaD8QFI ------END CERTIFICATE----- - -NetLock Express (Class C) Root -============================== ------BEGIN CERTIFICATE----- -MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUxETAPBgNVBAcT -CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV -BAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQDEytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBD -KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJ -BgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 -dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMrTmV0TG9j -ayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzANBgkqhkiG9w0BAQEFAAOB -jQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNAOoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3Z -W3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63 -euyucYT2BDMIJTLrdKwWRMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQw -DgYDVR0PAQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEWggJN -RklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0YWxhbm9zIFN6b2xn -YWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBB -IGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBOZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1i -aXp0b3NpdGFzYSB2ZWRpLiBBIGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0 -ZWxlIGF6IGVsb2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs -ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25sYXBqYW4gYSBo -dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kga2VyaGV0byBheiBlbGxlbm9y -emVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4gSU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5k -IHRoZSB1c2Ugb2YgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQ -UyBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwg -YXQgY3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmYta3UzbM2 -xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2gpO0u9f38vf5NNwgMvOOW -gyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4Fp1hBWeAyNDYpQcCNJgEjTME1A== ------END CERTIFICATE----- - -XRamp Global CA Root -==================== ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE -BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj -dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB -dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx -HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg -U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu -IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx -foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE -zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs -AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry -xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud -EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap -oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC -AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc -/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt -qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n -nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz -8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= ------END CERTIFICATE----- - -Go Daddy Class 2 CA -=================== ------BEGIN CERTIFICATE----- -MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY -VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG -A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g -RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD -ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv -2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 -qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j -YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY -vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O -BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o -atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu -MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG -A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim -PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt -I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ -HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI -Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b -vZ8= ------END CERTIFICATE----- - -Starfield Class 2 CA -==================== ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc -U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo -MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG -A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG -SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY -bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ -JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm -epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN -F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF -MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f -hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo -bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs -afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM -PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl -xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD -KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 -QBFGmh95DmK/D5fs4C8fF5Q= ------END CERTIFICATE----- - -StartCom Certification Authority -================================ ------BEGIN CERTIFICATE----- -MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN -U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu -ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 -NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk -LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg -U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw -ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y -o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ -Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d -eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt -2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z -6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ -osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ -untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc -UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT -37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE -FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0 -Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj -YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH -AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw -Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg -U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5 -LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl -cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh -cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT -dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC -AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh -3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm -vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk -fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3 -fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ -EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq -yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl -1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/ -lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro -g14= ------END CERTIFICATE----- - -Taiwan GRCA -=========== ------BEGIN CERTIFICATE----- -MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG -EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X -DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv -dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN -w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5 -BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O -1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO -htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov -J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7 -Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t -B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB -O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8 -lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV -HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2 -09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ -TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj -Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2 -Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU -D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz -DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk -Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk -7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ -CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy -+fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS ------END CERTIFICATE----- - -Firmaprofesional Root CA -======================== ------BEGIN CERTIFICATE----- -MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMxIjAgBgNVBAcT -GUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1dG9yaWRhZCBkZSBDZXJ0aWZp -Y2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FA -ZmlybWFwcm9mZXNpb25hbC5jb20wHhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTEL -MAkGA1UEBhMCRVMxIjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMT -OUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2 -ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20wggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5uCp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5V -j1H5WuretXDE7aTt/6MNbg9kUDGvASdYrv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJH -lShbz++AbOCQl4oBPB3zhxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf -3H5idPayBQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcLiam8 -NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcbAgMBAAGjgZ8wgZww -KgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lvbmFsLmNvbTASBgNVHRMBAf8ECDAG -AQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1Ud -DwEB/wQEAwIBBjAdBgNVHQ4EFgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQAD -ggEBAEdz/o0nVPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq -u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36mhoEyIwOdyPdf -wUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzflZKG+TQyTmAyX9odtsz/ny4Cm -7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBpQWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YG -VM+h4k0460tQtcsm9MracEpqoeJ5quGnM/b9Sh/22WA= ------END CERTIFICATE----- - -Wells Fargo Root CA -=================== ------BEGIN CERTIFICATE----- -MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCVVMxFDASBgNV -BAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhv -cml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN -MDAxMDExMTY0MTI4WhcNMjEwMTE0MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dl -bGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEv -MC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n135zHCLielTWi5MbqNQ1mX -x3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHESxP9cMIlrCL1dQu3U+SlK93OvRw6esP3 -E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4OJgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5 -OEL8pahbSCOz6+MlsoCultQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4j -sNtlAHCEAQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMBAAGj -YTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcBCzAyMDAGCCsGAQUF -BwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRwb2xpY3kwDQYJKoZIhvcNAQEFBQAD -ggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrv -m+0fazbuSCUlFLZWohDo7qd/0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0R -OhPs7fpvcmR7nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx -x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ33ZwmVxwQ023 -tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s= ------END CERTIFICATE----- - -Swisscom Root CA 1 -================== ------BEGIN CERTIFICATE----- -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 -NY6E0F/6MBr1mmz0DlP5OlvRHA== ------END CERTIFICATE----- - -DigiCert Assured ID Root CA -=========================== ------BEGIN CERTIFICATE----- -MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw -IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx -MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL -ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO -9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy -UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW -/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy -oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf -GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF -66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq -hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc -EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn -SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i -8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe -+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== ------END CERTIFICATE----- - -DigiCert Global Root CA -======================= ------BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw -HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw -MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 -dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn -TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 -BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H -4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y -7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB -o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm -8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF -BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr -EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt -tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 -UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ------END CERTIFICATE----- - -DigiCert High Assurance EV Root CA -================================== ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw -KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw -MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ -MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu -Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t -Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS -OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 -MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ -NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe -h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB -Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY -JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ -V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp -myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK -mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe -vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K ------END CERTIFICATE----- - -Certplus Class 2 Primary CA -=========================== ------BEGIN CERTIFICATE----- -MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE -BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN -OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy -dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR -5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ -Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO -YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e -e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME -CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ -YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t -L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD -P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R -TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+ -7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW -//1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 -l7+ijrRU ------END CERTIFICATE----- - -DST Root CA X3 -============== ------BEGIN CERTIFICATE----- -MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK -ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X -DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1 -cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT -rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9 -UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy -xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d -utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T -AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ -MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug -dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE -GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw -RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS -fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ ------END CERTIFICATE----- - -DST ACES CA X6 -============== ------BEGIN CERTIFICATE----- -MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG -EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT -MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha -MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE -CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI -DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa -pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow -GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy -MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu -Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy -dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU -CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2 -5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t -Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq -nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs -vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3 -oKfN5XozNmr6mis= ------END CERTIFICATE----- - -TURKTRUST Certificate Services Provider Root 1 -============================================== ------BEGIN CERTIFICATE----- -MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVTVCBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGDAJUUjEP -MA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0 -acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMx -MDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsg -U2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYDVQQHDAZB -TktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBC -aWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GX -yGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8i -Si9BB35JYbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ -8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4 -W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRME -BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46 -sWrv7/hg0Uw2ZkUd82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxE -q8Sn5RTOPEFhfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy -B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgY -nNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H ------END CERTIFICATE----- - -TURKTRUST Certificate Services Provider Root 2 -============================================== ------BEGIN CERTIFICATE----- -MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP -MA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg -QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcN -MDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVr -dHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEPMA0G -A1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls -acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqe -LCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKI -x+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2g -QrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr -5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMB -AAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8G -A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/ntt -Rbj2hWyfIvwqECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 -Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+ -hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P -9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5 -UrbnBEI= ------END CERTIFICATE----- - -SwissSign Platinum CA - G2 -========================== ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -SwissSign Gold CA - G2 -====================== ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -SwissSign Silver CA - G2 -======================== ------BEGIN CERTIFICATE----- -MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT -BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X -DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3 -aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG -9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644 -N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm -+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH -6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu -MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h -qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5 -FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs -ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc -celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X -CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB -tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 -cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P -4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F -kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L -3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx -/uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa -DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP -e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu -WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ -DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub -DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u ------END CERTIFICATE----- - -GeoTrust Primary Certification Authority -======================================== ------BEGIN CERTIFICATE----- -MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx -CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ -cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN -b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9 -nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge -RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt -tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI -hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K -Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN -NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa -Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG -1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= ------END CERTIFICATE----- - -thawte Primary Root CA -====================== ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE -BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 -aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv -cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3 -MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg -SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv -KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT -FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs -oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ -1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc -q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K -aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p -afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD -VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF -AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE -uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX -xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89 -jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH -z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA== ------END CERTIFICATE----- - -VeriSign Class 3 Public Primary Certification Authority - G5 -============================================================ ------BEGIN CERTIFICATE----- -MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE -BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO -ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk -IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln -biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh -dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz -j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD -Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/ -Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r -fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/ -BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv -Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy -aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG -SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+ -X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE -KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC -Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE -ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq ------END CERTIFICATE----- - -SecureTrust CA -============== ------BEGIN CERTIFICATE----- -MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG -EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy -dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe -BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC -ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX -OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t -DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH -GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b -01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH -ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ -BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj -aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ -KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu -SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf -mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ -nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR -3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= ------END CERTIFICATE----- - -Secure Global CA -================ ------BEGIN CERTIFICATE----- -MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG -EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH -bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg -MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg -Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx -YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ -bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g -8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV -HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi -0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud -EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn -oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA -MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ -OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn -CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 -3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc -f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW ------END CERTIFICATE----- - -COMODO Certification Authority -============================== ------BEGIN CERTIFICATE----- -MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE -BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG -A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 -dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb -MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD -T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH -+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww -xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV -4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA -1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI -rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k -b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC -AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP -OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ -RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc -IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN -+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== ------END CERTIFICATE----- - -Network Solutions Certificate Authority -======================================= ------BEGIN CERTIFICATE----- -MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG -EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr -IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx -MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu -MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx -jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT -aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT -crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc -/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB -AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP -BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv -bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA -A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q -4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ -GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv -wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD -ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey ------END CERTIFICATE----- - -WellsSecure Public Root Certificate Authority -============================================= ------BEGIN CERTIFICATE----- -MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM -F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw -NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN -MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl -bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD -VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1 -iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13 -i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8 -bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB -K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB -AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu -cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm -lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB -i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww -GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg -Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI -K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0 -bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj -qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es -E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ -tylv2G0xffX8oRAHh84vWdw+WNs= ------END CERTIFICATE----- - -COMODO ECC Certification Authority -================================== ------BEGIN CERTIFICATE----- -MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC -R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE -ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB -dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix -GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR -Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo -b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X -4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni -wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG -FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA -U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= ------END CERTIFICATE----- - -IGC/A -===== ------BEGIN CERTIFICATE----- -MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAkZSMQ8wDQYD -VQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVE -Q1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZy -MB4XDTAyMTIxMzE0MjkyM1oXDTIwMTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQI -EwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NT -STEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaIs9z4iPf930Pfeo2aSVz2 -TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCW -So7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYy -HF2fYPepraX/z9E0+X1bF8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNd -frGoRpAxVs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGdPDPQ -tQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNVHSAEDjAMMAoGCCqB -egF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAxNjAfBgNVHSMEGDAWgBSjBS8YYFDC -iQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUFAAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RK -q89toB9RlPhJy3Q2FLwV3duJL92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3Q -MZsyK10XZZOYYLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg -Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2aNjSaTFR+FwNI -lQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R0982gaEbeC9xs/FZTEYYKKuF -0mBWWg== ------END CERTIFICATE----- - -Security Communication EV RootCA1 -================================= ------BEGIN CERTIFICATE----- -MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc -U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh -dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE -BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl -Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO -/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX -WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z -ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4 -bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK -9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG -SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm -iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG -Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW -mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW -T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 ------END CERTIFICATE----- - -OISTE WISeKey Global Root GA CA -=============================== ------BEGIN CERTIFICATE----- -MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE -BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG -A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH -bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD -VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw -IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5 -IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9 -Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg -Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD -d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ -/yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R -LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ -KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm -MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4 -+vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa -hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY -okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0= ------END CERTIFICATE----- - -S-TRUST Authentication and Encryption Root CA 2005 PN -===================================================== ------BEGIN CERTIFICATE----- -MIIEezCCA2OgAwIBAgIQNxkY5lNUfBq1uMtZWts1tzANBgkqhkiG9w0BAQUFADCBrjELMAkGA1UE -BhMCREUxIDAeBgNVBAgTF0JhZGVuLVd1ZXJ0dGVtYmVyZyAoQlcpMRIwEAYDVQQHEwlTdHV0dGdh -cnQxKTAnBgNVBAoTIERldXRzY2hlciBTcGFya2Fzc2VuIFZlcmxhZyBHbWJIMT4wPAYDVQQDEzVT -LVRSVVNUIEF1dGhlbnRpY2F0aW9uIGFuZCBFbmNyeXB0aW9uIFJvb3QgQ0EgMjAwNTpQTjAeFw0w -NTA2MjIwMDAwMDBaFw0zMDA2MjEyMzU5NTlaMIGuMQswCQYDVQQGEwJERTEgMB4GA1UECBMXQmFk -ZW4tV3VlcnR0ZW1iZXJnIChCVykxEjAQBgNVBAcTCVN0dXR0Z2FydDEpMCcGA1UEChMgRGV1dHNj -aGVyIFNwYXJrYXNzZW4gVmVybGFnIEdtYkgxPjA8BgNVBAMTNVMtVFJVU1QgQXV0aGVudGljYXRp -b24gYW5kIEVuY3J5cHRpb24gUm9vdCBDQSAyMDA1OlBOMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEA2bVKwdMz6tNGs9HiTNL1toPQb9UY6ZOvJ44TzbUlNlA0EmQpoVXhOmCTnijJ4/Ob -4QSwI7+Vio5bG0F/WsPoTUzVJBY+h0jUJ67m91MduwwA7z5hca2/OnpYH5Q9XIHV1W/fuJvS9eXL -g3KSwlOyggLrra1fFi2SU3bxibYs9cEv4KdKb6AwajLrmnQDaHgTncovmwsdvs91DSaXm8f1Xgqf -eN+zvOyauu9VjxuapgdjKRdZYgkqeQd3peDRF2npW932kKvimAoA0SVtnteFhy+S8dF2g08LOlk3 -KC8zpxdQ1iALCvQm+Z845y2kuJuJja2tyWp9iRe79n+Ag3rm7QIDAQABo4GSMIGPMBIGA1UdEwEB -/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMCkGA1UdEQQiMCCkHjAcMRowGAYDVQQDExFTVFJv -bmxpbmUxLTIwNDgtNTAdBgNVHQ4EFgQUD8oeXHngovMpttKFswtKtWXsa1IwHwYDVR0jBBgwFoAU -D8oeXHngovMpttKFswtKtWXsa1IwDQYJKoZIhvcNAQEFBQADggEBAK8B8O0ZPCjoTVy7pWMciDMD -pwCHpB8gq9Yc4wYfl35UvbfRssnV2oDsF9eK9XvCAPbpEW+EoFolMeKJ+aQAPzFoLtU96G7m1R08 -P7K9n3frndOMusDXtk3sU5wPBG7qNWdX4wple5A64U8+wwCSersFiXOMy6ZNwPv2AtawB6MDwidA -nwzkhYItr5pCHdDHjfhA7p0GVxzZotiAFP7hYy0yh9WUUpY6RsZxlj33mA6ykaqP2vROJAA5Veit -F7nTNCtKqUDMFypVZUF0Qn71wK/Ik63yGFs9iQzbRzkk+OBM8h+wPQrKBU6JIRrjKpms/H+h8Q8b -Hz2eBIPdltkdOpQ= ------END CERTIFICATE----- - -Microsec e-Szigno Root CA -========================= ------BEGIN CERTIFICATE----- -MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE -BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL -EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0 -MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz -dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT -GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG -d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N -oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc -QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ -PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb -MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG -IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD -VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3 -LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A -dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn -AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA -4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg -AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA -egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6 -Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO -PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv -c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h -cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw -IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT -WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV -MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER -MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp -Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal -HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT -nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE -aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a -86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK -yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB -S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= ------END CERTIFICATE----- - -Certigna -======== ------BEGIN CERTIFICATE----- -MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw -EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 -MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI -Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q -XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH -GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p -ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg -DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf -Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ -tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ -BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J -SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA -hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ -ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu -PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY -1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw -WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== ------END CERTIFICATE----- - -AC Ra\xC3\xADz Certic\xC3\xA1mara S.A. -====================================== ------BEGIN CERTIFICATE----- -MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNVBAYT -AkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRpZmljYWNpw7NuIERpZ2l0YWwg -LSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwaQUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4w -HhcNMDYxMTI3MjA0NjI5WhcNMzAwNDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+ -U29jaWVkYWQgQ2FtZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJh -IFMuQS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkqhkiG9w0B -AQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeGqentLhM0R7LQcNzJPNCN -yu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzLfDe3fezTf3MZsGqy2IiKLUV0qPezuMDU -2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQY5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU3 -4ojC2I+GdV75LaeHM/J4Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP -2yYe68yQ54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+bMMCm -8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48jilSH5L887uvDdUhf -HjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++EjYfDIJss2yKHzMI+ko6Kh3VOz3vCa -Mh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/ztA/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK -5lw1omdMEWux+IBkAC1vImHFrEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1b -czwmPS9KvqfJpxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE -AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCBlTCBkgYEVR0g -ADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFyYS5jb20vZHBjLzBaBggrBgEF -BQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW507WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2Ug -cHVlZGVuIGVuY29udHJhciBlbiBsYSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEf -AygPU3zmpFmps4p6xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuX -EpBcunvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/Jre7Ir5v -/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dpezy4ydV/NgIlqmjCMRW3 -MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42gzmRkBDI8ck1fj+404HGIGQatlDCIaR4 -3NAvO2STdPCWkPHv+wlaNECW8DYSwaN0jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wk -eZBWN7PGKX6jD/EpOe9+XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f -/RWmnkJDW2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/RL5h -RqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35rMDOhYil/SrnhLecU -Iw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxkBYn8eNZcLCZDqQ== ------END CERTIFICATE----- - -TC TrustCenter Class 2 CA II -============================ ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC -REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy -IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw -MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 -c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE -AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw -IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2 -xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ -Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u -SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB -7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 -Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU -cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i -SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G -dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ -KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj -TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP -JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk -vQ== ------END CERTIFICATE----- - -TC TrustCenter Class 3 CA II -============================ ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC -REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy -IENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYw -MTEyMTQ0MTU3WhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 -c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UE -AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJWHt4bNwcwIi9v8Qbxq63W -yKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+QVl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo -6SI7dYnWRBpl8huXJh0obazovVkdKyT21oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZ -uV3bOx4a+9P/FRQI2AlqukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk -2ZyqBwi1Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NXXAek0CSnwPIA1DCB -7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 -Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU -cnVzdENlbnRlciUyMENsYXNzJTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i -SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlNirTzwppVMXzE -O2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8TtXqluJucsG7Kv5sbviRmEb8 -yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9 -IJqDnxrcOfHFcqMRA/07QlIp2+gB95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal -092Y+tTmBvTwtiBjS+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc -5A== ------END CERTIFICATE----- - -TC TrustCenter Universal CA I -============================= ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC -REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy -IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN -MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg -VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw -JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC -qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv -xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw -ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O -gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j -BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG -1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy -vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3 -ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT -ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a -7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY ------END CERTIFICATE----- - -Deutsche Telekom Root CA 2 -========================== ------BEGIN CERTIFICATE----- -MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT -RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG -A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5 -MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G -A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS -b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5 -bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI -KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY -AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK -Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV -jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV -HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr -E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy -zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8 -rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G -dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU -Cm26OWMohpLzGITY+9HPBVZkVw== ------END CERTIFICATE----- - -ComSign CA -========== ------BEGIN CERTIFICATE----- -MIIDkzCCAnugAwIBAgIQFBOWgxRVjOp7Y+X8NId3RDANBgkqhkiG9w0BAQUFADA0MRMwEQYDVQQD -EwpDb21TaWduIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0wNDAzMjQxMTMy -MThaFw0yOTAzMTkxNTAyMThaMDQxEzARBgNVBAMTCkNvbVNpZ24gQ0ExEDAOBgNVBAoTB0NvbVNp -Z24xCzAJBgNVBAYTAklMMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8ORUaSvTx49q -ROR+WCf4C9DklBKK8Rs4OC8fMZwG1Cyn3gsqrhqg455qv588x26i+YtkbDqthVVRVKU4VbirgwTy -P2Q298CNQ0NqZtH3FyrV7zb6MBBC11PN+fozc0yz6YQgitZBJzXkOPqUm7h65HkfM/sb2CEJKHxN -GGleZIp6GZPKfuzzcuc3B1hZKKxC+cX/zT/npfo4sdAMx9lSGlPWgcxCejVb7Us6eva1jsz/D3zk -YDaHL63woSV9/9JLEYhwVKZBqGdTUkJe5DSe5L6j7KpiXd3DTKaCQeQzC6zJMw9kglcq/QytNuEM -rkvF7zuZ2SOzW120V+x0cAwqTwIDAQABo4GgMIGdMAwGA1UdEwQFMAMBAf8wPQYDVR0fBDYwNDAy -oDCgLoYsaHR0cDovL2ZlZGlyLmNvbXNpZ24uY28uaWwvY3JsL0NvbVNpZ25DQS5jcmwwDgYDVR0P -AQH/BAQDAgGGMB8GA1UdIwQYMBaAFEsBmz5WGmU2dst7l6qSBe4y5ygxMB0GA1UdDgQWBBRLAZs+ -VhplNnbLe5eqkgXuMucoMTANBgkqhkiG9w0BAQUFAAOCAQEA0Nmlfv4pYEWdfoPPbrxHbvUanlR2 -QnG0PFg/LUAlQvaBnPGJEMgOqnhPOAlXsDzACPw1jvFIUY0McXS6hMTXcpuEfDhOZAYnKuGntewI -mbQKDdSFc8gS4TXt8QUxHXOZDOuWyt3T5oWq8Ir7dcHyCTxlZWTzTNity4hp8+SDtwy9F1qWF8pb -/627HOkthIDYIb6FUtnUdLlphbpN7Sgy6/lhSuTENh4Z3G+EER+V9YMoGKgzkkMn3V0TBEVPh9VG -zT2ouvDzuFYkRes3x+F2T3I5GN9+dHLHcy056mDmrRGiVod7w2ia/viMcKjfZTL0pECMocJEAw6U -AGegcQCCSA== ------END CERTIFICATE----- - -ComSign Secured CA -================== ------BEGIN CERTIFICATE----- -MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE -AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w -NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD -QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs -49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH -7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB -kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1 -9guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw -AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t -U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA -j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC -AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a -BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp -FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP -51qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz -OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== ------END CERTIFICATE----- - -Cybertrust Global Root -====================== ------BEGIN CERTIFICATE----- -MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li -ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4 -MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD -ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA -+Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW -0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL -AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin -89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT -8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP -BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2 -MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G -A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO -lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi -5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2 -hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T -X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW -WL1WMRJOEcgh4LMRkWXbtKaIOM5V ------END CERTIFICATE----- - -ePKI Root Certification Authority -================================= ------BEGIN CERTIFICATE----- -MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG -EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg -Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx -MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq -MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B -AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs -IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi -lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv -qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX -12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O -WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ -ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao -lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ -vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi -Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi -MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH -ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 -1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq -KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV -xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP -NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r -GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE -xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx -gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy -sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD -BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= ------END CERTIFICATE----- - -T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3 -============================================================================================================================= ------BEGIN CERTIFICATE----- -MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH -DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q -aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry -b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV -BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg -S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4 -MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl -IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF -n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl -IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft -dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl -cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO -Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1 -xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR -6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL -hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd -BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF -MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4 -N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT -y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh -LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M -dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI= ------END CERTIFICATE----- - -Buypass Class 2 CA 1 -==================== ------BEGIN CERTIFICATE----- -MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAxMB4XDTA2 -MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh -c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7M -cXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLXl18xoS83 -0r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVBHfCuuCkslFJgNJQ72uA4 -0Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/R -uFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0P -AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV -1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt -7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2 -fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w -wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho ------END CERTIFICATE----- - -Buypass Class 3 CA 1 -==================== ------BEGIN CERTIFICATE----- -MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1 -MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh -c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx -ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0 -n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia -AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c -1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P -AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7 -pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA -EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5 -htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj -el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 ------END CERTIFICATE----- - -EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 -========================================================================== ------BEGIN CERTIFICATE----- -MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNVBAMML0VCRyBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMTcwNQYDVQQKDC5FQkcg -QmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXptZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAe -Fw0wNjA4MTcwMDIxMDlaFw0xNjA4MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25p -ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2lt -IFRla25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h4fuXd7hxlugTlkaDT7by -X3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAktiHq6yOU/im/+4mRDGSaBUorzAzu8T2b -gmmkTPiab+ci2hC6X5L8GCcKqKpE+i4stPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfr -eYteIAbTdgtsApWjluTLdlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZ -TqNGFav4c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8UmTDGy -Y5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z+kI2sSXFCjEmN1Zn -uqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0OLna9XvNRiYuoP1Vzv9s6xiQFlpJI -qkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMWOeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vm -ExH8nYQKE3vwO9D8owrXieqWfo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0 -Nokb+Clsi7n2l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB -/wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgwFoAU587GT/wW -Z5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+8ygjdsZs93/mQJ7ANtyVDR2t -FcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgm -zJNSroIBk5DKd8pNSe/iWtkqvTDOTLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64k -XPBfrAowzIpAoHMEwfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqT -bCmYIai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJnxk1Gj7sU -RT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4QDgZxGhBM/nV+/x5XOULK -1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9qKd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt -2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11thie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQ -Y9iJSrSq3RZj9W6+YKH47ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9 -AahH3eU7QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT ------END CERTIFICATE----- - -certSIGN ROOT CA -================ ------BEGIN CERTIFICATE----- -MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD -VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa -Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE -CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I -JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH -rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 -ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD -0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 -AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B -Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB -AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 -SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 -x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt -vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz -TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD ------END CERTIFICATE----- - -CNNIC ROOT -========== ------BEGIN CERTIFICATE----- -MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE -ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw -OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD -o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz -VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT -VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or -czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK -y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC -wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S -lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5 -Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM -O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8 -BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2 -G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m -mxE= ------END CERTIFICATE----- - -ApplicationCA - Japanese Government -=================================== ------BEGIN CERTIFICATE----- -MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT -SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw -MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl -cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4 -fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN -wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE -jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu -nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU -WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV -BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD -vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs -o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g -/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD -io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW -dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL -rosot4LKGAfmt1t06SAZf7IbiVQ= ------END CERTIFICATE----- - -GeoTrust Primary Certification Authority - G3 -============================================= ------BEGIN CERTIFICATE----- -MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE -BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0 -IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy -eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz -NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo -YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT -LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j -K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE -c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C -IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu -dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr -2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9 -cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE -Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD -AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s -t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt ------END CERTIFICATE----- - -thawte Primary Root CA - G2 -=========================== ------BEGIN CERTIFICATE----- -MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC -VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu -IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg -Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV -MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG -b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt -IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS -LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5 -8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU -mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN -G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K -rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== ------END CERTIFICATE----- - -thawte Primary Root CA - G3 -=========================== ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE -BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 -aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv -cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w -ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh -d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD -VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG -A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At -P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC -+BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY -7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW -vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ -KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK -A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu -t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC -8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm -er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A= ------END CERTIFICATE----- - -GeoTrust Primary Certification Authority - G2 -============================================= ------BEGIN CERTIFICATE----- -MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu -Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1 -OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg -MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl -b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG -BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc -KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD -VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+ -EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m -ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2 -npaqBA+K ------END CERTIFICATE----- - -VeriSign Universal Root Certification Authority -=============================================== ------BEGIN CERTIFICATE----- -MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE -BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO -ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk -IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u -IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV -UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv -cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj -1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP -MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72 -9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I -AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR -tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G -CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O -a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud -DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3 -Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx -Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx -P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P -wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4 -mJO37M2CYfE45k+XmCpajQ== ------END CERTIFICATE----- - -VeriSign Class 3 Public Primary Certification Authority - G4 -============================================================ ------BEGIN CERTIFICATE----- -MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC -VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3 -b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz -ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU -cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo -b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5 -IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8 -Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz -rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB -/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw -HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u -Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD -A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx -AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== ------END CERTIFICATE----- - -NetLock Arany (Class Gold) Főtanúsítvány -============================================ ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G -A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 -dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB -cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx -MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO -ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 -c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu -0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw -/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk -H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw -fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 -neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW -qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta -YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC -bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna -NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu -dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= ------END CERTIFICATE----- - -Staat der Nederlanden Root CA - G2 -================================== ------BEGIN CERTIFICATE----- -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 -66+KAQ== ------END CERTIFICATE----- - -CA Disig -======== ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK -QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw -MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz -bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm -GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD -Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo -hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt -ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w -gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P -AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz -aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff -ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa -BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t -WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3 -mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ -CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K -ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA -4Z7CRneC9VkGjCFMhwnN5ag= ------END CERTIFICATE----- - -Juur-SK -======= ------BEGIN CERTIFICATE----- -MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcNAQkBFglwa2lA -c2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMRAw -DgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMwMVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqG -SIb3DQEJARYJcGtpQHNrLmVlMQswCQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVy -aW1pc2tlc2t1czEQMA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOBSvZiF3tf -TQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkzABpTpyHhOEvWgxutr2TC -+Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvHLCu3GFH+4Hv2qEivbDtPL+/40UceJlfw -UR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMPPbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDa -Tpxt4brNj3pssAki14sL2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQF -MAMBAf8wggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwICMIHD -HoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDkAGwAagBhAHMAdABh -AHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0AHMAZQBlAHIAaQBtAGkAcwBrAGUA -cwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABzAGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABr -AGkAbgBuAGkAdABhAG0AaQBzAGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nw -cy8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE -FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcYP2/v6X2+MA4G -A1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOiCfP+JmeaUOTDBS8rNXiRTHyo -ERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+gkcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyL -abVAyJRld/JXIWY7zoVAtjNjGr95HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678 -IIbsSt4beDI3poHSna9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkh -Mp6qqIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0ZTbvGRNs2 -yyqcjg== ------END CERTIFICATE----- - -Hongkong Post Root CA 1 -======================= ------BEGIN CERTIFICATE----- -MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT -DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx -NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n -IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 -ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr -auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh -qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY -V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV -HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i -h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio -l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei -IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps -T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT -c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== ------END CERTIFICATE----- - -SecureSign RootCA11 -=================== ------BEGIN CERTIFICATE----- -MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi -SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS -b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw -KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 -cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL -TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO -wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq -g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP -O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA -bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX -t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh -OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r -bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ -Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 -y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 -lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= ------END CERTIFICATE----- - -ACEDICOM Root -============= ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -Verisign Class 1 Public Primary Certification Authority -======================================================= ------BEGIN CERTIFICATE----- -MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx -FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmltYXJ5 -IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow -XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAx -IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA -A4GNADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0fzGVuDLDQ -VoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHiTkVWaR94AoDa3EeRKbs2 -yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFgVKTk8d6Pa -XCUDfGD67gmZPCcQcMgMCeazh88K4hiWNWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n -0a3hUKw8fGJLj7qE1xIVGx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZ -RjXZ+Hxb ------END CERTIFICATE----- - -Verisign Class 3 Public Primary Certification Authority -======================================================= ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx -FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5 -IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow -XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz -IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA -A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94 -f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol -hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBABByUqkFFBky -CEHwxWsKzH4PIRnN5GfcX6kb5sroc50i2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWX -bj9T/UWZYB2oK0z5XqcJ2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/ -D/xwzoiQ ------END CERTIFICATE----- - -Microsec e-Szigno Root CA 2009 -============================== ------BEGIN CERTIFICATE----- -MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER -MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv -c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o -dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE -BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt -U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA -fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG -0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA -pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm -1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC -AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf -QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE -FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o -lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX -I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 -tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 -yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi -LXpUq3DDfSJlgnCW ------END CERTIFICATE----- - -E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi -=================================================== ------BEGIN CERTIFICATE----- -MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG -EwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE8MDoGA1UEAxMz -ZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3 -MDEwNDExMzI0OFoXDTE3MDEwNDExMzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0 -cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9u -aWsgU2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdUMZTe1RK6UxYC6lhj71vY -8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlTL/jDj/6z/P2douNffb7tC+Bg62nsM+3Y -jfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAI -JjjcJRFHLfO6IxClv7wC90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk -9Ok0oSy1c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/BAQD -AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoEVtstxNulMA0GCSqG -SIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLPqk/CaOv/gKlR6D1id4k9CnU58W5d -F4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwq -D2fK/A+JYZ1lpTzlvBNbCNvj/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4 -Vwpm+Vganf2XKWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq -fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX ------END CERTIFICATE----- - -GlobalSign Root CA - R3 -======================= ------BEGIN CERTIFICATE----- -MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv -YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh -bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT -aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln -bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt -iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ -0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 -rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl -OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 -xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE -FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 -lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 -EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E -bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 -YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r -kpeDMdmztcpHWD9f ------END CERTIFICATE----- - -TC TrustCenter Universal CA III -=============================== ------BEGIN CERTIFICATE----- -MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezELMAkGA1UEBhMC -REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy -IFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAe -Fw0wOTA5MDkwODE1MjdaFw0yOTEyMzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNU -QyBUcnVzdENlbnRlciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0Ex -KDAmBgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF5+cvAqBNLaT6hdqbJYUt -QCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYvDIRlzg9uwliT6CwLOunBjvvya8o84pxO -juT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8vzArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+Eut -CHnNaYlAJ/Uqwa1D7KRTyGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1 -M4BDj5yjdipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBhMB8G -A1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI4jANBgkqhkiG9w0BAQUFAAOCAQEA -g8ev6n9NCjw5sWi+e22JLumzCecYV42FmhfzdkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+ -KGwWaODIl0YgoGhnYIg5IFHYaAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhK -BgePxLcHsU0GDeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV -CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPHLQNjO9Po5KIq -woIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg== ------END CERTIFICATE----- - -Autoridad de Certificacion Firmaprofesional CIF A62634068 -========================================================= ------BEGIN CERTIFICATE----- -MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA -BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 -MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw -QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB -NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD -Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P -B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY -7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH -ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI -plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX -MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX -LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK -bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU -vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud -EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH -DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp -cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA -bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx -ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx -51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk -R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP -T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f -Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl -osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR -crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR -saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD -KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi -6Et8Vcad+qMUu2WFbm5PEn4KPJ2V ------END CERTIFICATE----- - -Izenpe.com -========== ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -Chambers of Commerce Root - 2008 -================================ ------BEGIN CERTIFICATE----- -MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD -MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv -bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu -QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy -Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl -ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF -EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl -cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA -XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj -h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/ -ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk -NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g -D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331 -lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ -0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj -ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2 -EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI -G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ -BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh -bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh -bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC -CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH -AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1 -wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH -3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU -RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6 -M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1 -YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF -9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK -zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG -nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg -OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ ------END CERTIFICATE----- - -Global Chambersign Root - 2008 -============================== ------BEGIN CERTIFICATE----- -MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD -MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv -bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu -QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx -NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg -Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ -QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD -aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf -VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf -XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0 -ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB -/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA -TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M -H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe -Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF -HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh -wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB -AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT -BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE -BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm -aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm -aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp -1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0 -dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG -/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6 -ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s -dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg -9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH -foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du -qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr -P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq -c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z -09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B ------END CERTIFICATE----- - -Go Daddy Root Certificate Authority - G2 -======================================== ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT -B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu -MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 -MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 -b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G -A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq -9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD -+qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd -fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl -NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 -BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac -vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r -5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV -N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO -LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 ------END CERTIFICATE----- - -Starfield Root Certificate Authority - G2 -========================================= ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT -B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s -b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 -eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw -DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg -VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB -dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv -W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs -bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk -N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf -ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU -JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol -TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx -4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw -F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K -pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ -c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 ------END CERTIFICATE----- - -Starfield Services Root Certificate Authority - G2 -================================================== ------BEGIN CERTIFICATE----- -MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT -B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s -b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl -IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT -dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg -Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 -h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa -hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP -LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB -rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG -SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP -E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy -xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd -iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza -YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 ------END CERTIFICATE----- - -AffirmTrust Commercial -====================== ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS -BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw -MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly -bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb -DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV -C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 -BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww -MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV -HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG -hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi -qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv -0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh -sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= ------END CERTIFICATE----- - -AffirmTrust Networking -====================== ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS -BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw -MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly -bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE -Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI -dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 -/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb -h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV -HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu -UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 -12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 -WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 -/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= ------END CERTIFICATE----- - -AffirmTrust Premium -=================== ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS -BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy -OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy -dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A -MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn -BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV -5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs -+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd -GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R -p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI -S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 -6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 -/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo -+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv -MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg -Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC -6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S -L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK -+4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV -BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg -IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 -g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb -zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== ------END CERTIFICATE----- - -AffirmTrust Premium ECC -======================= ------BEGIN CERTIFICATE----- -MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV -BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx -MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U -cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA -IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ -N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW -BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK -BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X -57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM -eQ== ------END CERTIFICATE----- - -Certum Trusted Network CA -========================= ------BEGIN CERTIFICATE----- -MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK -ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy -MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU -ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC -l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J -J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 -fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 -cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB -Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw -DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj -jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 -mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj -Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI -03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= ------END CERTIFICATE----- - -Certinomis - Autorité Racine -============================= ------BEGIN CERTIFICATE----- -MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK -Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg -LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG -A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw -JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa -wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly -Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw -2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N -jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q -c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC -lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb -xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g -530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna -4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G -A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ -KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x -WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva -R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40 -nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B -CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv -JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE -qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b -WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE -wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/ -vgt2Fl43N+bYdJeimUV5 ------END CERTIFICATE----- - -Root CA Generalitat Valenciana -============================== ------BEGIN CERTIFICATE----- -MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJFUzEfMB0GA1UE -ChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290 -IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcNMDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3 -WjBoMQswCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UE -CxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+WmmmO3I2 -F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKjSgbwJ/BXufjpTjJ3Cj9B -ZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGlu6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQ -D0EbtFpKd71ng+CT516nDOeB0/RSrFOyA8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXte -JajCq+TA81yc477OMUxkHl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMB -AAGjggM7MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBraS5n -dmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIICIwYKKwYBBAG/VQIB -ADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBl -AHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIAYQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIA -YQBsAGkAdABhAHQAIABWAGEAbABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQBy -AGEAYwBpAPMAbgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA -aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMAaQBvAG4AYQBt -AGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQAZQAgAEEAdQB0AG8AcgBpAGQA -YQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBu -AHQAcgBhACAAZQBuACAAbABhACAAZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAA -OgAvAC8AdwB3AHcALgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0 -dHA6Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+yeAT8MIGV -BgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQswCQYDVQQGEwJFUzEfMB0G -A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5S -b290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRh -TvW1yEICKrNcda3FbcrnlD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdz -Ckj+IHLtb8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg9J63 -NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XFducTZnV+ZfsBn5OH -iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt -+GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= ------END CERTIFICATE----- - -A-Trust-nQual-03 -================ ------BEGIN CERTIFICATE----- -MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYGA1UE -Cgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy -a2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5R -dWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgw -RgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0 -ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMMEEEtVHJ1 -c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtPWFuA/OQO8BBC4SA -zewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUjlUC5B3ilJfYKvUWG6Nm9wASOhURh73+n -yfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPE -SU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4 -iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3V -cuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdV -eRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40 -ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmr -sQd7TZjTXLDR8KdCoLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZd -JXDRZslo+S4RFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS -mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6 -ahq97BvIxYSazQ== ------END CERTIFICATE----- - -TWCA Root Certification Authority -================================= ------BEGIN CERTIFICATE----- -MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ -VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG -EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB -IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx -QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC -oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP -4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r -y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG -9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC -mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW -QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY -T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny -Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== ------END CERTIFICATE----- - -Security Communication RootCA2 -============================== ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc -U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh -dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC -SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy -aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ -+T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R -3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV -spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K -EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 -QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB -CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj -u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk -3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q -tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 -mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 ------END CERTIFICATE----- - -EC-ACC -====== ------BEGIN CERTIFICATE----- -MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE -BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w -ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD -VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE -CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT -BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7 -MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt -SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl -Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh -cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK -w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT -ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4 -HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a -E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw -0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD -VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0 -Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l -dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ -lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa -Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe -l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2 -E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D -5EI= ------END CERTIFICATE----- - -Hellenic Academic and Research Institutions RootCA 2011 -======================================================= ------BEGIN CERTIFICATE----- -MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT -O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y -aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z -IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT -AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z -IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo -IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI -1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa -71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u -8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH -3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/ -MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8 -MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu -b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt -XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 -TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD -/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N -7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4 ------END CERTIFICATE----- - -Actalis Authentication Root CA -============================== ------BEGIN CERTIFICATE----- -MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM -BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE -AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky -MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz -IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 -IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ -wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa -by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6 -zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f -YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2 -oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l -EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7 -hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8 -EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5 -jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY -iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt -ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI -WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0 -JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx -K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+ -Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC -4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo -2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz -lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem -OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9 -vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== ------END CERTIFICATE----- - -Trustis FPS Root CA -=================== ------BEGIN CERTIFICATE----- -MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG -EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290 -IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV -BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ -RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk -H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa -cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt -o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA -AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd -BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c -GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC -yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P -8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV -l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl -iB6XzCGcKQENZetX2fNXlrtIzYE= ------END CERTIFICATE----- - -StartCom Certification Authority -================================ ------BEGIN CERTIFICATE----- -MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN -U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu -ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 -NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk -LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg -U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw -ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y -o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ -Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d -eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt -2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z -6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ -osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ -untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc -UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT -37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD -VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ -Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0 -dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu -c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv -bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0 -aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0 -aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t -L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG -cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5 -fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm -N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN -Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T -tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX -e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA -2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs -HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE -JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib -D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8= ------END CERTIFICATE----- - -StartCom Certification Authority G2 -=================================== ------BEGIN CERTIFICATE----- -MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN -U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE -ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O -o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG -4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi -Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul -Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs -O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H -vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L -nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS -FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa -z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ -KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K -2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk -J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+ -JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG -/+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc -nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld -blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc -l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm -7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm -obp573PYtlNXLfbQ4ddI ------END CERTIFICATE----- - -Buypass Class 2 Root CA -======================= ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X -DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 -eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw -DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 -g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn -9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b -/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU -CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff -awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI -zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn -Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX -Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs -M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF -AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s -A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI -osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S -aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd -DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD -LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 -oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC -wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS -CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN -rJgWVqA= ------END CERTIFICATE----- - -Buypass Class 3 Root CA -======================= ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X -DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 -eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw -DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH -sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR -5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh -7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ -ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH -2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV -/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ -RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA -Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq -j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF -AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV -cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G -uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG -Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 -ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 -KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz -6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug -UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe -eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi -Cp/HuZc= ------END CERTIFICATE----- - -T-TeleSec GlobalRoot Class 3 -============================ ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM -IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU -cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx -MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz -dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD -ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK -9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU -NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF -iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W -0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr -AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb -fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT -ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h -P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml -e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== ------END CERTIFICATE----- - -EE Certification Centre Root CA -=============================== ------BEGIN CERTIFICATE----- -MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG -EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy -dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw -MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB -UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy -ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB -DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM -TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2 -rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw -93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN -P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T -AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ -MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF -BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj -xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM -lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u -uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU -3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM -dcGWxZ0= ------END CERTIFICATE----- diff --git a/awx/lib/site-packages/pip/cmdoptions.py b/awx/lib/site-packages/pip/cmdoptions.py index 4bf910cfdc..8ed3d91fc6 100644 --- a/awx/lib/site-packages/pip/cmdoptions.py +++ b/awx/lib/site-packages/pip/cmdoptions.py @@ -1,6 +1,15 @@ -"""shared options and groups""" -from optparse import make_option, OptionGroup -from pip.locations import build_prefix +""" +shared options and groups + +The principle here is to define options once, but *not* instantiate them globally. +One reason being that options with action='append' can carry state between parses. +pip parse's general options twice internally, and shouldn't pass on state. +To be consistent, all options will follow this design. + +""" +import copy +from optparse import OptionGroup, SUPPRESS_HELP, Option +from pip.locations import build_prefix, default_log_file def make_option_group(group, parser): @@ -11,21 +20,147 @@ def make_option_group(group, parser): """ option_group = OptionGroup(parser, group['name']) for option in group['options']: - option_group.add_option(option) + option_group.add_option(option.make()) return option_group +class OptionMaker(object): + """Class that stores the args/kwargs that would be used to make an Option, + for making them later, and uses deepcopy's to reset state.""" + def __init__(self, *args, **kwargs): + self.args = args + self.kwargs = kwargs + def make(self): + args_copy = copy.deepcopy(self.args) + kwargs_copy = copy.deepcopy(self.kwargs) + return Option(*args_copy, **kwargs_copy) + ########### # options # ########### -index_url = make_option( +help_ = OptionMaker( + '-h', '--help', + dest='help', + action='help', + help='Show help.') + +require_virtualenv = OptionMaker( + # Run only if inside a virtualenv, bail if not. + '--require-virtualenv', '--require-venv', + dest='require_venv', + action='store_true', + default=False, + help=SUPPRESS_HELP) + +verbose = OptionMaker( + '-v', '--verbose', + dest='verbose', + action='count', + default=0, + help='Give more output. Option is additive, and can be used up to 3 times.') + +version = OptionMaker( + '-V', '--version', + dest='version', + action='store_true', + help='Show version and exit.') + +quiet = OptionMaker( + '-q', '--quiet', + dest='quiet', + action='count', + default=0, + help='Give less output.') + +log = OptionMaker( + '--log', + dest='log', + metavar='path', + help='Path to a verbose appending log. This log is inactive by default.') + +log_explicit_levels = OptionMaker( + # Writes the log levels explicitely to the log' + '--log-explicit-levels', + dest='log_explicit_levels', + action='store_true', + default=False, + help=SUPPRESS_HELP) + +log_file = OptionMaker( + # The default log file + '--log-file', '--local-log', + dest='log_file', + metavar='path', + default=default_log_file, + help='Path to a verbose non-appending log, that only logs failures. This log is active by default at %default.') + +no_input = OptionMaker( + # Don't ask for input + '--no-input', + dest='no_input', + action='store_true', + default=False, + help=SUPPRESS_HELP) + +proxy = OptionMaker( + '--proxy', + dest='proxy', + type='str', + default='', + help="Specify a proxy in the form [user:passwd@]proxy.server:port.") + +timeout = OptionMaker( + '--timeout', '--default-timeout', + metavar='sec', + dest='timeout', + type='float', + default=15, + help='Set the socket timeout (default %default seconds).') + +default_vcs = OptionMaker( + # The default version control system for editables, e.g. 'svn' + '--default-vcs', + dest='default_vcs', + type='str', + default='', + help=SUPPRESS_HELP) + +skip_requirements_regex = OptionMaker( + # A regex to be used to skip requirements + '--skip-requirements-regex', + dest='skip_requirements_regex', + type='str', + default='', + help=SUPPRESS_HELP) + +exists_action = OptionMaker( + # Option when path already exist + '--exists-action', + dest='exists_action', + type='choice', + choices=['s', 'i', 'w', 'b'], + default=[], + action='append', + metavar='action', + help="Default action when a path already exists: " + "(s)witch, (i)gnore, (w)ipe, (b)ackup.") + +cert = OptionMaker( + '--cert', + dest='cert', + type='str', + default='', + metavar='path', + help = "Path to alternate CA bundle.") + +index_url = OptionMaker( '-i', '--index-url', '--pypi-url', dest='index_url', metavar='URL', default='https://pypi.python.org/simple/', help='Base URL of Python Package Index (default %default).') -extra_index_url = make_option( +extra_index_url = OptionMaker( '--extra-index-url', dest='extra_index_urls', metavar='URL', @@ -33,14 +168,14 @@ extra_index_url = make_option( default=[], help='Extra URLs of package indexes to use in addition to --index-url.') -no_index = make_option( +no_index = OptionMaker( '--no-index', dest='no_index', action='store_true', default=False, help='Ignore package index (only looking at --find-links URLs instead).') -find_links = make_option( +find_links = OptionMaker( '-f', '--find-links', dest='find_links', action='append', @@ -48,22 +183,24 @@ find_links = make_option( metavar='url', help="If a url or path to an html file, then parse for links to archives. If a local path or file:// url that's a directory, then look for archives in the directory listing.") -use_mirrors = make_option( +# TODO: Remove after 1.6 +use_mirrors = OptionMaker( '-M', '--use-mirrors', dest='use_mirrors', action='store_true', default=False, - help='Use the PyPI mirrors as a fallback in case the main index is down.') + help=SUPPRESS_HELP) -mirrors = make_option( +# TODO: Remove after 1.6 +mirrors = OptionMaker( '--mirrors', dest='mirrors', metavar='URL', action='append', default=[], - help='Specific mirror URLs to query when --use-mirrors is used.') + help=SUPPRESS_HELP) -allow_external = make_option( +allow_external = OptionMaker( "--allow-external", dest="allow_external", action="append", @@ -72,40 +209,52 @@ allow_external = make_option( help="Allow the installation of externally hosted files", ) -allow_all_external = make_option( +allow_all_external = OptionMaker( "--allow-all-external", dest="allow_all_external", action="store_true", - default=True, # TODO: Change to False after 1.4 has been released + default=False, help="Allow the installation of all externally hosted files", ) -# TODO: NOOP after 1.4 has been released -no_allow_external = make_option( +# Remove after 1.7 +no_allow_external = OptionMaker( "--no-allow-external", dest="allow_all_external", action="store_false", - help="Disallow the installation of all externally hosted files", + default=False, + help=SUPPRESS_HELP, ) -allow_unsafe = make_option( - "--allow-insecure", - dest="allow_insecure", +# Remove --allow-insecure after 1.7 +allow_unsafe = OptionMaker( + "--allow-unverified", "--allow-insecure", + dest="allow_unverified", action="append", default=[], metavar="PACKAGE", help="Allow the installation of insecure and unverifiable files", ) -no_allow_unsafe = make_option( +# Remove after 1.7 +no_allow_unsafe = OptionMaker( "--no-allow-insecure", dest="allow_all_insecure", action="store_false", - default=True, - help="Disallow the installation of insecure and unverifiable files" + default=False, + help=SUPPRESS_HELP ) -requirements = make_option( +# Remove after 1.5 +process_dependency_links = OptionMaker( + "--process-dependency-links", + dest="process_dependency_links", + action="store_true", + default=False, + help="Enable the processing of dependency links.", +) + +requirements = OptionMaker( '-r', '--requirement', dest='requirements', action='append', @@ -114,27 +263,37 @@ requirements = make_option( help='Install from the given requirements file. ' 'This option can be used multiple times.') -use_wheel = make_option( +use_wheel = OptionMaker( '--use-wheel', dest='use_wheel', action='store_true', - help='Find and prefer wheel archives when searching indexes and find-links locations. Default to accepting source archives.') + help=SUPPRESS_HELP, +) -download_cache = make_option( +no_use_wheel = OptionMaker( + '--no-use-wheel', + dest='use_wheel', + action='store_false', + default=True, + help=('Do not Find and prefer wheel archives when searching indexes and ' + 'find-links locations.'), +) + +download_cache = OptionMaker( '--download-cache', dest='download_cache', metavar='dir', default=None, help='Cache downloaded packages in

.') -no_deps = make_option( +no_deps = OptionMaker( '--no-deps', '--no-dependencies', dest='ignore_dependencies', action='store_true', default=False, help="Don't install package dependencies.") -build_dir = make_option( +build_dir = OptionMaker( '-b', '--build', '--build-dir', '--build-directory', dest='build_dir', metavar='dir', @@ -143,7 +302,7 @@ build_dir = make_option( 'The default in a virtualenv is "/build". ' 'The default for global installs is "/pip_build_".') -install_options = make_option( +install_options = OptionMaker( '--install-option', dest='install_options', action='append', @@ -153,7 +312,7 @@ install_options = make_option( "Use multiple --install-option options to pass multiple options to setup.py install. " "If you are using an option with a directory path, be sure to use absolute path.") -global_options = make_option( +global_options = OptionMaker( '--global-option', dest='global_options', action='append', @@ -161,7 +320,7 @@ global_options = make_option( help="Extra global options to be supplied to the setup.py " "call before the install command.") -no_clean = make_option( +no_clean = OptionMaker( '--no-clean', action='store_true', default=False, @@ -172,6 +331,27 @@ no_clean = make_option( # groups # ########## +general_group = { + 'name': 'General Options', + 'options': [ + help_, + require_virtualenv, + verbose, + version, + quiet, + log_file, + log, + log_explicit_levels, + no_input, + proxy, + timeout, + default_vcs, + skip_requirements_regex, + exists_action, + cert, + ] + } + index_group = { 'name': 'Package Index Options', 'options': [ @@ -186,5 +366,6 @@ index_group = { no_allow_external, allow_unsafe, no_allow_unsafe, + process_dependency_links, ] } diff --git a/awx/lib/site-packages/pip/commands/bundle.py b/awx/lib/site-packages/pip/commands/bundle.py index 0b7f15093a..b2c6287d58 100644 --- a/awx/lib/site-packages/pip/commands/bundle.py +++ b/awx/lib/site-packages/pip/commands/bundle.py @@ -34,13 +34,14 @@ class BundleCommand(InstallCommand): ## ## ## Due to lack of interest and maintenance, ## ## 'pip bundle' and support for installing ## - ## from *.pybundle files is now deprecated, ## - ## and will be removed in pip v1.5. ## + ## from *.pybundle files is deprecated, as ## + ## of v1.4 and will be removed in a ## + ## future release. ## ## ## ############################################### """) - logger.notify(deprecation) + logger.warn(deprecation) if not args: raise InstallationError('You must give a bundle filename') diff --git a/awx/lib/site-packages/pip/commands/help.py b/awx/lib/site-packages/pip/commands/help.py index 4771db7539..2253387322 100644 --- a/awx/lib/site-packages/pip/commands/help.py +++ b/awx/lib/site-packages/pip/commands/help.py @@ -27,7 +27,7 @@ class HelpCommand(Command): raise CommandError(' - '.join(msg)) - command = commands[cmd_name](self.main_parser) # instantiate + command = commands[cmd_name]() command.parser.print_help() return SUCCESS diff --git a/awx/lib/site-packages/pip/commands/install.py b/awx/lib/site-packages/pip/commands/install.py index bcdc9c1ae6..81ee1c433b 100644 --- a/awx/lib/site-packages/pip/commands/install.py +++ b/awx/lib/site-packages/pip/commands/install.py @@ -51,8 +51,8 @@ class InstallCommand(Command): metavar='path/url', help='Install a project in editable mode (i.e. setuptools "develop mode") from a local project path or a VCS url.') - cmd_opts.add_option(cmdoptions.requirements) - cmd_opts.add_option(cmdoptions.build_dir) + cmd_opts.add_option(cmdoptions.requirements.make()) + cmd_opts.add_option(cmdoptions.build_dir.make()) cmd_opts.add_option( '-t', '--target', @@ -68,7 +68,7 @@ class InstallCommand(Command): default=None, help="Download packages into instead of installing them, regardless of what's already installed.") - cmd_opts.add_option(cmdoptions.download_cache) + cmd_opts.add_option(cmdoptions.download_cache.make()) cmd_opts.add_option( '--src', '--source', '--source-dir', '--source-directory', @@ -99,23 +99,23 @@ class InstallCommand(Command): action='store_true', help='Ignore the installed packages (reinstalling instead).') - cmd_opts.add_option(cmdoptions.no_deps) + cmd_opts.add_option(cmdoptions.no_deps.make()) cmd_opts.add_option( '--no-install', dest='no_install', action='store_true', - help="Download and unpack all packages, but don't actually install them.") + help="DEPRECATED. Download and unpack all packages, but don't actually install them.") cmd_opts.add_option( '--no-download', dest='no_download', action="store_true", - help="Don't download any packages, just install the ones already downloaded " + help="DEPRECATED. Don't download any packages, just install the ones already downloaded " "(completes an install run with --no-install).") - cmd_opts.add_option(cmdoptions.install_options) - cmd_opts.add_option(cmdoptions.global_options) + cmd_opts.add_option(cmdoptions.install_options.make()) + cmd_opts.add_option(cmdoptions.global_options.make()) cmd_opts.add_option( '--user', @@ -127,7 +127,7 @@ class InstallCommand(Command): '--egg', dest='as_egg', action='store_true', - help="Install as self contained egg file, like easy_install does.") + help="Install packages as eggs, not 'flat', like pip normally does. This option is not about installing *from* eggs. (WARNING: Because this option overrides pip's normal install logic, requirements files may not behave as expected.)") cmd_opts.add_option( '--root', @@ -136,7 +136,23 @@ class InstallCommand(Command): default=None, help="Install everything relative to this alternate root directory.") - cmd_opts.add_option(cmdoptions.use_wheel) + cmd_opts.add_option( + "--compile", + action="store_true", + dest="compile", + default=True, + help="Compile py files to pyc", + ) + + cmd_opts.add_option( + "--no-compile", + action="store_false", + dest="compile", + help="Do not compile py files to pyc", + ) + + cmd_opts.add_option(cmdoptions.use_wheel.make()) + cmd_opts.add_option(cmdoptions.no_use_wheel.make()) cmd_opts.add_option( '--pre', @@ -144,14 +160,14 @@ class InstallCommand(Command): default=False, help="Include pre-release and development versions. By default, pip only finds stable versions.") - cmd_opts.add_option(cmdoptions.no_clean) + cmd_opts.add_option(cmdoptions.no_clean.make()) index_opts = cmdoptions.make_option_group(cmdoptions.index_group, self.parser) self.parser.insert_option_group(0, index_opts) self.parser.insert_option_group(0, cmd_opts) - def _build_package_finder(self, options, index_urls): + def _build_package_finder(self, options, index_urls, session): """ Create a package finder appropriate to this install command. This method is meant to be overridden by subclasses, not @@ -159,14 +175,14 @@ class InstallCommand(Command): """ return PackageFinder(find_links=options.find_links, index_urls=index_urls, - use_mirrors=options.use_mirrors, - mirrors=options.mirrors, use_wheel=options.use_wheel, allow_external=options.allow_external, - allow_insecure=options.allow_insecure, + allow_unverified=options.allow_unverified, allow_all_external=options.allow_all_external, - allow_all_insecure=options.allow_all_insecure, allow_all_prereleases=options.pre, + process_dependency_links= + options.process_dependency_links, + session=session, ) def run(self, options, args): @@ -196,7 +212,22 @@ class InstallCommand(Command): logger.notify('Ignoring indexes: %s' % ','.join(index_urls)) index_urls = [] - finder = self._build_package_finder(options, index_urls) + if options.use_mirrors: + logger.deprecated("1.7", + "--use-mirrors has been deprecated and will be removed" + " in the future. Explicit uses of --index-url and/or " + "--extra-index-url is suggested.") + + if options.mirrors: + logger.deprecated("1.7", + "--mirrors has been deprecated and will be removed in " + " the future. Explicit uses of --index-url and/or " + "--extra-index-url is suggested.") + index_urls += options.mirrors + + session = self._build_session(options) + + finder = self._build_package_finder(options, index_urls, session) requirement_set = RequirementSet( build_dir=options.build_dir, @@ -209,7 +240,10 @@ class InstallCommand(Command): ignore_dependencies=options.ignore_dependencies, force_reinstall=options.force_reinstall, use_user_site=options.use_user_site, - target_dir=temp_target_dir) + target_dir=temp_target_dir, + session=session, + pycompile=options.compile, + ) for name in args: requirement_set.add_requirement( InstallRequirement.from_line(name, None)) @@ -217,7 +251,7 @@ class InstallCommand(Command): requirement_set.add_requirement( InstallRequirement.from_editable(name, default_vcs=options.default_vcs)) for filename in options.requirements: - for req in parse_requirements(filename, finder=finder, options=options): + for req in parse_requirements(filename, finder=finder, options=options, session=session): requirement_set.add_requirement(req) if not requirement_set.has_requirements: opts = {'name': self.name} @@ -252,7 +286,8 @@ class InstallCommand(Command): requirement_set.create_bundle(self.bundle_filename) logger.notify('Created bundle in %s' % self.bundle_filename) except PreviousBuildDirError: - return + options.no_clean = True + raise finally: # Clean up if (not options.no_clean) and ((not options.no_install) or options.download_dir): diff --git a/awx/lib/site-packages/pip/commands/list.py b/awx/lib/site-packages/pip/commands/list.py index aaae7694db..207f06885c 100644 --- a/awx/lib/site-packages/pip/commands/list.py +++ b/awx/lib/site-packages/pip/commands/list.py @@ -54,19 +54,19 @@ class ListCommand(Command): self.parser.insert_option_group(0, index_opts) self.parser.insert_option_group(0, cmd_opts) - def _build_package_finder(self, options, index_urls): + def _build_package_finder(self, options, index_urls, session): """ Create a package finder appropriate to this list command. """ return PackageFinder(find_links=options.find_links, index_urls=index_urls, - use_mirrors=options.use_mirrors, - mirrors=options.mirrors, allow_external=options.allow_external, - allow_insecure=options.allow_insecure, + allow_unverified=options.allow_unverified, allow_all_external=options.allow_all_external, - allow_all_insecure=options.allow_all_insecure, allow_all_prereleases=options.pre, + process_dependency_links= + options.process_dependency_links, + session=session, ) def run(self, options, args): @@ -91,6 +91,19 @@ class ListCommand(Command): logger.notify('Ignoring indexes: %s' % ','.join(index_urls)) index_urls = [] + if options.use_mirrors: + logger.deprecated("1.7", + "--use-mirrors has been deprecated and will be removed" + " in the future. Explicit uses of --index-url and/or " + "--extra-index-url is suggested.") + + if options.mirrors: + logger.deprecated("1.7", + "--mirrors has been deprecated and will be removed in " + " the future. Explicit uses of --index-url and/or " + "--extra-index-url is suggested.") + index_urls += options.mirrors + dependency_links = [] for dist in get_installed_distributions(local_only=options.local, skip=self.skip): if dist.has_metadata('dependency_links.txt'): @@ -98,7 +111,9 @@ class ListCommand(Command): dist.get_metadata_lines('dependency_links.txt'), ) - finder = self._build_package_finder(options, index_urls) + session = self._build_session(options) + + finder = self._build_package_finder(options, index_urls, session) finder.add_dependency_links(dependency_links) installed_packages = get_installed_distributions(local_only=options.local, include_editables=False, skip=self.skip) diff --git a/awx/lib/site-packages/pip/commands/uninstall.py b/awx/lib/site-packages/pip/commands/uninstall.py index 388053b20f..b7099cf8ce 100644 --- a/awx/lib/site-packages/pip/commands/uninstall.py +++ b/awx/lib/site-packages/pip/commands/uninstall.py @@ -38,15 +38,20 @@ class UninstallCommand(Command): self.parser.insert_option_group(0, self.cmd_opts) def run(self, options, args): + session = self._build_session(options) + requirement_set = RequirementSet( build_dir=None, src_dir=None, - download_dir=None) + download_dir=None, + session=session, + ) for name in args: requirement_set.add_requirement( InstallRequirement.from_line(name)) for filename in options.requirements: - for req in parse_requirements(filename, options=options): + for req in parse_requirements(filename, + options=options, session=session): requirement_set.add_requirement(req) if not requirement_set.has_requirements: raise InstallationError('You must give at least one requirement ' diff --git a/awx/lib/site-packages/pip/commands/wheel.py b/awx/lib/site-packages/pip/commands/wheel.py index 5bf1c2333b..cb3e962543 100644 --- a/awx/lib/site-packages/pip/commands/wheel.py +++ b/awx/lib/site-packages/pip/commands/wheel.py @@ -9,7 +9,7 @@ from pip.log import logger from pip.exceptions import CommandError, PreviousBuildDirError from pip.req import InstallRequirement, RequirementSet, parse_requirements from pip.util import normalize_path -from pip.wheel import WheelBuilder, wheel_setuptools_support, setuptools_requirement +from pip.wheel import WheelBuilder, wheel_setuptools_support from pip import cmdoptions DEFAULT_WHEEL_DIR = os.path.join(normalize_path(os.curdir), 'wheelhouse') @@ -48,17 +48,18 @@ class WheelCommand(Command): metavar='dir', default=DEFAULT_WHEEL_DIR, help="Build wheels into , where the default is '/wheelhouse'.") - cmd_opts.add_option(cmdoptions.use_wheel) + cmd_opts.add_option(cmdoptions.use_wheel.make()) + cmd_opts.add_option(cmdoptions.no_use_wheel.make()) cmd_opts.add_option( '--build-option', dest='build_options', metavar='options', action='append', help="Extra arguments to be supplied to 'setup.py bdist_wheel'.") - cmd_opts.add_option(cmdoptions.requirements) - cmd_opts.add_option(cmdoptions.download_cache) - cmd_opts.add_option(cmdoptions.no_deps) - cmd_opts.add_option(cmdoptions.build_dir) + cmd_opts.add_option(cmdoptions.requirements.make()) + cmd_opts.add_option(cmdoptions.download_cache.make()) + cmd_opts.add_option(cmdoptions.no_deps.make()) + cmd_opts.add_option(cmdoptions.build_dir.make()) cmd_opts.add_option( '--global-option', @@ -74,7 +75,7 @@ class WheelCommand(Command): default=False, help="Include pre-release and development versions. By default, pip only finds stable versions.") - cmd_opts.add_option(cmdoptions.no_clean) + cmd_opts.add_option(cmdoptions.no_clean.make()) index_opts = cmdoptions.make_option_group(cmdoptions.index_group, self.parser) @@ -87,25 +88,40 @@ class WheelCommand(Command): try: import wheel.bdist_wheel except ImportError: - raise CommandError("'pip wheel' requires bdist_wheel from the 'wheel' distribution.") + raise CommandError("'pip wheel' requires the 'wheel' package. To fix this, run: pip install wheel") if not wheel_setuptools_support(): - raise CommandError("'pip wheel' requires %s." % setuptools_requirement) + raise CommandError("'pip wheel' requires setuptools>=0.8. To fix this, run: pip install --upgrade setuptools") index_urls = [options.index_url] + options.extra_index_urls if options.no_index: logger.notify('Ignoring indexes: %s' % ','.join(index_urls)) index_urls = [] + if options.use_mirrors: + logger.deprecated("1.7", + "--use-mirrors has been deprecated and will be removed" + " in the future. Explicit uses of --index-url and/or " + "--extra-index-url is suggested.") + + if options.mirrors: + logger.deprecated("1.7", + "--mirrors has been deprecated and will be removed in " + " the future. Explicit uses of --index-url and/or " + "--extra-index-url is suggested.") + index_urls += options.mirrors + + session = self._build_session(options) + finder = PackageFinder(find_links=options.find_links, index_urls=index_urls, - use_mirrors=options.use_mirrors, - mirrors=options.mirrors, use_wheel=options.use_wheel, allow_external=options.allow_external, - allow_insecure=options.allow_insecure, + allow_unverified=options.allow_unverified, allow_all_external=options.allow_all_external, - allow_all_insecure=options.allow_all_insecure, allow_all_prereleases=options.pre, + process_dependency_links= + options.process_dependency_links, + session=session, ) options.build_dir = os.path.abspath(options.build_dir) @@ -115,7 +131,9 @@ class WheelCommand(Command): download_dir=None, download_cache=options.download_cache, ignore_dependencies=options.ignore_dependencies, - ignore_installed=True) + ignore_installed=True, + session=session, + ) #parse args and/or requirements files for name in args: @@ -126,7 +144,7 @@ class WheelCommand(Command): InstallRequirement.from_line(name, None)) for filename in options.requirements: - for req in parse_requirements(filename, finder=finder, options=options): + for req in parse_requirements(filename, finder=finder, options=options, session=session): if req.editable or (req.name is None and req.url.endswith(".whl")): logger.notify("ignoring %s" % req.url) continue @@ -151,8 +169,8 @@ class WheelCommand(Command): ) wb.build() except PreviousBuildDirError: - return + options.no_clean = True + raise finally: if not options.no_clean: requirement_set.cleanup_files() - diff --git a/awx/lib/site-packages/pip/download.py b/awx/lib/site-packages/pip/download.py index 653495f2a3..cfd528eb35 100644 --- a/awx/lib/site-packages/pip/download.py +++ b/awx/lib/site-packages/pip/download.py @@ -1,36 +1,38 @@ import cgi -import getpass +import email.utils import hashlib +import getpass import mimetypes import os import platform import re import shutil -import socket -import ssl import sys import tempfile import pip -from pip.backwardcompat import (urllib, urllib2, httplib, - urlparse, string_types, get_http_message_param, - match_hostname, CertificateError) +from pip.backwardcompat import urllib, urlparse, raw_input from pip.exceptions import InstallationError, HashMismatch from pip.util import (splitext, rmtree, format_size, display_path, backup_dir, ask_path_exists, unpack_file, create_download_cache_folder, cache_download) from pip.vcs import vcs from pip.log import logger -from pip.locations import default_cert_path +from pip._vendor import requests +from pip._vendor.requests.adapters import BaseAdapter +from pip._vendor.requests.auth import AuthBase, HTTPBasicAuth +from pip._vendor.requests.exceptions import InvalidURL +from pip._vendor.requests.models import Response +from pip._vendor.requests.structures import CaseInsensitiveDict -__all__ = ['get_file_content', 'urlopen', - 'is_url', 'url_to_path', 'path_to_url', 'path_to_url2', - 'geturl', 'is_archive_file', 'unpack_vcs_link', +__all__ = ['get_file_content', + 'is_url', 'url_to_path', 'path_to_url', + 'is_archive_file', 'unpack_vcs_link', 'unpack_file_url', 'is_vcs_url', 'is_file_url', 'unpack_http_url'] -def build_user_agent(): +def user_agent(): """Return a string representing the user agent.""" _implementation = platform.python_implementation() @@ -41,7 +43,10 @@ def build_user_agent(): sys.pypy_version_info.minor, sys.pypy_version_info.micro) if sys.pypy_version_info.releaselevel != 'final': - _implementation_version = ''.join([_implementation_version, sys.pypy_version_info.releaselevel]) + _implementation_version = ''.join([ + _implementation_version, + sys.pypy_version_info.releaselevel, + ]) elif _implementation == 'Jython': _implementation_version = platform.python_version() # Complete Guess elif _implementation == 'IronPython': @@ -61,9 +66,182 @@ def build_user_agent(): '%s/%s' % (p_system, p_release)]) -def get_file_content(url, comes_from=None): +class MultiDomainBasicAuth(AuthBase): + + def __init__(self, prompting=True): + self.prompting = prompting + self.passwords = {} + + def __call__(self, req): + parsed = urlparse.urlparse(req.url) + + # Get the netloc without any embedded credentials + netloc = parsed.netloc.split("@", 1)[-1] + + # Set the url of the request to the url without any credentials + req.url = urlparse.urlunparse(parsed[:1] + (netloc,) + parsed[2:]) + + # Use any stored credentials that we have for this netloc + username, password = self.passwords.get(netloc, (None, None)) + + # Extract credentials embedded in the url if we have none stored + if username is None: + username, password = self.parse_credentials(parsed.netloc) + + if username or password: + # Store the username and password + self.passwords[netloc] = (username, password) + + # Send the basic auth with this request + req = HTTPBasicAuth(username or "", password or "")(req) + + # Attach a hook to handle 401 responses + req.register_hook("response", self.handle_401) + + return req + + def handle_401(self, resp, **kwargs): + # We only care about 401 responses, anything else we want to just + # pass through the actual response + if resp.status_code != 401: + return resp + + # We are not able to prompt the user so simple return the response + if not self.prompting: + return resp + + parsed = urlparse.urlparse(resp.url) + + # Prompt the user for a new username and password + username = raw_input("User for %s: " % parsed.netloc) + password = getpass.getpass("Password: ") + + # Store the new username and password to use for future requests + if username or password: + self.passwords[parsed.netloc] = (username, password) + + # Consume content and release the original connection to allow our new + # request to reuse the same one. + resp.content + resp.raw.release_conn() + + # Add our new username and password to the request + req = HTTPBasicAuth(username or "", password or "")(resp.request) + + # Send our new request + new_resp = resp.connection.send(req, **kwargs) + new_resp.history.append(resp) + + return new_resp + + def parse_credentials(self, netloc): + if "@" in netloc: + userinfo = netloc.rsplit("@", 1)[0] + if ":" in userinfo: + return userinfo.split(":", 1) + return userinfo, None + return None, None + + +class LocalFSResponse(object): + + def __init__(self, fileobj): + self.fileobj = fileobj + + def __getattr__(self, name): + return getattr(self.fileobj, name) + + def read(self, amt=None, decode_content=None, cache_content=False): + return self.fileobj.read(amt) + + # Insert Hacks to Make Cookie Jar work w/ Requests + @property + def _original_response(self): + class FakeMessage(object): + def getheaders(self, header): + return [] + + def get_all(self, header, default): + return [] + + class FakeResponse(object): + @property + def msg(self): + return FakeMessage() + + return FakeResponse() + + +class LocalFSAdapter(BaseAdapter): + + def send(self, request, stream=None, timeout=None, verify=None, cert=None, + proxies=None): + parsed_url = urlparse.urlparse(request.url) + + # We only work for requests with a host of localhost + if parsed_url.netloc.lower() != "localhost": + raise InvalidURL("Invalid URL %r: Only localhost is allowed" % + request.url) + + real_url = urlparse.urlunparse(parsed_url[:1] + ("",) + parsed_url[2:]) + pathname = url_to_path(real_url) + + resp = Response() + resp.status_code = 200 + resp.url = real_url + + stats = os.stat(pathname) + modified = email.utils.formatdate(stats.st_mtime, usegmt=True) + resp.headers = CaseInsensitiveDict({ + "Content-Type": mimetypes.guess_type(pathname)[0] or "text/plain", + "Content-Length": stats.st_size, + "Last-Modified": modified, + }) + + resp.raw = LocalFSResponse(open(pathname, "rb")) + resp.close = resp.raw.close + + return resp + + def close(self): + pass + + +class PipSession(requests.Session): + + timeout = None + + def __init__(self, *args, **kwargs): + super(PipSession, self).__init__(*args, **kwargs) + + # Attach our User Agent to the request + self.headers["User-Agent"] = user_agent() + + # Attach our Authentication handler to the session + self.auth = MultiDomainBasicAuth() + + # Enable file:// urls + self.mount("file://", LocalFSAdapter()) + + def request(self, method, url, *args, **kwargs): + # Make file:// urls not fail due to lack of a hostname + parsed = urlparse.urlparse(url) + if parsed.scheme == "file": + url = urlparse.urlunparse(parsed[:1] + ("localhost",) + parsed[2:]) + + # Allow setting a default timeout on a session + kwargs.setdefault("timeout", self.timeout) + + # Dispatch the actual request + return super(PipSession, self).request(method, url, *args, **kwargs) + + +def get_file_content(url, comes_from=None, session=None): """Gets the content of a file; it may be a filename, file: URL, or http: URL. Returns (location, content). Content is unicode.""" + if session is None: + session = PipSession() + match = _scheme_re.search(url) if match: scheme = match.group(1).lower() @@ -84,9 +262,9 @@ def get_file_content(url, comes_from=None): url = path else: ## FIXME: catch some errors - resp = urlopen(url) - encoding = get_http_message_param(resp.headers, 'charset', 'utf-8') - return geturl(resp), resp.read().decode(encoding) + resp = session.get(url) + resp.raise_for_status() + return resp.url, resp.text try: f = open(url) content = f.read() @@ -101,218 +279,6 @@ def get_file_content(url, comes_from=None): _scheme_re = re.compile(r'^(http|https|file):', re.I) _url_slash_drive_re = re.compile(r'/*([a-z])\|', re.I) -class VerifiedHTTPSConnection(httplib.HTTPSConnection): - """ - A connection that wraps connections with ssl certificate verification. - """ - def connect(self): - - self.connection_kwargs = {} - - #TODO: refactor compatibility logic into backwardcompat? - - # for > py2.5 - if hasattr(self, 'timeout'): - self.connection_kwargs.update(timeout = self.timeout) - - # for >= py2.7 - if hasattr(self, 'source_address'): - self.connection_kwargs.update(source_address = self.source_address) - - sock = socket.create_connection((self.host, self.port), **self.connection_kwargs) - - # for >= py2.7 - if getattr(self, '_tunnel_host', None): - self.sock = sock - self._tunnel() - - # get alternate bundle or use our included bundle - cert_path = os.environ.get('PIP_CERT', '') or default_cert_path - - self.sock = ssl.wrap_socket(sock, - self.key_file, - self.cert_file, - cert_reqs=ssl.CERT_REQUIRED, - ca_certs=cert_path) - - try: - match_hostname(self.sock.getpeercert(), self.host) - except CertificateError: - self.sock.shutdown(socket.SHUT_RDWR) - self.sock.close() - raise - - - -class VerifiedHTTPSHandler(urllib2.HTTPSHandler): - """ - A HTTPSHandler that uses our own VerifiedHTTPSConnection. - """ - def __init__(self, connection_class = VerifiedHTTPSConnection): - self.specialized_conn_class = connection_class - urllib2.HTTPSHandler.__init__(self) - def https_open(self, req): - return self.do_open(self.specialized_conn_class, req) - - -class URLOpener(object): - """ - pip's own URL helper that adds HTTP auth and proxy support - """ - def __init__(self): - self.passman = urllib2.HTTPPasswordMgrWithDefaultRealm() - self.proxy_handler = None - - def __call__(self, url): - """ - If the given url contains auth info or if a normal request gets a 401 - response, an attempt is made to fetch the resource using basic HTTP - auth. - - """ - url, username, password, scheme = self.extract_credentials(url) - if username is None: - try: - response = self.get_opener(scheme=scheme).open(url) - except urllib2.HTTPError: - e = sys.exc_info()[1] - if e.code != 401: - raise - response = self.get_response(url) - else: - response = self.get_response(url, username, password) - return response - - def get_request(self, url): - """ - Wraps the URL to retrieve to protects against "creative" - interpretation of the RFC: http://bugs.python.org/issue8732 - """ - if isinstance(url, string_types): - url = urllib2.Request(url, headers={'Accept-encoding': 'identity'}) - return url - - def get_response(self, url, username=None, password=None): - """ - does the dirty work of actually getting the rsponse object using urllib2 - and its HTTP auth builtins. - """ - scheme, netloc, path, query, frag = urlparse.urlsplit(url) - req = self.get_request(url) - - stored_username, stored_password = self.passman.find_user_password(None, netloc) - # see if we have a password stored - if stored_username is None: - if username is None and self.prompting: - username = urllib.quote(raw_input('User for %s: ' % netloc)) - password = urllib.quote(getpass.getpass('Password: ')) - if username and password: - self.passman.add_password(None, netloc, username, password) - stored_username, stored_password = self.passman.find_user_password(None, netloc) - authhandler = urllib2.HTTPBasicAuthHandler(self.passman) - opener = self.get_opener(authhandler, scheme=scheme) - # FIXME: should catch a 401 and offer to let the user reenter credentials - return opener.open(req) - - def get_opener(self, *args, **kwargs): - """ - Build an OpenerDirector instance based on the scheme and proxy option - """ - - args = list(args) - if self.proxy_handler: - args.extend([self.proxy_handler, urllib2.CacheFTPHandler]) - - if kwargs.get('scheme') == 'https': - https_handler = VerifiedHTTPSHandler() - director = urllib2.build_opener(https_handler, *args) - #strip out HTTPHandler to prevent MITM spoof - for handler in director.handlers: - if isinstance(handler, urllib2.HTTPHandler): - director.handlers.remove(handler) - else: - director = urllib2.build_opener(*args) - - # Add our new headers to the opener - headers = [x for x in director.addheaders if x[0].lower() != "user-agent"] - headers.append(("User-agent", build_user_agent())) - director.addheaders = headers - - return director - - def setup(self, proxystr='', prompting=True): - """ - Sets the proxy handler given the option passed on the command - line. If an empty string is passed it looks at the HTTP_PROXY - environment variable. - """ - self.prompting = prompting - proxy = self.get_proxy(proxystr) - if proxy: - self.proxy_handler = urllib2.ProxyHandler({"http": proxy, "ftp": proxy, "https": proxy}) - - def parse_credentials(self, netloc): - if "@" in netloc: - userinfo = netloc.rsplit("@", 1)[0] - if ":" in userinfo: - return userinfo.split(":", 1) - return userinfo, None - return None, None - - def extract_credentials(self, url): - """ - Extracts user/password from a url. - - Returns a tuple: - (url-without-auth, username, password) - """ - if isinstance(url, urllib2.Request): - result = urlparse.urlsplit(url.get_full_url()) - else: - result = urlparse.urlsplit(url) - scheme, netloc, path, query, frag = result - - username, password = self.parse_credentials(netloc) - if username is None: - return url, None, None, scheme - elif password is None and self.prompting: - # remove the auth credentials from the url part - netloc = netloc.replace('%s@' % username, '', 1) - # prompt for the password - prompt = 'Password for %s@%s: ' % (username, netloc) - password = urllib.quote(getpass.getpass(prompt)) - else: - # remove the auth credentials from the url part - netloc = netloc.replace('%s:%s@' % (username, password), '', 1) - - target_url = urlparse.urlunsplit((scheme, netloc, path, query, frag)) - return target_url, username, password, scheme - - def get_proxy(self, proxystr=''): - """ - Get the proxy given the option passed on the command line. - If an empty string is passed it looks at the HTTP_PROXY - environment variable. - """ - if not proxystr: - proxystr = os.environ.get('HTTP_PROXY', '') - if proxystr: - if '@' in proxystr: - user_password, server_port = proxystr.split('@', 1) - if ':' in user_password: - user, password = user_password.split(':', 1) - else: - user = user_password - prompt = 'Password for %s@%s: ' % (user, server_port) - password = urllib.quote(getpass.getpass(prompt)) - return '%s:%s@%s' % (user, password, server_port) - else: - return proxystr - else: - return None - -urlopen = URLOpener() - def is_url(name): """Returns true if the name looks like a URL""" @@ -342,19 +308,6 @@ _url_drive_re = re.compile('^([a-z])[:|]', re.I) def path_to_url(path): - """ - Convert a path to a file: URL. The path will be made absolute. - """ - path = os.path.normcase(os.path.abspath(path)) - if _drive_re.match(path): - path = path[0] + '|' + path[2:] - url = urllib.quote(path) - url = url.replace(os.path.sep, '/') - url = url.lstrip('/') - return 'file:///' + url - - -def path_to_url2(path): """ Convert a path to a file: URL. The path will be made absolute and have quoted path parts. @@ -368,30 +321,6 @@ def path_to_url2(path): return 'file:///' + drive + url -def geturl(urllib2_resp): - """ - Use instead of urllib.addinfourl.geturl(), which appears to have - some issues with dropping the double slash for certain schemes - (e.g. file://). This implementation is probably over-eager, as it - always restores '://' if it is missing, and it appears some url - schemata aren't always followed by '//' after the colon, but as - far as I know pip doesn't need any of those. - The URI RFC can be found at: http://tools.ietf.org/html/rfc1630 - - This function assumes that - scheme:/foo/bar - is the same as - scheme:///foo/bar - """ - url = urllib2_resp.geturl() - scheme, rest = url.split(':', 1) - if rest.startswith('//'): - return url - else: - # FIXME: write a good test to cover it - return '%s://%s' % (scheme, rest) - - def is_archive_file(name): """Return True if `name` is a considered as an archive file.""" archives = ('.zip', '.tar.gz', '.tar.bz2', '.tgz', '.tar', '.pybundle', @@ -417,7 +346,7 @@ def unpack_file_url(link, location): # delete the location since shutil will create it again :( if os.path.isdir(location): rmtree(location) - shutil.copytree(source, location) + shutil.copytree(source, location, symlinks=True) else: unpack_file(source, location, content_type, link) @@ -474,7 +403,7 @@ def _download_url(resp, link, temp_location): except ValueError: logger.warn("Unsupported hash name %s for package %s" % (link.hash_name, link)) try: - total_length = int(resp.info()['content-length']) + total_length = int(resp.headers['content-length']) except (ValueError, KeyError, TypeError): total_length = 0 downloaded = 0 @@ -491,10 +420,7 @@ def _download_url(resp, link, temp_location): logger.notify('Downloading %s' % show_url) logger.info('Downloading from URL %s' % link) - while True: - chunk = resp.read(4096) - if not chunk: - break + for chunk in resp.iter_content(4096): downloaded += len(chunk) if show_progress: if not total_length: @@ -534,7 +460,11 @@ def _copy_file(filename, location, content_type, link): logger.notify('Saved %s' % display_path(download_location)) -def unpack_http_url(link, location, download_cache, download_dir=None): +def unpack_http_url(link, location, download_cache, download_dir=None, + session=None): + if session is None: + session = PipSession() + temp_dir = tempfile.mkdtemp('-unpack', 'pip-') temp_location = None target_url = link.url.split('#', 1)[0] @@ -599,11 +529,18 @@ def unpack_http_url(link, location, download_cache, download_dir=None): # We don't have either a cached or a downloaded copy if not temp_location: - resp = _get_response_from_url(target_url, link) - content_type = resp.info().get('content-type', '') + try: + resp = session.get(target_url, stream=True) + resp.raise_for_status() + except requests.HTTPError as exc: + logger.fatal("HTTP error %s while getting %s" % + (exc.response.status_code, link)) + raise + + content_type = resp.headers.get('content-type', '') filename = link.filename # fallback # Have a look at the Content-Disposition header for a better guess - content_disposition = resp.info().get('content-disposition') + content_disposition = resp.headers.get('content-disposition') if content_disposition: type, params = cgi.parse_header(content_disposition) # We use ``or`` here because we don't want to use an "empty" value @@ -614,8 +551,8 @@ def unpack_http_url(link, location, download_cache, download_dir=None): ext = mimetypes.guess_extension(content_type) if ext: filename += ext - if not ext and link.url != geturl(resp): - ext = os.path.splitext(geturl(resp))[1] + if not ext and link.url != resp.url: + ext = os.path.splitext(resp.url)[1] if ext: filename += ext temp_location = os.path.join(temp_dir, filename) @@ -631,23 +568,3 @@ def unpack_http_url(link, location, download_cache, download_dir=None): if not (already_cached or already_downloaded): os.unlink(temp_location) os.rmdir(temp_dir) - - -def _get_response_from_url(target_url, link): - try: - resp = urlopen(target_url) - except urllib2.HTTPError: - e = sys.exc_info()[1] - logger.fatal("HTTP error %s while getting %s" % (e.code, link)) - raise - except IOError: - e = sys.exc_info()[1] - # Typically an FTP error - logger.fatal("Error %s while getting %s" % (e, link)) - raise - return resp - - -class Urllib2HeadRequest(urllib2.Request): - def get_method(self): - return "HEAD" diff --git a/awx/lib/site-packages/pip/exceptions.py b/awx/lib/site-packages/pip/exceptions.py index 55158af361..febebfb290 100644 --- a/awx/lib/site-packages/pip/exceptions.py +++ b/awx/lib/site-packages/pip/exceptions.py @@ -36,3 +36,11 @@ class PreviousBuildDirError(PipError): class HashMismatch(InstallationError): """Distribution file hash values don't match.""" + + +class InvalidWheelFilename(InstallationError): + """Invalid wheel filename.""" + + +class UnsupportedWheel(InstallationError): + """Unsupported wheel.""" diff --git a/awx/lib/site-packages/pip/index.py b/awx/lib/site-packages/pip/index.py index 98a6cac5b5..45d4707590 100644 --- a/awx/lib/site-packages/pip/index.py +++ b/awx/lib/site-packages/pip/index.py @@ -3,41 +3,31 @@ import sys import os import re -import gzip import mimetypes import posixpath import pkg_resources -import random -import socket -import ssl -import string -import zlib - -try: - import threading -except ImportError: - import dummy_threading as threading from pip.log import logger from pip.util import Inf, normalize_name, splitext, is_prerelease -from pip.exceptions import DistributionNotFound, BestVersionAlreadyInstalled,\ - InstallationError -from pip.backwardcompat import (WindowsError, BytesIO, - Queue, urlparse, - URLError, HTTPError, u, - product, url2pathname, - Empty as QueueEmpty) -from pip.backwardcompat import CertificateError -from pip.download import urlopen, path_to_url2, url_to_path, geturl, Urllib2HeadRequest -from pip.wheel import Wheel, wheel_ext, wheel_setuptools_support, setuptools_requirement +from pip.exceptions import (DistributionNotFound, BestVersionAlreadyInstalled, + InstallationError, InvalidWheelFilename, UnsupportedWheel) +from pip.backwardcompat import urlparse, url2pathname +from pip.download import PipSession, url_to_path, path_to_url +from pip.wheel import Wheel, wheel_ext, wheel_setuptools_support from pip.pep425tags import supported_tags, supported_tags_noarch, get_platform -from pip.vendor import html5lib +from pip._vendor import html5lib, requests +from pip._vendor.requests.exceptions import SSLError + __all__ = ['PackageFinder'] DEFAULT_MIRROR_HOSTNAME = "last.pypi.python.org" +INSECURE_SCHEMES = { + "http": ["https"], +} + class PackageFinder(object): """This finds packages. @@ -47,46 +37,47 @@ class PackageFinder(object): """ def __init__(self, find_links, index_urls, - use_mirrors=False, mirrors=None, main_mirror_url=None, - use_wheel=False, allow_external=[], allow_insecure=[], - allow_all_external=False, allow_all_insecure=False, - allow_all_prereleases=False): + use_wheel=True, allow_external=[], allow_unverified=[], + allow_all_external=False, allow_all_prereleases=False, + process_dependency_links=False, session=None): self.find_links = find_links self.index_urls = index_urls self.dependency_links = [] self.cache = PageCache() # These are boring links that have already been logged somehow: self.logged_links = set() - if use_mirrors: - self.mirror_urls = self._get_mirror_urls(mirrors, main_mirror_url) - logger.info('Using PyPI mirrors: %s' % ', '.join(self.mirror_urls)) - else: - self.mirror_urls = [] + self.use_wheel = use_wheel # Do we allow (safe and verifiable) externally hosted files? self.allow_external = set(normalize_name(n) for n in allow_external) # Which names are allowed to install insecure and unverifiable files? - self.allow_insecure = set(normalize_name(n) for n in allow_insecure) + self.allow_unverified = set( + normalize_name(n) for n in allow_unverified + ) # Do we allow all (safe and verifiable) externally hosted files? self.allow_all_external = allow_all_external - # Do we allow unsafe and unverifiable files? - self.allow_all_insecure = allow_all_insecure - # Stores if we ignored any external links so that we can instruct # end users how to install them if no distributions are available self.need_warn_external = False # Stores if we ignored any unsafe links so that we can instruct # end users how to install them if no distributions are available - self.need_warn_insecure = False + self.need_warn_unverified = False # Do we want to allow _all_ pre-releases? self.allow_all_prereleases = allow_all_prereleases + # Do we process dependency links? + self.process_dependency_links = process_dependency_links + self._have_warned_dependency_links = False + + # The Session we'll use to make requests + self.session = session or PipSession() + @property def use_wheel(self): return self._use_wheel @@ -95,14 +86,22 @@ class PackageFinder(object): def use_wheel(self, value): self._use_wheel = value if self._use_wheel and not wheel_setuptools_support(): - raise InstallationError("pip's wheel support requires %s." % setuptools_requirement) + raise InstallationError("pip's wheel support requires setuptools >= 0.8 for dist-info support.") def add_dependency_links(self, links): ## FIXME: this shouldn't be global list this, it should only ## apply to requirements of the package that specifies the ## dependency_links value ## FIXME: also, we should track comes_from (i.e., use Link) - self.dependency_links.extend(links) + if self.process_dependency_links: + if not self._have_warned_dependency_links: + logger.deprecated( + "1.6", + "Dependency Links processing has been deprecated with an " + "accelerated time schedule and will be removed in pip 1.6", + ) + self._have_warned_dependency_links = True + self.dependency_links.extend(links) def _sort_locations(self, locations): """ @@ -114,7 +113,7 @@ class PackageFinder(object): # puts the url for the given file path into the appropriate list def sort_path(path): - url = path_to_url2(path) + url = path_to_url(path) if mimetypes.guess_type(url, strict=False)[0] == 'text/html': urls.append(url) else: @@ -160,11 +159,13 @@ class PackageFinder(object): parsed_version, link, _ = link_tuple if self.use_wheel: support_num = len(supported_tags) - if link == InfLink: # existing install + if link == INSTALLED_VERSION: pri = 1 - elif link.wheel: - # all wheel links are known to be supported at this stage - pri = -(link.wheel.support_index_min()) + elif link.ext == wheel_ext: + wheel = Wheel(link.filename) # can raise InvalidWheelFilename + if not wheel.supported(): + raise UnsupportedWheel("%s is not a supported wheel for this platform. It can't be sorted." % wheel.filename) + pri = -(wheel.support_index_min()) else: # sdist pri = -(support_num) return (parsed_version, pri) @@ -202,14 +203,10 @@ class PackageFinder(object): if page is None: url_name = self._find_url_name(Link(self.index_urls[0], trusted=True), url_name, req) or req.url_name - # Combine index URLs with mirror URLs here to allow - # adding more index URLs from requirements files - all_index_urls = self.index_urls + self.mirror_urls - if url_name is not None: locations = [ mkurl_pypi_url(url) - for url in all_index_urls] + self.find_links + for url in self.index_urls] + self.find_links else: locations = list(self.find_links) for version in req.absolute_versions: @@ -222,8 +219,7 @@ class PackageFinder(object): file_locations.extend(_flocations) # We trust every url that the user has given us whether it was given - # via --index-url, --user-mirrors/--mirror, or --find-links or a - # default option thereof + # via --index-url or --find-links locations = [Link(url, trusted=True) for url in url_locations] # We explicitly do not trust links that came from dependency_links @@ -232,6 +228,29 @@ class PackageFinder(object): logger.debug('URLs to search for versions for %s:' % req) for location in locations: logger.debug('* %s' % location) + + # Determine if this url used a secure transport mechanism + parsed = urlparse.urlparse(str(location)) + if parsed.scheme in INSECURE_SCHEMES: + secure_schemes = INSECURE_SCHEMES[parsed.scheme] + + if len(secure_schemes) == 1: + ctx = (location, parsed.scheme, secure_schemes[0], + parsed.netloc) + logger.warn("%s uses an insecure transport scheme (%s). " + "Consider using %s if %s has it available" % + ctx) + elif len(secure_schemes) > 1: + ctx = (location, parsed.scheme, ", ".join(secure_schemes), + parsed.netloc) + logger.warn("%s uses an insecure transport scheme (%s). " + "Consider using one of %s if %s has any of " + "them available" % ctx) + else: + ctx = (location, parsed.scheme) + logger.warn("%s uses an insecure transport scheme (%s)." % + ctx) + found_versions = [] found_versions.extend( self._package_versions( @@ -258,14 +277,15 @@ class PackageFinder(object): logger.warn("Some externally hosted files were ignored (use " "--allow-external %s to allow)." % req.name) - if self.need_warn_insecure: + if self.need_warn_unverified: logger.warn("Some insecure and unverifiable files were ignored" - " (use --allow-insecure %s to allow)." % req.name) + " (use --allow-unverified %s to allow)." % + req.name) raise DistributionNotFound('No distributions at all found for %s' % req) installed_version = [] if req.satisfied_by is not None: - installed_version = [(req.satisfied_by.parsed_version, InfLink, req.satisfied_by.version)] + installed_version = [(req.satisfied_by.parsed_version, INSTALLED_VERSION, req.satisfied_by.version)] if file_versions: file_versions.sort(reverse=True) logger.info('Local files found: %s' % ', '.join([url_to_path(link.url) for parsed, link, version in file_versions])) @@ -280,14 +300,14 @@ class PackageFinder(object): elif is_prerelease(version) and not (self.allow_all_prereleases or req.prereleases): # If this version isn't the already installed one, then # ignore it if it's a pre-release. - if link is not InfLink: + if link is not INSTALLED_VERSION: logger.info("Ignoring link %s, version %s is a pre-release (use --pre to allow)." % (link, version)) continue applicable_versions.append((parsed_version, link, version)) applicable_versions = self._sort_versions(applicable_versions) - existing_applicable = bool([link for parsed_version, link, version in applicable_versions if link is InfLink]) + existing_applicable = bool([link for parsed_version, link, version in applicable_versions if link is INSTALLED_VERSION]) if not upgrade and existing_applicable: - if applicable_versions[0][1] is InfLink: + if applicable_versions[0][1] is INSTALLED_VERSION: logger.info('Existing installed version (%s) is most up-to-date and satisfies requirement' % req.satisfied_by.version) else: @@ -302,12 +322,13 @@ class PackageFinder(object): logger.warn("Some externally hosted files were ignored (use " "--allow-external to allow).") - if self.need_warn_insecure: + if self.need_warn_unverified: logger.warn("Some insecure and unverifiable files were ignored" - " (use --allow-insecure %s to allow)." % req.name) + " (use --allow-unverified %s to allow)." % + req.name) raise DistributionNotFound('No distributions matching the version for %s' % req) - if applicable_versions[0][1] is InfLink: + if applicable_versions[0][1] is INSTALLED_VERSION: # We have an existing version, and its the best version logger.info('Installed version (%s) is most up-to-date (past versions: %s)' % (req.satisfied_by.version, ', '.join([version for parsed_version, link, version in applicable_versions[1:]]) or 'none')) @@ -318,18 +339,22 @@ class PackageFinder(object): selected_version = applicable_versions[0][1] - # TODO: Remove after 1.4 has been released if (selected_version.internal is not None and not selected_version.internal): - logger.warn("You are installing an externally hosted file. Future " - "versions of pip will default to disallowing " - "externally hosted files.") + logger.warn("%s an externally hosted file and may be " + "unreliable" % req.name) if (selected_version.verifiable is not None and not selected_version.verifiable): - logger.warn("You are installing a potentially insecure and " - "unverifiable file. Future versions of pip will " - "default to disallowing insecure files.") + logger.warn("%s is potentially insecure and " + "unverifiable." % req.name) + + if selected_version._deprecated_regex: + logger.deprecated( + "1.7", + "%s discovered using a deprecated method of parsing, " + "in the future it will no longer be discovered" % req.name + ) return selected_version @@ -354,38 +379,25 @@ class PackageFinder(object): return None def _get_pages(self, locations, req): - """Yields (page, page_url) from the given locations, skipping - locations that have errors, and adding download/homepage links""" - pending_queue = Queue() - for location in locations: - pending_queue.put(location) - done = [] + """ + Yields (page, page_url) from the given locations, skipping + locations that have errors, and adding download/homepage links + """ + all_locations = list(locations) seen = set() - threads = [] - for i in range(min(10, len(locations))): - t = threading.Thread(target=self._get_queued_page, args=(req, pending_queue, done, seen)) - t.setDaemon(True) - threads.append(t) - t.start() - for t in threads: - t.join() - return done - _log_lock = threading.Lock() - - def _get_queued_page(self, req, pending_queue, done, seen): - while 1: - try: - location = pending_queue.get(False) - except QueueEmpty: - return + while all_locations: + location = all_locations.pop(0) if location in seen: continue seen.add(location) + page = self._get_page(location, req) if page is None: continue - done.append(page) + + yield page + for link in page.rel_links(): normalized = normalize_name(req.name).lower() @@ -398,15 +410,14 @@ class PackageFinder(object): if (link.trusted is not None and not link.trusted - and not normalized in self.allow_insecure - and not self.allow_all_insecure): # TODO: Remove after release + and not normalized in self.allow_unverified): logger.debug("Not searching %s for urls, it is an " "untrusted link and cannot produce safe or " "verifiable files." % link) - self.need_warn_insecure = True + self.need_warn_unverified = True continue - pending_queue.put(link) + all_locations.append(link) _egg_fragment_re = re.compile(r'#egg=([^&]*)') _egg_info_re = re.compile(r'([a-z0-9_.]+)-([a-z0-9_.-]+)', re.I) @@ -470,30 +481,39 @@ class PackageFinder(object): logger.debug('Skipping link %s; macosx10 one' % (link)) self.logged_links.add(link) return [] - if link.wheel and link.wheel.name.lower() == search_name.lower(): - version = link.wheel.version - if not link.wheel.supported(): + if ext == wheel_ext: + try: + wheel = Wheel(link.filename) + except InvalidWheelFilename: + logger.debug('Skipping %s because the wheel filename is invalid' % link) + return [] + if wheel.name.lower() != search_name.lower(): + logger.debug('Skipping link %s; wrong project name (not %s)' % (link, search_name)) + return [] + if not wheel.supported(): logger.debug('Skipping %s because it is not compatible with this Python' % link) return [] - # This is a dirty hack to prevent installing Binary Wheels from - # PyPI or one of its mirrors unless it is a Windows Binary - # Wheel. This is paired with a change to PyPI disabling - # uploads for the same. Once we have a mechanism for enabling - # support for binary wheels on linux that deals with the - # inherent problems of binary distribution this can be - # removed. + # PyPI unless it is a Windows or Mac Binary Wheel. This is + # paired with a change to PyPI disabling uploads for the + # same. Once we have a mechanism for enabling support for binary + # wheels on linux that deals with the inherent problems of + # binary distribution this can be removed. comes_from = getattr(link, "comes_from", None) - if (not platform.startswith('win') + if (( + not platform.startswith('win') + and not platform.startswith('macosx') + ) and comes_from is not None and urlparse.urlparse(comes_from.url).netloc.endswith( "pypi.python.org")): - if not link.wheel.supported(tags=supported_tags_noarch): + if not wheel.supported(tags=supported_tags_noarch): logger.debug( "Skipping %s because it is a pypi-hosted binary " "Wheel on an unsupported platform" % link ) return [] + version = wheel.version if not version: version = self._egg_info_matches(egg_info, search_name, link) @@ -513,14 +533,14 @@ class PackageFinder(object): if (link.verifiable is not None and not link.verifiable - and not normalize_name(search_name).lower() in self.allow_insecure - and not self.allow_all_insecure): # TODO: Remove after release + and not (normalize_name(search_name).lower() + in self.allow_unverified)): # We have a link that we are sure we cannot verify it's integrity, # so we should skip it unless we are allowing unsafe installs # for this requirement. logger.debug("Skipping %s because it is an insecure and " "unverifiable file." % link) - self.need_warn_insecure = True + self.need_warn_unverified = True return [] match = self._py_version_re.search(version) @@ -551,28 +571,10 @@ class PackageFinder(object): return None def _get_page(self, link, req): - return HTMLPage.get_page(link, req, cache=self.cache) - - def _get_mirror_urls(self, mirrors=None, main_mirror_url=None): - """Retrieves a list of URLs from the main mirror DNS entry - unless a list of mirror URLs are passed. - """ - if not mirrors: - mirrors = get_mirrors(main_mirror_url) - # Should this be made "less random"? E.g. netselect like? - random.shuffle(mirrors) - - mirror_urls = set() - for mirror_url in mirrors: - mirror_url = mirror_url.rstrip('/') - # Make sure we have a valid URL - if not any([mirror_url.startswith(scheme) for scheme in ["http://", "https://", "file://"]]): - mirror_url = "http://%s" % mirror_url - if not mirror_url.endswith("/simple"): - mirror_url = "%s/simple" % mirror_url - mirror_urls.add(mirror_url + '/') - - return list(mirror_urls) + return HTMLPage.get_page(link, req, + cache=self.cache, + session=self.session, + ) class PageCache(object): @@ -624,7 +626,10 @@ class HTMLPage(object): return self.url @classmethod - def get_page(cls, link, req, cache=None, skip_archives=True): + def get_page(cls, link, req, cache=None, skip_archives=True, session=None): + if session is None: + session = PipSession() + url = link.url url = url.split('#', 1)[0] if cache.too_many_failures(url): @@ -649,7 +654,9 @@ class HTMLPage(object): filename = link.filename for bad_ext in ['.tar', '.tar.gz', '.tar.bz2', '.tgz', '.zip']: if filename.endswith(bad_ext): - content_type = cls._get_content_type(url) + content_type = cls._get_content_type(url, + session=session, + ) if content_type.lower().startswith('text/html'): break else: @@ -668,18 +675,8 @@ class HTMLPage(object): url = urlparse.urljoin(url, 'index.html') logger.debug(' file: URL is directory, getting %s' % url) - resp = urlopen(url) - - real_url = geturl(resp) - headers = resp.info() - contents = resp.read() - encoding = headers.get('Content-Encoding', None) - #XXX need to handle exceptions and add testing for this - if encoding is not None: - if encoding == 'gzip': - contents = gzip.GzipFile(fileobj=BytesIO(contents)).read() - if encoding == 'deflate': - contents = zlib.decompress(contents) + resp = session.get(url) + resp.raise_for_status() # The check for archives above only works if the url ends with # something that looks like an archive. However that is not a @@ -688,7 +685,7 @@ class HTMLPage(object): # Unless we issue a HEAD request on every url we cannot know # ahead of time for sure if something is HTML or not. However we # can check after we've downloaded it. - content_type = headers.get('Content-Type', 'unknown') + content_type = resp.headers.get('Content-Type', 'unknown') if not content_type.lower().startswith("text/html"): logger.debug('Skipping page %s because of Content-Type: %s' % (link, content_type)) @@ -696,59 +693,53 @@ class HTMLPage(object): cache.set_is_archive(url) return None - inst = cls(u(contents), real_url, headers, trusted=link.trusted) - except (HTTPError, URLError, socket.timeout, socket.error, OSError, WindowsError): - e = sys.exc_info()[1] - desc = str(e) - if isinstance(e, socket.timeout): - log_meth = logger.info - level =1 - desc = 'timed out' - elif isinstance(e, URLError): - #ssl/certificate error - if hasattr(e, 'reason') and (isinstance(e.reason, ssl.SSLError) or isinstance(e.reason, CertificateError)): - desc = 'There was a problem confirming the ssl certificate: %s' % e - log_meth = logger.notify - else: - log_meth = logger.info - if hasattr(e, 'reason') and isinstance(e.reason, socket.timeout): - desc = 'timed out' - level = 1 - else: - level = 2 - elif isinstance(e, HTTPError) and e.code == 404: - ## FIXME: notify? - log_meth = logger.info - level = 2 - else: - log_meth = logger.info - level = 1 - log_meth('Could not fetch URL %s: %s' % (link, desc)) - log_meth('Will skip URL %s when looking for download links for %s' % (link.url, req)) + inst = cls(resp.text, resp.url, resp.headers, trusted=link.trusted) + except requests.HTTPError as exc: + level = 2 if exc.response.status_code == 404 else 1 + cls._handle_fail(req, link, exc, url, cache=cache, level=level) + except requests.Timeout: + cls._handle_fail(req, link, "timed out", url, cache=cache) + except SSLError as exc: + reason = ("There was a problem confirming the ssl certificate: " + "%s" % exc) + cls._handle_fail(req, link, reason, url, + cache=cache, + level=2, + meth=logger.notify, + ) + else: if cache is not None: - cache.add_page_failure(url, level) - return None - if cache is not None: - cache.add_page([url, real_url], inst) - return inst + cache.add_page([url, resp.url], inst) + return inst @staticmethod - def _get_content_type(url): + def _handle_fail(req, link, reason, url, cache=None, level=1, meth=None): + if meth is None: + meth = logger.info + + meth("Could not fetch URL %s: %s", link, reason) + meth("Will skip URL %s when looking for download links for %s" % + (link.url, req)) + + if cache is not None: + cache.add_page_failure(url, level) + + @staticmethod + def _get_content_type(url, session=None): """Get the Content-Type of the given url, using a HEAD request""" + if session is None: + session = PipSession() + scheme, netloc, path, query, fragment = urlparse.urlsplit(url) if not scheme in ('http', 'https', 'ftp', 'ftps'): ## FIXME: some warning or something? ## assertion error? return '' - req = Urllib2HeadRequest(url, headers={'Host': netloc}) - resp = urlopen(req) - try: - if hasattr(resp, 'code') and resp.code != 200 and scheme not in ('ftp', 'ftps'): - ## FIXME: doesn't handle redirects - return '' - return resp.info().get('content-type', '') - finally: - resp.close() + + resp = session.head(url, allow_redirects=True) + resp.raise_for_status() + + return resp.headers.get("Content-Type", "") @property def api_version(self): @@ -828,7 +819,7 @@ class HTMLPage(object): if not url: continue url = self.clean_link(urlparse.urljoin(self.base_url, url)) - yield Link(url, self, trusted=False) + yield Link(url, self, trusted=False, _deprecated_regex=True) _clean_re = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I) @@ -842,16 +833,13 @@ class HTMLPage(object): class Link(object): - def __init__(self, url, comes_from=None, internal=None, trusted=None): + def __init__(self, url, comes_from=None, internal=None, trusted=None, + _deprecated_regex=False): self.url = url self.comes_from = comes_from self.internal = internal self.trusted = trusted - - # Set whether it's a wheel - self.wheel = None - if url != Inf and self.splitext()[1] == wheel_ext: - self.wheel = Wheel(self.filename) + self._deprecated_regex = _deprecated_regex def __str__(self): if self.comes_from: @@ -901,6 +889,10 @@ class Link(object): def splitext(self): return splitext(posixpath.basename(self.path.rstrip('/'))) + @property + def ext(self): + return self.splitext()[1] + @property def url_without_fragment(self): scheme, netloc, path, query, fragment = urlparse.urlsplit(self.url) @@ -970,8 +962,10 @@ class Link(object): # This link came from an untrusted source and we cannot trust it return False -#An "Infinite Link" that compares greater than other links -InfLink = Link(Inf) #this object is not currently used as a sortable + +# An object to represent the "link" for the installed version of a requirement. +# Using Inf as the url makes it sort higher. +INSTALLED_VERSION = Link(Inf) def get_requirement_from_url(url): @@ -997,45 +991,3 @@ def package_to_requirement(package_name): return '%s==%s' % (name, version) else: return name - - -def get_mirrors(hostname=None): - """Return the list of mirrors from the last record found on the DNS - entry:: - - >>> from pip.index import get_mirrors - >>> get_mirrors() - ['a.pypi.python.org', 'b.pypi.python.org', 'c.pypi.python.org', - 'd.pypi.python.org'] - - Originally written for the distutils2 project by Alexis Metaireau. - """ - if hostname is None: - hostname = DEFAULT_MIRROR_HOSTNAME - - # return the last mirror registered on PyPI. - last_mirror_hostname = None - try: - last_mirror_hostname = socket.gethostbyname_ex(hostname)[0] - except socket.gaierror: - return [] - if not last_mirror_hostname or last_mirror_hostname == DEFAULT_MIRROR_HOSTNAME: - last_mirror_hostname = "z.pypi.python.org" - end_letter = last_mirror_hostname.split(".", 1) - - # determine the list from the last one. - return ["%s.%s" % (s, end_letter[1]) for s in string_range(end_letter[0])] - - -def string_range(last): - """Compute the range of string between "a" and last. - - This works for simple "a to z" lists, but also for "a to zz" lists. - """ - for k in range(len(last)): - for x in product(string.ascii_lowercase, repeat=k+1): - result = ''.join(x) - yield result - if result == last: - return - diff --git a/awx/lib/site-packages/pip/locations.py b/awx/lib/site-packages/pip/locations.py index 26d8676b69..1d40265168 100644 --- a/awx/lib/site-packages/pip/locations.py +++ b/awx/lib/site-packages/pip/locations.py @@ -6,10 +6,9 @@ import os import tempfile from distutils.command.install import install, SCHEME_KEYS import getpass -from pip.backwardcompat import get_python_lib +from pip.backwardcompat import get_python_lib, get_path_uid, user_site import pip.exceptions -default_cert_path = os.path.join(os.path.dirname(__file__), 'cacert.pem') DELETE_MARKER_MESSAGE = '''\ This file is placed here by pip to indicate the source was put @@ -35,7 +34,12 @@ def running_under_virtualenv(): Return True if we're running inside a virtualenv, False otherwise. """ - return hasattr(sys, 'real_prefix') + if hasattr(sys, 'real_prefix'): + return True + elif sys.prefix != getattr(sys, "base_prefix", sys.prefix): + return True + + return False def virtualenv_no_global(): @@ -68,17 +72,18 @@ def _get_build_prefix(): except OSError: file_uid = None try: - fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) - file_uid = os.fstat(fd).st_uid - os.close(fd) + # raises OSError for symlinks + # https://github.com/pypa/pip/pull/935#discussion_r5307003 + file_uid = get_path_uid(path) except OSError: file_uid = None + if file_uid != os.geteuid(): - msg = "The temporary folder for building (%s) is not owned by your user!" \ + msg = "The temporary folder for building (%s) is either not owned by you, or is a symlink." \ % path print (msg) print("pip will not work until the temporary folder is " + \ - "either deleted or owned by your user account.") + "either deleted or is a real directory owned by your user account.") raise pip.exceptions.InstallationError(msg) return path @@ -86,9 +91,8 @@ if running_under_virtualenv(): build_prefix = os.path.join(sys.prefix, 'build') src_prefix = os.path.join(sys.prefix, 'src') else: - # Use tempfile to create a temporary folder for build - # Note: we are NOT using mkdtemp so we can have a consistent build dir - # Note: using realpath due to tmp dirs on OSX being symlinks + # Note: intentionally NOT using mkdtemp + # See https://github.com/pypa/pip/issues/906 for plan to move to mkdtemp build_prefix = _get_build_prefix() ## FIXME: keep src in cwd for now (it is not a temporary folder) @@ -100,6 +104,7 @@ else: # under Mac OS X + virtualenv sys.prefix is not properly resolved # it is something like /path/to/python/bin/.. +# Note: using realpath due to tmp dirs on OSX being symlinks build_prefix = os.path.abspath(os.path.realpath(build_prefix)) src_prefix = os.path.abspath(src_prefix) @@ -109,14 +114,17 @@ site_packages = get_python_lib() user_dir = os.path.expanduser('~') if sys.platform == 'win32': bin_py = os.path.join(sys.prefix, 'Scripts') + bin_user = os.path.join(user_site, 'Scripts') if user_site else None # buildout uses 'bin' on Windows too? if not os.path.exists(bin_py): bin_py = os.path.join(sys.prefix, 'bin') + bin_user = os.path.join(user_site, 'bin') if user_site else None default_storage_dir = os.path.join(user_dir, 'pip') default_config_file = os.path.join(default_storage_dir, 'pip.ini') default_log_file = os.path.join(default_storage_dir, 'pip.log') else: bin_py = os.path.join(sys.prefix, 'bin') + bin_user = os.path.join(user_site, 'bin') if user_site else None default_storage_dir = os.path.join(user_dir, '.pip') default_config_file = os.path.join(default_storage_dir, 'pip.conf') default_log_file = os.path.join(default_storage_dir, 'pip.log') @@ -128,7 +136,7 @@ else: default_log_file = os.path.join(user_dir, 'Library/Logs/pip.log') -def distutils_scheme(dist_name, user=False, home=None): +def distutils_scheme(dist_name, user=False, home=None, root=None): """ Return a distutils install scheme """ @@ -136,16 +144,18 @@ def distutils_scheme(dist_name, user=False, home=None): scheme = {} d = Distribution({'name': dist_name}) - i = install(d) + d.parse_config_files() + i = d.get_command_obj('install', create=True) + # NOTE: setting user or home has the side-effect of creating the home dir or + # user base for installations during finalize_options() + # ideally, we'd prefer a scheme class that has no side-effects. i.user = user or i.user i.home = home or i.home + i.root = root or i.root i.finalize_options() for key in SCHEME_KEYS: scheme[key] = getattr(i, 'install_'+key) - #be backward-compatible with what pip has always done? - scheme['scripts'] = bin_py - if running_under_virtualenv(): scheme['headers'] = os.path.join(sys.prefix, 'include', @@ -153,4 +163,10 @@ def distutils_scheme(dist_name, user=False, home=None): 'python' + sys.version[:3], dist_name) + if root is not None: + scheme["headers"] = os.path.join( + root, + os.path.abspath(scheme["headers"])[1:], + ) + return scheme diff --git a/awx/lib/site-packages/pip/log.py b/awx/lib/site-packages/pip/log.py index 9eb02b90d2..6770a042d6 100644 --- a/awx/lib/site-packages/pip/log.py +++ b/awx/lib/site-packages/pip/log.py @@ -2,9 +2,56 @@ """ import sys +import os import logging +import pkg_resources + from pip import backwardcompat +from pip._vendor import colorama + + +def _color_wrap(*colors): + def wrapped(inp): + return "".join(list(colors) + [inp, colorama.Style.RESET_ALL]) + return wrapped + + +def should_color(consumer, environ, std=(sys.stdout, sys.stderr)): + real_consumer = (consumer if not isinstance(consumer, colorama.AnsiToWin32) + else consumer.wrapped) + + # If consumer isn't stdout or stderr we shouldn't colorize it + if real_consumer not in std: + return False + + # If consumer is a tty we should color it + if hasattr(real_consumer, "isatty") and real_consumer.isatty(): + return True + + # If we have an ASNI term we should color it + if environ.get("TERM") == "ANSI": + return True + + # If anything else we should not color it + return False + + +def should_warn(current_version, removal_version): + # Our Significant digits on versions is 2, so remove everything but the + # first two places. + current_version = ".".join(current_version.split(".")[:2]) + removal_version = ".".join(removal_version.split(".")[:2]) + + # Our warning threshold is one minor version before removal, so we + # decrement the minor version by one + major, minor = removal_version.split(".") + minor = str(int(minor) - 1) + warn_version = ".".join([major, minor]) + + # Test if our current_version should be a warn + return (pkg_resources.parse_version(current_version) + < pkg_resources.parse_version(warn_version)) class Logger(object): @@ -22,6 +69,12 @@ class Logger(object): LEVELS = [VERBOSE_DEBUG, DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL] + COLORS = { + WARN: _color_wrap(colorama.Fore.YELLOW), + ERROR: _color_wrap(colorama.Fore.RED), + FATAL: _color_wrap(colorama.Fore.RED), + } + def __init__(self): self.consumers = [] self.indent = 0 @@ -29,6 +82,18 @@ class Logger(object): self.in_progress = None self.in_progress_hanging = False + def add_consumers(self, *consumers): + if sys.platform.startswith("win"): + for level, consumer in consumers: + if hasattr(consumer, "write"): + self.consumers.append( + (level, colorama.AnsiToWin32(consumer)), + ) + else: + self.consumers.append((level, consumer)) + else: + self.consumers.extend(consumers) + def debug(self, msg, *args, **kw): self.log(self.DEBUG, msg, *args, **kw) @@ -42,18 +107,45 @@ class Logger(object): self.log(self.WARN, msg, *args, **kw) def error(self, msg, *args, **kw): - self.log(self.WARN, msg, *args, **kw) + self.log(self.ERROR, msg, *args, **kw) def fatal(self, msg, *args, **kw): self.log(self.FATAL, msg, *args, **kw) + def deprecated(self, removal_version, msg, *args, **kwargs): + """ + Logs deprecation message which is log level WARN if the + ``removal_version`` is > 1 minor release away and log level ERROR + otherwise. + + removal_version should be the version that the deprecated feature is + expected to be removed in, so something that will not exist in + version 1.7, but will in 1.6 would have a removal_version of 1.7. + """ + from pip import __version__ + + if should_warn(__version__, removal_version): + self.warn(msg, *args, **kwargs) + else: + self.error(msg, *args, **kwargs) + def log(self, level, msg, *args, **kw): if args: if kw: raise TypeError( "You may give positional or keyword arguments, not both") args = args or kw - rendered = None + + # render + if args: + rendered = msg % args + else: + rendered = msg + rendered = ' ' * self.indent + rendered + if self.explicit_levels: + ## FIXME: should this be a name, not a level number? + rendered = '%02i %s' % (level, rendered) + for consumer_level, consumer in self.consumers: if self.level_matches(level, consumer_level): if (self.in_progress_hanging @@ -61,18 +153,17 @@ class Logger(object): self.in_progress_hanging = False sys.stdout.write('\n') sys.stdout.flush() - if rendered is None: - if args: - rendered = msg % args - else: - rendered = msg - rendered = ' ' * self.indent + rendered - if self.explicit_levels: - ## FIXME: should this be a name, not a level number? - rendered = '%02i %s' % (level, rendered) if hasattr(consumer, 'write'): - rendered += '\n' - backwardcompat.fwrite(consumer, rendered) + write_content = rendered + '\n' + if should_color(consumer, os.environ): + # We are printing to stdout or stderr and it supports + # colors so render our text colored + colorizer = self.COLORS.get(level, lambda x: x) + write_content = colorizer(write_content) + + consumer.write(write_content) + if hasattr(consumer, 'flush'): + consumer.flush() else: consumer(rendered) diff --git a/awx/lib/site-packages/pip/req.py b/awx/lib/site-packages/pip/req.py index 93af61c9d3..f05aeeb66b 100644 --- a/awx/lib/site-packages/pip/req.py +++ b/awx/lib/site-packages/pip/req.py @@ -1,6 +1,7 @@ from email.parser import FeedParser import os import imp +import locale import pkg_resources import re import sys @@ -11,9 +12,9 @@ import zipfile from distutils.util import change_root from pip.locations import (bin_py, running_under_virtualenv,PIP_DELETE_MARKER_FILENAME, - write_delete_marker_file) -from pip.exceptions import (InstallationError, UninstallationError, - BestVersionAlreadyInstalled, + write_delete_marker_file, bin_user) +from pip.exceptions import (InstallationError, UninstallationError, UnsupportedWheel, + BestVersionAlreadyInstalled, InvalidWheelFilename, DistributionNotFound, PreviousBuildDirError) from pip.vcs import vcs from pip.log import logger @@ -27,18 +28,43 @@ from pip.backwardcompat import (urlparse, urllib, uses_pycache, get_python_version, b) from pip.index import Link from pip.locations import build_prefix -from pip.download import (get_file_content, is_url, url_to_path, +from pip.download import (PipSession, get_file_content, is_url, url_to_path, path_to_url, is_archive_file, unpack_vcs_link, is_vcs_url, is_file_url, unpack_file_url, unpack_http_url) import pip.wheel -from pip.wheel import move_wheel_files +from pip.wheel import move_wheel_files, Wheel, wheel_ext + + +def read_text_file(filename): + """Return the contents of *filename*. + + Try to decode the file contents with utf-8, the preffered system encoding + (e.g., cp1252 on some Windows machines) and latin1, in that order. Decoding + a byte string with latin1 will never raise an error. In the worst case, the + returned string will contain some garbage characters. + + """ + with open(filename, 'rb') as fp: + data = fp.read() + + encodings = ['utf-8', locale.getpreferredencoding(False), 'latin1'] + for enc in encodings: + try: + data = data.decode(enc) + except UnicodeDecodeError: + continue + break + + assert type(data) != bytes # Latin1 should have worked. + return data + class InstallRequirement(object): def __init__(self, req, comes_from, source_dir=None, editable=False, url=None, as_egg=False, update=True, prereleases=None, - from_bundle=False): + editable_options=None, from_bundle=False, pycompile=True): self.extras = () if isinstance(req, string_types): req = pkg_resources.Requirement.parse(req) @@ -47,6 +73,11 @@ class InstallRequirement(object): self.comes_from = comes_from self.source_dir = source_dir self.editable = editable + + if editable_options is None: + editable_options = {} + + self.editable_options = editable_options self.url = url self.as_egg = as_egg self._egg_info_path = None @@ -68,6 +99,8 @@ class InstallRequirement(object): self.target_dir = None self.from_bundle = from_bundle + self.pycompile = pycompile + # True if pre-releases are acceptable if prereleases: self.prereleases = True @@ -84,7 +117,11 @@ class InstallRequirement(object): else: source_dir = None - res = cls(name, comes_from, source_dir=source_dir, editable=True, url=url, prereleases=True) + res = cls(name, comes_from, source_dir=source_dir, + editable=True, + url=url, + editable_options=extras_override, + prereleases=True) if extras_override is not None: res.extras = extras_override @@ -123,6 +160,12 @@ class InstallRequirement(object): if link.scheme == 'file' and re.search(r'\.\./', url): url = path_to_url(os.path.normpath(os.path.abspath(link.path))) + # fail early for invalid or unsupported wheels + if link.ext == wheel_ext: + wheel = Wheel(link.filename) # can raise InvalidWheelFilename + if not wheel.supported(): + raise UnsupportedWheel("%s is not a supported wheel on this platform." % wheel.filename) + else: req = name @@ -218,14 +261,24 @@ class InstallRequirement(object): @property def setup_py(self): - return os.path.join(self.source_dir, 'setup.py') + setup_file = 'setup.py' + + if self.editable_options and 'subdirectory' in self.editable_options: + setup_py = os.path.join(self.source_dir, + self.editable_options['subdirectory'], + setup_file) + + else: + setup_py = os.path.join(self.source_dir, setup_file) + + return setup_py def run_egg_info(self, force_root_egg_info=False): assert self.source_dir if self.name: - logger.notify('Running setup.py egg_info for package %s' % self.name) + logger.notify('Running setup.py (path:%s) egg_info for package %s' % (self.setup_py, self.name)) else: - logger.notify('Running setup.py egg_info for package from %s' % self.url) + logger.notify('Running setup.py (path:%s) egg_info for package from %s' % (self.setup_py, self.url)) logger.indent += 2 try: @@ -271,6 +324,7 @@ __file__ = __SETUP_PY__ from setuptools.command import egg_info import pkg_resources import os +import tokenize def replacement_run(self): self.mkpath(self.egg_info) installer = self.distribution.fetch_build_egg @@ -281,7 +335,7 @@ def replacement_run(self): writer(self, ep.name, os.path.join(self.egg_info,ep.name)) self.find_sources() egg_info.egg_info.run = replacement_run -exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec')) +exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec')) """ def egg_info_data(self, filename): @@ -293,9 +347,7 @@ exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec')) filename = self.egg_info_path(filename) if not os.path.exists(filename): return None - fp = open(filename, 'r') - data = fp.read() - fp.close() + data = read_text_file(filename) return data def egg_info_path(self, filename): @@ -506,9 +558,13 @@ exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec')) # find distutils scripts= scripts if dist.has_metadata('scripts') and dist.metadata_isdir('scripts'): for script in dist.metadata_listdir('scripts'): - paths_to_remove.add(os.path.join(bin_py, script)) + if dist_in_usersite(dist): + bin_dir = bin_user + else: + bin_dir = bin_py + paths_to_remove.add(os.path.join(bin_dir, script)) if sys.platform == 'win32': - paths_to_remove.add(os.path.join(bin_py, script) + '.bat') + paths_to_remove.add(os.path.join(bin_dir, script) + '.bat') # find console_scripts if dist.has_metadata('entry_points.txt'): @@ -516,11 +572,15 @@ exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec')) config.readfp(FakeFile(dist.get_metadata_lines('entry_points.txt'))) if config.has_section('console_scripts'): for name, value in config.items('console_scripts'): - paths_to_remove.add(os.path.join(bin_py, name)) + if dist_in_usersite(dist): + bin_dir = bin_user + else: + bin_dir = bin_py + paths_to_remove.add(os.path.join(bin_dir, name)) if sys.platform == 'win32': - paths_to_remove.add(os.path.join(bin_py, name) + '.exe') - paths_to_remove.add(os.path.join(bin_py, name) + '.exe.manifest') - paths_to_remove.add(os.path.join(bin_py, name) + '-script.py') + paths_to_remove.add(os.path.join(bin_dir, name) + '.exe') + paths_to_remove.add(os.path.join(bin_dir, name) + '.exe.manifest') + paths_to_remove.add(os.path.join(bin_dir, name) + '-script.py') paths_to_remove.remove(auto_confirm) self.uninstalled = paths_to_remove @@ -592,7 +652,7 @@ exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec')) self.install_editable(install_options, global_options) return if self.is_wheel: - self.move_wheel_files(self.source_dir) + self.move_wheel_files(self.source_dir, root=root) self.install_succeeded = True return @@ -602,8 +662,8 @@ exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec')) install_args = [sys.executable] install_args.append('-c') install_args.append( - "import setuptools;__file__=%r;"\ - "exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))" % self.setup_py) + "import setuptools, tokenize;__file__=%r;"\ + "exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))" % self.setup_py) install_args += list(global_options) + ['install','--record', record_filename] if not self.as_egg: @@ -612,6 +672,11 @@ exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec')) if root is not None: install_args += ['--root', root] + if self.pycompile: + install_args += ["--compile"] + else: + install_args += ["--no-compile"] + if running_under_virtualenv(): ## FIXME: I'm not sure if this is a reasonable location; probably not ## but we can't put it in the default location, as that is a virtualenv symlink that isn't writable @@ -687,7 +752,7 @@ exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec')) ## FIXME: should we do --install-headers here too? call_subprocess( [sys.executable, '-c', - "import setuptools; __file__=%r; exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))" % self.setup_py] + "import setuptools, tokenize; __file__=%r; exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))" % self.setup_py] + list(global_options) + ['develop', '--no-deps'] + list(install_options), cwd=self.source_dir, filter_stdout=self._filter_install, @@ -811,8 +876,14 @@ exec(compile(open(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec')) self._bundle_build_dirs = bundle_build_dirs self._bundle_editable_dirs = bundle_editable_dirs - def move_wheel_files(self, wheeldir): - move_wheel_files(self.name, self.req, wheeldir, user=self.use_user_site, home=self.target_dir) + def move_wheel_files(self, wheeldir, root=None): + move_wheel_files( + self.name, self.req, wheeldir, + user=self.use_user_site, + home=self.target_dir, + root=root, + pycompile=self.pycompile, + ) @property def delete_marker_filename(self): @@ -852,7 +923,8 @@ class RequirementSet(object): def __init__(self, build_dir, src_dir, download_dir, download_cache=None, upgrade=False, ignore_installed=False, as_egg=False, target_dir=None, - ignore_dependencies=False, force_reinstall=False, use_user_site=False): + ignore_dependencies=False, force_reinstall=False, use_user_site=False, + session=None, pycompile=True): self.build_dir = build_dir self.src_dir = src_dir self.download_dir = download_dir @@ -871,6 +943,8 @@ class RequirementSet(object): self.as_egg = as_egg self.use_user_site = use_user_site self.target_dir = target_dir #set from --target option + self.session = session or PipSession() + self.pycompile = pycompile def __str__(self): reqs = [req for req in self.requirements.values() @@ -883,6 +957,7 @@ class RequirementSet(object): install_req.as_egg = self.as_egg install_req.use_user_site = self.use_user_site install_req.target_dir = self.target_dir + install_req.pycompile = self.pycompile if not name: #url or path requirement w/o an egg fragment self.unnamed_requirements.append(install_req) @@ -1067,16 +1142,13 @@ class RequirementSet(object): # inconsistencies are logged later, but do not fail the # installation. elif os.path.exists(os.path.join(location, 'setup.py')): - msg = textwrap.dedent(""" + raise PreviousBuildDirError(textwrap.dedent(""" pip can't proceed with requirement '%s' due to a pre-existing build directory. location: %s This is likely due to a previous installation that failed. pip is being responsible and not assuming it can delete this. Please delete it and try again. - """ % (req_to_install, location)) - e = PreviousBuildDirError(msg) - logger.fatal(msg) - raise e + """ % (req_to_install, location))) else: ## FIXME: this won't upgrade when there's an existing package unpacked in `location` if req_to_install.url is None: @@ -1143,7 +1215,8 @@ class RequirementSet(object): install = False # req_to_install.req is only avail after unpack for URL pkgs # repeat check_if_exists to uninstall-on-upgrade (#14) - req_to_install.check_if_exists() + if not self.ignore_installed: + req_to_install.check_if_exists() if req_to_install.satisfied_by: if self.upgrade or self.ignore_installed: #don't uninstall conflict if user install and and conflict is not user install @@ -1235,7 +1308,7 @@ class RequirementSet(object): else: if self.download_cache: self.download_cache = os.path.expanduser(self.download_cache) - retval = unpack_http_url(link, location, self.download_cache, self.download_dir) + retval = unpack_http_url(link, location, self.download_cache, self.download_dir, self.session) if only_download: write_delete_marker_file(location) return retval @@ -1394,13 +1467,20 @@ def _make_build_dir(build_dir): _scheme_re = re.compile(r'^(http|https|file):', re.I) -def parse_requirements(filename, finder=None, comes_from=None, options=None): +def parse_requirements(filename, finder=None, comes_from=None, options=None, + session=None): + if session is None: + session = PipSession() + skip_match = None skip_regex = options.skip_requirements_regex if options else None if skip_regex: skip_match = re.compile(skip_regex) reqs_file_dir = os.path.dirname(os.path.abspath(filename)) - filename, content = get_file_content(filename, comes_from=comes_from) + filename, content = get_file_content(filename, + comes_from=comes_from, + session=session, + ) for line_number, line in enumerate(content.splitlines()): line_number += 1 line = line.strip() @@ -1418,7 +1498,7 @@ def parse_requirements(filename, finder=None, comes_from=None, options=None): req_url = urlparse.urljoin(filename, req_url) elif not _scheme_re.search(req_url): req_url = os.path.join(os.path.dirname(filename), req_url) - for item in parse_requirements(req_url, finder, comes_from=filename, options=options): + for item in parse_requirements(req_url, finder, comes_from=filename, options=options, session=session): yield item elif line.startswith('-Z') or line.startswith('--always-unzip'): # No longer used, but previously these were used in @@ -1457,13 +1537,19 @@ def parse_requirements(filename, finder=None, comes_from=None, options=None): finder.allow_external |= set([normalize_name(line).lower()]) elif line.startswith("--allow-all-external"): finder.allow_all_external = True + # Remove in 1.7 elif line.startswith("--no-allow-external"): - finder.allow_external = False + pass + # Remove in 1.7 elif line.startswith("--no-allow-insecure"): - finder.allow_all_insecure = False + pass + # Remove after 1.7 elif line.startswith("--allow-insecure"): line = line[len("--allow-insecure"):].strip().lstrip("=") - finder.allow_insecure |= set([normalize_name(line).lower()]) + finder.allow_unverified |= set([normalize_name(line).lower()]) + elif line.startswith("--allow-unverified"): + line = line[len("--allow-unverified"):].strip().lstrip("=") + finder.allow_unverified |= set([normalize_name(line).lower()]) else: comes_from = '-r %s (line %s)' % (filename, line_number) if line.startswith('-e') or line.startswith('--editable'): @@ -1477,6 +1563,47 @@ def parse_requirements(filename, finder=None, comes_from=None, options=None): req = InstallRequirement.from_line(line, comes_from, prereleases=getattr(options, "pre", None)) yield req +def _strip_postfix(req): + """ + Strip req postfix ( -dev, 0.2, etc ) + """ + ## FIXME: use package_to_requirement? + match = re.search(r'^(.*?)(?:-dev|-\d.*)$', req) + if match: + # Strip off -dev, -0.2, etc. + req = match.group(1) + return req + +def _build_req_from_url(url): + + parts = [p for p in url.split('#', 1)[0].split('/') if p] + + req = None + if parts[-2] in ('tags', 'branches', 'tag', 'branch'): + req = parts[-3] + elif parts[-1] == 'trunk': + req = parts[-2] + return req + +def _build_editable_options(req): + + """ + This method generates a dictionary of the query string + parameters contained in a given editable URL. + """ + regexp = re.compile(r"[\?#&](?P[^&=]+)=(?P[^&=]+)") + matched = regexp.findall(req) + + if matched: + ret = dict() + for option in matched: + (name, value) = option + if name in ret: + raise Exception("%s option already defined" % name) + ret[name] = value + return ret + return None + def parse_editable(editable_req, default_vcs=None): """Parses svn+http://blahblah@rev#egg=Foobar into a requirement @@ -1508,37 +1635,39 @@ def parse_editable(editable_req, default_vcs=None): for version_control in vcs: if url.lower().startswith('%s:' % version_control): url = '%s+%s' % (version_control, url) + break + if '+' not in url: if default_vcs: url = default_vcs + '+' + url else: raise InstallationError( - '%s should either by a path to a local project or a VCS url beginning with svn+, git+, hg+, or bzr+' % editable_req) + '%s should either be a path to a local project or a VCS url beginning with svn+, git+, hg+, or bzr+' % editable_req) + vc_type = url.split('+', 1)[0].lower() + if not vcs.get_backend(vc_type): error_message = 'For --editable=%s only ' % editable_req + \ ', '.join([backend.name + '+URL' for backend in vcs.backends]) + \ ' is currently supported' raise InstallationError(error_message) - match = re.search(r'(?:#|#.*?&)egg=([^&]*)', editable_req) - if (not match or not match.group(1)) and vcs.get_backend(vc_type): - parts = [p for p in editable_req.split('#', 1)[0].split('/') if p] - if parts[-2] in ('tags', 'branches', 'tag', 'branch'): - req = parts[-3] - elif parts[-1] == 'trunk': - req = parts[-2] - else: - raise InstallationError( - '--editable=%s is not the right format; it must have #egg=Package' - % editable_req) + + try: + options = _build_editable_options(editable_req) + except Exception: + message = sys.exc_info()[1] + raise InstallationError( + '--editable=%s error in editable options:%s' % (editable_req, message)) + + if not options or 'egg' not in options: + req = _build_req_from_url(editable_req) + if not req: + raise InstallationError('--editable=%s is not the right format; it must have #egg=Package' % editable_req) else: - req = match.group(1) - ## FIXME: use package_to_requirement? - match = re.search(r'^(.*?)(?:-dev|-\d.*)$', req) - if match: - # Strip off -dev, -0.2, etc. - req = match.group(1) - return req, url, None + req = options['egg'] + + package = _strip_postfix(req) + return package, url, options class UninstallPathSet(object): diff --git a/awx/lib/site-packages/pip/status_codes.py b/awx/lib/site-packages/pip/status_codes.py index b6208e9644..5e29502cdd 100644 --- a/awx/lib/site-packages/pip/status_codes.py +++ b/awx/lib/site-packages/pip/status_codes.py @@ -2,4 +2,5 @@ SUCCESS = 0 ERROR = 1 UNKNOWN_ERROR = 2 VIRTUALENV_NOT_FOUND = 3 +PREVIOUS_BUILD_DIR_ERROR = 4 NO_MATCHES_FOUND = 23 diff --git a/awx/lib/site-packages/pip/util.py b/awx/lib/site-packages/pip/util.py index 77f9de6efc..eb18ac9869 100644 --- a/awx/lib/site-packages/pip/util.py +++ b/awx/lib/site-packages/pip/util.py @@ -14,7 +14,7 @@ from pip.backwardcompat import(WindowsError, string_types, raw_input, console_to_str, user_site, PermissionError) from pip.locations import site_packages, running_under_virtualenv, virtualenv_no_global from pip.log import logger -from pip.vendor.distlib import version +from pip._vendor.distlib import version __all__ = ['rmtree', 'display_path', 'backup_dir', 'find_command', 'ask', 'Inf', @@ -117,7 +117,7 @@ def get_pathext(default_pathext=None): def ask_path_exists(message, options): - for action in os.environ.get('PIP_EXISTS_ACTION', ''): + for action in os.environ.get('PIP_EXISTS_ACTION', '').split(): if action in options: return action return ask(message, options) @@ -272,7 +272,7 @@ def normalize_path(path): Convert a path to its canonical, case-normalized, absolute version. """ - return os.path.normcase(os.path.realpath(path)) + return os.path.normcase(os.path.realpath(os.path.expanduser(path))) def splitext(path): @@ -348,7 +348,7 @@ def dist_is_editable(dist): return req.editable def get_installed_distributions(local_only=True, - skip=('setuptools', 'pip', 'python'), + skip=('setuptools', 'pip', 'python', 'distribute'), include_editables=True, editables_only=False): """ @@ -467,9 +467,22 @@ def get_terminal_size(): return int(cr[1]), int(cr[0]) +def current_umask(): + """Get the current umask which involves having to set it temporarily.""" + mask = os.umask(0) + os.umask(mask) + return mask + + def unzip_file(filename, location, flatten=True): - """Unzip the file (zip file located at filename) to the destination - location""" + """ + Unzip the file (with path `filename`) to the destination `location`. All + files are written based on system defaults and umask (i.e. permissions are + not preserved), except that regular file members with any execute + permissions (user, group, or world) have "chmod +x" applied after being + written. Note that for windows, any execute changes using os.chmod are + no-ops per the python docs. + """ if not os.path.exists(location): os.makedirs(location) zipfp = open(filename, 'rb') @@ -496,17 +509,25 @@ def unzip_file(filename, location, flatten=True): fp.write(data) finally: fp.close() - unix_attributes = info.external_attr >> 16 - if unix_attributes: - os.chmod(fn, unix_attributes) - - + mode = info.external_attr >> 16 + # if mode and regular file and any execute permissions for user/group/world? + if mode and stat.S_ISREG(mode) and mode & 0o111: + # make dest file have execute for user/group/world (chmod +x) + # no-op on windows per python docs + os.chmod(fn, (0o777-current_umask() | 0o111)) finally: zipfp.close() def untar_file(filename, location): - """Untar the file (tar file located at filename) to the destination location""" + """ + Untar the file (with path `filename`) to the destination `location`. + All files are written based on system defaults and umask (i.e. permissions + are not preserved), except that regular file members with any execute + permissions (user, group, or world) have "chmod +x" applied after being + written. Note that for windows, any execute changes using os.chmod are + no-ops per the python docs. + """ if not os.path.exists(location): os.makedirs(location) if filename.lower().endswith('.gz') or filename.lower().endswith('.tgz'): @@ -565,6 +586,11 @@ def untar_file(filename, location): finally: destfp.close() fp.close() + # member have any execute permissions for user/group/world? + if member.mode & 0o111: + # make dest file have execute for user/group/world + # no-op on windows per python docs + os.chmod(path, (0o777-current_umask() | 0o111)) finally: tar.close() @@ -683,11 +709,11 @@ def is_prerelease(vers): Will return True if it is a pre-release and False if not. Versions are assumed to be a pre-release if they cannot be parsed. """ - normalized = version.suggest_normalized_version(vers) + normalized = version._suggest_normalized_version(vers) if normalized is None: # Cannot normalize, assume it is a pre-release return True - parsed = version.normalized_key(normalized) + parsed = version._normalized_key(normalized) return any([any([y in set(["a", "b", "c", "rc", "dev"]) for y in x]) for x in parsed]) diff --git a/awx/lib/site-packages/pip/vcs/bazaar.py b/awx/lib/site-packages/pip/vcs/bazaar.py index 86f4bbc624..c62c9c85a5 100644 --- a/awx/lib/site-packages/pip/vcs/bazaar.py +++ b/awx/lib/site-packages/pip/vcs/bazaar.py @@ -5,7 +5,7 @@ from pip.backwardcompat import urlparse from pip.log import logger from pip.util import rmtree, display_path, call_subprocess from pip.vcs import vcs, VersionControl -from pip.download import path_to_url2 +from pip.download import path_to_url class Bazaar(VersionControl): @@ -89,7 +89,7 @@ class Bazaar(VersionControl): if line.startswith(x): repo = line.split(x)[1] if self._is_local_repository(repo): - return path_to_url2(repo) + return path_to_url(repo) return repo return None diff --git a/awx/lib/site-packages/pip/vcs/mercurial.py b/awx/lib/site-packages/pip/vcs/mercurial.py index af427f77e7..2dbe3fc001 100644 --- a/awx/lib/site-packages/pip/vcs/mercurial.py +++ b/awx/lib/site-packages/pip/vcs/mercurial.py @@ -6,7 +6,7 @@ from pip.util import call_subprocess from pip.util import display_path, rmtree from pip.log import logger from pip.vcs import vcs, VersionControl -from pip.download import path_to_url2 +from pip.download import path_to_url from pip.backwardcompat import ConfigParser @@ -86,7 +86,7 @@ class Mercurial(VersionControl): [self.cmd, 'showconfig', 'paths.default'], show_stdout=False, cwd=location).strip() if self._is_local_repository(url): - url = path_to_url2(url) + url = path_to_url(url) return url.strip() def get_tag_revs(self, location): diff --git a/awx/lib/site-packages/pip/vendor/__init__.py b/awx/lib/site-packages/pip/vendor/__init__.py deleted file mode 100644 index a996951fc2..0000000000 --- a/awx/lib/site-packages/pip/vendor/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -""" -pip.vendor is for vendoring dependencies of pip to prevent needing pip to -depend on something external. - -Files inside of pip.vendor should be considered immutable and should only be -updated to versions from upstream. -""" -from __future__ import absolute_import diff --git a/awx/lib/site-packages/pip/wheel.py b/awx/lib/site-packages/pip/wheel.py index bd22a89f4b..fa3e270969 100644 --- a/awx/lib/site-packages/pip/wheel.py +++ b/awx/lib/site-packages/pip/wheel.py @@ -3,6 +3,7 @@ Support for installing and building the "wheel" binary package format. """ from __future__ import with_statement +import compileall import csv import functools import hashlib @@ -13,36 +14,30 @@ import shutil import sys from base64 import urlsafe_b64encode +from pip.backwardcompat import ConfigParser, StringIO +from pip.exceptions import InvalidWheelFilename from pip.locations import distutils_scheme from pip.log import logger from pip import pep425tags from pip.util import call_subprocess, normalize_path, make_path_relative +from pip._vendor.distlib.scripts import ScriptMaker wheel_ext = '.whl' -# don't use pkg_resources.Requirement.parse, to avoid the override in distribute, -# that converts 'setuptools' to 'distribute'. -setuptools_requirement = list(pkg_resources.parse_requirements("setuptools>=0.8"))[0] def wheel_setuptools_support(): """ Return True if we have a setuptools that supports wheel. """ - fulfilled = False - try: - installed_setuptools = pkg_resources.get_distribution('setuptools') - if installed_setuptools in setuptools_requirement: - fulfilled = True - except pkg_resources.DistributionNotFound: - pass + fulfilled = hasattr(pkg_resources, 'DistInfoDistribution') if not fulfilled: - logger.warn("%s is required for wheel installs." % setuptools_requirement) + logger.warn("Wheel installs require setuptools >= 0.8 for dist-info support.") return fulfilled def rehash(path, algo='sha256', blocksize=1<<20): """Return (hash, length) for path using hashlib.new(algo)""" h = hashlib.new(algo) length = 0 - with open(path) as f: + with open(path, 'rb') as f: block = f.read(blocksize) while block: length += len(block) @@ -112,10 +107,39 @@ def root_is_purelib(name, wheeldir): return True return False -def move_wheel_files(name, req, wheeldir, user=False, home=None): + +def get_entrypoints(filename): + if not os.path.exists(filename): + return {}, {} + + # This is done because you can pass a string to entry_points wrappers which + # means that they may or may not be valid INI files. The attempt here is to + # strip leading and trailing whitespace in order to make them valid INI + # files. + with open(filename) as fp: + data = StringIO() + for line in fp: + data.write(line.strip()) + data.write("\n") + data.seek(0) + + cp = ConfigParser.RawConfigParser() + cp.readfp(data) + + console = {} + gui = {} + if cp.has_section('console_scripts'): + console = dict(cp.items('console_scripts')) + if cp.has_section('gui_scripts'): + gui = dict(cp.items('gui_scripts')) + return console, gui + + +def move_wheel_files(name, req, wheeldir, user=False, home=None, root=None, + pycompile=True): """Install a wheel""" - scheme = distutils_scheme(name, user=user, home=home) + scheme = distutils_scheme(name, user=user, home=home, root=root) if root_is_purelib(name, wheeldir): lib_dir = scheme['purelib'] @@ -125,8 +149,18 @@ def move_wheel_files(name, req, wheeldir, user=False, home=None): info_dir = [] data_dirs = [] source = wheeldir.rstrip(os.path.sep) + os.path.sep + + # Record details of the files moved + # installed = files copied from the wheel to the destination + # changed = files changed while installing (scripts #! line typically) + # generated = files newly generated during the install (script wrappers) installed = {} changed = set() + generated = [] + + # Compile all of the pyc files that we're going to be installing + if pycompile: + compileall.compile_dir(source, force=True, quiet=True) def normpath(src, p): return make_path_relative(src, p).replace(os.path.sep, '/') @@ -139,7 +173,7 @@ def move_wheel_files(name, req, wheeldir, user=False, home=None): if modified: changed.add(destfile) - def clobber(source, dest, is_base, fixer=None): + def clobber(source, dest, is_base, fixer=None, filter=None): if not os.path.exists(dest): # common for the 'include' path os.makedirs(dest) @@ -161,6 +195,9 @@ def move_wheel_files(name, req, wheeldir, user=False, home=None): if not os.path.exists(destsubdir): os.makedirs(destsubdir) for f in files: + # Skip unwanted files + if filter and filter(f): + continue srcfile = os.path.join(dir, f) destfile = os.path.join(dest, basedir, f) shutil.move(srcfile, destfile) @@ -173,15 +210,139 @@ def move_wheel_files(name, req, wheeldir, user=False, home=None): assert info_dir, "%s .dist-info directory not found" % req + # Get the defined entry points + ep_file = os.path.join(info_dir[0], 'entry_points.txt') + console, gui = get_entrypoints(ep_file) + + def is_entrypoint_wrapper(name): + # EP, EP.exe and EP-script.py are scripts generated for + # entry point EP by setuptools + if name.lower().endswith('.exe'): + matchname = name[:-4] + elif name.lower().endswith('-script.py'): + matchname = name[:-10] + elif name.lower().endswith(".pya"): + matchname = name[:-4] + else: + matchname = name + # Ignore setuptools-generated scripts + return (matchname in console or matchname in gui) + for datadir in data_dirs: fixer = None + filter = None for subdir in os.listdir(os.path.join(wheeldir, datadir)): fixer = None if subdir == 'scripts': fixer = fix_script + filter = is_entrypoint_wrapper source = os.path.join(wheeldir, datadir, subdir) dest = scheme[subdir] - clobber(source, dest, False, fixer=fixer) + clobber(source, dest, False, fixer=fixer, filter=filter) + + maker = ScriptMaker(None, scheme['scripts']) + + # Ensure we don't generate any variants for scripts because this is almost + # never what somebody wants. + # See https://bitbucket.org/pypa/distlib/issue/35/ + maker.variants = set(('', )) + + # This is required because otherwise distlib creates scripts that are not + # executable. + # See https://bitbucket.org/pypa/distlib/issue/32/ + maker.set_mode = True + + # Simplify the script and fix the fact that the default script swallows + # every single stack trace. + # See https://bitbucket.org/pypa/distlib/issue/34/ + # See https://bitbucket.org/pypa/distlib/issue/33/ + def _get_script_text(entry): + return maker.script_template % { + "module": entry.prefix, + "import_name": entry.suffix.split(".")[0], + "func": entry.suffix, + } + + maker._get_script_text = _get_script_text + maker.script_template = """# -*- coding: utf-8 -*- +import re +import sys + +from %(module)s import %(import_name)s + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(%(func)s()) +""" + + # Special case pip and setuptools to generate versioned wrappers + # + # The issue is that some projects (specifically, pip and setuptools) use + # code in setup.py to create "versioned" entry points - pip2.7 on Python + # 2.7, pip3.3 on Python 3.3, etc. But these entry points are baked into + # the wheel metadata at build time, and so if the wheel is installed with + # a *different* version of Python the entry points will be wrong. The + # correct fix for this is to enhance the metadata to be able to describe + # such versioned entry points, but that won't happen till Metadata 2.0 is + # available. + # In the meantime, projects using versioned entry points will either have + # incorrect versioned entry points, or they will not be able to distribute + # "universal" wheels (i.e., they will need a wheel per Python version). + # + # Because setuptools and pip are bundled with _ensurepip and virtualenv, + # we need to use universal wheels. So, as a stopgap until Metadata 2.0, we + # override the versioned entry points in the wheel and generate the + # correct ones. This code is purely a short-term measure until Metadat 2.0 + # is available. + # + # To add the level of hack in this section of code, in order to support + # ensurepip this code will look for an ``ENSUREPIP_OPTIONS`` environment + # variable which will control which version scripts get installed. + # + # ENSUREPIP_OPTIONS=altinstall + # - Only pipX.Y and easy_install-X.Y will be generated and installed + # ENSUREPIP_OPTIONS=install + # - pipX.Y, pipX, easy_install-X.Y will be generated and installed. Note + # that this option is technically if ENSUREPIP_OPTIONS is set and is + # not altinstall + # DEFAULT + # - The default behavior is to install pip, pipX, pipX.Y, easy_install + # and easy_install-X.Y. + pip_script = console.pop('pip', None) + if pip_script: + if "ENSUREPIP_OPTIONS" not in os.environ: + spec = 'pip = ' + pip_script + generated.extend(maker.make(spec)) + + if os.environ.get("ENSUREPIP_OPTIONS", "") != "altinstall": + spec = 'pip%s = %s' % (sys.version[:1], pip_script) + generated.extend(maker.make(spec)) + + spec = 'pip%s = %s' % (sys.version[:3], pip_script) + generated.extend(maker.make(spec)) + # Delete any other versioned pip entry points + pip_ep = [k for k in console if re.match(r'pip(\d(\.\d)?)?$', k)] + for k in pip_ep: + del console[k] + easy_install_script = console.pop('easy_install', None) + if easy_install_script: + if "ENSUREPIP_OPTIONS" not in os.environ: + spec = 'easy_install = ' + easy_install_script + generated.extend(maker.make(spec)) + + spec = 'easy_install-%s = %s' % (sys.version[:3], easy_install_script) + generated.extend(maker.make(spec)) + # Delete any other versioned easy_install entry points + easy_install_ep = [k for k in console + if re.match(r'easy_install(-\d\.\d)?$', k)] + for k in easy_install_ep: + del console[k] + + # Generate the console and GUI entry points specified in the wheel + if len(console) > 0: + generated.extend(maker.make_multiple(['%s = %s' % kv for kv in console.items()])) + if len(gui) > 0: + generated.extend(maker.make_multiple(['%s = %s' % kv for kv in gui.items()], {'gui': True})) record = os.path.join(info_dir[0], 'RECORD') temp_record = os.path.join(info_dir[0], 'RECORD.pip') @@ -194,6 +355,9 @@ def move_wheel_files(name, req, wheeldir, user=False, home=None): if row[0] in changed: row[1], row[2] = rehash(row[0]) writer.writerow(row) + for f in generated: + h, l = rehash(f) + writer.writerow((f, h, l)) for f in installed: writer.writerow((installed[f], '', '')) shutil.move(temp_record, record) @@ -243,10 +407,17 @@ class Wheel(object): re.VERBOSE) def __init__(self, filename): + """ + :raises InvalidWheelFilename: when the filename is invalid for a wheel + """ wheel_info = self.wheel_file_re.match(filename) + if not wheel_info: + raise InvalidWheelFilename("%s is not a valid wheel filename." % filename) self.filename = filename self.name = wheel_info.group('name').replace('_', '-') - self.version = wheel_info.group('ver') + # we'll assume "_" means "-" due to wheel naming scheme + # (https://github.com/pypa/pip/issues/1150) + self.version = wheel_info.group('ver').replace('_', '-') self.pyversions = wheel_info.group('pyver').split('.') self.abis = wheel_info.group('abi').split('.') self.plats = wheel_info.group('plat').split('.') @@ -257,9 +428,10 @@ class Wheel(object): def support_index_min(self, tags=None): """ - Return the lowest index that a file_tag achieves in the supported_tags list - e.g. if there are 8 supported tags, and one of the file tags is first in the - list, then return 0. + Return the lowest index that one of the wheel's file_tag combinations + achieves in the supported_tags list e.g. if there are 8 supported tags, + and one of the file tags is first in the list, then return 0. Returns + None is the wheel is not supported. """ if tags is None: # for mock tags = pep425tags.supported_tags diff --git a/awx/lib/site-packages/pkg_resources.py b/awx/lib/site-packages/pkg_resources.py index 0297601629..efe5d34d77 100644 --- a/awx/lib/site-packages/pkg_resources.py +++ b/awx/lib/site-packages/pkg_resources.py @@ -22,6 +22,14 @@ import zipfile import zipimport import warnings import stat +import functools +import pkgutil +import token +import symbol +import operator +import platform +from pkgutil import get_importer + try: from urlparse import urlparse, urlunparse except ImportError: @@ -35,28 +43,15 @@ try: basestring next = lambda o: o.next() from cStringIO import StringIO as BytesIO - def exec_(code, globs=None, locs=None): - if globs is None: - frame = sys._getframe(1) - globs = frame.f_globals - if locs is None: - locs = frame.f_locals - del frame - elif locs is None: - locs = globs - exec("""exec code in globs, locs""") except NameError: basestring = str from io import BytesIO - exec_ = eval("exec") def execfile(fn, globs=None, locs=None): if globs is None: globs = globals() if locs is None: locs = globs - exec_(compile(open(fn).read(), fn, 'exec'), globs, locs) - import functools - reduce = functools.reduce + exec(compile(open(fn).read(), fn, 'exec'), globs, locs) # capture these to bypass sandboxing from os import utime @@ -716,7 +711,7 @@ class Environment(object): `platform` is an optional string specifying the name of the platform that platform-specific distributions must be compatible with. If unspecified, it defaults to the current platform. `python` is an - optional string naming the desired version of Python (e.g. ``'2.4'``); + optional string naming the desired version of Python (e.g. ``'3.3'``); it defaults to the current version. You may explicitly set `platform` (and/or `python`) to ``None`` if you @@ -1112,143 +1107,159 @@ def to_filename(name): """ return name.replace('-','_') -_marker_names = { - 'os': ['name'], 'sys': ['platform'], - 'platform': ['version','machine','python_implementation'], - 'python_version': [], 'python_full_version': [], 'extra':[], -} -_marker_values = { - 'os_name': lambda: os.name, - 'sys_platform': lambda: sys.platform, - 'python_full_version': lambda: sys.version.split()[0], - 'python_version': lambda:'%s.%s' % (sys.version_info[0], sys.version_info[1]), - 'platform_version': lambda: _platinfo('version'), - 'platform_machine': lambda: _platinfo('machine'), - 'python_implementation': lambda: _platinfo('python_implementation') or _pyimp(), -} - -def _platinfo(attr): - try: - import platform - except ImportError: - return '' - return getattr(platform, attr, lambda:'')() - -def _pyimp(): - if sys.platform=='cli': - return 'IronPython' - elif sys.platform.startswith('java'): - return 'Jython' - elif '__pypy__' in sys.builtin_module_names: - return 'PyPy' - else: - return 'CPython' - -def normalize_exception(exc): - """ - Given a SyntaxError from a marker evaluation, normalize the error message: - - Remove indications of filename and line number. - - Replace platform-specific error messages with standard error messages. - """ - subs = { - 'unexpected EOF while parsing': 'invalid syntax', - 'parenthesis is never closed': 'invalid syntax', +class MarkerEvaluation(object): + values = { + 'os_name': lambda: os.name, + 'sys_platform': lambda: sys.platform, + 'python_full_version': lambda: sys.version.split()[0], + 'python_version': lambda:'%s.%s' % (sys.version_info[0], sys.version_info[1]), + 'platform_version': platform.version, + 'platform_machine': platform.machine, + 'python_implementation': platform.python_implementation, } - exc.filename = None - exc.lineno = None - exc.msg = subs.get(exc.msg, exc.msg) - return exc + @classmethod + def is_invalid_marker(cls, text): + """ + Validate text as a PEP 426 environment marker; return an exception + if invalid or False otherwise. + """ + try: + cls.evaluate_marker(text) + except SyntaxError: + return cls.normalize_exception(sys.exc_info()[1]) + return False -def invalid_marker(text): - """Validate text as a PEP 426 environment marker; return exception or False""" - try: - evaluate_marker(text) - except SyntaxError: - return normalize_exception(sys.exc_info()[1]) - return False + @staticmethod + def normalize_exception(exc): + """ + Given a SyntaxError from a marker evaluation, normalize the error message: + - Remove indications of filename and line number. + - Replace platform-specific error messages with standard error messages. + """ + subs = { + 'unexpected EOF while parsing': 'invalid syntax', + 'parenthesis is never closed': 'invalid syntax', + } + exc.filename = None + exc.lineno = None + exc.msg = subs.get(exc.msg, exc.msg) + return exc -def evaluate_marker(text, extra=None, _ops={}): - """ - Evaluate a PEP 426 environment marker on CPython 2.4+. - Return a boolean indicating the marker result in this environment. - Raise SyntaxError if marker is invalid. + @classmethod + def and_test(cls, nodelist): + # MUST NOT short-circuit evaluation, or invalid syntax can be skipped! + return functools.reduce(operator.and_, [cls.interpret(nodelist[i]) for i in range(1,len(nodelist),2)]) - This implementation uses the 'parser' module, which is not implemented on - Jython and has been superseded by the 'ast' module in Python 2.6 and - later. - """ + @classmethod + def test(cls, nodelist): + # MUST NOT short-circuit evaluation, or invalid syntax can be skipped! + return functools.reduce(operator.or_, [cls.interpret(nodelist[i]) for i in range(1,len(nodelist),2)]) - if not _ops: + @classmethod + def atom(cls, nodelist): + t = nodelist[1][0] + if t == token.LPAR: + if nodelist[2][0] == token.RPAR: + raise SyntaxError("Empty parentheses") + return cls.interpret(nodelist[2]) + raise SyntaxError("Language feature not supported in environment markers") - from token import NAME, STRING - import token - import symbol - import operator + @classmethod + def comparison(cls, nodelist): + if len(nodelist)>4: + raise SyntaxError("Chained comparison not allowed in environment markers") + comp = nodelist[2][1] + cop = comp[1] + if comp[0] == token.NAME: + if len(nodelist[2]) == 3: + if cop == 'not': + cop = 'not in' + else: + cop = 'is not' + try: + cop = cls.get_op(cop) + except KeyError: + raise SyntaxError(repr(cop)+" operator not allowed in environment markers") + return cop(cls.evaluate(nodelist[1]), cls.evaluate(nodelist[3])) - def and_test(nodelist): - # MUST NOT short-circuit evaluation, or invalid syntax can be skipped! - return reduce(operator.and_, [interpret(nodelist[i]) for i in range(1,len(nodelist),2)]) + @classmethod + def get_op(cls, op): + ops = { + symbol.test: cls.test, + symbol.and_test: cls.and_test, + symbol.atom: cls.atom, + symbol.comparison: cls.comparison, + 'not in': lambda x, y: x not in y, + 'in': lambda x, y: x in y, + '==': operator.eq, + '!=': operator.ne, + } + if hasattr(symbol, 'or_test'): + ops[symbol.or_test] = cls.test + return ops[op] - def test(nodelist): - # MUST NOT short-circuit evaluation, or invalid syntax can be skipped! - return reduce(operator.or_, [interpret(nodelist[i]) for i in range(1,len(nodelist),2)]) + @classmethod + def evaluate_marker(cls, text, extra=None): + """ + Evaluate a PEP 426 environment marker on CPython 2.4+. + Return a boolean indicating the marker result in this environment. + Raise SyntaxError if marker is invalid. - def atom(nodelist): - t = nodelist[1][0] - if t == token.LPAR: - if nodelist[2][0] == token.RPAR: - raise SyntaxError("Empty parentheses") - return interpret(nodelist[2]) - raise SyntaxError("Language feature not supported in environment markers") + This implementation uses the 'parser' module, which is not implemented on + Jython and has been superseded by the 'ast' module in Python 2.6 and + later. + """ + return cls.interpret(parser.expr(text).totuple(1)[1]) - def comparison(nodelist): - if len(nodelist)>4: - raise SyntaxError("Chained comparison not allowed in environment markers") - comp = nodelist[2][1] - cop = comp[1] - if comp[0] == NAME: - if len(nodelist[2]) == 3: - if cop == 'not': - cop = 'not in' - else: - cop = 'is not' - try: - cop = _ops[cop] - except KeyError: - raise SyntaxError(repr(cop)+" operator not allowed in environment markers") - return cop(evaluate(nodelist[1]), evaluate(nodelist[3])) + @classmethod + def _markerlib_evaluate(cls, text): + """ + Evaluate a PEP 426 environment marker using markerlib. + Return a boolean indicating the marker result in this environment. + Raise SyntaxError if marker is invalid. + """ + import _markerlib + # markerlib implements Metadata 1.2 (PEP 345) environment markers. + # Translate the variables to Metadata 2.0 (PEP 426). + env = _markerlib.default_environment() + for key in env.keys(): + new_key = key.replace('.', '_') + env[new_key] = env.pop(key) + try: + result = _markerlib.interpret(text, env) + except NameError: + e = sys.exc_info()[1] + raise SyntaxError(e.args[0]) + return result - _ops.update({ - symbol.test: test, symbol.and_test: and_test, symbol.atom: atom, - symbol.comparison: comparison, 'not in': lambda x,y: x not in y, - 'in': lambda x,y: x in y, '==': operator.eq, '!=': operator.ne, - }) - if hasattr(symbol,'or_test'): - _ops[symbol.or_test] = test + if 'parser' not in globals(): + # Fall back to less-complete _markerlib implementation if 'parser' module + # is not available. + evaluate_marker = _markerlib_evaluate - def interpret(nodelist): + @classmethod + def interpret(cls, nodelist): while len(nodelist)==2: nodelist = nodelist[1] try: - op = _ops[nodelist[0]] + op = cls.get_op(nodelist[0]) except KeyError: raise SyntaxError("Comparison or logical expression expected") - raise SyntaxError("Language feature not supported in environment markers: "+symbol.sym_name[nodelist[0]]) return op(nodelist) - def evaluate(nodelist): + @classmethod + def evaluate(cls, nodelist): while len(nodelist)==2: nodelist = nodelist[1] kind = nodelist[0] name = nodelist[1] - #while len(name)==2: name = name[1] - if kind==NAME: + if kind==token.NAME: try: - op = _marker_values[name] + op = cls.values[name] except KeyError: raise SyntaxError("Unknown name %r" % name) return op() - if kind==STRING: + if kind==token.STRING: s = nodelist[1] if s[:1] not in "'\"" or s.startswith('"""') or s.startswith("'''") \ or '\\' in s: @@ -1257,32 +1268,8 @@ def evaluate_marker(text, extra=None, _ops={}): return s[1:-1] raise SyntaxError("Language feature not supported in environment markers") - return interpret(parser.expr(text).totuple(1)[1]) - -def _markerlib_evaluate(text): - """ - Evaluate a PEP 426 environment marker using markerlib. - Return a boolean indicating the marker result in this environment. - Raise SyntaxError if marker is invalid. - """ - import _markerlib - # markerlib implements Metadata 1.2 (PEP 345) environment markers. - # Translate the variables to Metadata 2.0 (PEP 426). - env = _markerlib.default_environment() - for key in env.keys(): - new_key = key.replace('.', '_') - env[new_key] = env.pop(key) - try: - result = _markerlib.interpret(text, env) - except NameError: - e = sys.exc_info()[1] - raise SyntaxError(e.args[0]) - return result - -if 'parser' not in globals(): - # fallback to less-complete _markerlib implementation if 'parser' module - # is not available. - evaluate_marker = _markerlib_evaluate +invalid_marker = MarkerEvaluation.is_invalid_marker +evaluate_marker = MarkerEvaluation.evaluate_marker class NullProvider: """Try to implement resources and metadata for arbitrary PEP 302 loaders""" @@ -1354,7 +1341,7 @@ class NullProvider: len(script_text), 0, script_text.split('\n'), script_filename ) script_code = compile(script_text,script_filename,'exec') - exec_(script_code, namespace, namespace) + exec(script_code, namespace, namespace) def _has(self, path): raise NotImplementedError( @@ -1712,83 +1699,6 @@ class EggMetadata(ZipProvider): self.module_path = importer.archive self._setup_prefix() - -class ImpWrapper: - """PEP 302 Importer that wraps Python's "normal" import algorithm""" - - def __init__(self, path=None): - self.path = path - - def find_module(self, fullname, path=None): - subname = fullname.split(".")[-1] - if subname != fullname and self.path is None: - return None - if self.path is None: - path = None - else: - path = [self.path] - try: - file, filename, etc = imp.find_module(subname, path) - except ImportError: - return None - return ImpLoader(file, filename, etc) - - -class ImpLoader: - """PEP 302 Loader that wraps Python's "normal" import algorithm""" - - def __init__(self, file, filename, etc): - self.file = file - self.filename = filename - self.etc = etc - - def load_module(self, fullname): - try: - mod = imp.load_module(fullname, self.file, self.filename, self.etc) - finally: - if self.file: self.file.close() - # Note: we don't set __loader__ because we want the module to look - # normal; i.e. this is just a wrapper for standard import machinery - return mod - - -def get_importer(path_item): - """Retrieve a PEP 302 "importer" for the given path item - - If there is no importer, this returns a wrapper around the builtin import - machinery. The returned importer is only cached if it was created by a - path hook. - """ - try: - importer = sys.path_importer_cache[path_item] - except KeyError: - for hook in sys.path_hooks: - try: - importer = hook(path_item) - except ImportError: - pass - else: - break - else: - importer = None - - sys.path_importer_cache.setdefault(path_item,importer) - if importer is None: - try: - importer = ImpWrapper(path_item) - except ImportError: - pass - return importer - -try: - from pkgutil import get_importer, ImpImporter -except ImportError: - pass # Python 2.3 or 2.4, use our own implementation -else: - ImpWrapper = ImpImporter # Python 2.5, use pkgutil's implementation - del ImpLoader, ImpImporter - - _declare_state('dict', _distribution_finders = {}) def register_finder(importer_type, distribution_finder): @@ -1865,7 +1775,7 @@ def find_on_path(importer, path_item, only=False): for item in find_distributions(os.path.join(path_item,line.rstrip())): yield item break -register_finder(ImpWrapper,find_on_path) +register_finder(pkgutil.ImpImporter,find_on_path) if importlib_bootstrap is not None: register_finder(importlib_bootstrap.FileFinder, find_on_path) @@ -1902,14 +1812,17 @@ def _handle_ns(packageName, path_item): module = sys.modules.get(packageName) if module is None: module = sys.modules[packageName] = imp.new_module(packageName) - module.__path__ = []; _set_parent_ns(packageName) + module.__path__ = [] + _set_parent_ns(packageName) elif not hasattr(module,'__path__'): raise TypeError("Not a package:", packageName) handler = _find_adapter(_namespace_handlers, importer) subpath = handler(importer,path_item,packageName,module) if subpath is not None: - path = module.__path__; path.append(subpath) - loader.load_module(packageName); module.__path__ = path + path = module.__path__ + path.append(subpath) + loader.load_module(packageName) + module.__path__ = path return subpath def declare_namespace(packageName): @@ -1966,7 +1879,7 @@ def file_ns_handler(importer, path_item, packageName, module): # Only return the path if it's not already there return subpath -register_namespace_handler(ImpWrapper,file_ns_handler) +register_namespace_handler(pkgutil.ImpImporter,file_ns_handler) register_namespace_handler(zipimport.zipimporter,file_ns_handler) if importlib_bootstrap is not None: @@ -2420,7 +2333,6 @@ class Distribution(object): bdir = os.path.dirname(nloc) npath= [(p and _normalize_cached(p) or p) for p in path] - bp = None for p, item in enumerate(npath): if item==nloc: break diff --git a/awx/lib/site-packages/rackspace_auth_openstack/plugin.py b/awx/lib/site-packages/rackspace_auth_openstack/plugin.py index 26dad76ddb..a006e3bfa7 100644 --- a/awx/lib/site-packages/rackspace_auth_openstack/plugin.py +++ b/awx/lib/site-packages/rackspace_auth_openstack/plugin.py @@ -30,7 +30,7 @@ def _authenticate(cls, auth_url): "RAX-KSKEY:apiKeyCredentials": { "username": cls.user, "apiKey": cls.password}, - "tenantName": cls.projectid}} + }} return cls._authenticate(auth_url, body) diff --git a/awx/lib/site-packages/requests/__init__.py b/awx/lib/site-packages/requests/__init__.py index 793ac22aab..d5d258e84c 100644 --- a/awx/lib/site-packages/requests/__init__.py +++ b/awx/lib/site-packages/requests/__init__.py @@ -42,8 +42,8 @@ is at . """ __title__ = 'requests' -__version__ = '2.0.1' -__build__ = 0x020001 +__version__ = '2.1.0' +__build__ = 0x020100 __author__ = 'Kenneth Reitz' __license__ = 'Apache 2.0' __copyright__ = 'Copyright 2013 Kenneth Reitz' diff --git a/awx/lib/site-packages/requests/adapters.py b/awx/lib/site-packages/requests/adapters.py index 0adca690cd..b62f64c85a 100644 --- a/awx/lib/site-packages/requests/adapters.py +++ b/awx/lib/site-packages/requests/adapters.py @@ -206,7 +206,10 @@ class HTTPAdapter(BaseAdapter): conn = self.proxy_manager[proxy].connection_from_url(url) else: - conn = self.poolmanager.connection_from_url(url.lower()) + # Only scheme should be lower case + parsed = urlparse(url) + url = parsed.geturl() + conn = self.poolmanager.connection_from_url(url) return conn @@ -232,7 +235,7 @@ class HTTPAdapter(BaseAdapter): :param proxies: A dictionary of schemes to proxy URLs. """ proxies = proxies or {} - scheme = urlparse(request.url).scheme.lower() + scheme = urlparse(request.url).scheme proxy = proxies.get(scheme) if proxy and scheme != 'https': @@ -289,7 +292,7 @@ class HTTPAdapter(BaseAdapter): :param stream: (optional) Whether to stream the request content. :param timeout: (optional) The timeout on the request. :param verify: (optional) Whether to verify SSL certificates. - :param vert: (optional) Any user-provided SSL certificate to be trusted. + :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. """ @@ -327,27 +330,40 @@ class HTTPAdapter(BaseAdapter): conn = conn.proxy_pool low_conn = conn._get_conn(timeout=timeout) - low_conn.putrequest(request.method, url, skip_accept_encoding=True) - for header, value in request.headers.items(): - low_conn.putheader(header, value) + try: + low_conn.putrequest(request.method, + url, + skip_accept_encoding=True) - low_conn.endheaders() + for header, value in request.headers.items(): + low_conn.putheader(header, value) - for i in request.body: - low_conn.send(hex(len(i))[2:].encode('utf-8')) - low_conn.send(b'\r\n') - low_conn.send(i) - low_conn.send(b'\r\n') - low_conn.send(b'0\r\n\r\n') + low_conn.endheaders() - r = low_conn.getresponse() - resp = HTTPResponse.from_httplib(r, - pool=conn, - connection=low_conn, - preload_content=False, - decode_content=False - ) + for i in request.body: + low_conn.send(hex(len(i))[2:].encode('utf-8')) + low_conn.send(b'\r\n') + low_conn.send(i) + low_conn.send(b'\r\n') + low_conn.send(b'0\r\n\r\n') + + r = low_conn.getresponse() + resp = HTTPResponse.from_httplib( + r, + pool=conn, + connection=low_conn, + preload_content=False, + decode_content=False + ) + except: + # If we hit any problems here, clean up the connection. + # Then, reraise so that we can handle the actual exception. + low_conn.close() + raise + else: + # All is well, return the connection to the pool. + conn._put_conn(low_conn) except socket.error as sockerr: raise ConnectionError(sockerr) diff --git a/awx/lib/site-packages/requests/auth.py b/awx/lib/site-packages/requests/auth.py index 30529e296e..6664cd80db 100644 --- a/awx/lib/site-packages/requests/auth.py +++ b/awx/lib/site-packages/requests/auth.py @@ -16,6 +16,7 @@ import logging from base64 import b64encode from .compat import urlparse, str +from .cookies import extract_cookies_to_jar from .utils import parse_dict_header log = logging.getLogger(__name__) @@ -63,6 +64,7 @@ class HTTPDigestAuth(AuthBase): self.last_nonce = '' self.nonce_count = 0 self.chal = {} + self.pos = None def build_digest_header(self, method, url): @@ -77,7 +79,7 @@ class HTTPDigestAuth(AuthBase): else: _algorithm = algorithm.upper() # lambdas assume digest modules are imported at the top level - if _algorithm == 'MD5': + if _algorithm == 'MD5' or _algorithm == 'MD5-SESS': def md5_utf8(x): if isinstance(x, str): x = x.encode('utf-8') @@ -89,7 +91,7 @@ class HTTPDigestAuth(AuthBase): x = x.encode('utf-8') return hashlib.sha1(x).hexdigest() hash_utf8 = sha_utf8 - # XXX MD5-sess + KD = lambda s, d: hash_utf8("%s:%s" % (s, d)) if hash_utf8 is None: @@ -105,23 +107,28 @@ class HTTPDigestAuth(AuthBase): A1 = '%s:%s:%s' % (self.username, realm, self.password) A2 = '%s:%s' % (method, path) + HA1 = hash_utf8(A1) + HA2 = hash_utf8(A2) + + if nonce == self.last_nonce: + self.nonce_count += 1 + else: + self.nonce_count = 1 + ncvalue = '%08x' % self.nonce_count + s = str(self.nonce_count).encode('utf-8') + s += nonce.encode('utf-8') + s += time.ctime().encode('utf-8') + s += os.urandom(8) + + cnonce = (hashlib.sha1(s).hexdigest()[:16]) + noncebit = "%s:%s:%s:%s:%s" % (nonce, ncvalue, cnonce, qop, HA2) + if _algorithm == 'MD5-SESS': + HA1 = hash_utf8('%s:%s:%s' % (HA1, nonce, cnonce)) + if qop is None: - respdig = KD(hash_utf8(A1), "%s:%s" % (nonce, hash_utf8(A2))) + respdig = KD(HA1, "%s:%s" % (nonce, HA2)) elif qop == 'auth' or 'auth' in qop.split(','): - if nonce == self.last_nonce: - self.nonce_count += 1 - else: - self.nonce_count = 1 - - ncvalue = '%08x' % self.nonce_count - s = str(self.nonce_count).encode('utf-8') - s += nonce.encode('utf-8') - s += time.ctime().encode('utf-8') - s += os.urandom(8) - - cnonce = (hashlib.sha1(s).hexdigest()[:16]) - noncebit = "%s:%s:%s:%s:%s" % (nonce, ncvalue, cnonce, qop, hash_utf8(A2)) - respdig = KD(hash_utf8(A1), noncebit) + respdig = KD(HA1, noncebit) else: # XXX handle auth-int. return None @@ -138,13 +145,17 @@ class HTTPDigestAuth(AuthBase): if entdig: base += ', digest="%s"' % entdig if qop: - base += ', qop=auth, nc=%s, cnonce="%s"' % (ncvalue, cnonce) + base += ', qop="auth", nc=%s, cnonce="%s"' % (ncvalue, cnonce) return 'Digest %s' % (base) def handle_401(self, r, **kwargs): """Takes the given response and tries digest-auth, if needed.""" + if self.pos is not None: + # Rewind the file position indicator of the body to where + # it was to resend the request. + r.request.body.seek(self.pos) num_401_calls = getattr(self, 'num_401_calls', 1) s_auth = r.headers.get('www-authenticate', '') @@ -159,7 +170,8 @@ class HTTPDigestAuth(AuthBase): r.content r.raw.release_conn() prep = r.request.copy() - prep.prepare_cookies(r.cookies) + extract_cookies_to_jar(prep._cookies, r.request, r.raw) + prep.prepare_cookies(prep._cookies) prep.headers['Authorization'] = self.build_digest_header( prep.method, prep.url) @@ -176,5 +188,9 @@ class HTTPDigestAuth(AuthBase): # If we have a saved nonce, skip the 401 if self.last_nonce: r.headers['Authorization'] = self.build_digest_header(r.method, r.url) + try: + self.pos = r.body.tell() + except AttributeError: + pass r.register_hook('response', self.handle_401) return r diff --git a/awx/lib/site-packages/requests/cacert.pem b/awx/lib/site-packages/requests/cacert.pem index e908bb6a11..729fe15d40 100644 --- a/awx/lib/site-packages/requests/cacert.pem +++ b/awx/lib/site-packages/requests/cacert.pem @@ -1791,37 +1791,6 @@ QWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YGVM+h4k0460tQtcsm9MracEpqoeJ5 quGnM/b9Sh/22WA= -----END CERTIFICATE----- -# Issuer: CN=Wells Fargo Root Certificate Authority O=Wells Fargo OU=Wells Fargo Certification Authority -# Subject: CN=Wells Fargo Root Certificate Authority O=Wells Fargo OU=Wells Fargo Certification Authority -# Label: "Wells Fargo Root CA" -# Serial: 971282334 -# MD5 Fingerprint: 20:0b:4a:7a:88:a7:a9:42:86:8a:5f:74:56:7b:88:05 -# SHA1 Fingerprint: 93:e6:ab:22:03:03:b5:23:28:dc:da:56:9e:ba:e4:d1:d1:cc:fb:65 -# SHA256 Fingerprint: 03:45:8b:6a:be:ec:c2:14:95:3d:97:14:9a:f4:53:91:69:1d:e9:f9:cd:cc:26:47:86:3a:3d:67:c9:5c:24:3b ------BEGIN CERTIFICATE----- -MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9v -dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDAxMDExMTY0MTI4WhcNMjEwMTE0 -MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSww -KgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0G -A1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n13 -5zHCLielTWi5MbqNQ1mXx3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHE -SxP9cMIlrCL1dQu3U+SlK93OvRw6esP3E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4O -JgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5OEL8pahbSCOz6+MlsoCu -ltQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4jsNtlAHCE -AQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMB -AAGjYTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcB -CzAyMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRw -b2xpY3kwDQYJKoZIhvcNAQEFBQADggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo -7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrvm+0fazbuSCUlFLZWohDo7qd/ -0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0ROhPs7fpvcmR7 -nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx -x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ -33ZwmVxwQ023tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s= ------END CERTIFICATE----- - # Issuer: CN=Swisscom Root CA 1 O=Swisscom OU=Digital Certificate Services # Subject: CN=Swisscom Root CA 1 O=Swisscom OU=Digital Certificate Services # Label: "Swisscom Root CA 1" @@ -4964,3 +4933,94 @@ G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL -----END CERTIFICATE----- + +# Issuer: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV +# Subject: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV +# Label: "ACCVRAIZ1" +# Serial: 6828503384748696800 +# MD5 Fingerprint: d0:a0:5a:ee:05:b6:09:94:21:a1:7d:f1:b2:29:82:02 +# SHA1 Fingerprint: 93:05:7a:88:15:c6:4f:ce:88:2f:fa:91:16:52:28:78:bc:53:64:17 +# SHA256 Fingerprint: 9a:6e:c0:12:e1:a7:da:9d:be:34:19:4d:47:8a:d7:c0:db:18:22:fb:07:1d:f1:29:81:49:6e:d1:04:38:41:13 +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE +AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw +CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ +BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND +VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb +qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY +HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo +G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA +lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr +IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ +0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH +k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 +4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO +m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa +cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl +uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI +KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls +ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG +AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT +VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG +CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA +cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA +QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA +7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA +cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA +QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA +czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu +aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt +aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud +DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF +BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp +D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU +JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m +AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD +vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms +tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH +7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA +h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF +d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H +pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- + +# Issuer: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA +# Subject: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA +# Label: "TWCA Global Root CA" +# Serial: 3262 +# MD5 Fingerprint: f9:03:7e:cf:e6:9e:3c:73:7a:2a:90:07:69:ff:2b:96 +# SHA1 Fingerprint: 9c:bb:48:53:f6:a4:f6:d3:52:a4:e8:32:52:55:60:13:f5:ad:af:65 +# SHA256 Fingerprint: 59:76:90:07:f7:68:5d:0f:cd:50:87:2f:9f:95:d5:75:5a:5b:2b:45:7d:81:f3:69:2b:61:0a:98:67:2f:0e:1b +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx +EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT +VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 +NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT +B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF +10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz +0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh +MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH +zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc +46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 +yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi +laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP +oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA +BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE +qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm +4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL +1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF +H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo +RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ +nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh +15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW +6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW +nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j +wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz +aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy +KwbQBM0= +-----END CERTIFICATE----- diff --git a/awx/lib/site-packages/requests/cookies.py b/awx/lib/site-packages/requests/cookies.py index ea56c065a5..c465f5521a 100644 --- a/awx/lib/site-packages/requests/cookies.py +++ b/awx/lib/site-packages/requests/cookies.py @@ -8,7 +8,7 @@ requests.utils imports from here, so be careful with imports. import time import collections -from .compat import cookielib, urlparse, Morsel +from .compat import cookielib, urlparse, urlunparse, Morsel try: import threading @@ -45,7 +45,18 @@ class MockRequest(object): return self.get_host() def get_full_url(self): - return self._r.url + # Only return the response's URL if the user hadn't set the Host + # header + if not self._r.headers.get('Host'): + return self._r.url + # If they did set it, retrieve it and reconstruct the expected domain + host = self._r.headers['Host'] + parsed = urlparse(self._r.url) + # Reconstruct the URL as we expect it + return urlunparse([ + parsed.scheme, host, parsed.path, parsed.params, parsed.query, + parsed.fragment + ]) def is_unverifiable(self): return True @@ -267,7 +278,7 @@ class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping): remove_cookie_by_name(self, name) def set_cookie(self, cookie, *args, **kwargs): - if cookie.value.startswith('"') and cookie.value.endswith('"'): + if hasattr(cookie.value, 'startswith') and cookie.value.startswith('"') and cookie.value.endswith('"'): cookie.value = cookie.value.replace('\\"', '') return super(RequestsCookieJar, self).set_cookie(cookie, *args, **kwargs) @@ -410,3 +421,25 @@ def cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True): cookiejar.set_cookie(create_cookie(name, cookie_dict[name])) return cookiejar + + +def merge_cookies(cookiejar, cookies): + """Add cookies to cookiejar and returns a merged CookieJar. + + :param cookiejar: CookieJar object to add the cookies to. + :param cookies: Dictionary or CookieJar object to be added. + """ + if not isinstance(cookiejar, cookielib.CookieJar): + raise ValueError('You can only merge into CookieJar') + + if isinstance(cookies, dict): + cookiejar = cookiejar_from_dict( + cookies, cookiejar=cookiejar, overwrite=False) + elif isinstance(cookies, cookielib.CookieJar): + try: + cookiejar.update(cookies) + except AttributeError: + for cookie_in_jar in cookies: + cookiejar.set_cookie(cookie_in_jar) + + return cookiejar diff --git a/awx/lib/site-packages/requests/models.py b/awx/lib/site-packages/requests/models.py index 5647bf3d40..34dce1819c 100644 --- a/awx/lib/site-packages/requests/models.py +++ b/awx/lib/site-packages/requests/models.py @@ -270,6 +270,9 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): self.url = None #: dictionary of HTTP headers. self.headers = None + # The `CookieJar` used to create the Cookie header will be stored here + # after prepare_cookies is called + self._cookies = None #: request body to send to the server. self.body = None #: dictionary of callback hooks, for internal usage. @@ -299,6 +302,7 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): p.method = self.method p.url = self.url p.headers = self.headers.copy() + p._cookies = self._cookies.copy() p.body = self.body p.hooks = self.hooks return p @@ -320,11 +324,17 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): except UnicodeDecodeError: pass + # Don't do any URL preparation for oddball schemes + if ':' in url and not url.lower().startswith('http'): + self.url = url + return + # Support for unicode domain names and paths. scheme, auth, host, port, path, query, fragment = parse_url(url) if not scheme: - raise MissingSchema("Invalid URL %r: No schema supplied" % url) + raise MissingSchema("Invalid URL {0!r}: No schema supplied. " + "Perhaps you meant http://{0}?".format(url)) if not host: raise InvalidURL("Invalid URL %r: No host supplied" % url) @@ -407,7 +417,7 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): raise NotImplementedError('Streamed bodies and files are mutually exclusive.') if length is not None: - self.headers['Content-Length'] = str(length) + self.headers['Content-Length'] = builtin_str(length) else: self.headers['Transfer-Encoding'] = 'chunked' else: @@ -433,12 +443,12 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): def prepare_content_length(self, body): if hasattr(body, 'seek') and hasattr(body, 'tell'): body.seek(0, 2) - self.headers['Content-Length'] = str(body.tell()) + self.headers['Content-Length'] = builtin_str(body.tell()) body.seek(0, 0) elif body is not None: l = super_len(body) if l: - self.headers['Content-Length'] = str(l) + self.headers['Content-Length'] = builtin_str(l) elif self.method not in ('GET', 'HEAD'): self.headers['Content-Length'] = '0' @@ -468,14 +478,13 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): """Prepares the given HTTP cookie data.""" if isinstance(cookies, cookielib.CookieJar): - cookies = cookies + self._cookies = cookies else: - cookies = cookiejar_from_dict(cookies) + self._cookies = cookiejar_from_dict(cookies) - if 'cookie' not in self.headers: - cookie_header = get_cookie_header(cookies, self) - if cookie_header is not None: - self.headers['Cookie'] = cookie_header + cookie_header = get_cookie_header(self._cookies, self) + if cookie_header is not None: + self.headers['Cookie'] = cookie_header def prepare_hooks(self, hooks): """Prepares the given hooks.""" @@ -488,6 +497,19 @@ class Response(object): server's response to an HTTP request. """ + __attrs__ = [ + '_content', + 'status_code', + 'headers', + 'url', + 'history', + 'encoding', + 'reason', + 'cookies', + 'elapsed', + 'request', + ] + def __init__(self): super(Response, self).__init__() @@ -527,6 +549,24 @@ class Response(object): #: and the arrival of the response (as a timedelta) self.elapsed = datetime.timedelta(0) + def __getstate__(self): + # Consume everything; accessing the content attribute makes + # sure the content has been fully read. + if not self._content_consumed: + self.content + + return dict( + (attr, getattr(self, attr, None)) + for attr in self.__attrs__ + ) + + def __setstate__(self, state): + for name, value in state.items(): + setattr(self, name, value) + + # pickled objects do not have .raw + setattr(self, '_content_consumed', True) + def __repr__(self): return '' % (self.status_code) @@ -647,8 +687,8 @@ class Response(object): def text(self): """Content of the response, in unicode. - if Response.encoding is None and chardet module is available, encoding - will be guessed. + If Response.encoding is None, encoding will be guessed using + ``charade``. """ # Try charset from content-type diff --git a/awx/lib/site-packages/requests/packages/urllib3/_collections.py b/awx/lib/site-packages/requests/packages/urllib3/_collections.py index 282b8d5e05..5907b0dc7c 100644 --- a/awx/lib/site-packages/requests/packages/urllib3/_collections.py +++ b/awx/lib/site-packages/requests/packages/urllib3/_collections.py @@ -5,7 +5,16 @@ # the MIT License: http://www.opensource.org/licenses/mit-license.php from collections import MutableMapping -from threading import RLock +try: + from threading import RLock +except ImportError: # Platform-specific: No threads available + class RLock: + def __enter__(self): + pass + + def __exit__(self, exc_type, exc_value, traceback): + pass + try: # Python 2.7+ from collections import OrderedDict diff --git a/awx/lib/site-packages/requests/packages/urllib3/connectionpool.py b/awx/lib/site-packages/requests/packages/urllib3/connectionpool.py index 1e5814357a..72011b5a33 100644 --- a/awx/lib/site-packages/requests/packages/urllib3/connectionpool.py +++ b/awx/lib/site-packages/requests/packages/urllib3/connectionpool.py @@ -461,6 +461,13 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): conn = None + # Merge the proxy headers. Only do this in HTTP. We have to copy the + # headers dict so we can safely change it without those changes being + # reflected in anyone else's copy. + if self.scheme == 'http': + headers = headers.copy() + headers.update(self.proxy_headers) + try: # Request a connection from the queue conn = self._get_conn(timeout=pool_timeout) diff --git a/awx/lib/site-packages/requests/packages/urllib3/contrib/pyopenssl.py b/awx/lib/site-packages/requests/packages/urllib3/contrib/pyopenssl.py index 91bc2fa4f7..f78e71706e 100644 --- a/awx/lib/site-packages/requests/packages/urllib3/contrib/pyopenssl.py +++ b/awx/lib/site-packages/requests/packages/urllib3/contrib/pyopenssl.py @@ -29,7 +29,7 @@ import ssl import select from cStringIO import StringIO -from .. import connectionpool +from .. import connection from .. import util __all__ = ['inject_into_urllib3', 'extract_from_urllib3'] @@ -52,20 +52,20 @@ _openssl_verify = { orig_util_HAS_SNI = util.HAS_SNI -orig_connectionpool_ssl_wrap_socket = connectionpool.ssl_wrap_socket +orig_connection_ssl_wrap_socket = connection.ssl_wrap_socket def inject_into_urllib3(): 'Monkey-patch urllib3 with PyOpenSSL-backed SSL-support.' - connectionpool.ssl_wrap_socket = ssl_wrap_socket + connection.ssl_wrap_socket = ssl_wrap_socket util.HAS_SNI = HAS_SNI def extract_from_urllib3(): 'Undo monkey-patching by :func:`inject_into_urllib3`.' - connectionpool.ssl_wrap_socket = orig_connectionpool_ssl_wrap_socket + connection.ssl_wrap_socket = orig_connection_ssl_wrap_socket util.HAS_SNI = orig_util_HAS_SNI diff --git a/awx/lib/site-packages/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py b/awx/lib/site-packages/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py index 2d61ac2139..3aa5b2e190 100644 --- a/awx/lib/site-packages/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py +++ b/awx/lib/site-packages/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py @@ -1,98 +1,13 @@ -"""The match_hostname() function from Python 3.2, essential when using SSL.""" +try: + # Python 3.2+ + from ssl import CertificateError, match_hostname +except ImportError: + try: + # Backport of the function from a pypi module + from backports.ssl_match_hostname import CertificateError, match_hostname + except ImportError: + # Our vendored copy + from _implementation import CertificateError, match_hostname -import re - -__version__ = '3.2.2' - -class CertificateError(ValueError): - pass - -def _dnsname_match(dn, hostname, max_wildcards=1): - """Matching according to RFC 6125, section 6.4.3 - - http://tools.ietf.org/html/rfc6125#section-6.4.3 - """ - pats = [] - if not dn: - return False - - parts = dn.split(r'.') - leftmost = parts[0] - - wildcards = leftmost.count('*') - if wildcards > max_wildcards: - # Issue #17980: avoid denials of service by refusing more - # than one wildcard per fragment. A survery of established - # policy among SSL implementations showed it to be a - # reasonable choice. - raise CertificateError( - "too many wildcards in certificate DNS name: " + repr(dn)) - - # speed up common case w/o wildcards - if not wildcards: - return dn.lower() == hostname.lower() - - # RFC 6125, section 6.4.3, subitem 1. - # The client SHOULD NOT attempt to match a presented identifier in which - # the wildcard character comprises a label other than the left-most label. - if leftmost == '*': - # When '*' is a fragment by itself, it matches a non-empty dotless - # fragment. - pats.append('[^.]+') - elif leftmost.startswith('xn--') or hostname.startswith('xn--'): - # RFC 6125, section 6.4.3, subitem 3. - # The client SHOULD NOT attempt to match a presented identifier - # where the wildcard character is embedded within an A-label or - # U-label of an internationalized domain name. - pats.append(re.escape(leftmost)) - else: - # Otherwise, '*' matches any dotless string, e.g. www* - pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) - - # add the remaining fragments, ignore any wildcards - for frag in parts[1:]: - pats.append(re.escape(frag)) - - pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) - return pat.match(hostname) - - -def match_hostname(cert, hostname): - """Verify that *cert* (in decoded format as returned by - SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 - rules are followed, but IP addresses are not accepted for *hostname*. - - CertificateError is raised on failure. On success, the function - returns nothing. - """ - if not cert: - raise ValueError("empty or no certificate") - dnsnames = [] - san = cert.get('subjectAltName', ()) - for key, value in san: - if key == 'DNS': - if _dnsname_match(value, hostname): - return - dnsnames.append(value) - if not dnsnames: - # The subject is only checked when there is no dNSName entry - # in subjectAltName - for sub in cert.get('subject', ()): - for key, value in sub: - # XXX according to RFC 2818, the most specific Common Name - # must be used. - if key == 'commonName': - if _dnsname_match(value, hostname): - return - dnsnames.append(value) - if len(dnsnames) > 1: - raise CertificateError("hostname %r " - "doesn't match either of %s" - % (hostname, ', '.join(map(repr, dnsnames)))) - elif len(dnsnames) == 1: - raise CertificateError("hostname %r " - "doesn't match %r" - % (hostname, dnsnames[0])) - else: - raise CertificateError("no appropriate commonName or " - "subjectAltName fields were found") +# Not needed, but documenting what we provide. +__all__ = ('CertificateError', 'match_hostname') diff --git a/awx/lib/site-packages/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py b/awx/lib/site-packages/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py new file mode 100644 index 0000000000..52f428733d --- /dev/null +++ b/awx/lib/site-packages/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py @@ -0,0 +1,105 @@ +"""The match_hostname() function from Python 3.3.3, essential when using SSL.""" + +# Note: This file is under the PSF license as the code comes from the python +# stdlib. http://docs.python.org/3/license.html + +import re + +__version__ = '3.4.0.2' + +class CertificateError(ValueError): + pass + + +def _dnsname_match(dn, hostname, max_wildcards=1): + """Matching according to RFC 6125, section 6.4.3 + + http://tools.ietf.org/html/rfc6125#section-6.4.3 + """ + pats = [] + if not dn: + return False + + # Ported from python3-syntax: + # leftmost, *remainder = dn.split(r'.') + parts = dn.split(r'.') + leftmost = parts[0] + remainder = parts[1:] + + wildcards = leftmost.count('*') + if wildcards > max_wildcards: + # Issue #17980: avoid denials of service by refusing more + # than one wildcard per fragment. A survey of established + # policy among SSL implementations showed it to be a + # reasonable choice. + raise CertificateError( + "too many wildcards in certificate DNS name: " + repr(dn)) + + # speed up common case w/o wildcards + if not wildcards: + return dn.lower() == hostname.lower() + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in which + # the wildcard character comprises a label other than the left-most label. + if leftmost == '*': + # When '*' is a fragment by itself, it matches a non-empty dotless + # fragment. + pats.append('[^.]+') + elif leftmost.startswith('xn--') or hostname.startswith('xn--'): + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + pats.append(re.escape(leftmost)) + else: + # Otherwise, '*' matches any dotless string, e.g. www* + pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) + + # add the remaining fragments, ignore any wildcards + for frag in remainder: + pats.append(re.escape(frag)) + + pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) + return pat.match(hostname) + + +def match_hostname(cert, hostname): + """Verify that *cert* (in decoded format as returned by + SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 + rules are followed, but IP addresses are not accepted for *hostname*. + + CertificateError is raised on failure. On success, the function + returns nothing. + """ + if not cert: + raise ValueError("empty or no certificate") + dnsnames = [] + san = cert.get('subjectAltName', ()) + for key, value in san: + if key == 'DNS': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if not dnsnames: + # The subject is only checked when there is no dNSName entry + # in subjectAltName + for sub in cert.get('subject', ()): + for key, value in sub: + # XXX according to RFC 2818, the most specific Common Name + # must be used. + if key == 'commonName': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if len(dnsnames) > 1: + raise CertificateError("hostname %r " + "doesn't match either of %s" + % (hostname, ', '.join(map(repr, dnsnames)))) + elif len(dnsnames) == 1: + raise CertificateError("hostname %r " + "doesn't match %r" + % (hostname, dnsnames[0])) + else: + raise CertificateError("no appropriate commonName or " + "subjectAltName fields were found") diff --git a/awx/lib/site-packages/requests/packages/urllib3/poolmanager.py b/awx/lib/site-packages/requests/packages/urllib3/poolmanager.py index e7f8667ee6..c16519f883 100644 --- a/awx/lib/site-packages/requests/packages/urllib3/poolmanager.py +++ b/awx/lib/site-packages/requests/packages/urllib3/poolmanager.py @@ -245,12 +245,11 @@ class ProxyManager(PoolManager): u = parse_url(url) if u.scheme == "http": - # It's too late to set proxy headers on per-request basis for - # tunnelled HTTPS connections, should use - # constructor's proxy_headers instead. + # For proxied HTTPS requests, httplib sets the necessary headers + # on the CONNECT to the proxy. For HTTP, we'll definitely + # need to set 'Host' at the very least. kw['headers'] = self._set_proxy_headers(url, kw.get('headers', self.headers)) - kw['headers'].update(self.proxy_headers) return super(ProxyManager, self).urlopen(method, url, redirect, **kw) diff --git a/awx/lib/site-packages/requests/packages/urllib3/response.py b/awx/lib/site-packages/requests/packages/urllib3/response.py index 4efff5a13b..6a1fe1a77c 100644 --- a/awx/lib/site-packages/requests/packages/urllib3/response.py +++ b/awx/lib/site-packages/requests/packages/urllib3/response.py @@ -90,6 +90,7 @@ class HTTPResponse(io.IOBase): self._body = body if body and isinstance(body, basestring) else None self._fp = None self._original_response = original_response + self._fp_bytes_read = 0 self._pool = pool self._connection = connection @@ -129,6 +130,14 @@ class HTTPResponse(io.IOBase): if self._fp: return self.read(cache_content=True) + def tell(self): + """ + Obtain the number of bytes pulled over the wire so far. May differ from + the amount of content returned by :meth:``HTTPResponse.read`` if bytes + are encoded on the wire (e.g, compressed). + """ + return self._fp_bytes_read + def read(self, amt=None, decode_content=None, cache_content=False): """ Similar to :meth:`httplib.HTTPResponse.read`, but with two additional @@ -183,6 +192,8 @@ class HTTPResponse(io.IOBase): self._fp.close() flush_decoder = True + self._fp_bytes_read += len(data) + try: if decode_content and self._decoder: data = self._decoder.decompress(data) diff --git a/awx/lib/site-packages/requests/packages/urllib3/util.py b/awx/lib/site-packages/requests/packages/urllib3/util.py index cf934d4246..46a0c48de1 100644 --- a/awx/lib/site-packages/requests/packages/urllib3/util.py +++ b/awx/lib/site-packages/requests/packages/urllib3/util.py @@ -426,7 +426,7 @@ def get_host(url): def make_headers(keep_alive=None, accept_encoding=None, user_agent=None, - basic_auth=None): + basic_auth=None, proxy_basic_auth=None): """ Shortcuts for generating request headers. @@ -447,6 +447,10 @@ def make_headers(keep_alive=None, accept_encoding=None, user_agent=None, Colon-separated username:password string for 'authorization: basic ...' auth header. + :param proxy_basic_auth: + Colon-separated username:password string for 'proxy-authorization: basic ...' + auth header. + Example: :: >>> make_headers(keep_alive=True, user_agent="Batman/1.0") @@ -474,6 +478,10 @@ def make_headers(keep_alive=None, accept_encoding=None, user_agent=None, headers['authorization'] = 'Basic ' + \ b64encode(six.b(basic_auth)).decode('utf-8') + if proxy_basic_auth: + headers['proxy-authorization'] = 'Basic ' + \ + b64encode(six.b(proxy_basic_auth)).decode('utf-8') + return headers diff --git a/awx/lib/site-packages/requests/sessions.py b/awx/lib/site-packages/requests/sessions.py index cc72f65d9d..06e17d4b94 100644 --- a/awx/lib/site-packages/requests/sessions.py +++ b/awx/lib/site-packages/requests/sessions.py @@ -12,8 +12,9 @@ import os from collections import Mapping from datetime import datetime -from .compat import cookielib, OrderedDict, urljoin, urlparse, urlunparse -from .cookies import cookiejar_from_dict, extract_cookies_to_jar, RequestsCookieJar +from .compat import cookielib, OrderedDict, urljoin, urlparse, builtin_str +from .cookies import ( + cookiejar_from_dict, extract_cookies_to_jar, RequestsCookieJar, merge_cookies) from .models import Request, PreparedRequest from .hooks import default_hooks, dispatch_hook from .utils import to_key_val_list, default_headers @@ -65,6 +66,22 @@ def merge_setting(request_setting, session_setting, dict_class=OrderedDict): return merged_setting +def merge_hooks(request_hooks, session_hooks, dict_class=OrderedDict): + """ + Properly merges both requests and session hooks. + + This is necessary because when request_hooks == {'response': []}, the + merge breaks Session hooks entirely. + """ + if session_hooks is None or session_hooks.get('response') == []: + return request_hooks + + if request_hooks is None or request_hooks.get('response') == []: + return session_hooks + + return merge_setting(request_hooks, session_hooks, dict_class) + + class SessionRedirectMixin(object): def resolve_redirects(self, resp, req, stream=False, timeout=None, verify=True, cert=None, proxies=None): @@ -94,9 +111,7 @@ class SessionRedirectMixin(object): # The scheme should be lower case... parsed = urlparse(url) - parsed = (parsed.scheme.lower(), parsed.netloc, parsed.path, - parsed.params, parsed.query, parsed.fragment) - url = urlunparse(parsed) + url = parsed.geturl() # Facilitate non-RFC2616-compliant 'location' headers # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource') @@ -114,8 +129,13 @@ class SessionRedirectMixin(object): method = 'GET' # Do what the browsers do, despite standards... - if (resp.status_code in (codes.moved, codes.found) and - method not in ('GET', 'HEAD')): + # First, turn 302s into GETs. + if resp.status_code == codes.found and method != 'HEAD': + method = 'GET' + + # Second, if a POST is responded to with a 301, turn it into a GET. + # This bizarre behaviour is explained in Issue 1704. + if resp.status_code == codes.moved and method == 'POST': method = 'GET' prepared_request.method = method @@ -133,7 +153,9 @@ class SessionRedirectMixin(object): except KeyError: pass - prepared_request.prepare_cookies(self.cookies) + extract_cookies_to_jar(prepared_request._cookies, + prepared_request, resp.raw) + prepared_request.prepare_cookies(prepared_request._cookies) resp = self.send( prepared_request, @@ -242,9 +264,8 @@ class Session(SessionRedirectMixin): cookies = cookiejar_from_dict(cookies) # Merge with session cookies - merged_cookies = RequestsCookieJar() - merged_cookies.update(self.cookies) - merged_cookies.update(cookies) + merged_cookies = merge_cookies( + merge_cookies(RequestsCookieJar(), self.cookies), cookies) # Set environment's basic authentication if not explicitly set. @@ -262,7 +283,7 @@ class Session(SessionRedirectMixin): params=merge_setting(request.params, self.params), auth=merge_setting(auth, self.auth), cookies=merged_cookies, - hooks=merge_setting(request.hooks, self.hooks), + hooks=merge_hooks(request.hooks, self.hooks), ) return p @@ -309,6 +330,9 @@ class Session(SessionRedirectMixin): :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. """ + + method = builtin_str(method) + # Create the Request. req = Request( method = method.upper(), @@ -323,9 +347,6 @@ class Session(SessionRedirectMixin): ) prep = self.prepare_request(req) - # Add param cookies to session cookies - self.cookies = cookiejar_from_dict(cookies, cookiejar=self.cookies, overwrite=False) - proxies = proxies or {} # Gather clues from the surrounding environment. diff --git a/awx/lib/site-packages/requests/utils.py b/awx/lib/site-packages/requests/utils.py index 5000105a65..c7e2b08943 100644 --- a/awx/lib/site-packages/requests/utils.py +++ b/awx/lib/site-packages/requests/utils.py @@ -17,13 +17,14 @@ import os import platform import re import sys -from netrc import netrc, NetrcParseError +import socket +import struct from . import __version__ from . import certs from .compat import parse_http_list as _parse_list_header -from .compat import (quote, urlparse, bytes, str, OrderedDict, urlunparse, - is_py2, is_py3, builtin_str, getproxies, proxy_bypass) +from .compat import (quote, urlparse, bytes, str, OrderedDict, unquote, is_py2, + builtin_str, getproxies, proxy_bypass) from .cookies import RequestsCookieJar, cookiejar_from_dict from .structures import CaseInsensitiveDict from .exceptions import MissingSchema, InvalidURL @@ -67,6 +68,8 @@ def get_netrc_auth(url): """Returns the Requests tuple auth for a given url from netrc.""" try: + from netrc import netrc, NetrcParseError + locations = (os.path.expanduser('~/{0}'.format(f)) for f in NETRC_FILES) netrc_path = None @@ -404,6 +407,56 @@ def requote_uri(uri): return quote(unquote_unreserved(uri), safe="!#$%&'()*+,/:;=?@[]~") +def address_in_network(ip, net): + """ + This function allows you to check if on IP belongs to a network subnet + Example: returns True if ip = 192.168.1.1 and net = 192.168.1.0/24 + returns False if ip = 192.168.1.1 and net = 192.168.100.0/24 + """ + ipaddr = struct.unpack('=L', socket.inet_aton(ip))[0] + netaddr, bits = net.split('/') + netmask = struct.unpack('=L', socket.inet_aton(dotted_netmask(int(bits))))[0] + network = struct.unpack('=L', socket.inet_aton(netaddr))[0] & netmask + return (ipaddr & netmask) == (network & netmask) + + +def dotted_netmask(mask): + """ + Converts mask from /xx format to xxx.xxx.xxx.xxx + Example: if mask is 24 function returns 255.255.255.0 + """ + bits = 0xffffffff ^ (1 << 32 - mask) - 1 + return socket.inet_ntoa(struct.pack('>I', bits)) + + +def is_ipv4_address(string_ip): + try: + socket.inet_aton(string_ip) + except socket.error: + return False + return True + + +def is_valid_cidr(string_network): + """Very simple check of the cidr format in no_proxy variable""" + if string_network.count('/') == 1: + try: + mask = int(string_network.split('/')[1]) + except ValueError: + return False + + if mask < 1 or mask > 32: + return False + + try: + socket.inet_aton(string_network.split('/')[0]) + except socket.error: + return False + else: + return False + return True + + def get_environ_proxies(url): """Return a dict of environment proxies.""" @@ -419,11 +472,18 @@ def get_environ_proxies(url): # the end of the netloc, both with and without the port. no_proxy = no_proxy.replace(' ', '').split(',') - for host in no_proxy: - if netloc.endswith(host) or netloc.split(':')[0].endswith(host): - # The URL does match something in no_proxy, so we don't want - # to apply the proxies on this URL. - return {} + ip = netloc.split(':')[0] + if is_ipv4_address(ip): + for proxy_ip in no_proxy: + if is_valid_cidr(proxy_ip): + if address_in_network(ip, proxy_ip): + return {} + else: + for host in no_proxy: + if netloc.endswith(host) or netloc.split(':')[0].endswith(host): + # The URL does match something in no_proxy, so we don't want + # to apply the proxies on this URL. + return {} # If the system proxy settings indicate that this URL should be bypassed, # don't proxy. @@ -436,7 +496,7 @@ def get_environ_proxies(url): return getproxies() -def default_user_agent(): +def default_user_agent(name="python-requests"): """Return a string representing the default user agent.""" _implementation = platform.python_implementation() @@ -462,7 +522,7 @@ def default_user_agent(): p_system = 'Unknown' p_release = 'Unknown' - return " ".join(['python-requests/%s' % __version__, + return " ".join(['%s/%s' % (name, __version__), '%s/%s' % (_implementation, _implementation_version), '%s/%s' % (p_system, p_release)]) @@ -557,6 +617,7 @@ def get_auth_from_url(url): """Given a url with authentication components, extract them into a tuple of username,password.""" if url: + url = unquote(url) parsed = urlparse(url) return (parsed.username, parsed.password) else: diff --git a/awx/lib/site-packages/rest_framework/__init__.py b/awx/lib/site-packages/rest_framework/__init__.py index 2bd2991baa..f5483b9d6c 100644 --- a/awx/lib/site-packages/rest_framework/__init__.py +++ b/awx/lib/site-packages/rest_framework/__init__.py @@ -1,6 +1,20 @@ -__version__ = '2.3.8' +""" +______ _____ _____ _____ __ _ +| ___ \ ___/ ___|_ _| / _| | | +| |_/ / |__ \ `--. | | | |_ _ __ __ _ _ __ ___ _____ _____ _ __| | __ +| /| __| `--. \ | | | _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ / +| |\ \| |___/\__/ / | | | | | | | (_| | | | | | | __/\ V V / (_) | | | < +\_| \_\____/\____/ \_/ |_| |_| \__,_|_| |_| |_|\___| \_/\_/ \___/|_| |_|\_| +""" -VERSION = __version__ # synonym +__title__ = 'Django REST framework' +__version__ = '2.3.10' +__author__ = 'Tom Christie' +__license__ = 'BSD 2-Clause' +__copyright__ = 'Copyright 2011-2013 Tom Christie' + +# Version synonym +VERSION = __version__ # Header encoding (see RFC5987) HTTP_HEADER_ENCODING = 'iso-8859-1' diff --git a/awx/lib/site-packages/rest_framework/compat.py b/awx/lib/site-packages/rest_framework/compat.py index b9d1dae6b2..581e29fc79 100644 --- a/awx/lib/site-packages/rest_framework/compat.py +++ b/awx/lib/site-packages/rest_framework/compat.py @@ -80,6 +80,14 @@ except ImportError: Image = None +def get_model_name(model_cls): + try: + return model_cls._meta.model_name + except AttributeError: + # < 1.6 used module_name instead of model_name + return model_cls._meta.module_name + + def get_concrete_model(model_cls): try: return model_cls._meta.concrete_model diff --git a/awx/lib/site-packages/rest_framework/fields.py b/awx/lib/site-packages/rest_framework/fields.py index 210c2537da..5a4f04a5bc 100644 --- a/awx/lib/site-packages/rest_framework/fields.py +++ b/awx/lib/site-packages/rest_framework/fields.py @@ -123,6 +123,7 @@ class Field(object): use_files = False form_field_class = forms.CharField type_label = 'field' + widget = None def __init__(self, source=None, label=None, help_text=None): self.parent = None @@ -134,9 +135,29 @@ class Field(object): if label is not None: self.label = smart_text(label) + else: + self.label = None if help_text is not None: self.help_text = strip_multiple_choice_msg(smart_text(help_text)) + else: + self.help_text = None + + self._errors = [] + self._value = None + self._name = None + + @property + def errors(self): + return self._errors + + def widget_html(self): + if not self.widget: + return '' + return self.widget.render(self._name, self._value) + + def label_tag(self): + return '' % (self._name, self.label) def initialize(self, parent, field_name): """ @@ -306,6 +327,7 @@ class WritableField(Field): return try: + data = data or {} if self.use_files: files = files or {} try: @@ -475,6 +497,7 @@ class ChoiceField(WritableField): } def __init__(self, choices=(), *args, **kwargs): + self.empty = kwargs.pop('empty', '') super(ChoiceField, self).__init__(*args, **kwargs) self.choices = choices if not self.required: @@ -491,6 +514,11 @@ class ChoiceField(WritableField): choices = property(_get_choices, _set_choices) + def metadata(self): + data = super(ChoiceField, self).metadata() + data['choices'] = [{'value': v, 'display_name': n} for v, n in self.choices] + return data + def validate(self, value): """ Validates that the input is in self.choices. @@ -515,9 +543,10 @@ class ChoiceField(WritableField): return False def from_native(self, value): - if value in validators.EMPTY_VALUES: - return None - return super(ChoiceField, self).from_native(value) + value = super(ChoiceField, self).from_native(value) + if value == self.empty or value in validators.EMPTY_VALUES: + return self.empty + return value class EmailField(CharField): @@ -756,6 +785,7 @@ class IntegerField(WritableField): type_name = 'IntegerField' type_label = 'integer' form_field_class = forms.IntegerField + empty = 0 default_error_messages = { 'invalid': _('Enter a whole number.'), @@ -787,6 +817,7 @@ class FloatField(WritableField): type_name = 'FloatField' type_label = 'float' form_field_class = forms.FloatField + empty = 0 default_error_messages = { 'invalid': _("'%s' value must be a float."), @@ -807,6 +838,7 @@ class DecimalField(WritableField): type_name = 'DecimalField' type_label = 'decimal' form_field_class = forms.DecimalField + empty = Decimal('0') default_error_messages = { 'invalid': _('Enter a number.'), @@ -939,7 +971,7 @@ class ImageField(FileField): return None from rest_framework.compat import Image - assert Image is not None, 'PIL must be installed for ImageField support' + assert Image is not None, 'Either Pillow or PIL must be installed for ImageField support.' # We need to get a file object for PIL. We might have a path or we might # have to read the data into memory. diff --git a/awx/lib/site-packages/rest_framework/filters.py b/awx/lib/site-packages/rest_framework/filters.py index 1693bcd24c..5c6a187c48 100644 --- a/awx/lib/site-packages/rest_framework/filters.py +++ b/awx/lib/site-packages/rest_framework/filters.py @@ -4,7 +4,7 @@ returned by list views. """ from __future__ import unicode_literals from django.db import models -from rest_framework.compat import django_filters, six, guardian +from rest_framework.compat import django_filters, six, guardian, get_model_name from functools import reduce import operator @@ -53,6 +53,7 @@ class DjangoFilterBackend(BaseFilterBackend): class Meta: model = queryset.model fields = filter_fields + order_by = True return AutoFilterSet return None @@ -123,6 +124,7 @@ class OrderingFilter(BaseFilterBackend): def remove_invalid_fields(self, queryset, ordering): field_names = [field.name for field in queryset.model._meta.fields] + field_names += queryset.query.aggregates.keys() return [term for term in ordering if term.lstrip('-') in field_names] def filter_queryset(self, request, queryset, view): @@ -157,7 +159,7 @@ class DjangoObjectPermissionsFilter(BaseFilterBackend): model_cls = queryset.model kwargs = { 'app_label': model_cls._meta.app_label, - 'model_name': model_cls._meta.module_name + 'model_name': get_model_name(model_cls) } permission = self.perm_format % kwargs return guardian.shortcuts.get_objects_for_user(user, permission, queryset) diff --git a/awx/lib/site-packages/rest_framework/generics.py b/awx/lib/site-packages/rest_framework/generics.py index 7d1bf79451..fd411ad385 100644 --- a/awx/lib/site-packages/rest_framework/generics.py +++ b/awx/lib/site-packages/rest_framework/generics.py @@ -25,13 +25,13 @@ def strict_positive_int(integer_string, cutoff=None): ret = min(ret, cutoff) return ret -def get_object_or_404(queryset, **filter_kwargs): +def get_object_or_404(queryset, *filter_args, **filter_kwargs): """ Same as Django's standard shortcut, but make sure to raise 404 if the filter_kwargs don't match the required types. """ try: - return _get_object_or_404(queryset, **filter_kwargs) + return _get_object_or_404(queryset, *filter_args, **filter_kwargs) except (TypeError, ValueError): raise Http404 @@ -54,6 +54,7 @@ class GenericAPIView(views.APIView): # If you want to use object lookups other than pk, set this attribute. # For more complex lookup requirements override `get_object()`. lookup_field = 'pk' + lookup_url_kwarg = None # Pagination settings paginate_by = api_settings.PAGINATE_BY @@ -147,8 +148,8 @@ class GenericAPIView(views.APIView): page_query_param = self.request.QUERY_PARAMS.get(self.page_kwarg) page = page_kwarg or page_query_param or 1 try: - page_number = strict_positive_int(page) - except ValueError: + page_number = paginator.validate_number(page) + except InvalidPage: if page == 'last': page_number = paginator.num_pages else: @@ -174,6 +175,14 @@ class GenericAPIView(views.APIView): method if you want to apply the configured filtering backend to the default queryset. """ + for backend in self.get_filter_backends(): + queryset = backend().filter_queryset(self.request, queryset, self) + return queryset + + def get_filter_backends(self): + """ + Returns the list of filter backends that this view requires. + """ filter_backends = self.filter_backends or [] if not filter_backends and self.filter_backend: warnings.warn( @@ -184,10 +193,8 @@ class GenericAPIView(views.APIView): PendingDeprecationWarning, stacklevel=2 ) filter_backends = [self.filter_backend] + return filter_backends - for backend in filter_backends: - queryset = backend().filter_queryset(self.request, queryset, self) - return queryset ######################## ### The following methods provide default implementations @@ -278,9 +285,11 @@ class GenericAPIView(views.APIView): pass # Deprecation warning # Perform the lookup filtering. + # Note that `pk` and `slug` are deprecated styles of lookup filtering. + lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field + lookup = self.kwargs.get(lookup_url_kwarg, None) pk = self.kwargs.get(self.pk_url_kwarg, None) slug = self.kwargs.get(self.slug_url_kwarg, None) - lookup = self.kwargs.get(self.lookup_field, None) if lookup is not None: filter_kwargs = {self.lookup_field: lookup} @@ -335,6 +344,18 @@ class GenericAPIView(views.APIView): """ pass + def pre_delete(self, obj): + """ + Placeholder method for calling before deleting an object. + """ + pass + + def post_delete(self, obj): + """ + Placeholder method for calling after saving an object. + """ + pass + def metadata(self, request): """ Return a dictionary of metadata about the view. diff --git a/awx/lib/site-packages/rest_framework/mixins.py b/awx/lib/site-packages/rest_framework/mixins.py index 426865ff93..43950c4bf6 100644 --- a/awx/lib/site-packages/rest_framework/mixins.py +++ b/awx/lib/site-packages/rest_framework/mixins.py @@ -6,6 +6,7 @@ which allows mixin classes to be composed in interesting ways. """ from __future__ import unicode_literals +from django.core.exceptions import ValidationError from django.http import Http404 from rest_framework import status from rest_framework.response import Response @@ -127,7 +128,12 @@ class UpdateModelMixin(object): files=request.FILES, partial=partial) if serializer.is_valid(): - self.pre_save(serializer.object) + try: + self.pre_save(serializer.object) + except ValidationError as err: + # full_clean on model instance may be called in pre_save, so we + # have to handle eventual errors. + return Response(err.message_dict, status=status.HTTP_400_BAD_REQUEST) self.object = serializer.save(**save_kwargs) self.post_save(self.object, created=created) return Response(serializer.data, status=success_status_code) @@ -158,7 +164,8 @@ class UpdateModelMixin(object): Set any attributes on the object that are implicit in the request. """ # pk and/or slug attributes are implicit in the URL. - lookup = self.kwargs.get(self.lookup_field, None) + lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field + lookup = self.kwargs.get(lookup_url_kwarg, None) pk = self.kwargs.get(self.pk_url_kwarg, None) slug = self.kwargs.get(self.slug_url_kwarg, None) slug_field = slug and self.slug_field or None @@ -185,5 +192,7 @@ class DestroyModelMixin(object): """ def destroy(self, request, *args, **kwargs): obj = self.get_object() + self.pre_delete(obj) obj.delete() + self.post_delete(obj) return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/awx/lib/site-packages/rest_framework/parsers.py b/awx/lib/site-packages/rest_framework/parsers.py index 98fc03417d..f1b3e38d40 100644 --- a/awx/lib/site-packages/rest_framework/parsers.py +++ b/awx/lib/site-packages/rest_framework/parsers.py @@ -83,7 +83,7 @@ class YAMLParser(BaseParser): data = stream.read().decode(encoding) return yaml.safe_load(data) except (ValueError, yaml.parser.ParserError) as exc: - raise ParseError('YAML parse error - %s' % six.u(exc)) + raise ParseError('YAML parse error - %s' % six.text_type(exc)) class FormParser(BaseParser): @@ -153,7 +153,7 @@ class XMLParser(BaseParser): try: tree = etree.parse(stream, parser=parser, forbid_dtd=True) except (etree.ParseError, ValueError) as exc: - raise ParseError('XML parse error - %s' % six.u(exc)) + raise ParseError('XML parse error - %s' % six.text_type(exc)) data = self._xml_convert(tree.getroot()) return data diff --git a/awx/lib/site-packages/rest_framework/permissions.py b/awx/lib/site-packages/rest_framework/permissions.py index 531847988f..ab6655e7ba 100644 --- a/awx/lib/site-packages/rest_framework/permissions.py +++ b/awx/lib/site-packages/rest_framework/permissions.py @@ -8,7 +8,8 @@ import warnings SAFE_METHODS = ['GET', 'HEAD', 'OPTIONS'] from django.http import Http404 -from rest_framework.compat import oauth2_provider_scope, oauth2_constants +from rest_framework.compat import (get_model_name, oauth2_provider_scope, + oauth2_constants) class BasePermission(object): @@ -116,7 +117,7 @@ class DjangoModelPermissions(BasePermission): """ kwargs = { 'app_label': model_cls._meta.app_label, - 'model_name': model_cls._meta.module_name + 'model_name': get_model_name(model_cls) } return [perm % kwargs for perm in self.perms_map[method]] @@ -177,7 +178,7 @@ class DjangoObjectPermissions(DjangoModelPermissions): def get_required_object_permissions(self, method, model_cls): kwargs = { 'app_label': model_cls._meta.app_label, - 'model_name': model_cls._meta.module_name + 'model_name': get_model_name(model_cls) } return [perm % kwargs for perm in self.perms_map[method]] diff --git a/awx/lib/site-packages/rest_framework/renderers.py b/awx/lib/site-packages/rest_framework/renderers.py index fca67eeeb0..fe4f43d48d 100644 --- a/awx/lib/site-packages/rest_framework/renderers.py +++ b/awx/lib/site-packages/rest_framework/renderers.py @@ -272,7 +272,9 @@ class TemplateHTMLRenderer(BaseRenderer): return [self.template_name] elif hasattr(view, 'get_template_names'): return view.get_template_names() - raise ImproperlyConfigured('Returned a template response with no template_name') + elif hasattr(view, 'template_name'): + return [view.template_name] + raise ImproperlyConfigured('Returned a template response with no `template_name` attribute set on either the view or response') def get_exception_template(self, response): template_names = [name % {'status_code': response.status_code} @@ -334,71 +336,15 @@ class HTMLFormRenderer(BaseRenderer): template = 'rest_framework/form.html' charset = 'utf-8' - def data_to_form_fields(self, data): - fields = {} - for key, val in data.fields.items(): - if getattr(val, 'read_only', True): - # Don't include read-only fields. - continue - - if getattr(val, 'fields', None): - # Nested data not supported by HTML forms. - continue - - kwargs = {} - kwargs['required'] = val.required - - #if getattr(v, 'queryset', None): - # kwargs['queryset'] = v.queryset - - if getattr(val, 'choices', None) is not None: - kwargs['choices'] = val.choices - - if getattr(val, 'regex', None) is not None: - kwargs['regex'] = val.regex - - if getattr(val, 'widget', None): - widget = copy.deepcopy(val.widget) - kwargs['widget'] = widget - - if getattr(val, 'default', None) is not None: - kwargs['initial'] = val.default - - if getattr(val, 'label', None) is not None: - kwargs['label'] = val.label - - if getattr(val, 'help_text', None) is not None: - kwargs['help_text'] = val.help_text - - fields[key] = val.form_field_class(**kwargs) - - return fields - def render(self, data, accepted_media_type=None, renderer_context=None): """ Render serializer data and return an HTML form, as a string. """ - # The HTMLFormRenderer currently uses something of a hack to render - # the content, by translating each of the serializer fields into - # an html form field, creating a dynamic form using those fields, - # and then rendering that form. - - # This isn't strictly neccessary, as we could render the serilizer - # fields to HTML directly. The implementation is historical and will - # likely change at some point. - - self.renderer_context = renderer_context or {} + renderer_context = renderer_context or {} request = renderer_context['request'] - # Creating an on the fly form see: - # http://stackoverflow.com/questions/3915024/dynamically-creating-classes-python - fields = self.data_to_form_fields(data) - DynamicForm = type(str('DynamicForm'), (forms.Form,), fields) - data = None if data.empty else data - template = loader.get_template(self.template) - context = RequestContext(request, {'form': DynamicForm(data)}) - + context = RequestContext(request, {'form': data}) return template.render(context) @@ -419,8 +365,13 @@ class BrowsableAPIRenderer(BaseRenderer): """ renderers = [renderer for renderer in view.renderer_classes if not issubclass(renderer, BrowsableAPIRenderer)] + non_template_renderers = [renderer for renderer in renderers + if not hasattr(renderer, 'get_template_names')] + if not renderers: return None + elif non_template_renderers: + return non_template_renderers[0]() return renderers[0]() def get_content(self, renderer, data, @@ -468,6 +419,13 @@ class BrowsableAPIRenderer(BaseRenderer): In the absence of the View having an associated form then return None. """ + if request.method == method: + data = request.DATA + files = request.FILES + else: + data = None + files = None + with override_method(view, request, method) as request: obj = getattr(view, 'object', None) if not self.show_form_for_method(view, method, request, obj): @@ -480,9 +438,10 @@ class BrowsableAPIRenderer(BaseRenderer): or not any(is_form_media_type(parser.media_type) for parser in view.parser_classes)): return - serializer = view.get_serializer(instance=obj) - + serializer = view.get_serializer(instance=obj, data=data, files=files) + serializer.is_valid() data = serializer.data + form_renderer = self.form_renderer_class() return form_renderer.render(data, self.accepted_media_type, self.renderer_context) @@ -564,6 +523,49 @@ class BrowsableAPIRenderer(BaseRenderer): def get_breadcrumbs(self, request): return get_breadcrumbs(request.path) + def get_context(self, data, accepted_media_type, renderer_context): + """ + Returns the context used to render. + """ + view = renderer_context['view'] + request = renderer_context['request'] + response = renderer_context['response'] + + renderer = self.get_default_renderer(view) + + raw_data_post_form = self.get_raw_data_form(view, 'POST', request) + raw_data_put_form = self.get_raw_data_form(view, 'PUT', request) + raw_data_patch_form = self.get_raw_data_form(view, 'PATCH', request) + raw_data_put_or_patch_form = raw_data_put_form or raw_data_patch_form + + context = { + 'content': self.get_content(renderer, data, accepted_media_type, renderer_context), + 'view': view, + 'request': request, + 'response': response, + 'description': self.get_description(view), + 'name': self.get_name(view), + 'version': VERSION, + 'breadcrumblist': self.get_breadcrumbs(request), + 'allowed_methods': view.allowed_methods, + 'available_formats': [renderer.format for renderer in view.renderer_classes], + + 'put_form': self.get_rendered_html_form(view, 'PUT', request), + 'post_form': self.get_rendered_html_form(view, 'POST', request), + 'delete_form': self.get_rendered_html_form(view, 'DELETE', request), + 'options_form': self.get_rendered_html_form(view, 'OPTIONS', request), + + 'raw_data_put_form': raw_data_put_form, + 'raw_data_post_form': raw_data_post_form, + 'raw_data_patch_form': raw_data_patch_form, + 'raw_data_put_or_patch_form': raw_data_put_or_patch_form, + + 'display_edit_forms': bool(response.status_code != 403), + + 'api_settings': api_settings + } + return context + def render(self, data, accepted_media_type=None, renderer_context=None): """ Render the HTML for the browsable API representation. @@ -571,60 +573,15 @@ class BrowsableAPIRenderer(BaseRenderer): self.accepted_media_type = accepted_media_type or '' self.renderer_context = renderer_context or {} - view = renderer_context['view'] - request = renderer_context['request'] - response = renderer_context['response'] - - renderer = self.get_default_renderer(view) - content = self.get_content(renderer, data, accepted_media_type, renderer_context) - - put_form = self.get_rendered_html_form(view, 'PUT', request) - post_form = self.get_rendered_html_form(view, 'POST', request) - patch_form = self.get_rendered_html_form(view, 'PATCH', request) - delete_form = self.get_rendered_html_form(view, 'DELETE', request) - options_form = self.get_rendered_html_form(view, 'OPTIONS', request) - - raw_data_put_form = self.get_raw_data_form(view, 'PUT', request) - raw_data_post_form = self.get_raw_data_form(view, 'POST', request) - raw_data_patch_form = self.get_raw_data_form(view, 'PATCH', request) - raw_data_put_or_patch_form = raw_data_put_form or raw_data_patch_form - - name = self.get_name(view) - description = self.get_description(view) - breadcrumb_list = self.get_breadcrumbs(request) - template = loader.get_template(self.template) - context = RequestContext(request, { - 'content': content, - 'view': view, - 'request': request, - 'response': response, - 'description': description, - 'name': name, - 'version': VERSION, - 'breadcrumblist': breadcrumb_list, - 'allowed_methods': view.allowed_methods, - 'available_formats': [renderer.format for renderer in view.renderer_classes], - - 'put_form': put_form, - 'post_form': post_form, - 'patch_form': patch_form, - 'delete_form': delete_form, - 'options_form': options_form, - - 'raw_data_put_form': raw_data_put_form, - 'raw_data_post_form': raw_data_post_form, - 'raw_data_patch_form': raw_data_patch_form, - 'raw_data_put_or_patch_form': raw_data_put_or_patch_form, - - 'api_settings': api_settings - }) - + context = self.get_context(data, accepted_media_type, renderer_context) + context = RequestContext(renderer_context['request'], context) ret = template.render(context) # Munge DELETE Response code to allow us to return content # (Do this *after* we've rendered the template so that we include # the normal deletion response code in the output) + response = renderer_context['response'] if response.status_code == status.HTTP_204_NO_CONTENT: response.status_code = status.HTTP_200_OK diff --git a/awx/lib/site-packages/rest_framework/request.py b/awx/lib/site-packages/rest_framework/request.py index 977d4d9657..b883d0d4ff 100644 --- a/awx/lib/site-packages/rest_framework/request.py +++ b/awx/lib/site-packages/rest_framework/request.py @@ -334,7 +334,7 @@ class Request(object): self._CONTENT_PARAM in self._data and self._CONTENTTYPE_PARAM in self._data): self._content_type = self._data[self._CONTENTTYPE_PARAM] - self._stream = BytesIO(self._data[self._CONTENT_PARAM].encode(HTTP_HEADER_ENCODING)) + self._stream = BytesIO(self._data[self._CONTENT_PARAM].encode(self.parser_context['encoding'])) self._data, self._files = (Empty, Empty) def _parse(self): diff --git a/awx/lib/site-packages/rest_framework/response.py b/awx/lib/site-packages/rest_framework/response.py index 5877c8a3e9..1dc6abcf6e 100644 --- a/awx/lib/site-packages/rest_framework/response.py +++ b/awx/lib/site-packages/rest_framework/response.py @@ -61,6 +61,10 @@ class Response(SimpleTemplateResponse): assert charset, 'renderer returned unicode, and did not specify ' \ 'a charset value.' return bytes(ret.encode(charset)) + + if not ret: + del self['Content-Type'] + return ret @property diff --git a/awx/lib/site-packages/rest_framework/serializers.py b/awx/lib/site-packages/rest_framework/serializers.py index a63c7f6c29..44e4b04b19 100644 --- a/awx/lib/site-packages/rest_framework/serializers.py +++ b/awx/lib/site-packages/rest_framework/serializers.py @@ -6,8 +6,8 @@ form encoded input. Serialization in REST framework is a two-phase process: 1. Serializers marshal between complex types like model instances, and -python primatives. -2. The process of marshalling between python primatives and request and +python primitives. +2. The process of marshalling between python primitives and request and response content is handled by parsers and renderers. """ from __future__ import unicode_literals @@ -32,9 +32,17 @@ from rest_framework.relations import * from rest_framework.fields import * +def pretty_name(name): + """Converts 'first_name' to 'First name'""" + if not name: + return '' + return name.replace('_', ' ').capitalize() + + class RelationsList(list): _deleted = [] + class NestedValidationError(ValidationError): """ The default ValidationError behavior is to stringify each item in the list @@ -49,9 +57,13 @@ class NestedValidationError(ValidationError): def __init__(self, message): if isinstance(message, dict): - self.messages = [message] + self._messages = [message] else: - self.messages = message + self._messages = message + + @property + def messages(self): + return self._messages class DictWithMetadata(dict): @@ -255,10 +267,13 @@ class BaseSerializer(WritableField): for field_name, field in self.fields.items(): if field_name in self._errors: continue + + source = field.source or field_name + if self.partial and source not in attrs: + continue try: validate_method = getattr(self, 'validate_%s' % field_name, None) if validate_method: - source = field.source or field_name attrs = validate_method(attrs, source) except ValidationError as err: self._errors[field_name] = self._errors.get(field_name, []) + list(err.messages) @@ -301,14 +316,19 @@ class BaseSerializer(WritableField): """ ret = self._dict_class() ret.fields = self._dict_class() - ret.empty = obj is None for field_name, field in self.fields.items(): + if field.read_only and obj is None: + continue field.initialize(parent=self, field_name=field_name) key = self.get_field_key(field_name) value = field.field_to_native(obj, field_name) + method = getattr(self, 'transform_%s' % field_name, None) + if callable(method): + value = method(obj, value) ret[key] = value - ret.fields[key] = field + ret.fields[key] = self.augment_field(field, field_name, key, value) + return ret def from_native(self, data, files): @@ -316,6 +336,7 @@ class BaseSerializer(WritableField): Deserialize primitives -> objects. """ self._errors = {} + if data is not None or files is not None: attrs = self.restore_fields(data, files) if attrs is not None: @@ -326,6 +347,15 @@ class BaseSerializer(WritableField): if not self._errors: return self.restore_object(attrs, instance=getattr(self, 'object', None)) + def augment_field(self, field, field_name, key, value): + # This horrible stuff is to manage serializers rendering to HTML + field._errors = self._errors.get(key) if self._errors else None + field._name = field_name + field._value = self.init_data.get(key) if self._errors and self.init_data else value + if not field.label: + field.label = pretty_name(key) + return field + def field_to_native(self, obj, field_name): """ Override default so that the serializer can be used as a nested field @@ -381,7 +411,7 @@ class BaseSerializer(WritableField): return # Set the serializer object if it exists - obj = getattr(self.parent.object, field_name) if self.parent.object else None + obj = get_component(self.parent.object, self.source or field_name) if self.parent.object else None obj = obj.all() if is_simple_callable(getattr(obj, 'all', None)) else obj if self.source == '*': @@ -518,6 +548,9 @@ class BaseSerializer(WritableField): """ Save the deserialized object and return it. """ + # Clear cached _data, which may be invalidated by `save()` + self._data = None + if isinstance(self.object, list): [self.save_object(item, **kwargs) for item in self.object] @@ -766,6 +799,8 @@ class ModelSerializer(Serializer): # TODO: TypedChoiceField? if model_field.flatchoices: # This ModelField contains choices kwargs['choices'] = model_field.flatchoices + if model_field.null: + kwargs['empty'] = None return ChoiceField(**kwargs) # put this below the ChoiceField because min_value isn't a valid initializer @@ -843,7 +878,7 @@ class ModelSerializer(Serializer): # Reverse m2m relations for (obj, model) in meta.get_all_related_m2m_objects_with_model(): - field_name = obj.field.related_query_name() + field_name = obj.get_accessor_name() if field_name in attrs: m2m_data[field_name] = attrs.pop(field_name) @@ -861,7 +896,10 @@ class ModelSerializer(Serializer): # Update an existing instance... if instance is not None: for key, val in attrs.items(): - setattr(instance, key, val) + try: + setattr(instance, key, val) + except ValueError: + self._errors[key] = self.error_messages['required'] # ...or create a new instance else: @@ -887,7 +925,7 @@ class ModelSerializer(Serializer): def save_object(self, obj, **kwargs): """ - Save the deserialized object and return it. + Save the deserialized object. """ if getattr(obj, '_nested_forward_relations', None): # Nested relationships need to be saved before we can save the diff --git a/awx/lib/site-packages/rest_framework/status.py b/awx/lib/site-packages/rest_framework/status.py index b9f249f9fc..7643537116 100644 --- a/awx/lib/site-packages/rest_framework/status.py +++ b/awx/lib/site-packages/rest_framework/status.py @@ -6,6 +6,23 @@ And RFC 6585 - http://tools.ietf.org/html/rfc6585 """ from __future__ import unicode_literals + +def is_informational(code): + return code >= 100 and code <= 199 + +def is_success(code): + return code >= 200 and code <= 299 + +def is_redirect(code): + return code >= 300 and code <= 399 + +def is_client_error(code): + return code >= 400 and code <= 499 + +def is_server_error(code): + return code >= 500 and code <= 599 + + HTTP_100_CONTINUE = 100 HTTP_101_SWITCHING_PROTOCOLS = 101 HTTP_200_OK = 200 diff --git a/awx/lib/site-packages/rest_framework/templates/rest_framework/base.html b/awx/lib/site-packages/rest_framework/templates/rest_framework/base.html index aa90e90c4f..495163b648 100644 --- a/awx/lib/site-packages/rest_framework/templates/rest_framework/base.html +++ b/awx/lib/site-packages/rest_framework/templates/rest_framework/base.html @@ -110,7 +110,9 @@
+ {% block description %} {{ description }} + {% endblock %}
{{ request.method }} {{ request.get_full_path }}
@@ -122,7 +124,7 @@
- {% if response.status_code != 403 %} + {% if display_edit_forms %} {% if post_form or raw_data_post_form %}
@@ -151,7 +153,7 @@ {% with form=raw_data_post_form %}
- {% include "rest_framework/form.html" %} + {% include "rest_framework/raw_data_form.html" %}
@@ -188,7 +190,7 @@ {% with form=raw_data_put_or_patch_form %}
- {% include "rest_framework/form.html" %} + {% include "rest_framework/raw_data_form.html" %}
{% if raw_data_put_form %} @@ -219,9 +221,6 @@
{% block footer %} - {% endblock %} {% block script %} diff --git a/awx/lib/site-packages/rest_framework/templates/rest_framework/form.html b/awx/lib/site-packages/rest_framework/templates/rest_framework/form.html index b27f652e98..b1e148df7e 100644 --- a/awx/lib/site-packages/rest_framework/templates/rest_framework/form.html +++ b/awx/lib/site-packages/rest_framework/templates/rest_framework/form.html @@ -1,13 +1,15 @@ {% load rest_framework %} {% csrf_token %} {{ form.non_field_errors }} -{% for field in form %} -
+{% for field in form.fields.values %} + {% if not field.read_only %} +
{{ field.label_tag|add_class:"control-label" }}
- {{ field }} - {{ field.help_text }} - + {{ field.widget_html }} + {% if field.help_text %}{{ field.help_text }}{% endif %} + {% for error in field.errors %}{{ error }}{% endfor %}
+ {% endif %} {% endfor %} diff --git a/awx/lib/site-packages/rest_framework/templates/rest_framework/raw_data_form.html b/awx/lib/site-packages/rest_framework/templates/rest_framework/raw_data_form.html new file mode 100644 index 0000000000..075279f7e9 --- /dev/null +++ b/awx/lib/site-packages/rest_framework/templates/rest_framework/raw_data_form.html @@ -0,0 +1,12 @@ +{% load rest_framework %} +{% csrf_token %} +{{ form.non_field_errors }} +{% for field in form %} +
+ {{ field.label_tag|add_class:"control-label" }} +
+ {{ field }} + {{ field.help_text }} +
+
+{% endfor %} diff --git a/awx/lib/site-packages/rest_framework/tests/test_fields.py b/awx/lib/site-packages/rest_framework/tests/test_fields.py index 34fbab9c92..5c96bce92d 100644 --- a/awx/lib/site-packages/rest_framework/tests/test_fields.py +++ b/awx/lib/site-packages/rest_framework/tests/test_fields.py @@ -42,6 +42,31 @@ class TimeFieldModelSerializer(serializers.ModelSerializer): model = TimeFieldModel +SAMPLE_CHOICES = [ + ('red', 'Red'), + ('green', 'Green'), + ('blue', 'Blue'), +] + + +class ChoiceFieldModel(models.Model): + choice = models.CharField(choices=SAMPLE_CHOICES, blank=True, max_length=255) + + +class ChoiceFieldModelSerializer(serializers.ModelSerializer): + class Meta: + model = ChoiceFieldModel + + +class ChoiceFieldModelWithNull(models.Model): + choice = models.CharField(choices=SAMPLE_CHOICES, blank=True, null=True, max_length=255) + + +class ChoiceFieldModelWithNullSerializer(serializers.ModelSerializer): + class Meta: + model = ChoiceFieldModelWithNull + + class BasicFieldTests(TestCase): def test_auto_now_fields_read_only(self): """ @@ -667,34 +692,71 @@ class ChoiceFieldTests(TestCase): """ Tests for the ChoiceField options generator """ - - SAMPLE_CHOICES = [ - ('red', 'Red'), - ('green', 'Green'), - ('blue', 'Blue'), - ] - def test_choices_required(self): """ Make sure proper choices are rendered if field is required """ - f = serializers.ChoiceField(required=True, choices=self.SAMPLE_CHOICES) - self.assertEqual(f.choices, self.SAMPLE_CHOICES) + f = serializers.ChoiceField(required=True, choices=SAMPLE_CHOICES) + self.assertEqual(f.choices, SAMPLE_CHOICES) def test_choices_not_required(self): """ Make sure proper choices (plus blank) are rendered if the field isn't required """ - f = serializers.ChoiceField(required=False, choices=self.SAMPLE_CHOICES) - self.assertEqual(f.choices, models.fields.BLANK_CHOICE_DASH + self.SAMPLE_CHOICES) + f = serializers.ChoiceField(required=False, choices=SAMPLE_CHOICES) + self.assertEqual(f.choices, models.fields.BLANK_CHOICE_DASH + SAMPLE_CHOICES) + + def test_invalid_choice_model(self): + s = ChoiceFieldModelSerializer(data={'choice': 'wrong_value'}) + self.assertFalse(s.is_valid()) + self.assertEqual(s.errors, {'choice': ['Select a valid choice. wrong_value is not one of the available choices.']}) + self.assertEqual(s.data['choice'], '') + + def test_empty_choice_model(self): + """ + Test that the 'empty' value is correctly passed and used depending on + the 'null' property on the model field. + """ + s = ChoiceFieldModelSerializer(data={'choice': ''}) + self.assertTrue(s.is_valid()) + self.assertEqual(s.data['choice'], '') + + s = ChoiceFieldModelWithNullSerializer(data={'choice': ''}) + self.assertTrue(s.is_valid()) + self.assertEqual(s.data['choice'], None) def test_from_native_empty(self): """ - Make sure from_native() returns None on empty param. + Make sure from_native() returns an empty string on empty param by default. """ - f = serializers.ChoiceField(choices=self.SAMPLE_CHOICES) - result = f.from_native('') - self.assertEqual(result, None) + f = serializers.ChoiceField(choices=SAMPLE_CHOICES) + self.assertEqual(f.from_native(''), '') + self.assertEqual(f.from_native(None), '') + + def test_from_native_empty_override(self): + """ + Make sure you can override from_native() behavior regarding empty values. + """ + f = serializers.ChoiceField(choices=SAMPLE_CHOICES, empty=None) + self.assertEqual(f.from_native(''), None) + self.assertEqual(f.from_native(None), None) + + def test_metadata_choices(self): + """ + Make sure proper choices are included in the field's metadata. + """ + choices = [{'value': v, 'display_name': n} for v, n in SAMPLE_CHOICES] + f = serializers.ChoiceField(choices=SAMPLE_CHOICES) + self.assertEqual(f.metadata()['choices'], choices) + + def test_metadata_choices_not_required(self): + """ + Make sure proper choices are included in the field's metadata. + """ + choices = [{'value': v, 'display_name': n} + for v, n in models.fields.BLANK_CHOICE_DASH + SAMPLE_CHOICES] + f = serializers.ChoiceField(required=False, choices=SAMPLE_CHOICES) + self.assertEqual(f.metadata()['choices'], choices) class EmailFieldTests(TestCase): diff --git a/awx/lib/site-packages/rest_framework/tests/test_files.py b/awx/lib/site-packages/rest_framework/tests/test_files.py index c13c38b868..78f4cf4252 100644 --- a/awx/lib/site-packages/rest_framework/tests/test_files.py +++ b/awx/lib/site-packages/rest_framework/tests/test_files.py @@ -80,3 +80,16 @@ class FileSerializerTests(TestCase): serializer = UploadedFileSerializer(data={'created': now, 'file': 'abc'}) self.assertFalse(serializer.is_valid()) self.assertEqual(serializer.errors, {'file': [errmsg]}) + + def test_validation_with_no_data(self): + """ + Validation should still function when no data dictionary is provided. + """ + now = datetime.datetime.now() + file = BytesIO(six.b('stuff')) + file.name = 'stuff.txt' + file.size = len(file.getvalue()) + uploaded_file = UploadedFile(file=file, created=now) + + serializer = UploadedFileSerializer(files={'file': file}) + self.assertFalse(serializer.is_valid()) diff --git a/awx/lib/site-packages/rest_framework/tests/test_filters.py b/awx/lib/site-packages/rest_framework/tests/test_filters.py index c9d9e7ffaa..614f45cc70 100644 --- a/awx/lib/site-packages/rest_framework/tests/test_filters.py +++ b/awx/lib/site-packages/rest_framework/tests/test_filters.py @@ -113,7 +113,7 @@ class IntegrationTestFiltering(CommonFilteringTestCase): Integration tests for filtered list views. """ - @unittest.skipUnless(django_filters, 'django-filters not installed') + @unittest.skipUnless(django_filters, 'django-filter not installed') def test_get_filtered_fields_root_view(self): """ GET requests to paginated ListCreateAPIView should return paginated results. @@ -142,7 +142,7 @@ class IntegrationTestFiltering(CommonFilteringTestCase): expected_data = [f for f in self.data if f['date'] == search_date] self.assertEqual(response.data, expected_data) - @unittest.skipUnless(django_filters, 'django-filters not installed') + @unittest.skipUnless(django_filters, 'django-filter not installed') def test_filter_with_queryset(self): """ Regression test for #814. @@ -157,7 +157,7 @@ class IntegrationTestFiltering(CommonFilteringTestCase): expected_data = [f for f in self.data if f['decimal'] == search_decimal] self.assertEqual(response.data, expected_data) - @unittest.skipUnless(django_filters, 'django-filters not installed') + @unittest.skipUnless(django_filters, 'django-filter not installed') def test_filter_with_get_queryset_only(self): """ Regression test for #834. @@ -168,7 +168,7 @@ class IntegrationTestFiltering(CommonFilteringTestCase): # Used to raise "issubclass() arg 2 must be a class or tuple of classes" # here when neither `model' nor `queryset' was specified. - @unittest.skipUnless(django_filters, 'django-filters not installed') + @unittest.skipUnless(django_filters, 'django-filter not installed') def test_get_filtered_class_root_view(self): """ GET requests to filtered ListCreateAPIView that have a filter_class set @@ -216,7 +216,7 @@ class IntegrationTestFiltering(CommonFilteringTestCase): f['decimal'] < search_decimal] self.assertEqual(response.data, expected_data) - @unittest.skipUnless(django_filters, 'django-filters not installed') + @unittest.skipUnless(django_filters, 'django-filter not installed') def test_incorrectly_configured_filter(self): """ An error should be displayed when the filter class is misconfigured. @@ -226,7 +226,7 @@ class IntegrationTestFiltering(CommonFilteringTestCase): request = factory.get('/') self.assertRaises(AssertionError, view, request) - @unittest.skipUnless(django_filters, 'django-filters not installed') + @unittest.skipUnless(django_filters, 'django-filter not installed') def test_unknown_filter(self): """ GET requests with filters that aren't configured should return 200. @@ -248,7 +248,7 @@ class IntegrationTestDetailFiltering(CommonFilteringTestCase): def _get_url(self, item): return reverse('detail-view', kwargs=dict(pk=item.pk)) - @unittest.skipUnless(django_filters, 'django-filters not installed') + @unittest.skipUnless(django_filters, 'django-filter not installed') def test_get_filtered_detail_view(self): """ GET requests to filtered RetrieveAPIView that have a filter_class set @@ -363,6 +363,12 @@ class OrdringFilterModel(models.Model): text = models.CharField(max_length=100) +class OrderingFilterRelatedModel(models.Model): + related_object = models.ForeignKey(OrdringFilterModel, + related_name="relateds") + + + class OrderingFilterTests(TestCase): def setUp(self): # Sequence of title/text is: @@ -472,3 +478,36 @@ class OrderingFilterTests(TestCase): {'id': 1, 'title': 'zyx', 'text': 'abc'}, ] ) + + def test_ordering_by_aggregate_field(self): + # create some related models to aggregate order by + num_objs = [2, 5, 3] + for obj, num_relateds in zip(OrdringFilterModel.objects.all(), + num_objs): + for _ in range(num_relateds): + new_related = OrderingFilterRelatedModel( + related_object=obj + ) + new_related.save() + + class OrderingListView(generics.ListAPIView): + model = OrdringFilterModel + filter_backends = (filters.OrderingFilter,) + ordering = 'title' + queryset = OrdringFilterModel.objects.all().annotate( + models.Count("relateds")) + + view = OrderingListView.as_view() + request = factory.get('?ordering=relateds__count') + response = view(request) + self.assertEqual( + response.data, + [ + {'id': 1, 'title': 'zyx', 'text': 'abc'}, + {'id': 3, 'title': 'xwv', 'text': 'cde'}, + {'id': 2, 'title': 'yxw', 'text': 'bcd'}, + ] + ) + + + diff --git a/awx/lib/site-packages/rest_framework/tests/test_generics.py b/awx/lib/site-packages/rest_framework/tests/test_generics.py index 79cd99ac51..996bd5b0e0 100644 --- a/awx/lib/site-packages/rest_framework/tests/test_generics.py +++ b/awx/lib/site-packages/rest_framework/tests/test_generics.py @@ -23,6 +23,10 @@ class InstanceView(generics.RetrieveUpdateDestroyAPIView): """ model = BasicModel + def get_queryset(self): + queryset = super(InstanceView, self).get_queryset() + return queryset.exclude(text='filtered out') + class SlugSerializer(serializers.ModelSerializer): slug = serializers.Field() # read only @@ -160,10 +164,10 @@ class TestInstanceView(TestCase): """ Create 3 BasicModel intances. """ - items = ['foo', 'bar', 'baz'] + items = ['foo', 'bar', 'baz', 'filtered out'] for item in items: BasicModel(text=item).save() - self.objects = BasicModel.objects + self.objects = BasicModel.objects.exclude(text='filtered out') self.data = [ {'id': obj.id, 'text': obj.text} for obj in self.objects.all() @@ -352,6 +356,17 @@ class TestInstanceView(TestCase): updated = self.objects.get(id=1) self.assertEqual(updated.text, 'foobar') + def test_put_to_filtered_out_instance(self): + """ + PUT requests to an URL of instance which is filtered out should not be + able to create new objects. + """ + data = {'text': 'foo'} + filtered_out_pk = BasicModel.objects.filter(text='filtered out')[0].pk + request = factory.put('/{0}'.format(filtered_out_pk), data, format='json') + response = self.view(request, pk=filtered_out_pk).render() + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + def test_put_as_create_on_id_based_url(self): """ PUT requests to RetrieveUpdateDestroyAPIView should create an object @@ -508,6 +523,25 @@ class ExclusiveFilterBackend(object): return queryset.filter(text='other') +class TwoFieldModel(models.Model): + field_a = models.CharField(max_length=100) + field_b = models.CharField(max_length=100) + + +class DynamicSerializerView(generics.ListCreateAPIView): + model = TwoFieldModel + renderer_classes = (renderers.BrowsableAPIRenderer, renderers.JSONRenderer) + + def get_serializer_class(self): + if self.request.method == 'POST': + class DynamicSerializer(serializers.ModelSerializer): + class Meta: + model = TwoFieldModel + fields = ('field_b',) + return DynamicSerializer + return super(DynamicSerializerView, self).get_serializer_class() + + class TestFilterBackendAppliedToViews(TestCase): def setUp(self): @@ -564,28 +598,6 @@ class TestFilterBackendAppliedToViews(TestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data, {'id': 1, 'text': 'foo'}) - -class TwoFieldModel(models.Model): - field_a = models.CharField(max_length=100) - field_b = models.CharField(max_length=100) - - -class DynamicSerializerView(generics.ListCreateAPIView): - model = TwoFieldModel - renderer_classes = (renderers.BrowsableAPIRenderer, renderers.JSONRenderer) - - def get_serializer_class(self): - if self.request.method == 'POST': - class DynamicSerializer(serializers.ModelSerializer): - class Meta: - model = TwoFieldModel - fields = ('field_b',) - return DynamicSerializer - return super(DynamicSerializerView, self).get_serializer_class() - - -class TestFilterBackendAppliedToViews(TestCase): - def test_dynamic_serializer_form_in_browsable_api(self): """ GET requests to ListCreateAPIView should return filtered list. diff --git a/awx/lib/site-packages/rest_framework/tests/test_pagination.py b/awx/lib/site-packages/rest_framework/tests/test_pagination.py index 4170d4b641..cadb515fa2 100644 --- a/awx/lib/site-packages/rest_framework/tests/test_pagination.py +++ b/awx/lib/site-packages/rest_framework/tests/test_pagination.py @@ -122,7 +122,7 @@ class IntegrationTestPaginationAndFiltering(TestCase): for obj in self.objects.all() ] - @unittest.skipUnless(django_filters, 'django-filters not installed') + @unittest.skipUnless(django_filters, 'django-filter not installed') def test_get_django_filter_paginated_filtered_root_view(self): """ GET requests to paginated filtered ListCreateAPIView should return @@ -430,3 +430,88 @@ class TestCustomPaginationSerializer(TestCase): 'objects': ['john', 'paul'] } self.assertEqual(serializer.data, expected) + + +class NonIntegerPage(object): + + def __init__(self, paginator, object_list, prev_token, token, next_token): + self.paginator = paginator + self.object_list = object_list + self.prev_token = prev_token + self.token = token + self.next_token = next_token + + def has_next(self): + return not not self.next_token + + def next_page_number(self): + return self.next_token + + def has_previous(self): + return not not self.prev_token + + def previous_page_number(self): + return self.prev_token + + +class NonIntegerPaginator(object): + + def __init__(self, object_list, per_page): + self.object_list = object_list + self.per_page = per_page + + def count(self): + # pretend like we don't know how many pages we have + return None + + def page(self, token=None): + if token: + try: + first = self.object_list.index(token) + except ValueError: + first = 0 + else: + first = 0 + n = len(self.object_list) + last = min(first + self.per_page, n) + prev_token = self.object_list[last - (2 * self.per_page)] if first else None + next_token = self.object_list[last] if last < n else None + return NonIntegerPage(self, self.object_list[first:last], prev_token, token, next_token) + + +class TestNonIntegerPagination(TestCase): + + + def test_custom_pagination_serializer(self): + objects = ['john', 'paul', 'george', 'ringo'] + paginator = NonIntegerPaginator(objects, 2) + + request = APIRequestFactory().get('/foobar') + serializer = CustomPaginationSerializer( + instance=paginator.page(), + context={'request': request} + ) + expected = { + 'links': { + 'next': 'http://testserver/foobar?page={0}'.format(objects[2]), + 'prev': None + }, + 'total_results': None, + 'objects': objects[:2] + } + self.assertEqual(serializer.data, expected) + + request = APIRequestFactory().get('/foobar') + serializer = CustomPaginationSerializer( + instance=paginator.page('george'), + context={'request': request} + ) + expected = { + 'links': { + 'next': None, + 'prev': 'http://testserver/foobar?page={0}'.format(objects[0]), + }, + 'total_results': None, + 'objects': objects[2:] + } + self.assertEqual(serializer.data, expected) diff --git a/awx/lib/site-packages/rest_framework/tests/test_permissions.py b/awx/lib/site-packages/rest_framework/tests/test_permissions.py index d08124f484..6e3a630345 100644 --- a/awx/lib/site-packages/rest_framework/tests/test_permissions.py +++ b/awx/lib/site-packages/rest_framework/tests/test_permissions.py @@ -4,7 +4,7 @@ from django.db import models from django.test import TestCase from django.utils import unittest from rest_framework import generics, status, permissions, authentication, HTTP_HEADER_ENCODING -from rest_framework.compat import guardian +from rest_framework.compat import guardian, get_model_name from rest_framework.filters import DjangoObjectPermissionsFilter from rest_framework.test import APIRequestFactory from rest_framework.tests.models import BasicModel @@ -202,7 +202,7 @@ class ObjectPermissionsIntegrationTests(TestCase): # give everyone model level permissions, as we are not testing those everyone = Group.objects.create(name='everyone') - model_name = BasicPermModel._meta.module_name + model_name = get_model_name(BasicPermModel) app_label = BasicPermModel._meta.app_label f = '{0}_{1}'.format perms = { diff --git a/awx/lib/site-packages/rest_framework/tests/test_renderers.py b/awx/lib/site-packages/rest_framework/tests/test_renderers.py index df6f4aa63f..f7de8fd725 100644 --- a/awx/lib/site-packages/rest_framework/tests/test_renderers.py +++ b/awx/lib/site-packages/rest_framework/tests/test_renderers.py @@ -64,11 +64,16 @@ class MockView(APIView): class MockGETView(APIView): - def get(self, request, **kwargs): return Response({'foo': ['bar', 'baz']}) +class EmptyGETView(APIView): + renderer_classes = (JSONRenderer,) + + def get(self, request, **kwargs): + return Response(status=status.HTTP_204_NO_CONTENT) + class HTMLView(APIView): renderer_classes = (BrowsableAPIRenderer, ) @@ -90,6 +95,7 @@ urlpatterns = patterns('', url(r'^jsonp/nojsonrenderer$', MockGETView.as_view(renderer_classes=[JSONPRenderer])), url(r'^html$', HTMLView.as_view()), url(r'^html1$', HTMLView1.as_view()), + url(r'^empty$', EmptyGETView.as_view()), url(r'^api', include('rest_framework.urls', namespace='rest_framework')) ) @@ -219,6 +225,16 @@ class RendererEndToEndTests(TestCase): self.assertEqual(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT)) self.assertEqual(resp.status_code, DUMMYSTATUS) + def test_204_no_content_responses_have_no_content_type_set(self): + """ + Regression test for #1196 + + https://github.com/tomchristie/django-rest-framework/issues/1196 + """ + resp = self.client.get('/empty') + self.assertEqual(resp.get('Content-Type', None), None) + self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT) + _flat_repr = '{"foo": ["bar", "baz"]}' _indented_repr = '{\n "foo": [\n "bar",\n "baz"\n ]\n}' @@ -328,7 +344,7 @@ if yaml: class YAMLRendererTests(TestCase): """ - Tests specific to the JSON Renderer + Tests specific to the YAML Renderer """ def test_render(self): @@ -354,6 +370,17 @@ if yaml: data = parser.parse(StringIO(content)) self.assertEqual(obj, data) + def test_render_decimal(self): + """ + Test YAML decimal rendering. + """ + renderer = YAMLRenderer() + content = renderer.render({'field': Decimal('111.2')}, 'application/yaml') + self.assertYAMLContains(content, "field: '111.2'") + + def assertYAMLContains(self, content, string): + self.assertTrue(string in content, '%r not in %r' % (string, content)) + class XMLRendererTestCase(TestCase): """ diff --git a/awx/lib/site-packages/rest_framework/tests/test_request.py b/awx/lib/site-packages/rest_framework/tests/test_request.py index 969d8024a9..a60e7615e9 100644 --- a/awx/lib/site-packages/rest_framework/tests/test_request.py +++ b/awx/lib/site-packages/rest_framework/tests/test_request.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals from django.contrib.auth.models import User from django.contrib.auth import authenticate, login, logout from django.contrib.sessions.middleware import SessionMiddleware +from django.core.handlers.wsgi import WSGIRequest from django.test import TestCase from rest_framework import status from rest_framework.authentication import SessionAuthentication @@ -15,12 +16,13 @@ from rest_framework.parsers import ( MultiPartParser, JSONParser ) -from rest_framework.request import Request +from rest_framework.request import Request, Empty from rest_framework.response import Response from rest_framework.settings import api_settings from rest_framework.test import APIRequestFactory, APIClient from rest_framework.views import APIView from rest_framework.compat import six +from io import BytesIO import json @@ -146,6 +148,34 @@ class TestContentParsing(TestCase): request.parsers = (JSONParser(), ) self.assertEqual(request.DATA, json_data) + def test_form_POST_unicode(self): + """ + JSON POST via default web interface with unicode data + """ + # Note: environ and other variables here have simplified content compared to real Request + CONTENT = b'_content_type=application%2Fjson&_content=%7B%22request%22%3A+4%2C+%22firm%22%3A+1%2C+%22text%22%3A+%22%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82%21%22%7D' + environ = { + 'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'application/x-www-form-urlencoded', + 'CONTENT_LENGTH': len(CONTENT), + 'wsgi.input': BytesIO(CONTENT), + } + wsgi_request = WSGIRequest(environ=environ) + wsgi_request._load_post_and_files() + parsers = (JSONParser(), FormParser(), MultiPartParser()) + parser_context = { + 'encoding': 'utf-8', + 'kwargs': {}, + 'args': (), + } + request = Request(wsgi_request, parsers=parsers, parser_context=parser_context) + method = request.method + self.assertEqual(method, 'POST') + self.assertEqual(request._content_type, 'application/json') + self.assertEqual(request._stream.getvalue(), b'{"request": 4, "firm": 1, "text": "\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82!"}') + self.assertEqual(request._data, Empty) + self.assertEqual(request._files, Empty) + # def test_accessing_post_after_data_form(self): # """ # Ensures request.POST can be accessed after request.DATA in diff --git a/awx/lib/site-packages/rest_framework/tests/test_serializer.py b/awx/lib/site-packages/rest_framework/tests/test_serializer.py index c24976603e..eca467ee27 100644 --- a/awx/lib/site-packages/rest_framework/tests/test_serializer.py +++ b/awx/lib/site-packages/rest_framework/tests/test_serializer.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models from django.db.models.fields import BLANK_CHOICE_DASH @@ -136,6 +137,7 @@ class BasicTests(TestCase): 'Happy new year!', datetime.datetime(2012, 1, 1) ) + self.actionitem = ActionItem(title='Some to do item',) self.data = { 'email': 'tom@example.com', 'content': 'Happy new year!', @@ -157,8 +159,7 @@ class BasicTests(TestCase): expected = { 'email': '', 'content': '', - 'created': None, - 'sub_comment': '' + 'created': None } self.assertEqual(serializer.data, expected) @@ -264,6 +265,20 @@ class BasicTests(TestCase): """ self.assertRaises(AssertionError, PersonSerializerInvalidReadOnly, []) + def test_serializer_data_is_cleared_on_save(self): + """ + Check _data attribute is cleared on `save()` + + Regression test for #1116 + — id field is not populated if `data` is accessed prior to `save()` + """ + serializer = ActionItemSerializer(self.actionitem) + self.assertIsNone(serializer.data.get('id',None), 'New instance. `id` should not be set.') + serializer.save() + self.assertIsNotNone(serializer.data.get('id',None), 'Model is saved. `id` should be set.') + + + class DictStyleSerializer(serializers.Serializer): """ @@ -496,6 +511,33 @@ class CustomValidationTests(TestCase): self.assertFalse(serializer.is_valid()) self.assertEqual(serializer.errors, {'email': ['Enter a valid email address.']}) + def test_partial_update(self): + """ + Make sure that validate_email isn't called when partial=True and email + isn't found in data. + """ + initial_data = { + 'email': 'tom@example.com', + 'content': 'A test comment', + 'created': datetime.datetime(2012, 1, 1) + } + + serializer = self.CommentSerializerWithFieldValidator(data=initial_data) + self.assertEqual(serializer.is_valid(), True) + instance = serializer.object + + new_content = 'An *updated* test comment' + partial_data = { + 'content': new_content + } + + serializer = self.CommentSerializerWithFieldValidator(instance=instance, + data=partial_data, + partial=True) + self.assertEqual(serializer.is_valid(), True) + instance = serializer.object + self.assertEqual(instance.content, new_content) + class PositiveIntegerAsChoiceTests(TestCase): def test_positive_integer_in_json_is_correctly_parsed(self): @@ -516,6 +558,29 @@ class ModelValidationTests(TestCase): self.assertFalse(second_serializer.is_valid()) self.assertEqual(second_serializer.errors, {'title': ['Album with this Title already exists.']}) + def test_foreign_key_is_null_with_partial(self): + """ + Test ModelSerializer validation with partial=True + + Specifically test that a null foreign key does not pass validation + """ + album = Album(title='test') + album.save() + + class PhotoSerializer(serializers.ModelSerializer): + class Meta: + model = Photo + + photo_serializer = PhotoSerializer(data={'description': 'test', 'album': album.pk}) + self.assertTrue(photo_serializer.is_valid()) + photo = photo_serializer.save() + + # Updating only the album (foreign key) + photo_serializer = PhotoSerializer(instance=photo, data={'album': ''}, partial=True) + self.assertFalse(photo_serializer.is_valid()) + self.assertTrue('album' in photo_serializer.errors) + self.assertEqual(photo_serializer.errors['album'], photo_serializer.error_messages['required']) + def test_foreign_key_with_partial(self): """ Test ModelSerializer validation with partial=True @@ -1643,3 +1708,38 @@ class SerializerSupportsManyRelationships(TestCase): serializer = SimpleSlugSourceModelSerializer(data={'text': 'foo', 'targets': [1, 2]}) self.assertTrue(serializer.is_valid()) self.assertEqual(serializer.data, {'text': 'foo', 'targets': [1, 2]}) + + +class TransformMethodsSerializer(serializers.Serializer): + a = serializers.CharField() + b_renamed = serializers.CharField(source='b') + + def transform_a(self, obj, value): + return value.lower() + + def transform_b_renamed(self, obj, value): + if value is not None: + return 'and ' + value + + +class TestSerializerTransformMethods(TestCase): + def setUp(self): + self.s = TransformMethodsSerializer() + + def test_transform_methods(self): + self.assertEqual( + self.s.to_native({'a': 'GREEN EGGS', 'b': 'HAM'}), + { + 'a': 'green eggs', + 'b_renamed': 'and HAM', + } + ) + + def test_missing_fields(self): + self.assertEqual( + self.s.to_native({'a': 'GREEN EGGS'}), + { + 'a': 'green eggs', + 'b_renamed': None, + } + ) diff --git a/awx/lib/site-packages/rest_framework/tests/test_serializer_empty.py b/awx/lib/site-packages/rest_framework/tests/test_serializer_empty.py new file mode 100644 index 0000000000..30cff3615f --- /dev/null +++ b/awx/lib/site-packages/rest_framework/tests/test_serializer_empty.py @@ -0,0 +1,15 @@ +from django.test import TestCase +from rest_framework import serializers + + +class EmptySerializerTestCase(TestCase): + def test_empty_serializer(self): + class FooBarSerializer(serializers.Serializer): + foo = serializers.IntegerField() + bar = serializers.SerializerMethodField('get_bar') + + def get_bar(self, obj): + return 'bar' + + serializer = FooBarSerializer() + self.assertEquals(serializer.data, {'foo': 0}) diff --git a/awx/lib/site-packages/rest_framework/tests/test_serializer_nested.py b/awx/lib/site-packages/rest_framework/tests/test_serializer_nested.py index 71d0e24b51..029f8bffdb 100644 --- a/awx/lib/site-packages/rest_framework/tests/test_serializer_nested.py +++ b/awx/lib/site-packages/rest_framework/tests/test_serializer_nested.py @@ -244,3 +244,70 @@ class WritableNestedSerializerObjectTests(TestCase): serializer = self.AlbumSerializer(data=data, many=True) self.assertEqual(serializer.is_valid(), True) self.assertEqual(serializer.object, expected_object) + + +class ForeignKeyNestedSerializerUpdateTests(TestCase): + def setUp(self): + class Artist(object): + def __init__(self, name): + self.name = name + + def __eq__(self, other): + return self.name == other.name + + class Album(object): + def __init__(self, name, artist): + self.name, self.artist = name, artist + + def __eq__(self, other): + return self.name == other.name and self.artist == other.artist + + class ArtistSerializer(serializers.Serializer): + name = serializers.CharField() + + def restore_object(self, attrs, instance=None): + if instance: + instance.name = attrs['name'] + else: + instance = Artist(attrs['name']) + return instance + + class AlbumSerializer(serializers.Serializer): + name = serializers.CharField() + by = ArtistSerializer(source='artist') + + def restore_object(self, attrs, instance=None): + if instance: + instance.name = attrs['name'] + instance.artist = attrs['artist'] + else: + instance = Album(attrs['name'], attrs['artist']) + return instance + + self.Artist = Artist + self.Album = Album + self.AlbumSerializer = AlbumSerializer + + def test_create_via_foreign_key_with_source(self): + """ + Check that we can both *create* and *update* into objects across + ForeignKeys that have a `source` specified. + Regression test for #1170 + """ + data = { + 'name': 'Discovery', + 'by': {'name': 'Daft Punk'}, + } + + expected = self.Album(artist=self.Artist('Daft Punk'), name='Discovery') + + # create + serializer = self.AlbumSerializer(data=data) + self.assertEqual(serializer.is_valid(), True) + self.assertEqual(serializer.object, expected) + + # update + original = self.Album(artist=self.Artist('The Bats'), name='Free All the Monsters') + serializer = self.AlbumSerializer(instance=original, data=data) + self.assertEqual(serializer.is_valid(), True) + self.assertEqual(serializer.object, expected) diff --git a/awx/lib/site-packages/rest_framework/tests/test_status.py b/awx/lib/site-packages/rest_framework/tests/test_status.py new file mode 100644 index 0000000000..7b1bdae31b --- /dev/null +++ b/awx/lib/site-packages/rest_framework/tests/test_status.py @@ -0,0 +1,33 @@ +from __future__ import unicode_literals +from django.test import TestCase +from rest_framework.status import ( + is_informational, is_success, is_redirect, is_client_error, is_server_error +) + + +class TestStatus(TestCase): + def test_status_categories(self): + self.assertFalse(is_informational(99)) + self.assertTrue(is_informational(100)) + self.assertTrue(is_informational(199)) + self.assertFalse(is_informational(200)) + + self.assertFalse(is_success(199)) + self.assertTrue(is_success(200)) + self.assertTrue(is_success(299)) + self.assertFalse(is_success(300)) + + self.assertFalse(is_redirect(299)) + self.assertTrue(is_redirect(300)) + self.assertTrue(is_redirect(399)) + self.assertFalse(is_redirect(400)) + + self.assertFalse(is_client_error(399)) + self.assertTrue(is_client_error(400)) + self.assertTrue(is_client_error(499)) + self.assertFalse(is_client_error(500)) + + self.assertFalse(is_server_error(499)) + self.assertTrue(is_server_error(500)) + self.assertTrue(is_server_error(599)) + self.assertFalse(is_server_error(600)) \ No newline at end of file diff --git a/awx/lib/site-packages/rest_framework/urlpatterns.py b/awx/lib/site-packages/rest_framework/urlpatterns.py index d9143bb4c9..0ff137b00a 100644 --- a/awx/lib/site-packages/rest_framework/urlpatterns.py +++ b/awx/lib/site-packages/rest_framework/urlpatterns.py @@ -57,6 +57,6 @@ def format_suffix_patterns(urlpatterns, suffix_required=False, allowed=None): allowed_pattern = '(%s)' % '|'.join(allowed) suffix_pattern = r'\.(?P<%s>%s)$' % (suffix_kwarg, allowed_pattern) else: - suffix_pattern = r'\.(?P<%s>[a-z]+)$' % suffix_kwarg + suffix_pattern = r'\.(?P<%s>[a-z0-9]+)$' % suffix_kwarg return apply_suffix_patterns(urlpatterns, suffix_pattern, suffix_required) diff --git a/awx/lib/site-packages/rest_framework/utils/encoders.py b/awx/lib/site-packages/rest_framework/utils/encoders.py index b26a2085a8..35ad206b9a 100644 --- a/awx/lib/site-packages/rest_framework/utils/encoders.py +++ b/awx/lib/site-packages/rest_framework/utils/encoders.py @@ -42,6 +42,8 @@ class JSONEncoder(json.JSONEncoder): return str(o.total_seconds()) elif isinstance(o, decimal.Decimal): return str(o) + elif hasattr(o, 'tolist'): + return o.tolist() elif hasattr(o, '__iter__'): return [i for i in o] return super(JSONEncoder, self).default(o) @@ -87,6 +89,9 @@ else: node.flow_style = best_style return node + SafeDumper.add_representer(decimal.Decimal, + SafeDumper.represent_decimal) + SafeDumper.add_representer(SortedDict, yaml.representer.SafeRepresenter.represent_dict) SafeDumper.add_representer(DictWithMetadata, diff --git a/awx/lib/site-packages/rest_framework/views.py b/awx/lib/site-packages/rest_framework/views.py index 853e646145..e863af6dd7 100644 --- a/awx/lib/site-packages/rest_framework/views.py +++ b/awx/lib/site-packages/rest_framework/views.py @@ -154,8 +154,8 @@ class APIView(View): Returns a dict that is passed through to Parser.parse(), as the `parser_context` keyword argument. """ - # Note: Additionally `request` will also be added to the context - # by the Request object. + # Note: Additionally `request` and `encoding` will also be added + # to the context by the Request object. return { 'view': self, 'args': getattr(self, 'args', ()), diff --git a/awx/lib/site-packages/rest_framework/viewsets.py b/awx/lib/site-packages/rest_framework/viewsets.py index d91323f22d..7eb29f99b1 100644 --- a/awx/lib/site-packages/rest_framework/viewsets.py +++ b/awx/lib/site-packages/rest_framework/viewsets.py @@ -9,7 +9,7 @@ Actions are only bound to methods at the point of instantiating the views. user_detail = UserViewSet.as_view({'get': 'retrieve'}) Typically, rather than instantiate views from viewsets directly, you'll -regsiter the viewset with a router and let the URL conf be determined +register the viewset with a router and let the URL conf be determined automatically. router = DefaultRouter() diff --git a/awx/lib/site-packages/setuptools/_backport/hashlib/__init__.py b/awx/lib/site-packages/setuptools/_backport/hashlib/__init__.py deleted file mode 100644 index 5aeab496af..0000000000 --- a/awx/lib/site-packages/setuptools/_backport/hashlib/__init__.py +++ /dev/null @@ -1,146 +0,0 @@ -# $Id$ -# -# Copyright (C) 2005 Gregory P. Smith (greg@krypto.org) -# Licensed to PSF under a Contributor Agreement. -# - -__doc__ = """hashlib module - A common interface to many hash functions. - -new(name, string='') - returns a new hash object implementing the - given hash function; initializing the hash - using the given string data. - -Named constructor functions are also available, these are much faster -than using new(): - -md5(), sha1(), sha224(), sha256(), sha384(), and sha512() - -More algorithms may be available on your platform but the above are -guaranteed to exist. - -NOTE: If you want the adler32 or crc32 hash functions they are available in -the zlib module. - -Choose your hash function wisely. Some have known collision weaknesses. -sha384 and sha512 will be slow on 32 bit platforms. - -Hash objects have these methods: - - update(arg): Update the hash object with the string arg. Repeated calls - are equivalent to a single call with the concatenation of all - the arguments. - - digest(): Return the digest of the strings passed to the update() method - so far. This may contain non-ASCII characters, including - NUL bytes. - - hexdigest(): Like digest() except the digest is returned as a string of - double length, containing only hexadecimal digits. - - copy(): Return a copy (clone) of the hash object. This can be used to - efficiently compute the digests of strings that share a common - initial substring. - -For example, to obtain the digest of the string 'Nobody inspects the -spammish repetition': - - >>> import hashlib - >>> m = hashlib.md5() - >>> m.update("Nobody inspects") - >>> m.update(" the spammish repetition") - >>> m.digest() - '\\xbbd\\x9c\\x83\\xdd\\x1e\\xa5\\xc9\\xd9\\xde\\xc9\\xa1\\x8d\\xf0\\xff\\xe9' - -More condensed: - - >>> hashlib.sha224("Nobody inspects the spammish repetition").hexdigest() - 'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2' - -""" - -# This tuple and __get_builtin_constructor() must be modified if a new -# always available algorithm is added. -__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512') - -algorithms = __always_supported - -__all__ = __always_supported + ('new', 'algorithms') - - -def __get_builtin_constructor(name): - try: - if name in ('SHA1', 'sha1'): - import _sha - return _sha.new - elif name in ('MD5', 'md5'): - import md5 - return md5.new - elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'): - import _sha256 - bs = name[3:] - if bs == '256': - return _sha256.sha256 - elif bs == '224': - return _sha256.sha224 - elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'): - import _sha512 - bs = name[3:] - if bs == '512': - return _sha512.sha512 - elif bs == '384': - return _sha512.sha384 - except ImportError: - pass # no extension module, this hash is unsupported. - - raise ValueError('unsupported hash type %s' % name) - - -def __get_openssl_constructor(name): - try: - f = getattr(_hashlib, 'openssl_' + name) - # Allow the C module to raise ValueError. The function will be - # defined but the hash not actually available thanks to OpenSSL. - f() - # Use the C function directly (very fast) - return f - except (AttributeError, ValueError): - return __get_builtin_constructor(name) - - -def __py_new(name, string=''): - """new(name, string='') - Return a new hashing object using the named algorithm; - optionally initialized with a string. - """ - return __get_builtin_constructor(name)(string) - - -def __hash_new(name, string=''): - """new(name, string='') - Return a new hashing object using the named algorithm; - optionally initialized with a string. - """ - try: - return _hashlib.new(name, string) - except ValueError: - # If the _hashlib module (OpenSSL) doesn't support the named - # hash, try using our builtin implementations. - # This allows for SHA224/256 and SHA384/512 support even though - # the OpenSSL library prior to 0.9.8 doesn't provide them. - return __get_builtin_constructor(name)(string) - - -try: - import _hashlib - new = __hash_new - __get_hash = __get_openssl_constructor -except ImportError: - new = __py_new - __get_hash = __get_builtin_constructor - -for __func_name in __always_supported: - # try them all, some may not work due to the OpenSSL - # version not supporting that algorithm. - try: - globals()[__func_name] = __get_hash(__func_name) - except ValueError: - import logging - logging.exception('code for hash %s was not found.', __func_name) - -# Cleanup locals() -del __always_supported, __func_name, __get_hash -del __py_new, __hash_new, __get_openssl_constructor diff --git a/awx/lib/site-packages/setuptools/_backport/hashlib/_sha.py b/awx/lib/site-packages/setuptools/_backport/hashlib/_sha.py deleted file mode 100644 index d49993c887..0000000000 --- a/awx/lib/site-packages/setuptools/_backport/hashlib/_sha.py +++ /dev/null @@ -1,359 +0,0 @@ -# -*- coding: iso-8859-1 -*- -"""A sample implementation of SHA-1 in pure Python. - - Framework adapted from Dinu Gherman's MD5 implementation by - J. Hallén and L. Creighton. SHA-1 implementation based directly on - the text of the NIST standard FIPS PUB 180-1. -""" - - -__date__ = '2004-11-17' -__version__ = 0.91 # Modernised by J. Hallén and L. Creighton for Pypy - - -import struct, copy - - -# ====================================================================== -# Bit-Manipulation helpers -# -# _long2bytes() was contributed by Barry Warsaw -# and is reused here with tiny modifications. -# ====================================================================== - -def _long2bytesBigEndian(n, blocksize=0): - """Convert a long integer to a byte string. - - If optional blocksize is given and greater than zero, pad the front - of the byte string with binary zeros so that the length is a multiple - of blocksize. - """ - - # After much testing, this algorithm was deemed to be the fastest. - s = '' - pack = struct.pack - while n > 0: - s = pack('>I', n & 0xffffffff) + s - n = n >> 32 - - # Strip off leading zeros. - for i in range(len(s)): - if s[i] != '\000': - break - else: - # Only happens when n == 0. - s = '\000' - i = 0 - - s = s[i:] - - # Add back some pad bytes. This could be done more efficiently - # w.r.t. the de-padding being done above, but sigh... - if blocksize > 0 and len(s) % blocksize: - s = (blocksize - len(s) % blocksize) * '\000' + s - - return s - - -def _bytelist2longBigEndian(list): - "Transform a list of characters into a list of longs." - - imax = len(list) // 4 - hl = [0] * imax - - j = 0 - i = 0 - while i < imax: - b0 = ord(list[j]) << 24 - b1 = ord(list[j+1]) << 16 - b2 = ord(list[j+2]) << 8 - b3 = ord(list[j+3]) - hl[i] = b0 | b1 | b2 | b3 - i = i+1 - j = j+4 - - return hl - - -def _rotateLeft(x, n): - "Rotate x (32 bit) left n bits circularly." - - return (x << n) | (x >> (32-n)) - - -# ====================================================================== -# The SHA transformation functions -# -# ====================================================================== - -def f0_19(B, C, D): - return (B & C) | ((~ B) & D) - -def f20_39(B, C, D): - return B ^ C ^ D - -def f40_59(B, C, D): - return (B & C) | (B & D) | (C & D) - -def f60_79(B, C, D): - return B ^ C ^ D - - -f = [f0_19, f20_39, f40_59, f60_79] - -# Constants to be used -K = [ - 0x5A827999, # ( 0 <= t <= 19) - 0x6ED9EBA1, # (20 <= t <= 39) - 0x8F1BBCDC, # (40 <= t <= 59) - 0xCA62C1D6 # (60 <= t <= 79) - ] - -class sha: - "An implementation of the MD5 hash function in pure Python." - - digest_size = digestsize = 20 - block_size = 1 - - def __init__(self): - "Initialisation." - - # Initial message length in bits(!). - self.length = 0 - self.count = [0, 0] - - # Initial empty message as a sequence of bytes (8 bit characters). - self.input = [] - - # Call a separate init function, that can be used repeatedly - # to start from scratch on the same object. - self.init() - - - def init(self): - "Initialize the message-digest and set all fields to zero." - - self.length = 0 - self.input = [] - - # Initial 160 bit message digest (5 times 32 bit). - self.H0 = 0x67452301 - self.H1 = 0xEFCDAB89 - self.H2 = 0x98BADCFE - self.H3 = 0x10325476 - self.H4 = 0xC3D2E1F0 - - def _transform(self, W): - - for t in range(16, 80): - W.append(_rotateLeft( - W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1) & 0xffffffff) - - A = self.H0 - B = self.H1 - C = self.H2 - D = self.H3 - E = self.H4 - - """ - This loop was unrolled to gain about 10% in speed - for t in range(0, 80): - TEMP = _rotateLeft(A, 5) + f[t/20] + E + W[t] + K[t/20] - E = D - D = C - C = _rotateLeft(B, 30) & 0xffffffff - B = A - A = TEMP & 0xffffffff - """ - - for t in range(0, 20): - TEMP = _rotateLeft(A, 5) + ((B & C) | ((~ B) & D)) + E + W[t] + K[0] - E = D - D = C - C = _rotateLeft(B, 30) & 0xffffffff - B = A - A = TEMP & 0xffffffff - - for t in range(20, 40): - TEMP = _rotateLeft(A, 5) + (B ^ C ^ D) + E + W[t] + K[1] - E = D - D = C - C = _rotateLeft(B, 30) & 0xffffffff - B = A - A = TEMP & 0xffffffff - - for t in range(40, 60): - TEMP = _rotateLeft(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2] - E = D - D = C - C = _rotateLeft(B, 30) & 0xffffffff - B = A - A = TEMP & 0xffffffff - - for t in range(60, 80): - TEMP = _rotateLeft(A, 5) + (B ^ C ^ D) + E + W[t] + K[3] - E = D - D = C - C = _rotateLeft(B, 30) & 0xffffffff - B = A - A = TEMP & 0xffffffff - - - self.H0 = (self.H0 + A) & 0xffffffff - self.H1 = (self.H1 + B) & 0xffffffff - self.H2 = (self.H2 + C) & 0xffffffff - self.H3 = (self.H3 + D) & 0xffffffff - self.H4 = (self.H4 + E) & 0xffffffff - - - # Down from here all methods follow the Python Standard Library - # API of the sha module. - - def update(self, inBuf): - """Add to the current message. - - Update the md5 object with the string arg. Repeated calls - are equivalent to a single call with the concatenation of all - the arguments, i.e. m.update(a); m.update(b) is equivalent - to m.update(a+b). - - The hash is immediately calculated for all full blocks. The final - calculation is made in digest(). It will calculate 1-2 blocks, - depending on how much padding we have to add. This allows us to - keep an intermediate value for the hash, so that we only need to - make minimal recalculation if we call update() to add more data - to the hashed string. - """ - - leninBuf = len(inBuf) - - # Compute number of bytes mod 64. - index = (self.count[1] >> 3) & 0x3F - - # Update number of bits. - self.count[1] = self.count[1] + (leninBuf << 3) - if self.count[1] < (leninBuf << 3): - self.count[0] = self.count[0] + 1 - self.count[0] = self.count[0] + (leninBuf >> 29) - - partLen = 64 - index - - if leninBuf >= partLen: - self.input[index:] = list(inBuf[:partLen]) - self._transform(_bytelist2longBigEndian(self.input)) - i = partLen - while i + 63 < leninBuf: - self._transform(_bytelist2longBigEndian(list(inBuf[i:i+64]))) - i = i + 64 - else: - self.input = list(inBuf[i:leninBuf]) - else: - i = 0 - self.input = self.input + list(inBuf) - - - def digest(self): - """Terminate the message-digest computation and return digest. - - Return the digest of the strings passed to the update() - method so far. This is a 16-byte string which may contain - non-ASCII characters, including null bytes. - """ - - H0 = self.H0 - H1 = self.H1 - H2 = self.H2 - H3 = self.H3 - H4 = self.H4 - input = [] + self.input - count = [] + self.count - - index = (self.count[1] >> 3) & 0x3f - - if index < 56: - padLen = 56 - index - else: - padLen = 120 - index - - padding = ['\200'] + ['\000'] * 63 - self.update(padding[:padLen]) - - # Append length (before padding). - bits = _bytelist2longBigEndian(self.input[:56]) + count - - self._transform(bits) - - # Store state in digest. - digest = _long2bytesBigEndian(self.H0, 4) + \ - _long2bytesBigEndian(self.H1, 4) + \ - _long2bytesBigEndian(self.H2, 4) + \ - _long2bytesBigEndian(self.H3, 4) + \ - _long2bytesBigEndian(self.H4, 4) - - self.H0 = H0 - self.H1 = H1 - self.H2 = H2 - self.H3 = H3 - self.H4 = H4 - self.input = input - self.count = count - - return digest - - - def hexdigest(self): - """Terminate and return digest in HEX form. - - Like digest() except the digest is returned as a string of - length 32, containing only hexadecimal digits. This may be - used to exchange the value safely in email or other non- - binary environments. - """ - return ''.join(['%02x' % ord(c) for c in self.digest()]) - - def copy(self): - """Return a clone object. - - Return a copy ('clone') of the md5 object. This can be used - to efficiently compute the digests of strings that share - a common initial substring. - """ - - return copy.deepcopy(self) - - -# ====================================================================== -# Mimic Python top-level functions from standard library API -# for consistency with the _sha module of the standard library. -# ====================================================================== - -# These are mandatory variables in the module. They have constant values -# in the SHA standard. - -digest_size = 20 -digestsize = 20 -blocksize = 1 - -def new(arg=None): - """Return a new sha crypto object. - - If arg is present, the method call update(arg) is made. - """ - - crypto = sha() - if arg: - crypto.update(arg) - - return crypto - - -if __name__ == "__main__": - a_str = "just a test string" - - assert 'da39a3ee5e6b4b0d3255bfef95601890afd80709' == new().hexdigest() - assert '3f0cf2e3d9e5903e839417dfc47fed6bfa6457f6' == new(a_str).hexdigest() - assert '0852b254078fe3772568a4aba37b917f3d4066ba' == new(a_str*7).hexdigest() - - s = new(a_str) - s.update(a_str) - assert '8862c1b50967f39d3db6bdc2877d9ccebd3102e5' == s.hexdigest() diff --git a/awx/lib/site-packages/setuptools/_backport/hashlib/_sha256.py b/awx/lib/site-packages/setuptools/_backport/hashlib/_sha256.py deleted file mode 100644 index 805dbd086c..0000000000 --- a/awx/lib/site-packages/setuptools/_backport/hashlib/_sha256.py +++ /dev/null @@ -1,260 +0,0 @@ -import struct - -SHA_BLOCKSIZE = 64 -SHA_DIGESTSIZE = 32 - - -def new_shaobject(): - return { - 'digest': [0]*8, - 'count_lo': 0, - 'count_hi': 0, - 'data': [0]* SHA_BLOCKSIZE, - 'local': 0, - 'digestsize': 0 - } - -ROR = lambda x, y: (((x & 0xffffffff) >> (y & 31)) | (x << (32 - (y & 31)))) & 0xffffffff -Ch = lambda x, y, z: (z ^ (x & (y ^ z))) -Maj = lambda x, y, z: (((x | y) & z) | (x & y)) -S = lambda x, n: ROR(x, n) -R = lambda x, n: (x & 0xffffffff) >> n -Sigma0 = lambda x: (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -Sigma1 = lambda x: (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -Gamma0 = lambda x: (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -Gamma1 = lambda x: (S(x, 17) ^ S(x, 19) ^ R(x, 10)) - -def sha_transform(sha_info): - W = [] - - d = sha_info['data'] - for i in xrange(0,16): - W.append( (d[4*i]<<24) + (d[4*i+1]<<16) + (d[4*i+2]<<8) + d[4*i+3]) - - for i in xrange(16,64): - W.append( (Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]) & 0xffffffff ) - - ss = sha_info['digest'][:] - - def RND(a,b,c,d,e,f,g,h,i,ki): - t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; - t1 = Sigma0(a) + Maj(a, b, c); - d += t0; - h = t0 + t1; - return d & 0xffffffff, h & 0xffffffff - - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],0,0x428a2f98); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],1,0x71374491); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],2,0xb5c0fbcf); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],3,0xe9b5dba5); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],4,0x3956c25b); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],5,0x59f111f1); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],6,0x923f82a4); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],7,0xab1c5ed5); - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],8,0xd807aa98); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],9,0x12835b01); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],10,0x243185be); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],11,0x550c7dc3); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],12,0x72be5d74); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],13,0x80deb1fe); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],14,0x9bdc06a7); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],15,0xc19bf174); - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],16,0xe49b69c1); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],17,0xefbe4786); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],18,0x0fc19dc6); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],19,0x240ca1cc); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],20,0x2de92c6f); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],21,0x4a7484aa); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],22,0x5cb0a9dc); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],23,0x76f988da); - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],24,0x983e5152); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],25,0xa831c66d); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],26,0xb00327c8); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],27,0xbf597fc7); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],28,0xc6e00bf3); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],29,0xd5a79147); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],30,0x06ca6351); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],31,0x14292967); - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],32,0x27b70a85); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],33,0x2e1b2138); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],34,0x4d2c6dfc); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],35,0x53380d13); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],36,0x650a7354); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],37,0x766a0abb); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],38,0x81c2c92e); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],39,0x92722c85); - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],40,0xa2bfe8a1); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],41,0xa81a664b); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],42,0xc24b8b70); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],43,0xc76c51a3); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],44,0xd192e819); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],45,0xd6990624); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],46,0xf40e3585); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],47,0x106aa070); - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],48,0x19a4c116); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],49,0x1e376c08); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],50,0x2748774c); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],51,0x34b0bcb5); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],52,0x391c0cb3); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],53,0x4ed8aa4a); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],54,0x5b9cca4f); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],55,0x682e6ff3); - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],56,0x748f82ee); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],57,0x78a5636f); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],58,0x84c87814); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],59,0x8cc70208); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],60,0x90befffa); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],61,0xa4506ceb); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],62,0xbef9a3f7); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],63,0xc67178f2); - - dig = [] - for i, x in enumerate(sha_info['digest']): - dig.append( (x + ss[i]) & 0xffffffff ) - sha_info['digest'] = dig - -def sha_init(): - sha_info = new_shaobject() - sha_info['digest'] = [0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19] - sha_info['count_lo'] = 0 - sha_info['count_hi'] = 0 - sha_info['local'] = 0 - sha_info['digestsize'] = 32 - return sha_info - -def sha224_init(): - sha_info = new_shaobject() - sha_info['digest'] = [0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4] - sha_info['count_lo'] = 0 - sha_info['count_hi'] = 0 - sha_info['local'] = 0 - sha_info['digestsize'] = 28 - return sha_info - -def getbuf(s): - if isinstance(s, str): - return s - elif isinstance(s, unicode): - return str(s) - else: - return buffer(s) - -def sha_update(sha_info, buffer): - count = len(buffer) - buffer_idx = 0 - clo = (sha_info['count_lo'] + (count << 3)) & 0xffffffff - if clo < sha_info['count_lo']: - sha_info['count_hi'] += 1 - sha_info['count_lo'] = clo - - sha_info['count_hi'] += (count >> 29) - - if sha_info['local']: - i = SHA_BLOCKSIZE - sha_info['local'] - if i > count: - i = count - - # copy buffer - for x in enumerate(buffer[buffer_idx:buffer_idx+i]): - sha_info['data'][sha_info['local']+x[0]] = struct.unpack('B', x[1])[0] - - count -= i - buffer_idx += i - - sha_info['local'] += i - if sha_info['local'] == SHA_BLOCKSIZE: - sha_transform(sha_info) - sha_info['local'] = 0 - else: - return - - while count >= SHA_BLOCKSIZE: - # copy buffer - sha_info['data'] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + SHA_BLOCKSIZE]] - count -= SHA_BLOCKSIZE - buffer_idx += SHA_BLOCKSIZE - sha_transform(sha_info) - - - # copy buffer - pos = sha_info['local'] - sha_info['data'][pos:pos+count] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + count]] - sha_info['local'] = count - -def sha_final(sha_info): - lo_bit_count = sha_info['count_lo'] - hi_bit_count = sha_info['count_hi'] - count = (lo_bit_count >> 3) & 0x3f - sha_info['data'][count] = 0x80; - count += 1 - if count > SHA_BLOCKSIZE - 8: - # zero the bytes in data after the count - sha_info['data'] = sha_info['data'][:count] + ([0] * (SHA_BLOCKSIZE - count)) - sha_transform(sha_info) - # zero bytes in data - sha_info['data'] = [0] * SHA_BLOCKSIZE - else: - sha_info['data'] = sha_info['data'][:count] + ([0] * (SHA_BLOCKSIZE - count)) - - sha_info['data'][56] = (hi_bit_count >> 24) & 0xff - sha_info['data'][57] = (hi_bit_count >> 16) & 0xff - sha_info['data'][58] = (hi_bit_count >> 8) & 0xff - sha_info['data'][59] = (hi_bit_count >> 0) & 0xff - sha_info['data'][60] = (lo_bit_count >> 24) & 0xff - sha_info['data'][61] = (lo_bit_count >> 16) & 0xff - sha_info['data'][62] = (lo_bit_count >> 8) & 0xff - sha_info['data'][63] = (lo_bit_count >> 0) & 0xff - - sha_transform(sha_info) - - dig = [] - for i in sha_info['digest']: - dig.extend([ ((i>>24) & 0xff), ((i>>16) & 0xff), ((i>>8) & 0xff), (i & 0xff) ]) - return ''.join([chr(i) for i in dig]) - -class sha256(object): - digest_size = digestsize = SHA_DIGESTSIZE - block_size = SHA_BLOCKSIZE - - def __init__(self, s=None): - self._sha = sha_init() - if s: - sha_update(self._sha, getbuf(s)) - - def update(self, s): - sha_update(self._sha, getbuf(s)) - - def digest(self): - return sha_final(self._sha.copy())[:self._sha['digestsize']] - - def hexdigest(self): - return ''.join(['%.2x' % ord(i) for i in self.digest()]) - - def copy(self): - new = sha256.__new__(sha256) - new._sha = self._sha.copy() - return new - -class sha224(sha256): - digest_size = digestsize = 28 - - def __init__(self, s=None): - self._sha = sha224_init() - if s: - sha_update(self._sha, getbuf(s)) - - def copy(self): - new = sha224.__new__(sha224) - new._sha = self._sha.copy() - return new - -if __name__ == "__main__": - a_str = "just a test string" - - assert 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' == sha256().hexdigest() - assert 'd7b553c6f09ac85d142415f857c5310f3bbbe7cdd787cce4b985acedd585266f' == sha256(a_str).hexdigest() - assert '8113ebf33c97daa9998762aacafe750c7cefc2b2f173c90c59663a57fe626f21' == sha256(a_str*7).hexdigest() - - s = sha256(a_str) - s.update(a_str) - assert '03d9963e05a094593190b6fc794cb1a3e1ac7d7883f0b5855268afeccc70d461' == s.hexdigest() diff --git a/awx/lib/site-packages/setuptools/_backport/hashlib/_sha512.py b/awx/lib/site-packages/setuptools/_backport/hashlib/_sha512.py deleted file mode 100644 index 68ff46f308..0000000000 --- a/awx/lib/site-packages/setuptools/_backport/hashlib/_sha512.py +++ /dev/null @@ -1,288 +0,0 @@ -""" -This code was Ported from CPython's sha512module.c -""" - -import struct - -SHA_BLOCKSIZE = 128 -SHA_DIGESTSIZE = 64 - - -def new_shaobject(): - return { - 'digest': [0]*8, - 'count_lo': 0, - 'count_hi': 0, - 'data': [0]* SHA_BLOCKSIZE, - 'local': 0, - 'digestsize': 0 - } - -ROR64 = lambda x, y: (((x & 0xffffffffffffffff) >> (y & 63)) | (x << (64 - (y & 63)))) & 0xffffffffffffffff -Ch = lambda x, y, z: (z ^ (x & (y ^ z))) -Maj = lambda x, y, z: (((x | y) & z) | (x & y)) -S = lambda x, n: ROR64(x, n) -R = lambda x, n: (x & 0xffffffffffffffff) >> n -Sigma0 = lambda x: (S(x, 28) ^ S(x, 34) ^ S(x, 39)) -Sigma1 = lambda x: (S(x, 14) ^ S(x, 18) ^ S(x, 41)) -Gamma0 = lambda x: (S(x, 1) ^ S(x, 8) ^ R(x, 7)) -Gamma1 = lambda x: (S(x, 19) ^ S(x, 61) ^ R(x, 6)) - -def sha_transform(sha_info): - W = [] - - d = sha_info['data'] - for i in xrange(0,16): - W.append( (d[8*i]<<56) + (d[8*i+1]<<48) + (d[8*i+2]<<40) + (d[8*i+3]<<32) + (d[8*i+4]<<24) + (d[8*i+5]<<16) + (d[8*i+6]<<8) + d[8*i+7]) - - for i in xrange(16,80): - W.append( (Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]) & 0xffffffffffffffff ) - - ss = sha_info['digest'][:] - - def RND(a,b,c,d,e,f,g,h,i,ki): - t0 = (h + Sigma1(e) + Ch(e, f, g) + ki + W[i]) & 0xffffffffffffffff - t1 = (Sigma0(a) + Maj(a, b, c)) & 0xffffffffffffffff - d = (d + t0) & 0xffffffffffffffff - h = (t0 + t1) & 0xffffffffffffffff - return d & 0xffffffffffffffff, h & 0xffffffffffffffff - - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],0,0x428a2f98d728ae22) - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],1,0x7137449123ef65cd) - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],2,0xb5c0fbcfec4d3b2f) - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],3,0xe9b5dba58189dbbc) - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],4,0x3956c25bf348b538) - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],5,0x59f111f1b605d019) - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],6,0x923f82a4af194f9b) - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],7,0xab1c5ed5da6d8118) - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],8,0xd807aa98a3030242) - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],9,0x12835b0145706fbe) - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],10,0x243185be4ee4b28c) - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],11,0x550c7dc3d5ffb4e2) - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],12,0x72be5d74f27b896f) - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],13,0x80deb1fe3b1696b1) - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],14,0x9bdc06a725c71235) - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],15,0xc19bf174cf692694) - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],16,0xe49b69c19ef14ad2) - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],17,0xefbe4786384f25e3) - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],18,0x0fc19dc68b8cd5b5) - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],19,0x240ca1cc77ac9c65) - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],20,0x2de92c6f592b0275) - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],21,0x4a7484aa6ea6e483) - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],22,0x5cb0a9dcbd41fbd4) - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],23,0x76f988da831153b5) - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],24,0x983e5152ee66dfab) - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],25,0xa831c66d2db43210) - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],26,0xb00327c898fb213f) - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],27,0xbf597fc7beef0ee4) - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],28,0xc6e00bf33da88fc2) - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],29,0xd5a79147930aa725) - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],30,0x06ca6351e003826f) - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],31,0x142929670a0e6e70) - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],32,0x27b70a8546d22ffc) - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],33,0x2e1b21385c26c926) - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],34,0x4d2c6dfc5ac42aed) - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],35,0x53380d139d95b3df) - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],36,0x650a73548baf63de) - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],37,0x766a0abb3c77b2a8) - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],38,0x81c2c92e47edaee6) - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],39,0x92722c851482353b) - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],40,0xa2bfe8a14cf10364) - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],41,0xa81a664bbc423001) - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],42,0xc24b8b70d0f89791) - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],43,0xc76c51a30654be30) - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],44,0xd192e819d6ef5218) - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],45,0xd69906245565a910) - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],46,0xf40e35855771202a) - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],47,0x106aa07032bbd1b8) - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],48,0x19a4c116b8d2d0c8) - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],49,0x1e376c085141ab53) - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],50,0x2748774cdf8eeb99) - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],51,0x34b0bcb5e19b48a8) - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],52,0x391c0cb3c5c95a63) - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],53,0x4ed8aa4ae3418acb) - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],54,0x5b9cca4f7763e373) - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],55,0x682e6ff3d6b2b8a3) - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],56,0x748f82ee5defb2fc) - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],57,0x78a5636f43172f60) - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],58,0x84c87814a1f0ab72) - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],59,0x8cc702081a6439ec) - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],60,0x90befffa23631e28) - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],61,0xa4506cebde82bde9) - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],62,0xbef9a3f7b2c67915) - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],63,0xc67178f2e372532b) - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],64,0xca273eceea26619c) - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],65,0xd186b8c721c0c207) - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],66,0xeada7dd6cde0eb1e) - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],67,0xf57d4f7fee6ed178) - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],68,0x06f067aa72176fba) - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],69,0x0a637dc5a2c898a6) - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],70,0x113f9804bef90dae) - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],71,0x1b710b35131c471b) - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],72,0x28db77f523047d84) - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],73,0x32caab7b40c72493) - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],74,0x3c9ebe0a15c9bebc) - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],75,0x431d67c49c100d4c) - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],76,0x4cc5d4becb3e42b6) - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],77,0x597f299cfc657e2a) - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],78,0x5fcb6fab3ad6faec) - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],79,0x6c44198c4a475817) - - dig = [] - for i, x in enumerate(sha_info['digest']): - dig.append( (x + ss[i]) & 0xffffffffffffffff ) - sha_info['digest'] = dig - -def sha_init(): - sha_info = new_shaobject() - sha_info['digest'] = [ 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179] - sha_info['count_lo'] = 0 - sha_info['count_hi'] = 0 - sha_info['local'] = 0 - sha_info['digestsize'] = 64 - return sha_info - -def sha384_init(): - sha_info = new_shaobject() - sha_info['digest'] = [ 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939, 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4] - sha_info['count_lo'] = 0 - sha_info['count_hi'] = 0 - sha_info['local'] = 0 - sha_info['digestsize'] = 48 - return sha_info - -def getbuf(s): - if isinstance(s, str): - return s - elif isinstance(s, unicode): - return str(s) - else: - return buffer(s) - -def sha_update(sha_info, buffer): - count = len(buffer) - buffer_idx = 0 - clo = (sha_info['count_lo'] + (count << 3)) & 0xffffffff - if clo < sha_info['count_lo']: - sha_info['count_hi'] += 1 - sha_info['count_lo'] = clo - - sha_info['count_hi'] += (count >> 29) - - if sha_info['local']: - i = SHA_BLOCKSIZE - sha_info['local'] - if i > count: - i = count - - # copy buffer - for x in enumerate(buffer[buffer_idx:buffer_idx+i]): - sha_info['data'][sha_info['local']+x[0]] = struct.unpack('B', x[1])[0] - - count -= i - buffer_idx += i - - sha_info['local'] += i - if sha_info['local'] == SHA_BLOCKSIZE: - sha_transform(sha_info) - sha_info['local'] = 0 - else: - return - - while count >= SHA_BLOCKSIZE: - # copy buffer - sha_info['data'] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + SHA_BLOCKSIZE]] - count -= SHA_BLOCKSIZE - buffer_idx += SHA_BLOCKSIZE - sha_transform(sha_info) - - # copy buffer - pos = sha_info['local'] - sha_info['data'][pos:pos+count] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + count]] - sha_info['local'] = count - -def sha_final(sha_info): - lo_bit_count = sha_info['count_lo'] - hi_bit_count = sha_info['count_hi'] - count = (lo_bit_count >> 3) & 0x7f - sha_info['data'][count] = 0x80; - count += 1 - if count > SHA_BLOCKSIZE - 16: - # zero the bytes in data after the count - sha_info['data'] = sha_info['data'][:count] + ([0] * (SHA_BLOCKSIZE - count)) - sha_transform(sha_info) - # zero bytes in data - sha_info['data'] = [0] * SHA_BLOCKSIZE - else: - sha_info['data'] = sha_info['data'][:count] + ([0] * (SHA_BLOCKSIZE - count)) - - sha_info['data'][112] = 0; - sha_info['data'][113] = 0; - sha_info['data'][114] = 0; - sha_info['data'][115] = 0; - sha_info['data'][116] = 0; - sha_info['data'][117] = 0; - sha_info['data'][118] = 0; - sha_info['data'][119] = 0; - - sha_info['data'][120] = (hi_bit_count >> 24) & 0xff - sha_info['data'][121] = (hi_bit_count >> 16) & 0xff - sha_info['data'][122] = (hi_bit_count >> 8) & 0xff - sha_info['data'][123] = (hi_bit_count >> 0) & 0xff - sha_info['data'][124] = (lo_bit_count >> 24) & 0xff - sha_info['data'][125] = (lo_bit_count >> 16) & 0xff - sha_info['data'][126] = (lo_bit_count >> 8) & 0xff - sha_info['data'][127] = (lo_bit_count >> 0) & 0xff - - sha_transform(sha_info) - - dig = [] - for i in sha_info['digest']: - dig.extend([ ((i>>56) & 0xff), ((i>>48) & 0xff), ((i>>40) & 0xff), ((i>>32) & 0xff), ((i>>24) & 0xff), ((i>>16) & 0xff), ((i>>8) & 0xff), (i & 0xff) ]) - return ''.join([chr(i) for i in dig]) - -class sha512(object): - digest_size = digestsize = SHA_DIGESTSIZE - block_size = SHA_BLOCKSIZE - - def __init__(self, s=None): - self._sha = sha_init() - if s: - sha_update(self._sha, getbuf(s)) - - def update(self, s): - sha_update(self._sha, getbuf(s)) - - def digest(self): - return sha_final(self._sha.copy())[:self._sha['digestsize']] - - def hexdigest(self): - return ''.join(['%.2x' % ord(i) for i in self.digest()]) - - def copy(self): - new = sha512.__new__(sha512) - new._sha = self._sha.copy() - return new - -class sha384(sha512): - digest_size = digestsize = 48 - - def __init__(self, s=None): - self._sha = sha384_init() - if s: - sha_update(self._sha, getbuf(s)) - - def copy(self): - new = sha384.__new__(sha384) - new._sha = self._sha.copy() - return new - -if __name__ == "__main__": - a_str = "just a test string" - - assert sha512().hexdigest() == "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" - assert sha512(a_str).hexdigest() == "68be4c6664af867dd1d01c8d77e963d87d77b702400c8fabae355a41b8927a5a5533a7f1c28509bbd65c5f3ac716f33be271fbda0ca018b71a84708c9fae8a53" - assert sha512(a_str*7).hexdigest() == "3233acdbfcfff9bff9fc72401d31dbffa62bd24e9ec846f0578d647da73258d9f0879f7fde01fe2cc6516af3f343807fdef79e23d696c923d79931db46bf1819" - - s = sha512(a_str) - s.update(a_str) - assert s.hexdigest() == "341aeb668730bbb48127d5531115f3c39d12cb9586a6ca770898398aff2411087cfe0b570689adf328cddeb1f00803acce6737a19f310b53bbdb0320828f75bb" diff --git a/awx/lib/site-packages/setuptools/command/__init__.py b/awx/lib/site-packages/setuptools/command/__init__.py index b063fa1925..29c9d75ad1 100644 --- a/awx/lib/site-packages/setuptools/command/__init__.py +++ b/awx/lib/site-packages/setuptools/command/__init__.py @@ -1,17 +1,13 @@ __all__ = [ 'alias', 'bdist_egg', 'bdist_rpm', 'build_ext', 'build_py', 'develop', 'easy_install', 'egg_info', 'install', 'install_lib', 'rotate', 'saveopts', - 'sdist', 'setopt', 'test', 'upload', 'install_egg_info', 'install_scripts', + 'sdist', 'setopt', 'test', 'install_egg_info', 'install_scripts', 'register', 'bdist_wininst', 'upload_docs', ] from setuptools.command import install_scripts import sys -if sys.version>='2.5': - # In Python 2.5 and above, distutils includes its own upload command - __all__.remove('upload') - from distutils.command.bdist import bdist if 'egg' not in bdist.format_commands: diff --git a/awx/lib/site-packages/setuptools/command/build_py.py b/awx/lib/site-packages/setuptools/command/build_py.py index 8751acd493..090b44d265 100644 --- a/awx/lib/site-packages/setuptools/command/build_py.py +++ b/awx/lib/site-packages/setuptools/command/build_py.py @@ -1,64 +1,17 @@ -import os.path, sys, fnmatch +import os +import sys +import fnmatch +import textwrap from distutils.command.build_py import build_py as _build_py from distutils.util import convert_path from glob import glob try: - from distutils.util import Mixin2to3 as _Mixin2to3 - # add support for converting doctests that is missing in 3.1 distutils - from distutils import log - from lib2to3.refactor import RefactoringTool, get_fixers_from_package - import setuptools - class DistutilsRefactoringTool(RefactoringTool): - def log_error(self, msg, *args, **kw): - log.error(msg, *args) - - def log_message(self, msg, *args): - log.info(msg, *args) - - def log_debug(self, msg, *args): - log.debug(msg, *args) - - class Mixin2to3(_Mixin2to3): - def run_2to3(self, files, doctests = False): - # See of the distribution option has been set, otherwise check the - # setuptools default. - if self.distribution.use_2to3 is not True: - return - if not files: - return - log.info("Fixing "+" ".join(files)) - self.__build_fixer_names() - self.__exclude_fixers() - if doctests: - if setuptools.run_2to3_on_doctests: - r = DistutilsRefactoringTool(self.fixer_names) - r.refactor(files, write=True, doctests_only=True) - else: - _Mixin2to3.run_2to3(self, files) - - def __build_fixer_names(self): - if self.fixer_names: return - self.fixer_names = [] - for p in setuptools.lib2to3_fixer_packages: - self.fixer_names.extend(get_fixers_from_package(p)) - if self.distribution.use_2to3_fixers is not None: - for p in self.distribution.use_2to3_fixers: - self.fixer_names.extend(get_fixers_from_package(p)) - - def __exclude_fixers(self): - excluded_fixers = getattr(self, 'exclude_fixers', []) - if self.distribution.use_2to3_exclude_fixers is not None: - excluded_fixers.extend(self.distribution.use_2to3_exclude_fixers) - for fixer_name in excluded_fixers: - if fixer_name in self.fixer_names: - self.fixer_names.remove(fixer_name) - + from setuptools.lib2to3_ex import Mixin2to3 except ImportError: class Mixin2to3: def run_2to3(self, files, doctests=True): - # Nothing done in 2.x - pass + "do nothing" class build_py(_build_py, Mixin2to3): """Enhanced 'build_py' command that includes data files with packages @@ -97,9 +50,10 @@ class build_py(_build_py, Mixin2to3): # output files are. self.byte_compile(_build_py.get_outputs(self, include_bytecode=0)) - def __getattr__(self,attr): + def __getattr__(self, attr): if attr=='data_files': # lazily compute data files - self.data_files = files = self._get_data_files(); return files + self.data_files = files = self._get_data_files() + return files return _build_py.__getattr__(self,attr) def build_module(self, module, module_file, package): @@ -126,7 +80,7 @@ class build_py(_build_py, Mixin2to3): filenames = [ file[plen:] for file in self.find_data_files(package, src_dir) ] - data.append( (package, src_dir, build_dir, filenames) ) + data.append((package, src_dir, build_dir, filenames)) return data def find_data_files(self, package, src_dir): @@ -141,7 +95,6 @@ class build_py(_build_py, Mixin2to3): def build_package_data(self): """Copy data files into build directory""" - lastdir = None for package, src_dir, build_dir, filenames in self.data_files: for filename in filenames: target = os.path.join(build_dir, filename) @@ -152,7 +105,6 @@ class build_py(_build_py, Mixin2to3): if copied and srcfile in self.distribution.convert_2to3_doctests: self.__doctests_2to3.append(outf) - def analyze_manifest(self): self.manifest_files = mf = {} if not self.distribution.include_package_data: @@ -217,10 +169,10 @@ class build_py(_build_py, Mixin2to3): if 'declare_namespace'.encode() not in f.read(): from distutils import log log.warn( - "WARNING: %s is a namespace package, but its __init__.py does\n" - "not declare_namespace(); setuptools 0.7 will REQUIRE this!\n" - '(See the setuptools manual under "Namespace Packages" for ' - "details.)\n", package + "WARNING: %s is a namespace package, but its __init__.py does\n" + "not declare_namespace(); setuptools 0.7 will REQUIRE this!\n" + '(See the setuptools manual under "Namespace Packages" for ' + "details.)\n", package ) f.close() return init_py @@ -229,14 +181,12 @@ class build_py(_build_py, Mixin2to3): self.packages_checked={} _build_py.initialize_options(self) - def get_package_dir(self, package): res = _build_py.get_package_dir(self, package) if self.distribution.src_root is not None: return os.path.join(self.distribution.src_root, res) return res - def exclude_data_files(self, package, src_dir, files): """Filter filenames for package's data files in 'src_dir'""" globs = (self.exclude_package_data.get('', []) @@ -260,21 +210,12 @@ def assert_relative(path): if not os.path.isabs(path): return path from distutils.errors import DistutilsSetupError - raise DistutilsSetupError( -"""Error: setup script specifies an absolute path: - - %s - -setup() arguments must *always* be /-separated paths relative to the -setup.py directory, *never* absolute paths. -""" % path - ) - - - - - - - + msg = textwrap.dedent(""" + Error: setup script specifies an absolute path: + %s + setup() arguments must *always* be /-separated paths relative to the + setup.py directory, *never* absolute paths. + """).lstrip() % path + raise DistutilsSetupError(msg) diff --git a/awx/lib/site-packages/setuptools/command/easy_install.py b/awx/lib/site-packages/setuptools/command/easy_install.py index 6ce19fa4df..08ebf3e589 100644 --- a/awx/lib/site-packages/setuptools/command/easy_install.py +++ b/awx/lib/site-packages/setuptools/command/easy_install.py @@ -1,4 +1,4 @@ -#!python +#!/usr/bin/env python """ Easy Install @@ -32,19 +32,7 @@ from distutils import log, dir_util import pkg_resources from setuptools import Command, _dont_write_bytecode from setuptools.sandbox import run_setup -try: - # Python 2.7 or >=3.2 - from sysconfig import get_config_vars, get_path - def _get_platlib(): - return get_path("platlib") - def _get_purelib(): - return get_path("purelib") -except ImportError: - from distutils.sysconfig import get_config_vars, get_python_lib - def _get_platlib(): - return get_python_lib(True) - def _get_purelib(): - return get_python_lib(False) +from setuptools.py31compat import get_path, get_config_vars from distutils.util import get_platform from distutils.util import convert_path, subst_vars @@ -56,7 +44,7 @@ from setuptools.archive_util import unpack_archive from setuptools.package_index import PackageIndex from setuptools.package_index import URL_SCHEME from setuptools.command import bdist_egg, egg_info -from setuptools.compat import (iteritems, maxsize, xrange, basestring, unicode, +from setuptools.compat import (iteritems, maxsize, basestring, unicode, reraise) from pkg_resources import ( yield_lines, normalize_path, resource_string, ensure_directory, @@ -65,18 +53,14 @@ from pkg_resources import ( VersionConflict, DEVELOP_DIST, ) -if '__VENV_LAUNCHER__' in os.environ: - sys_executable = os.environ['__VENV_LAUNCHER__'] -else: - sys_executable = os.path.normpath(sys.executable) +sys_executable = os.environ.get('__VENV_LAUNCHER__', + os.path.normpath(sys.executable)) __all__ = [ 'samefile', 'easy_install', 'PthDistributions', 'extract_wininst_cfg', 'main', 'get_exe_prefixes', ] -HAS_USER_SITE = not sys.version < "2.6" and site.ENABLE_USER_SITE - def is_64bit(): return struct.calcsize("P") == 8 @@ -148,7 +132,7 @@ class easy_install(Command): 'no-deps', 'local-snapshots-ok', 'version' ] - if HAS_USER_SITE: + if site.ENABLE_USER_SITE: help_msg = "install in user site-package '%s'" % site.USER_SITE user_options.append(('user', None, help_msg)) boolean_options.append('user') @@ -157,7 +141,7 @@ class easy_install(Command): create_index = PackageIndex def initialize_options(self): - if HAS_USER_SITE: + if site.ENABLE_USER_SITE: whereami = os.path.abspath(__file__) self.user = whereami.startswith(site.USER_SITE) else: @@ -182,7 +166,7 @@ class easy_install(Command): self.install_data = None self.install_base = None self.install_platbase = None - if HAS_USER_SITE: + if site.ENABLE_USER_SITE: self.install_userbase = site.USER_BASE self.install_usersite = site.USER_SITE else: @@ -240,13 +224,13 @@ class easy_install(Command): 'abiflags': getattr(sys, 'abiflags', ''), } - if HAS_USER_SITE: + if site.ENABLE_USER_SITE: self.config_vars['userbase'] = self.install_userbase self.config_vars['usersite'] = self.install_usersite # fix the install_dir if "--user" was used #XXX: duplicate of the code in the setup command - if self.user and HAS_USER_SITE: + if self.user and site.ENABLE_USER_SITE: self.create_home_path() if self.install_userbase is None: raise DistutilsPlatformError( @@ -376,7 +360,7 @@ class easy_install(Command): outputs = self.outputs if self.root: # strip any package prefix root_len = len(self.root) - for counter in xrange(len(outputs)): + for counter in range(len(outputs)): outputs[counter] = outputs[counter][root_len:] from distutils import file_util self.execute( @@ -1288,10 +1272,11 @@ def get_site_dirs(): 'Python', sys.version[:3], 'site-packages')) - for site_lib in (_get_purelib(), _get_platlib()): + lib_paths = get_path('purelib'), get_path('platlib') + for site_lib in lib_paths: if site_lib not in sitedirs: sitedirs.append(site_lib) - if HAS_USER_SITE: + if site.ENABLE_USER_SITE: sitedirs.append(site.USER_SITE) sitedirs = list(map(normalize_path, sitedirs)) @@ -1373,10 +1358,9 @@ def extract_wininst_cfg(dist_filename): else: null_byte = chr(0) config = part.split(null_byte, 1)[0] - # Now the config is in bytes, but on Python 3, it must be - # unicode for the RawConfigParser, so decode it. Is this the - # right encoding? - config = config.decode('ascii') + # Now the config is in bytes, but for RawConfigParser, it should + # be text, so decode it. + config = config.decode(sys.getfilesystemencoding()) cfg.readfp(StringIO(config)) except ConfigParser.Error: return None diff --git a/awx/lib/site-packages/setuptools/command/egg_info.py b/awx/lib/site-packages/setuptools/command/egg_info.py index a0ba530590..5953aad4f6 100644 --- a/awx/lib/site-packages/setuptools/command/egg_info.py +++ b/awx/lib/site-packages/setuptools/command/egg_info.py @@ -2,18 +2,20 @@ Create a distribution's .egg-info directory and contents""" -# This module should be kept compatible with Python 2.3 -import os, re, sys +import os +import re +import sys + from setuptools import Command -from distutils.errors import * +import distutils.errors from distutils import log from setuptools.command.sdist import sdist from setuptools.compat import basestring from setuptools import svn_utils from distutils.util import convert_path from distutils.filelist import FileList as _FileList -from pkg_resources import parse_requirements, safe_name, parse_version, \ - safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename +from pkg_resources import (parse_requirements, safe_name, parse_version, + safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename) from setuptools.command.sdist import walk_revctrl @@ -36,12 +38,6 @@ class egg_info(Command): negative_opt = {'no-svn-revision': 'tag-svn-revision', 'no-date': 'tag-date'} - - - - - - def initialize_options(self): self.egg_name = None self.egg_version = None @@ -55,35 +51,16 @@ class egg_info(Command): def save_version_info(self, filename): from setuptools.command.setopt import edit_config - edit_config( - filename, - {'egg_info': - {'tag_svn_revision':0, 'tag_date': 0, 'tag_build': self.tags()} - } + values = dict( + egg_info=dict( + tag_svn_revision=0, + tag_date=0, + tag_build=self.tags(), + ) ) + edit_config(filename, values) - - - - - - - - - - - - - - - - - - - - - - def finalize_options (self): + def finalize_options(self): self.egg_name = safe_name(self.distribution.get_name()) self.vtags = self.tags() self.egg_version = self.tagged_version() @@ -93,7 +70,7 @@ class egg_info(Command): parse_requirements('%s==%s' % (self.egg_name,self.egg_version)) ) except ValueError: - raise DistutilsOptionError( + raise distutils.errors.DistutilsOptionError( "Invalid distribution name or version syntax: %s-%s" % (self.egg_name,self.egg_version) ) @@ -123,7 +100,6 @@ class egg_info(Command): pd._parsed_version = parse_version(self.egg_version) self.distribution._patched_dist = None - def write_or_delete_file(self, what, filename, data, force=False): """Write `data` to `filename` or delete if empty @@ -194,34 +170,14 @@ class egg_info(Command): os.path.exists('.svn') or os.path.exists('PKG-INFO') ): version += '-r%s' % self.get_svn_revision() if self.tag_date: - import time; version += time.strftime("-%Y%m%d") + import time + version += time.strftime("-%Y%m%d") return version - - - - - - - - - - - - - - - - @staticmethod def get_svn_revision(): return str(svn_utils.SvnInfo.load(os.curdir).get_revision()) - - - - - def find_sources(self): """Generate SOURCES.txt manifest file""" manifest_filename = os.path.join(self.egg_info,"SOURCES.txt") @@ -269,17 +225,11 @@ class FileList(_FileList): self.files.append(path) - - - - - - class manifest_maker(sdist): template = "MANIFEST.in" - def initialize_options (self): + def initialize_options(self): self.use_defaults = 1 self.prune = 1 self.manifest_only = 1 @@ -301,7 +251,7 @@ class manifest_maker(sdist): self.filelist.remove_duplicates() self.write_manifest() - def write_manifest (self): + def write_manifest(self): """Write the file list in 'self.filelist' (presumably as filled in by 'add_defaults()' and 'read_template()') to the manifest file named by 'self.manifest'. @@ -340,7 +290,7 @@ class manifest_maker(sdist): ei_cmd = self.get_finalized_command('egg_info') self.filelist.include_pattern("*", prefix=ei_cmd.egg_info) - def prune_file_list (self): + def prune_file_list(self): build = self.get_finalized_command('build') base_dir = self.distribution.get_fullname() self.filelist.exclude_pattern(None, prefix=build.build_base) @@ -349,7 +299,7 @@ class manifest_maker(sdist): self.filelist.exclude_pattern(sep+r'(RCS|CVS|\.svn)'+sep, is_regex=1) -def write_file (filename, contents): +def write_file(filename, contents): """Create a file with the specified name and write 'contents' (a sequence of strings without line terminators) to it. """ @@ -360,24 +310,12 @@ def write_file (filename, contents): f.write(contents) f.close() - - - - - - - - - - - - def write_pkg_info(cmd, basename, filename): log.info("writing %s", filename) if not cmd.dry_run: metadata = cmd.distribution.metadata metadata.version, oldver = cmd.egg_version, metadata.version - metadata.name, oldname = cmd.egg_name, metadata.name + metadata.name, oldname = cmd.egg_name, metadata.name try: # write unescaped data to PKG-INFO, so older pkg_resources # can still parse it @@ -406,14 +344,14 @@ def write_requirements(cmd, basename, filename): def write_toplevel_names(cmd, basename, filename): pkgs = dict.fromkeys( - [k.split('.',1)[0] + [ + k.split('.',1)[0] for k in cmd.distribution.iter_distribution_names() ] ) cmd.write_file("top-level names", filename, '\n'.join(pkgs)+'\n') - def overwrite_arg(cmd, basename, filename): write_arg(cmd, basename, filename, True) @@ -452,7 +390,3 @@ def get_pkg_info_revision(): return int(match.group(1)) f.close() return 0 - - - -# diff --git a/awx/lib/site-packages/setuptools/command/sdist.py b/awx/lib/site-packages/setuptools/command/sdist.py index 6249e75c63..77a3852b96 100644 --- a/awx/lib/site-packages/setuptools/command/sdist.py +++ b/awx/lib/site-packages/setuptools/command/sdist.py @@ -35,10 +35,10 @@ class re_finder(object): f.close() for match in self.pattern.finditer(data): path = match.group(1) - if postproc: + if self.postproc: #postproc used to be used when the svn finder #was an re_finder for calling unescape - path = postproc(path) + path = self.postproc(path) yield svn_utils.joinpath(dirname,path) def __call__(self, dirname=''): path = svn_utils.joinpath(dirname, self.path) diff --git a/awx/lib/site-packages/setuptools/command/upload.py b/awx/lib/site-packages/setuptools/command/upload.py deleted file mode 100644 index a6eff3855b..0000000000 --- a/awx/lib/site-packages/setuptools/command/upload.py +++ /dev/null @@ -1,183 +0,0 @@ -"""distutils.command.upload - -Implements the Distutils 'upload' subcommand (upload package to PyPI).""" - -from distutils import errors -from distutils import log -from distutils.core import Command -from distutils.spawn import spawn -try: - from hashlib import md5 -except ImportError: - from md5 import md5 -import os -import sys -import socket -import platform -import base64 - -from setuptools.compat import urlparse, StringIO, httplib, ConfigParser - -class upload(Command): - - description = "upload binary package to PyPI" - - DEFAULT_REPOSITORY = 'https://pypi.python.org/pypi' - - user_options = [ - ('repository=', 'r', - "url of repository [default: %s]" % DEFAULT_REPOSITORY), - ('show-response', None, - 'display full response text from server'), - ('sign', 's', - 'sign files to upload using gpg'), - ('identity=', 'i', 'GPG identity used to sign files'), - ] - boolean_options = ['show-response', 'sign'] - - def initialize_options(self): - self.username = '' - self.password = '' - self.repository = '' - self.show_response = 0 - self.sign = False - self.identity = None - - def finalize_options(self): - if self.identity and not self.sign: - raise errors.DistutilsOptionError( - "Must use --sign for --identity to have meaning" - ) - if 'HOME' in os.environ: - rc = os.path.join(os.environ['HOME'], '.pypirc') - if os.path.exists(rc): - self.announce('Using PyPI login from %s' % rc) - config = ConfigParser.ConfigParser({ - 'username':'', - 'password':'', - 'repository':''}) - config.read(rc) - if not self.repository: - self.repository = config.get('server-login', 'repository') - if not self.username: - self.username = config.get('server-login', 'username') - if not self.password: - self.password = config.get('server-login', 'password') - if not self.repository: - self.repository = self.DEFAULT_REPOSITORY - - def run(self): - if not self.distribution.dist_files: - raise errors.DistutilsOptionError("No dist file created in earlier command") - for command, pyversion, filename in self.distribution.dist_files: - self.upload_file(command, pyversion, filename) - - def upload_file(self, command, pyversion, filename): - # Sign if requested - if self.sign: - gpg_args = ["gpg", "--detach-sign", "-a", filename] - if self.identity: - gpg_args[2:2] = ["--local-user", self.identity] - spawn(gpg_args, - dry_run=self.dry_run) - - # Fill in the data - f = open(filename,'rb') - content = f.read() - f.close() - basename = os.path.basename(filename) - comment = '' - if command=='bdist_egg' and self.distribution.has_ext_modules(): - comment = "built on %s" % platform.platform(terse=1) - data = { - ':action':'file_upload', - 'protocol_version':'1', - 'name':self.distribution.get_name(), - 'version':self.distribution.get_version(), - 'content':(basename,content), - 'filetype':command, - 'pyversion':pyversion, - 'md5_digest':md5(content).hexdigest(), - } - if command == 'bdist_rpm': - dist, version, id = platform.dist() - if dist: - comment = 'built for %s %s' % (dist, version) - elif command == 'bdist_dumb': - comment = 'built for %s' % platform.platform(terse=1) - data['comment'] = comment - - if self.sign: - asc_file = open(filename + ".asc") - data['gpg_signature'] = (os.path.basename(filename) + ".asc", asc_file.read()) - asc_file.close() - - # set up the authentication - auth = "Basic " + base64.encodestring(self.username + ":" + self.password).strip() - - # Build up the MIME payload for the POST data - boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' - sep_boundary = '\n--' + boundary - end_boundary = sep_boundary + '--' - body = StringIO() - for key, value in data.items(): - # handle multiple entries for the same name - if not isinstance(value, list): - value = [value] - for value in value: - if type(value) is tuple: - fn = ';filename="%s"' % value[0] - value = value[1] - else: - fn = "" - value = str(value) - body.write(sep_boundary) - body.write('\nContent-Disposition: form-data; name="%s"'%key) - body.write(fn) - body.write("\n\n") - body.write(value) - if value and value[-1] == '\r': - body.write('\n') # write an extra newline (lurve Macs) - body.write(end_boundary) - body.write("\n") - body = body.getvalue() - - self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO) - - # build the Request - # We can't use urllib2 since we need to send the Basic - # auth right with the first request - schema, netloc, url, params, query, fragments = \ - urlparse(self.repository) - assert not params and not query and not fragments - if schema == 'http': - http = httplib.HTTPConnection(netloc) - elif schema == 'https': - http = httplib.HTTPSConnection(netloc) - else: - raise AssertionError("unsupported schema " + schema) - - data = '' - try: - http.connect() - http.putrequest("POST", url) - http.putheader('Content-type', - 'multipart/form-data; boundary=%s'%boundary) - http.putheader('Content-length', str(len(body))) - http.putheader('Authorization', auth) - http.endheaders() - http.send(body) - except socket.error: - e = sys.exc_info()[1] - self.announce(str(e), log.ERROR) - return - - r = http.getresponse() - if r.status == 200: - self.announce('Server response (%s): %s' % (r.status, r.reason), - log.INFO) - else: - self.announce('Upload failed (%s): %s' % (r.status, r.reason), - log.ERROR) - if self.show_response: - print('-'*75, r.read(), '-'*75) diff --git a/awx/lib/site-packages/setuptools/command/upload_docs.py b/awx/lib/site-packages/setuptools/command/upload_docs.py index 12bc916bb1..cad7a52d1b 100644 --- a/awx/lib/site-packages/setuptools/command/upload_docs.py +++ b/awx/lib/site-packages/setuptools/command/upload_docs.py @@ -17,20 +17,11 @@ from pkg_resources import iter_entry_points from distutils import log from distutils.errors import DistutilsOptionError +from distutils.command.upload import upload -try: - from distutils.command.upload import upload -except ImportError: - from setuptools.command.upload import upload +from setuptools.compat import httplib, urlparse, unicode, iteritems, PY3 -from setuptools.compat import httplib, urlparse, unicode, iteritems - -_IS_PYTHON3 = sys.version > '3' - -if _IS_PYTHON3: - errors = 'surrogateescape' -else: - errors = 'strict' +errors = 'surrogateescape' if PY3 else 'strict' # This is not just a replacement for byte literals @@ -124,7 +115,7 @@ class upload_docs(upload): # set up the authentication credentials = b(self.username + ':' + self.password) credentials = standard_b64encode(credentials) - if sys.version_info >= (3,): + if PY3: credentials = credentials.decode('ascii') auth = "Basic " + credentials @@ -136,7 +127,7 @@ class upload_docs(upload): for key, values in iteritems(data): title = '\nContent-Disposition: form-data; name="%s"' % key # handle multiple entries for the same name - if type(values) != type([]): + if not isinstance(values, list): values = [values] for value in values: if type(value) is tuple: @@ -171,12 +162,11 @@ class upload_docs(upload): raise AssertionError("unsupported schema "+schema) data = '' - loglevel = log.INFO try: conn.connect() conn.putrequest("POST", url) - conn.putheader('Content-type', - 'multipart/form-data; boundary=%s'%boundary) + content_type = 'multipart/form-data; boundary=%s' % boundary + conn.putheader('Content-type', content_type) conn.putheader('Content-length', str(len(body))) conn.putheader('Authorization', auth) conn.endheaders() diff --git a/awx/lib/site-packages/setuptools/compat.py b/awx/lib/site-packages/setuptools/compat.py index bbc98d6644..7b824ba2ff 100644 --- a/awx/lib/site-packages/setuptools/compat.py +++ b/awx/lib/site-packages/setuptools/compat.py @@ -23,29 +23,16 @@ if sys.version_info[0] < 3: maxsize = sys.maxint next = lambda o: o.next() numeric_types = (int, long, float) - reduce = reduce unichr = unichr unicode = unicode bytes = str - from urllib import url2pathname, splittag + from urllib import url2pathname, splittag, pathname2url import urllib2 from urllib2 import urlopen, HTTPError, URLError, unquote, splituser from urlparse import urlparse, urlunparse, urljoin, urlsplit, urlunsplit - xrange = xrange filterfalse = itertools.ifilterfalse - def exec_(code, globs=None, locs=None): - if globs is None: - frame = sys._getframe(1) - globs = frame.f_globals - if locs is None: - locs = frame.f_locals - del frame - elif locs is None: - locs = globs - exec("""exec code in globs, locs""") - - exec_("""def reraise(tp, value, tb=None): + exec("""def reraise(tp, value, tb=None): raise tp, value, tb""") else: PY3 = True @@ -53,7 +40,6 @@ else: basestring = str import builtins import configparser as ConfigParser - exec_ = eval('exec') from io import StringIO, BytesIO func_code = lambda o: o.__code__ func_globals = lambda o: o.__globals__ @@ -67,18 +53,16 @@ else: maxsize = sys.maxsize next = next numeric_types = (int, float) - from functools import reduce unichr = chr unicode = str bytes = bytes from urllib.error import HTTPError, URLError import urllib.request as urllib2 - from urllib.request import urlopen, url2pathname + from urllib.request import urlopen, url2pathname, pathname2url from urllib.parse import ( urlparse, urlunparse, unquote, splituser, urljoin, urlsplit, urlunsplit, splittag, ) - xrange = range filterfalse = itertools.filterfalse def execfile(fn, globs=None, locs=None): @@ -91,7 +75,7 @@ else: source = f.read() finally: f.close() - exec_(compile(source, fn, 'exec'), globs, locs) + exec(compile(source, fn, 'exec'), globs, locs) def reraise(tp, value, tb=None): if value.__traceback__ is not tb: diff --git a/awx/lib/site-packages/setuptools/lib2to3_ex.py b/awx/lib/site-packages/setuptools/lib2to3_ex.py new file mode 100644 index 0000000000..feef591a88 --- /dev/null +++ b/awx/lib/site-packages/setuptools/lib2to3_ex.py @@ -0,0 +1,58 @@ +""" +Customized Mixin2to3 support: + + - adds support for converting doctests + + +This module raises an ImportError on Python 2. +""" + +from distutils.util import Mixin2to3 as _Mixin2to3 +from distutils import log +from lib2to3.refactor import RefactoringTool, get_fixers_from_package +import setuptools + +class DistutilsRefactoringTool(RefactoringTool): + def log_error(self, msg, *args, **kw): + log.error(msg, *args) + + def log_message(self, msg, *args): + log.info(msg, *args) + + def log_debug(self, msg, *args): + log.debug(msg, *args) + +class Mixin2to3(_Mixin2to3): + def run_2to3(self, files, doctests = False): + # See of the distribution option has been set, otherwise check the + # setuptools default. + if self.distribution.use_2to3 is not True: + return + if not files: + return + log.info("Fixing "+" ".join(files)) + self.__build_fixer_names() + self.__exclude_fixers() + if doctests: + if setuptools.run_2to3_on_doctests: + r = DistutilsRefactoringTool(self.fixer_names) + r.refactor(files, write=True, doctests_only=True) + else: + _Mixin2to3.run_2to3(self, files) + + def __build_fixer_names(self): + if self.fixer_names: return + self.fixer_names = [] + for p in setuptools.lib2to3_fixer_packages: + self.fixer_names.extend(get_fixers_from_package(p)) + if self.distribution.use_2to3_fixers is not None: + for p in self.distribution.use_2to3_fixers: + self.fixer_names.extend(get_fixers_from_package(p)) + + def __exclude_fixers(self): + excluded_fixers = getattr(self, 'exclude_fixers', []) + if self.distribution.use_2to3_exclude_fixers is not None: + excluded_fixers.extend(self.distribution.use_2to3_exclude_fixers) + for fixer_name in excluded_fixers: + if fixer_name in self.fixer_names: + self.fixer_names.remove(fixer_name) diff --git a/awx/lib/site-packages/setuptools/package_index.py b/awx/lib/site-packages/setuptools/package_index.py index 4c9e40a7b1..0e51b72c55 100644 --- a/awx/lib/site-packages/setuptools/package_index.py +++ b/awx/lib/site-packages/setuptools/package_index.py @@ -5,6 +5,8 @@ import re import shutil import socket import base64 +import hashlib +from functools import wraps from pkg_resources import ( CHECKOUT_DIST, Distribution, BINARY_DIST, normalize_path, SOURCE_DIST, @@ -17,11 +19,10 @@ from distutils.errors import DistutilsError from setuptools.compat import (urllib2, httplib, StringIO, HTTPError, urlparse, urlunparse, unquote, splituser, url2pathname, name2codepoint, - unichr, urljoin, urlsplit, urlunsplit) + unichr, urljoin, urlsplit, urlunsplit, + ConfigParser) from setuptools.compat import filterfalse from fnmatch import translate -from setuptools.py24compat import hashlib -from setuptools.py24compat import wraps from setuptools.py26compat import strip_fragment from setuptools.py27compat import get_all_headers @@ -907,8 +908,13 @@ def _encode_auth(auth): """ A function compatible with Python 2.3-3.3 that will encode auth from a URL suitable for an HTTP header. - >>> _encode_auth('username%3Apassword') - u'dXNlcm5hbWU6cGFzc3dvcmQ=' + >>> str(_encode_auth('username%3Apassword')) + 'dXNlcm5hbWU6cGFzc3dvcmQ=' + + Long auth strings should not cause a newline to be inserted. + >>> long_auth = 'username:' + 'password'*10 + >>> chr(10) in str(_encode_auth(long_auth)) + False """ auth_s = unquote(auth) # convert to bytes @@ -918,7 +924,61 @@ def _encode_auth(auth): # convert back to a string encoded = encoded_bytes.decode() # strip the trailing carriage return - return encoded.rstrip() + return encoded.replace('\n','') + +class Credential(object): + """ + A username/password pair. Use like a namedtuple. + """ + def __init__(self, username, password): + self.username = username + self.password = password + + def __iter__(self): + yield self.username + yield self.password + + def __str__(self): + return '%(username)s:%(password)s' % vars(self) + +class PyPIConfig(ConfigParser.ConfigParser): + + def __init__(self): + """ + Load from ~/.pypirc + """ + defaults = dict.fromkeys(['username', 'password', 'repository'], '') + ConfigParser.ConfigParser.__init__(self, defaults) + + rc = os.path.join(os.path.expanduser('~'), '.pypirc') + if os.path.exists(rc): + self.read(rc) + + @property + def creds_by_repository(self): + sections_with_repositories = [ + section for section in self.sections() + if self.get(section, 'repository').strip() + ] + + return dict(map(self._get_repo_cred, sections_with_repositories)) + + def _get_repo_cred(self, section): + repo = self.get(section, 'repository').strip() + return repo, Credential( + self.get(section, 'username').strip(), + self.get(section, 'password').strip(), + ) + + def find_credential(self, url): + """ + If the URL indicated appears to be a repository defined in this + config, return the credential for that repository. + """ + for repository, cred in self.creds_by_repository.items(): + if url.startswith(repository): + return cred + def open_with_auth(url, opener=urllib2.urlopen): """Open a urllib2 request, handling HTTP authentication""" @@ -935,6 +995,13 @@ def open_with_auth(url, opener=urllib2.urlopen): else: auth = None + if not auth: + cred = PyPIConfig().find_credential(url) + if cred: + auth = str(cred) + info = cred.username, url + log.info('Authenticating as %s for %s (from .pypirc)' % info) + if auth: auth = "Basic " + _encode_auth(auth) new_url = urlunparse((scheme,host,path,params,query,frag)) @@ -972,7 +1039,7 @@ def local_open(url): files = [] for f in os.listdir(filename): if f=='index.html': - fp = open(os.path.join(filename,f),'rb') + fp = open(os.path.join(filename,f),'r') body = fp.read() fp.close() break @@ -986,5 +1053,5 @@ def local_open(url): else: status, message, body = 404, "Path not found", "Not found" - return HTTPError(url, status, message, - {'content-type':'text/html'}, StringIO(body)) + headers = {'content-type': 'text/html'} + return HTTPError(url, status, message, headers, StringIO(body)) diff --git a/awx/lib/site-packages/setuptools/py24compat.py b/awx/lib/site-packages/setuptools/py24compat.py deleted file mode 100644 index 40e9ae0f74..0000000000 --- a/awx/lib/site-packages/setuptools/py24compat.py +++ /dev/null @@ -1,17 +0,0 @@ -""" -Forward-compatibility support for Python 2.4 and earlier -""" - -# from jaraco.compat 1.2 -try: - from functools import wraps -except ImportError: - def wraps(func): - "Just return the function unwrapped" - return lambda x: x - - -try: - import hashlib -except ImportError: - from setuptools._backport import hashlib diff --git a/awx/lib/site-packages/setuptools/py31compat.py b/awx/lib/site-packages/setuptools/py31compat.py new file mode 100644 index 0000000000..dbb324b0e3 --- /dev/null +++ b/awx/lib/site-packages/setuptools/py31compat.py @@ -0,0 +1,11 @@ +__all__ = ['get_config_vars', 'get_path'] + +try: + # Python 2.7 or >=3.2 + from sysconfig import get_config_vars, get_path +except ImportError: + from distutils.sysconfig import get_config_vars, get_python_lib + def get_path(name): + if name not in ('platlib', 'purelib'): + raise ValueError("Name must be purelib or platlib") + return get_python_lib(name=='platlib') diff --git a/awx/lib/site-packages/setuptools/sandbox.py b/awx/lib/site-packages/setuptools/sandbox.py index 29fc07b8d9..042c595897 100644 --- a/awx/lib/site-packages/setuptools/sandbox.py +++ b/awx/lib/site-packages/setuptools/sandbox.py @@ -1,4 +1,13 @@ -import os, sys, tempfile, operator, pkg_resources +import os +import sys +import tempfile +import operator +import functools +import itertools +import re + +import pkg_resources + if os.name == "java": import org.python.modules.posix.PosixModule as _os else: @@ -11,40 +20,12 @@ _open = open from distutils.errors import DistutilsError from pkg_resources import working_set -from setuptools.compat import builtins, execfile, reduce +from setuptools.compat import builtins, execfile __all__ = [ "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", ] - - - - - - - - - - - - - - - - - - - - - - - - - - - - def run_setup(setup_script, args): """Run a distutils setup script, sandboxed in its directory""" old_dir = os.getcwd() @@ -93,7 +74,6 @@ def run_setup(setup_script, args): tempfile.tempdir = save_tmp - class AbstractSandbox: """Wrap 'os' module and 'open()' builtin for virtualizing setup scripts""" @@ -136,7 +116,6 @@ class AbstractSandbox: for name in ["rename", "link", "symlink"]: if hasattr(_os,name): locals()[name] = _mk_dual_path_wrapper(name) - def _mk_single_path_wrapper(name, original=None): original = original or getattr(_os,name) def wrap(self,path,*args,**kw): @@ -220,10 +199,19 @@ class DirectorySandbox(AbstractSandbox): "utime", "lchown", "chroot", "mkfifo", "mknod", "tempnam", ]) + _exception_patterns = [ + # Allow lib2to3 to attempt to save a pickled grammar object (#121) + '.*lib2to3.*\.pickle$', + ] + "exempt writing to paths that match the pattern" + def __init__(self, sandbox, exceptions=_EXCEPTIONS): self._sandbox = os.path.normcase(os.path.realpath(sandbox)) self._prefix = os.path.join(self._sandbox,'') - self._exceptions = [os.path.normcase(os.path.realpath(path)) for path in exceptions] + self._exceptions = [ + os.path.normcase(os.path.realpath(path)) + for path in exceptions + ] AbstractSandbox.__init__(self) def _violation(self, operation, *args, **kw): @@ -243,28 +231,38 @@ class DirectorySandbox(AbstractSandbox): def tmpnam(self): self._violation("tmpnam") - def _ok(self,path): + def _ok(self, path): active = self._active try: self._active = False realpath = os.path.normcase(os.path.realpath(path)) - if (self._exempted(realpath) or realpath == self._sandbox - or realpath.startswith(self._prefix)): - return True + return ( + self._exempted(realpath) + or realpath == self._sandbox + or realpath.startswith(self._prefix) + ) finally: self._active = active def _exempted(self, filepath): - exception_matches = map(filepath.startswith, self._exceptions) - return True in exception_matches + start_matches = ( + filepath.startswith(exception) + for exception in self._exceptions + ) + pattern_matches = ( + re.match(pattern, filepath) + for pattern in self._exception_patterns + ) + candidates = itertools.chain(start_matches, pattern_matches) + return any(candidates) - def _remap_input(self,operation,path,*args,**kw): + def _remap_input(self, operation, path, *args, **kw): """Called for path inputs""" if operation in self.write_ops and not self._ok(path): self._violation(operation, os.path.realpath(path), *args, **kw) return path - def _remap_pair(self,operation,src,dst,*args,**kw): + def _remap_pair(self, operation, src, dst, *args, **kw): """Called for path pairs like rename, link, and symlink operations""" if not self._ok(src) or not self._ok(dst): self._violation(operation, src, dst, *args, **kw) @@ -276,7 +274,7 @@ class DirectorySandbox(AbstractSandbox): self._violation("os.open", file, flags, mode, *args, **kw) return _os.open(file,flags,mode, *args, **kw) -WRITE_FLAGS = reduce( +WRITE_FLAGS = functools.reduce( operator.or_, [getattr(_os, a, 0) for a in "O_WRONLY O_RDWR O_APPEND O_CREAT O_TRUNC O_TEMPORARY".split()] ) diff --git a/awx/lib/site-packages/setuptools/ssl_support.py b/awx/lib/site-packages/setuptools/ssl_support.py index 346188f2f8..7b5f429f8f 100644 --- a/awx/lib/site-packages/setuptools/ssl_support.py +++ b/awx/lib/site-packages/setuptools/ssl_support.py @@ -1,4 +1,8 @@ -import sys, os, socket, atexit, re +import os +import socket +import atexit +import re + import pkg_resources from pkg_resources import ResolutionError, ExtractionError from setuptools.compat import urllib2 @@ -38,51 +42,6 @@ for what, where in ( is_available = ssl is not None and object not in (HTTPSHandler, HTTPSConnection) - - - -try: - from socket import create_connection -except ImportError: - from socket import error - _GLOBAL_DEFAULT_TIMEOUT = getattr(socket, '_GLOBAL_DEFAULT_TIMEOUT', object()) - def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT, - source_address=None): - """Connect to *address* and return the socket object. - - Convenience function. Connect to *address* (a 2-tuple ``(host, - port)``) and return the socket object. Passing the optional - *timeout* parameter will set the timeout on the socket instance - before attempting to connect. If no *timeout* is supplied, the - global default timeout setting returned by :func:`getdefaulttimeout` - is used. If *source_address* is set it must be a tuple of (host, port) - for the socket to bind as a source address before making the connection. - An host of '' or port 0 tells the OS to use the default. - """ - host, port = address - err = None - for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - sock = None - try: - sock = socket.socket(af, socktype, proto) - if timeout is not _GLOBAL_DEFAULT_TIMEOUT: - sock.settimeout(timeout) - if source_address: - sock.bind(source_address) - sock.connect(sa) - return sock - - except error: - err = True - if sock is not None: - sock.close() - if err: - raise - else: - raise error("getaddrinfo returns an empty list") - - try: from ssl import CertificateError, match_hostname except ImportError: @@ -191,28 +150,6 @@ if not match_hostname: "subjectAltName fields were found") - - - - - - - - - - - - - - - - - - - - - - class VerifyingHTTPSHandler(HTTPSHandler): """Simple verifying handler: no auth, subclasses, timeouts, etc.""" @@ -233,8 +170,8 @@ class VerifyingHTTPSConn(HTTPSConnection): self.ca_bundle = ca_bundle def connect(self): - sock = create_connection( - (self.host, self.port), getattr(self,'source_address',None) + sock = socket.create_connection( + (self.host, self.port), getattr(self, 'source_address', None) ) # Handle the socket if a (proxy) tunnel is present @@ -259,7 +196,6 @@ def opener_for(ca_bundle=None): ).open - _wincerts = None def get_win_certfile(): @@ -296,8 +232,3 @@ def find_ca_bundle(): return pkg_resources.resource_filename('certifi', 'cacert.pem') except (ImportError, ResolutionError, ExtractionError): return None - - - - - diff --git a/awx/lib/site-packages/setuptools/svn_utils.py b/awx/lib/site-packages/setuptools/svn_utils.py index 6ac31a2471..a9bdc5c334 100644 --- a/awx/lib/site-packages/setuptools/svn_utils.py +++ b/awx/lib/site-packages/setuptools/svn_utils.py @@ -5,9 +5,10 @@ from distutils import log import xml.dom.pulldom import shlex import locale +import codecs import unicodedata import warnings -from setuptools.compat import unicode, bytes +from setuptools.compat import unicode from xml.sax.saxutils import unescape try: @@ -37,7 +38,7 @@ def _run_command(args, stdout=_PIPE, stderr=_PIPE, encoding=None, stream=0): except OSError: return 1, '' - #doubled checked and + #doubled checked and data = decode_as_string(data, encoding) #communciate calls wait() @@ -72,28 +73,56 @@ def joinpath(prefix, *suffix): return os.path.join(*suffix) return os.path.join(prefix, *suffix) +def determine_console_encoding(): + try: + #try for the preferred encoding + encoding = locale.getpreferredencoding() + + #see if the locale.getdefaultlocale returns null + #some versions of python\platforms return US-ASCII + #when it cannot determine an encoding + if not encoding or encoding == "US-ASCII": + encoding = locale.getdefaultlocale()[1] + + if encoding: + codecs.lookup(encoding) # make sure a lookup error is not made + + except (locale.Error, LookupError): + encoding = None + + is_osx = sys.platform == "darwin" + if not encoding: + return ["US-ASCII", "utf-8"][is_osx] + elif encoding.startswith("mac-") and is_osx: + #certain versions of python would return mac-roman as default + #OSX as a left over of earlier mac versions. + return "utf-8" + else: + return encoding + +_console_encoding = determine_console_encoding() def decode_as_string(text, encoding=None): """ Decode the console or file output explicitly using getpreferredencoding. The text paraemeter should be a encoded string, if not no decode occurs - If no encoding is given, getpreferredencoding is used. If encoding is - specified, that is used instead. This would be needed for SVN --xml + If no encoding is given, getpreferredencoding is used. If encoding is + specified, that is used instead. This would be needed for SVN --xml output. Unicode is explicitly put in composed NFC form. - - --xml should be UTF-8 (SVN Issue 2938) the discussion on the Subversion + + --xml should be UTF-8 (SVN Issue 2938) the discussion on the Subversion DEV List from 2007 seems to indicate the same. """ - #text should be a byte string + #text should be a byte string if encoding is None: - encoding = locale.getpreferredencoding() + encoding = _console_encoding if not isinstance(text, unicode): text = text.decode(encoding) - + text = unicodedata.normalize('NFC', text) - + return text @@ -129,7 +158,7 @@ def parse_externals_xml(decoded_str, prefix=''): path = path[len(prefix)+1:] data = _get_target_property(node) - #data should be decoded already + #data should be decoded already for external in parse_external_prop(data): externals.append(joinpath(path, external)) @@ -219,7 +248,13 @@ class SvnInfo(object): def load(cls, dirname=''): normdir = os.path.normpath(dirname) code, data = _run_command(['svn', 'info', normdir]) - has_svn = os.path.isdir(os.path.join(normdir, '.svn')) + # Must check for some contents, as some use empty directories + # in testcases + svn_dir = os.path.join(normdir, '.svn') + has_svn = (os.path.isfile(os.path.join(svn_dir, 'entries')) or + os.path.isfile(os.path.join(svn_dir, 'dir-props')) or + os.path.isfile(os.path.join(svn_dir, 'dir-prop-base'))) + svn_version = tuple(cls.get_svn_version().split('.')) try: @@ -227,18 +262,18 @@ class SvnInfo(object): except ValueError: base_svn_version = tuple() - if has_svn and (code or not base_svn_version - or base_svn_version < (1, 3)): - log.warn('Fallback onto .svn parsing') + if not has_svn: + return SvnInfo(dirname) + + if code or not base_svn_version or base_svn_version < (1, 3): warnings.warn(("No SVN 1.3+ command found: falling back " "on pre 1.7 .svn parsing"), DeprecationWarning) return SvnFileInfo(dirname) - elif not has_svn: - return SvnInfo(dirname) - elif base_svn_version < (1, 5): + + if base_svn_version < (1, 5): return Svn13Info(dirname) - else: - return Svn15Info(dirname) + + return Svn15Info(dirname) def __init__(self, path=''): self.path = path diff --git a/awx/lib/site-packages/setuptools/tests/doctest.py b/awx/lib/site-packages/setuptools/tests/doctest.py index 35d588d074..47293c3c9c 100644 --- a/awx/lib/site-packages/setuptools/tests/doctest.py +++ b/awx/lib/site-packages/setuptools/tests/doctest.py @@ -109,7 +109,7 @@ import __future__ import sys, traceback, inspect, linecache, os, re, types import unittest, difflib, pdb, tempfile import warnings -from setuptools.compat import StringIO, execfile, exec_, func_code, im_func +from setuptools.compat import StringIO, execfile, func_code, im_func # Don't whine about the deprecated is_private function in this # module's tests. @@ -1250,7 +1250,7 @@ class DocTestRunner: # keyboard interrupts.) try: # Don't blink! This is where the user's code gets run. - exec_(compile(example.source, filename, "single", + exec(compile(example.source, filename, "single", compileflags, 1), test.globs) self.debugger.set_continue() # ==== Example Finished ==== exception = None diff --git a/awx/lib/site-packages/setuptools/tests/environment.py b/awx/lib/site-packages/setuptools/tests/environment.py index 7c754b8e8c..476d280ae2 100644 --- a/awx/lib/site-packages/setuptools/tests/environment.py +++ b/awx/lib/site-packages/setuptools/tests/environment.py @@ -5,6 +5,9 @@ import tempfile import unittest import shutil import stat +import unicodedata + +from subprocess import Popen as _Popen, PIPE as _PIPE def _extract(self, member, path=None, pwd=None): @@ -25,13 +28,14 @@ def _extract_from_zip(self, name, dest_path): finally: dest_file.close() + def _extract_member(self, member, targetpath, pwd): """for zipfile py2.5 borrowed from cpython""" # build the destination pathname, replacing # forward slashes to platform specific separators. # Strip trailing path separator, unless it represents the root. if (targetpath[-1:] in (os.path.sep, os.path.altsep) - and len(os.path.splitdrive(targetpath)[1]) > 1): + and len(os.path.splitdrive(targetpath)[1]) > 1): targetpath = targetpath[:-1] # don't include leading "/" from file name if present @@ -74,6 +78,9 @@ class ZippedEnvironment(unittest.TestCase): old_cwd = None def setUp(self): + if self.datafile is None or self.dataname is None: + return + if not os.path.isfile(self.datafile): self.old_cwd = None return @@ -94,6 +101,10 @@ class ZippedEnvironment(unittest.TestCase): os.chdir(os.path.join(self.temp_dir, self.dataname)) def tearDown(self): + #Assume setUp was never completed + if self.dataname is None or self.datafile is None: + return + try: if self.old_cwd: os.chdir(self.old_cwd) @@ -102,3 +113,53 @@ class ZippedEnvironment(unittest.TestCase): #sigh? pass + +def _which_dirs(cmd): + result = set() + for path in os.environ.get('PATH', '').split(os.pathsep): + filename = os.path.join(path, cmd) + if os.access(filename, os.X_OK): + result.add(path) + return result + + +def run_setup_py(cmd, pypath=None, path=None, + data_stream=0, env=None): + """ + Execution command for tests, separate from those used by the + code directly to prevent accidental behavior issues + """ + if env is None: + env = dict() + for envname in os.environ: + env[envname] = os.environ[envname] + + #override the python path if needed + if pypath is not None: + env["PYTHONPATH"] = pypath + + #overide the execution path if needed + if path is not None: + env["PATH"] = path + if not env.get("PATH", ""): + env["PATH"] = _which_dirs("tar").union(_which_dirs("gzip")) + env["PATH"] = os.pathsep.join(env["PATH"]) + + cmd = [sys.executable, "setup.py"] + list(cmd) + + #regarding the shell argument, see: http://bugs.python.org/issue8557 + try: + proc = _Popen(cmd, stdout=_PIPE, stderr=_PIPE, + shell=(sys.platform == 'win32'), env=env) + + data = proc.communicate()[data_stream] + except OSError: + return 1, '' + + #decode the console string if needed + if hasattr(data, "decode"): + data = data.decode() # should use the preffered encoding + data = unicodedata.normalize('NFC', data) + + #communciate calls wait() + return proc.returncode, data diff --git a/awx/lib/site-packages/setuptools/tests/test_easy_install.py b/awx/lib/site-packages/setuptools/tests/test_easy_install.py index 189e3d55df..a90ae23fc1 100644 --- a/awx/lib/site-packages/setuptools/tests/test_easy_install.py +++ b/awx/lib/site-packages/setuptools/tests/test_easy_install.py @@ -6,32 +6,22 @@ import shutil import tempfile import unittest import site -from setuptools.compat import StringIO, BytesIO, next -from setuptools.compat import urlparse +import contextlib import textwrap import tarfile +import logging import distutils.core from setuptools.compat import StringIO, BytesIO, next, urlparse from setuptools.sandbox import run_setup, SandboxViolation -from setuptools.command.easy_install import easy_install, fix_jython_executable, get_script_args, nt_quote_arg -from setuptools.command.easy_install import PthDistributions +from setuptools.command.easy_install import ( + easy_install, fix_jython_executable, get_script_args, nt_quote_arg) +from setuptools.command.easy_install import PthDistributions from setuptools.command import easy_install as easy_install_pkg from setuptools.dist import Distribution from pkg_resources import Distribution as PRDistribution import setuptools.tests.server -try: - # import multiprocessing solely for the purpose of testing its existence - __import__('multiprocessing') - import logging - _LOG = logging.getLogger('test_easy_install') - logging.basicConfig(level=logging.INFO, stream=sys.stderr) - _MULTIPROC = True -except ImportError: - _MULTIPROC = False - _LOG = None - class FakeDist(object): def get_entry_map(self, group): if group != 'console_scripts': @@ -140,31 +130,29 @@ class TestUserInstallTest(unittest.TestCase): f.close() self.old_cwd = os.getcwd() os.chdir(self.dir) - if sys.version >= "2.6": - self.old_has_site = easy_install_pkg.HAS_USER_SITE - self.old_file = easy_install_pkg.__file__ - self.old_base = site.USER_BASE - site.USER_BASE = tempfile.mkdtemp() - self.old_site = site.USER_SITE - site.USER_SITE = tempfile.mkdtemp() - easy_install_pkg.__file__ = site.USER_SITE + + self.old_enable_site = site.ENABLE_USER_SITE + self.old_file = easy_install_pkg.__file__ + self.old_base = site.USER_BASE + site.USER_BASE = tempfile.mkdtemp() + self.old_site = site.USER_SITE + site.USER_SITE = tempfile.mkdtemp() + easy_install_pkg.__file__ = site.USER_SITE def tearDown(self): os.chdir(self.old_cwd) shutil.rmtree(self.dir) - if sys.version >= "2.6": - shutil.rmtree(site.USER_BASE) - shutil.rmtree(site.USER_SITE) - site.USER_BASE = self.old_base - site.USER_SITE = self.old_site - easy_install_pkg.HAS_USER_SITE = self.old_has_site - easy_install_pkg.__file__ = self.old_file + + shutil.rmtree(site.USER_BASE) + shutil.rmtree(site.USER_SITE) + site.USER_BASE = self.old_base + site.USER_SITE = self.old_site + site.ENABLE_USER_SITE = self.old_enable_site + easy_install_pkg.__file__ = self.old_file def test_user_install_implied(self): - easy_install_pkg.HAS_USER_SITE = True # disabled sometimes + site.ENABLE_USER_SITE = True # disabled sometimes #XXX: replace with something meaningfull - if sys.version < "2.6": - return #SKIP dist = Distribution() dist.script_name = 'setup.py' cmd = easy_install(dist) @@ -173,15 +161,19 @@ class TestUserInstallTest(unittest.TestCase): self.assertTrue(cmd.user, 'user should be implied') def test_multiproc_atexit(self): - if not _MULTIPROC: + try: + __import__('multiprocessing') + except ImportError: + # skip the test if multiprocessing is not available return - _LOG.info('this should not break') + + log = logging.getLogger('test_easy_install') + logging.basicConfig(level=logging.INFO, stream=sys.stderr) + log.info('this should not break') def test_user_install_not_implied_without_usersite_enabled(self): - easy_install_pkg.HAS_USER_SITE = False # usually enabled + site.ENABLE_USER_SITE = False # usually enabled #XXX: replace with something meaningfull - if sys.version < "2.6": - return #SKIP dist = Distribution() dist.script_name = 'setup.py' cmd = easy_install(dist) @@ -246,7 +238,6 @@ class TestUserInstallTest(unittest.TestCase): test_pkg = os.path.join(self.dir, 'test_pkg') test_setup_py = os.path.join(test_pkg, 'setup.py') - test_setup_cfg = os.path.join(test_pkg, 'setup.cfg') os.mkdir(test_pkg) f = open(test_setup_py, 'w') @@ -273,9 +264,8 @@ class TestUserInstallTest(unittest.TestCase): sys.stderr = StringIO() try: try: - reset_setup_stop_context( - lambda: run_setup(test_setup_py, ['install']) - ) + with reset_setup_stop_context(): + run_setup(test_setup_py, ['install']) except SandboxViolation: self.fail('Installation caused SandboxViolation') finally: @@ -300,45 +290,33 @@ class TestSetupRequires(unittest.TestCase): # Some platforms (Jython) don't find a port to which to bind, # so skip this test for them. return - - # I realize this is all-but-impossible to read, because it was - # ported from some well-factored, safe code using 'with'. If you - # need to maintain this code, consider making the changes in - # the parent revision (of this comment) and then port the changes - # back for Python 2.4 (or deprecate Python 2.4). - - def install(dist_file): - def install_at(temp_install_dir): - def install_env(): + # create an sdist that has a build-time dependency. + with TestSetupRequires.create_sdist() as dist_file: + with tempdir_context() as temp_install_dir: + with environment_context(PYTHONPATH=temp_install_dir): ei_params = ['--index-url', p_index.url, '--allow-hosts', p_index_loc, '--exclude-scripts', '--install-dir', temp_install_dir, dist_file] - def install_clean_reset(): - def install_clean_argv(): + with reset_setup_stop_context(): + with argv_context(['easy_install']): # attempt to install the dist. It should fail because # it doesn't exist. self.assertRaises(SystemExit, easy_install_pkg.main, ei_params) - argv_context(install_clean_argv, ['easy_install']) - reset_setup_stop_context(install_clean_reset) - environment_context(install_env, PYTHONPATH=temp_install_dir) - tempdir_context(install_at) - - # create an sdist that has a build-time dependency. - self.create_sdist(install) - # there should have been two or three requests to the server # (three happens on Python 3.3a) self.assertTrue(2 <= len(p_index.requests) <= 3) self.assertEqual(p_index.requests[0].path, '/does-not-exist/') - def create_sdist(self, installer): + @staticmethod + @contextlib.contextmanager + def create_sdist(): """ - Create an sdist with a setup_requires dependency (of something that - doesn't exist) and invoke installer on it. + Return an sdist with a setup_requires dependency (of something that + doesn't exist) """ - def build_sdist(dir): + with tempdir_context() as dir: dist_path = os.path.join(dir, 'setuptools-test-fetcher-1.0.tar.gz') make_trivial_sdist( dist_path, @@ -350,8 +328,7 @@ class TestSetupRequires(unittest.TestCase): setup_requires = ['does-not-exist'], ) """).lstrip()) - installer(dist_path) - tempdir_context(build_sdist) + yield dist_path def make_trivial_sdist(dist_path, setup_py): @@ -374,44 +351,37 @@ def make_trivial_sdist(dist_path, setup_py): dist.close() -def tempdir_context(f, cd=lambda dir:None): - """ - Invoke f in the context - """ +@contextlib.contextmanager +def tempdir_context(cd=lambda dir:None): temp_dir = tempfile.mkdtemp() orig_dir = os.getcwd() try: cd(temp_dir) - f(temp_dir) + yield temp_dir finally: cd(orig_dir) shutil.rmtree(temp_dir) -def environment_context(f, **updates): - """ - Invoke f in the context - """ +@contextlib.contextmanager +def environment_context(**updates): old_env = os.environ.copy() os.environ.update(updates) try: - f() + yield finally: for key in updates: del os.environ[key] os.environ.update(old_env) -def argv_context(f, repl): - """ - Invoke f in the context - """ +@contextlib.contextmanager +def argv_context(repl): old_argv = sys.argv[:] sys.argv[:] = repl - try: - f() - finally: - sys.argv[:] = old_argv + yield + sys.argv[:] = old_argv -def reset_setup_stop_context(f): +@contextlib.contextmanager +def reset_setup_stop_context(): """ When the setuptools tests are run using setup.py test, and then one wants to invoke another setup() command (such as easy_install) @@ -420,7 +390,5 @@ def reset_setup_stop_context(f): """ setup_stop_after = distutils.core._setup_stop_after distutils.core._setup_stop_after = None - try: - f() - finally: - distutils.core._setup_stop_after = setup_stop_after + yield + distutils.core._setup_stop_after = setup_stop_after diff --git a/awx/lib/site-packages/setuptools/tests/test_egg_info.py b/awx/lib/site-packages/setuptools/tests/test_egg_info.py index 7abafd7165..278543662f 100644 --- a/awx/lib/site-packages/setuptools/tests/test_egg_info.py +++ b/awx/lib/site-packages/setuptools/tests/test_egg_info.py @@ -1,3 +1,4 @@ + import os import sys import tempfile @@ -5,12 +6,16 @@ import shutil import unittest import pkg_resources +import warnings from setuptools.command import egg_info from setuptools import svn_utils +from setuptools.tests import environment, test_svn +from setuptools.tests.py26compat import skipIf ENTRIES_V10 = pkg_resources.resource_string(__name__, 'entries-v10') "An entries file generated with svn 1.6.17 against the legacy Setuptools repo" + class TestEggInfo(unittest.TestCase): def setUp(self): @@ -29,7 +34,8 @@ class TestEggInfo(unittest.TestCase): entries_f = open(fn, 'wb') entries_f.write(entries) entries_f.close() - + + @skipIf(not test_svn._svn_check, "No SVN to text, in the first place") def test_version_10_format(self): """ """ @@ -37,7 +43,7 @@ class TestEggInfo(unittest.TestCase): #to ensure I return using svnversion what would had been returned version_str = svn_utils.SvnInfo.get_svn_version() version = [int(x) for x in version_str.split('.')[:2]] - if version != [1,6]: + if version != [1, 6]: if hasattr(self, 'skipTest'): self.skipTest('') else: @@ -56,19 +62,112 @@ class TestEggInfo(unittest.TestCase): if env.lower() == 'path': path_variable = env - if path_variable is None: - self.skipTest('Cannot figure out how to modify path') - - old_path = os.environ[path_variable] - os.environ[path_variable] = '' + if path_variable: + old_path = os.environ[path_variable] + os.environ[path_variable] = '' + #catch_warnings not available until py26 + warning_filters = warnings.filters + warnings.filters = warning_filters[:] try: + warnings.simplefilter("ignore", DeprecationWarning) self._write_entries(ENTRIES_V10) rev = egg_info.egg_info.get_svn_revision() finally: - os.environ[path_variable] = old_path + #restore the warning filters + warnings.filters = warning_filters + #restore the os path + if path_variable: + os.environ[path_variable] = old_path self.assertEqual(rev, '89000') +DUMMY_SOURCE_TXT = """CHANGES.txt +CONTRIBUTORS.txt +HISTORY.txt +LICENSE +MANIFEST.in +README.txt +setup.py +dummy/__init__.py +dummy/test.txt +dummy.egg-info/PKG-INFO +dummy.egg-info/SOURCES.txt +dummy.egg-info/dependency_links.txt +dummy.egg-info/top_level.txt""" + + +class TestSvnDummy(environment.ZippedEnvironment): + + def setUp(self): + version = svn_utils.SvnInfo.get_svn_version() + if not version: # None or Empty + return None + + self.base_version = tuple([int(x) for x in version.split('.')][:2]) + + if not self.base_version: + raise ValueError('No SVN tools installed') + elif self.base_version < (1, 3): + raise ValueError('Insufficient SVN Version %s' % version) + elif self.base_version >= (1, 9): + #trying the latest version + self.base_version = (1, 8) + + self.dataname = "dummy%i%i" % self.base_version + self.datafile = os.path.join('setuptools', 'tests', + 'svn_data', self.dataname + ".zip") + super(TestSvnDummy, self).setUp() + + @skipIf(not test_svn._svn_check, "No SVN to text, in the first place") + def test_sources(self): + code, data = environment.run_setup_py(["sdist"], + pypath=self.old_cwd, + data_stream=1) + if code: + raise AssertionError(data) + + sources = os.path.join('dummy.egg-info', 'SOURCES.txt') + infile = open(sources, 'r') + try: + read_contents = infile.read() + finally: + infile.close() + del infile + + self.assertEqual(DUMMY_SOURCE_TXT, read_contents) + + return data + + +class TestSvnDummyLegacy(environment.ZippedEnvironment): + + def setUp(self): + self.base_version = (1, 6) + self.dataname = "dummy%i%i" % self.base_version + self.datafile = os.path.join('setuptools', 'tests', + 'svn_data', self.dataname + ".zip") + super(TestSvnDummyLegacy, self).setUp() + + def test_sources(self): + code, data = environment.run_setup_py(["sdist"], + pypath=self.old_cwd, + path="", + data_stream=1) + if code: + raise AssertionError(data) + + sources = os.path.join('dummy.egg-info', 'SOURCES.txt') + infile = open(sources, 'r') + try: + read_contents = infile.read() + finally: + infile.close() + del infile + + self.assertEqual(DUMMY_SOURCE_TXT, read_contents) + + return data + def test_suite(): return unittest.defaultTestLoader.loadTestsFromName(__name__) diff --git a/awx/lib/site-packages/setuptools/tests/test_packageindex.py b/awx/lib/site-packages/setuptools/tests/test_packageindex.py index 08969b7e8c..664566a36c 100644 --- a/awx/lib/site-packages/setuptools/tests/test_packageindex.py +++ b/awx/lib/site-packages/setuptools/tests/test_packageindex.py @@ -1,9 +1,10 @@ """Package Index Tests """ import sys +import os import unittest import pkg_resources -from setuptools.compat import urllib2, httplib, HTTPError, unicode +from setuptools.compat import urllib2, httplib, HTTPError, unicode, pathname2url import distutils.errors import setuptools.package_index from setuptools.tests.server import IndexServer @@ -151,6 +152,21 @@ class TestPackageIndex(unittest.TestCase): self.assertEqual(url, 'https://example.com/bar') self.assertEqual(rev, '2995') + def test_local_index(self): + """ + local_open should be able to read an index from the file system. + """ + f = open('index.html', 'w') + f.write('
content
') + f.close() + try: + url = 'file:' + pathname2url(os.getcwd()) + '/' + res = setuptools.package_index.local_open(url) + finally: + os.remove('index.html') + assert 'content' in res.read() + + class TestContentCheckers(unittest.TestCase): def test_md5(self): diff --git a/awx/lib/site-packages/setuptools/tests/test_sdist.py b/awx/lib/site-packages/setuptools/tests/test_sdist.py index 716893dcbe..71d10757bc 100644 --- a/awx/lib/site-packages/setuptools/tests/test_sdist.py +++ b/awx/lib/site-packages/setuptools/tests/test_sdist.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """sdist tests""" -from __future__ import with_statement import locale import os import shutil @@ -10,7 +9,8 @@ import tempfile import unittest import unicodedata import re -from setuptools.tests import environment +from setuptools.tests import environment, test_svn +from setuptools.tests.py26compat import skipIf from setuptools.compat import StringIO, unicode from setuptools.tests.py26compat import skipIf @@ -401,104 +401,100 @@ class TestSdistTest(unittest.TestCase): self.assertTrue(filename in cmd.filelist.files) -def soruce_test(self): - code, data = svn_utils._run_command([sys.executable, "setup.py", "egg_info"], stream=1) - - if code: - raise AssertionError(data) - - sources = os.path.join('dummy.egg-info', 'SOURCES.txt') - contents = """CHANGES.txt -CONTRIBUTORS.txt -HISTORY.txt -LICENSE -MANIFEST.in -README.txt -setup.py -dummy/__init__.py -dummy/test.txt -dummy.egg-info/PKG-INFO -dummy.egg-info/SOURCES.txt -dummy.egg-info/dependency_links.txt -dummy.egg-info/top_level.txt""" - - with open(sources, 'r') as infile: - read_contents = infile.read() - - self.assertEqual(contents, read_contents) - - -class TestSvnDummy(environment.ZippedEnvironment): +class TestDummyOutput(environment.ZippedEnvironment): def setUp(self): - version = svn_utils.SvnInfo.get_svn_version() - self.base_version = tuple([int(x) for x in version.split('.')][:2]) - - if not self.base_version: - raise ValueError('No SVN tools installed') - elif self.base_version < (1,3): - raise ValueError('Insufficient SVN Version %s' % version) - elif self.base_version >= (1,9): - #trying the latest version - self.base_version = (1,8) - - self.dataname = "dummy%i%i" % self.base_version self.datafile = os.path.join('setuptools', 'tests', - 'svn_data', self.dataname + ".zip") - super(TestSvnDummy, self).setUp() - - def test_sources(self): - soruce_test(self) + 'svn_data', "dummy.zip") + self.dataname = "dummy" + super(TestDummyOutput, self).setUp() + def _run(self): + code, data = environment.run_setup_py(["sdist"], + pypath=self.old_cwd, + data_stream=0) + if code: + info = "DIR: " + os.path.abspath('.') + info += "\n SDIST RETURNED: %i\n\n" % code + info += data + raise AssertionError(info) -class TestSvnDummyLegacy(environment.ZippedEnvironment): + datalines = data.splitlines() - def setUp(self): - self.base_version = (1,6) - self.path_variable = None - for env in os.environ: - if env.lower() == 'path': - self.path_variable = env - self.old_path = os.environ[self.path_variable] - os.environ[self.path_variable] = '' + possible = ( + "running sdist", + "running egg_info", + "creating dummy\.egg-info", + "writing dummy\.egg-info", + "writing top-level names to dummy\.egg-info", + "writing dependency_links to dummy\.egg-info", + "writing manifest file 'dummy\.egg-info", + "reading manifest file 'dummy\.egg-info", + "reading manifest template 'MANIFEST\.in'", + "writing manifest file 'dummy\.egg-info", + "creating dummy-0.1.1", + "making hard links in dummy-0\.1\.1", + "copying files to dummy-0\.1\.1", + "copying \S+ -> dummy-0\.1\.1", + "copying dummy", + "copying dummy\.egg-info", + "hard linking \S+ -> dummy-0\.1\.1", + "hard linking dummy", + "hard linking dummy\.egg-info", + "Writing dummy-0\.1\.1", + "creating dist", + "creating 'dist", + "Creating tar archive", + "running check", + "adding 'dummy-0\.1\.1", + "tar .+ dist/dummy-0\.1\.1\.tar dummy-0\.1\.1", + "gzip .+ dist/dummy-0\.1\.1\.tar", + "removing 'dummy-0\.1\.1' \\(and everything under it\\)", + ) - if self.path_variable is None: - self.skipTest('Cannot figure out how to modify path') + print(" DIR: " + os.path.abspath('.')) + for line in datalines: + found = False + for pattern in possible: + if re.match(pattern, line): + print(" READ: " + line) + found = True + break + if not found: + raise AssertionError("Unexpexected: %s\n-in-\n%s" + % (line, data)) - self.dataname = "dummy%i%i" % self.base_version - self.datafile = os.path.join('setuptools', 'tests', - 'svn_data', self.dataname + ".zip") - super(TestSvnDummyLegacy, self).setUp() - - def tearDown(self): - os.environ[self.path_variable] = self.old_path - super(TestSvnDummyLegacy, self).tearDown() + return data def test_sources(self): - soruce_test(self) + self._run() class TestSvn(environment.ZippedEnvironment): def setUp(self): version = svn_utils.SvnInfo.get_svn_version() + if not version: # None or Empty + return + self.base_version = tuple([int(x) for x in version.split('.')][:2]) if not self.base_version: raise ValueError('No SVN tools installed') - elif self.base_version < (1,3): + elif self.base_version < (1, 3): raise ValueError('Insufficient SVN Version %s' % version) - elif self.base_version >= (1,9): + elif self.base_version >= (1, 9): #trying the latest version - self.base_version = (1,8) + self.base_version = (1, 8) self.dataname = "svn%i%i_example" % self.base_version self.datafile = os.path.join('setuptools', 'tests', 'svn_data', self.dataname + ".zip") super(TestSvn, self).setUp() + @skipIf(not test_svn._svn_check, "No SVN to text, in the first place") def test_walksvn(self): - if self.base_version >= (1,6): + if self.base_version >= (1, 6): folder2 = 'third party2' folder3 = 'third party3' else: @@ -520,7 +516,7 @@ class TestSvn(environment.ZippedEnvironment): os.path.join('folder', folder2, 'Changes.txt'), os.path.join('folder', folder2, 'MD5SUMS'), os.path.join('folder', folder2, 'WatashiNiYomimasu.txt'), - os.path.join( 'folder', folder3, 'Changes.txt'), + os.path.join('folder', folder3, 'Changes.txt'), os.path.join('folder', folder3, 'fin'), os.path.join('folder', folder3, 'MD5SUMS'), os.path.join('folder', folder3, 'oops'), @@ -529,11 +525,11 @@ class TestSvn(environment.ZippedEnvironment): os.path.join('folder', 'third_party', 'WatashiNiYomimasu.txt'), os.path.join('folder', 'lalala.txt'), os.path.join('folder', 'quest.txt'), - #The example will have a deleted file (or should) but shouldn't return it - ]) + # The example will have a deleted file + # (or should) but shouldn't return it + ]) self.assertEqual(set(x for x in walk_revctrl()), expected) def test_suite(): return unittest.defaultTestLoader.loadTestsFromName(__name__) - diff --git a/awx/lib/site-packages/setuptools/tests/test_svn.py b/awx/lib/site-packages/setuptools/tests/test_svn.py index 5418b9a43e..afee32b6d2 100644 --- a/awx/lib/site-packages/setuptools/tests/test_svn.py +++ b/awx/lib/site-packages/setuptools/tests/test_svn.py @@ -3,12 +3,25 @@ import os +import sys import unittest import codecs +import subprocess from setuptools.tests import environment from setuptools.compat import unicode, unichr from setuptools import svn_utils +from setuptools.tests.py26compat import skipIf + + +def _do_svn_check(): + try: + subprocess.check_call(["svn", "--version"], + shell=(sys.platform == 'win32')) + return True + except (OSError, subprocess.CalledProcessError): + return False +_svn_check = _do_svn_check() class TestSvnVersion(unittest.TestCase): @@ -20,7 +33,10 @@ class TestSvnVersion(unittest.TestCase): path_variable = env if path_variable is None: - self.skipTest('Cannot figure out how to modify path') + try: + self.skipTest('Cannot figure out how to modify path') + except AttributeError: # PY26 doesn't have this + return old_path = os.environ[path_variable] os.environ[path_variable] = '' @@ -30,6 +46,7 @@ class TestSvnVersion(unittest.TestCase): finally: os.environ[path_variable] = old_path + @skipIf(not _svn_check, "No SVN to text, in the first place") def test_svn_should_exist(self): version = svn_utils.SvnInfo.get_svn_version() self.assertNotEqual(version, '') @@ -169,11 +186,14 @@ class TestSvn(environment.ZippedEnvironment): def setUp(self): version = svn_utils.SvnInfo.get_svn_version() + if not version: # empty or null + self.dataname = None + self.datafile = None + return + self.base_version = tuple([int(x) for x in version.split('.')[:2]]) - if not self.base_version: - raise ValueError('No SVN tools installed') - elif self.base_version < (1,3): + if self.base_version < (1,3): raise ValueError('Insufficient SVN Version %s' % version) elif self.base_version >= (1,9): #trying the latest version @@ -184,10 +204,12 @@ class TestSvn(environment.ZippedEnvironment): 'svn_data', self.dataname + ".zip") super(TestSvn, self).setUp() + @skipIf(not _svn_check, "No SVN to text, in the first place") def test_revision(self): rev = svn_utils.SvnInfo.load('.').get_revision() self.assertEqual(rev, 6) + @skipIf(not _svn_check, "No SVN to text, in the first place") def test_entries(self): expected = set([ (os.path.join('a file'), 'file'), @@ -200,6 +222,7 @@ class TestSvn(environment.ZippedEnvironment): info = svn_utils.SvnInfo.load('.') self.assertEqual(set(x for x in info.entries), expected) + @skipIf(not _svn_check, "No SVN to text, in the first place") def test_externals(self): if self.base_version >= (1,6): folder2 = 'third party2' diff --git a/awx/lib/site-packages/setuptools/version.py b/awx/lib/site-packages/setuptools/version.py index e39833240e..668c3446ee 100644 --- a/awx/lib/site-packages/setuptools/version.py +++ b/awx/lib/site-packages/setuptools/version.py @@ -1 +1 @@ -__version__ = '1.3.2' +__version__ = '2.0.2' diff --git a/awx/lib/site-packages/south/__init__.py b/awx/lib/site-packages/south/__init__.py index 7b8df0dff6..86642c6b4f 100644 --- a/awx/lib/site-packages/south/__init__.py +++ b/awx/lib/site-packages/south/__init__.py @@ -2,7 +2,7 @@ South - Useable migrations for Django apps """ -__version__ = "0.8.3" +__version__ = "0.8.4" __authors__ = [ "Andrew Godwin ", "Andy McCurdy " diff --git a/awx/lib/site-packages/south/hacks/django_1_0.py b/awx/lib/site-packages/south/hacks/django_1_0.py index 2f364a02fd..e4a60c66a9 100644 --- a/awx/lib/site-packages/south/hacks/django_1_0.py +++ b/awx/lib/site-packages/south/hacks/django_1_0.py @@ -19,7 +19,7 @@ class SkipFlushCommand(FlushCommand): class Hacks: - def set_installed_apps(self, apps, preserve_models=False): + def set_installed_apps(self, apps): """ Sets Django's INSTALLED_APPS setting to be effectively the list passed in. """ @@ -36,7 +36,7 @@ class Hacks: apps, settings.INSTALLED_APPS, ) - self._redo_app_cache(preserve_models=preserve_models) + self._redo_app_cache() def reset_installed_apps(self): @@ -47,7 +47,7 @@ class Hacks: self._redo_app_cache() - def _redo_app_cache(self, preserve_models=False): + def _redo_app_cache(self): """ Used to repopulate AppCache after fiddling with INSTALLED_APPS. """ @@ -55,8 +55,7 @@ class Hacks: cache.handled = set() if django.VERSION >= (1, 6) else {} cache.postponed = [] cache.app_store = SortedDict() - if not preserve_models: - cache.app_models = SortedDict() + cache.app_models = SortedDict() cache.app_errors = {} cache._populate() diff --git a/awx/lib/site-packages/south/migration/migrators.py b/awx/lib/site-packages/south/migration/migrators.py index 9338ef0118..f405a15046 100644 --- a/awx/lib/site-packages/south/migration/migrators.py +++ b/awx/lib/site-packages/south/migration/migrators.py @@ -9,7 +9,7 @@ import traceback from django.core.management import call_command from django.core.management.commands import loaddata from django.db import models -from django.conf import settings +from django import VERSION as DJANGO_VERSION import south.db from south import exceptions @@ -17,7 +17,6 @@ from south.db import DEFAULT_DB_ALIAS from south.models import MigrationHistory from south.signals import ran_migration from south.utils.py3 import StringIO -from south.hacks import hacks class Migrator(object): @@ -217,13 +216,38 @@ class LoadInitialDataMigrator(MigratorWrapper): # Load initial data, if we ended up at target if self.verbosity: print(" - Loading initial data for %s." % target.app_label()) + if DJANGO_VERSION < (1, 6): + self.pre_1_6(target, db) + else: + self.post_1_6(target, db) + + def pre_1_6(self, target, db): # Override Django's get_apps call temporarily to only load from the # current app - hacks.set_installed_apps([ia for ia in settings.INSTALLED_APPS if ia.split(".")[-1] == target.app_label()], preserve_models=True) + old_get_apps = models.get_apps + new_get_apps = lambda: [models.get_app(target.app_label())] + models.get_apps = new_get_apps + loaddata.get_apps = new_get_apps try: call_command('loaddata', 'initial_data', verbosity=self.verbosity, database=db) finally: - hacks.reset_installed_apps() + models.get_apps = old_get_apps + loaddata.get_apps = old_get_apps + + def post_1_6(self, target, db): + import django.db.models.loading + ## build a new 'AppCache' object with just the app we care about. + old_cache = django.db.models.loading.cache + new_cache = django.db.models.loading.AppCache() + new_cache.get_apps = lambda: [new_cache.get_app(target.app_label())] + + ## monkeypatch + django.db.models.loading.cache = new_cache + try: + call_command('loaddata', 'initial_data', verbosity=self.verbosity, database=db) + finally: + ## unmonkeypatch + django.db.models.loading.cache = old_cache def migrate_many(self, target, migrations, database): migrator = self._migrator diff --git a/awx/lib/site-packages/taggit/__init__.py b/awx/lib/site-packages/taggit/__init__.py index ca04bbe69d..c2b916e78e 100644 --- a/awx/lib/site-packages/taggit/__init__.py +++ b/awx/lib/site-packages/taggit/__init__.py @@ -1 +1 @@ -VERSION = (0, 10, 0) +VERSION = (0, 12, 0, 'alpha', 0) diff --git a/awx/lib/site-packages/taggit/managers.py b/awx/lib/site-packages/taggit/managers.py index 56fec6064c..4c23e7e31b 100644 --- a/awx/lib/site-packages/taggit/managers.py +++ b/awx/lib/site-packages/taggit/managers.py @@ -1,9 +1,10 @@ from __future__ import unicode_literals +from operator import attrgetter from django import VERSION from django.contrib.contenttypes.generic import GenericRelation from django.contrib.contenttypes.models import ContentType -from django.db import models +from django.db import models, router from django.db.models.fields import Field from django.db.models.fields.related import ManyToManyRel, RelatedField, add_lazy_relation from django.db.models.related import RelatedObject @@ -29,8 +30,8 @@ def _model_name(model): class TaggableRel(ManyToManyRel): - def __init__(self, field): - self.related_name = None + def __init__(self, field, related_name): + self.related_name = related_name self.limit_choices_to = {} self.symmetrical = True self.multiple = True @@ -56,30 +57,36 @@ class ExtraJoinRestriction(object): def as_sql(self, qn, connection): if len(self.content_types) == 1: extra_where = "%s.%s = %%s" % (qn(self.alias), qn(self.col)) - params = [self.content_types[0]] else: extra_where = "%s.%s IN (%s)" % (qn(self.alias), qn(self.col), ','.join(['%s'] * len(self.content_types))) - params = self.content_types - return extra_where, params + return extra_where, self.content_types def relabel_aliases(self, change_map): self.alias = change_map.get(self.alias, self.alias) + def clone(self): + return self.__class__(self.alias, self.col, self.content_types[:]) + class TaggableManager(RelatedField, Field): - def __init__(self, verbose_name=_("Tags"), - help_text=_("A comma-separated list of tags."), through=None, blank=False): - Field.__init__(self, verbose_name=verbose_name, help_text=help_text, blank=blank) + _related_name_counter = 0 + + def __init__(self, verbose_name=_("Tags"), help_text=_("A comma-separated list of tags."), + through=None, blank=False, related_name=None): + Field.__init__(self, verbose_name=verbose_name, help_text=help_text, blank=blank, null=True, serialize=False) self.through = through or TaggedItem - self.rel = TaggableRel(self) + self.rel = TaggableRel(self, related_name) def __get__(self, instance, model): if instance is not None and instance.pk is None: raise ValueError("%s objects need to have a primary key value " "before you can access their tags." % model.__name__) manager = _TaggableManager( - through=self.through, model=model, instance=instance + through=self.through, + model=model, + instance=instance, + prefetch_cache_name = self.name ) return manager @@ -89,6 +96,7 @@ class TaggableManager(RelatedField, Field): else: self.set_attributes_from_name(name) self.model = cls + cls._meta.add_field(self) setattr(cls, name, self) if not cls._meta.abstract: @@ -102,6 +110,7 @@ class TaggableManager(RelatedField, Field): else: self.post_through_setup(cls) + def __lt__(self, other): """ Required contribute_to_class as Django uses bisect @@ -119,7 +128,12 @@ class TaggableManager(RelatedField, Field): self.related = RelatedObject(self.through, cls, self) if self.use_gfk: tagged_items = GenericRelation(self.through) - tagged_items.contribute_to_class(cls, "tagged_items") + tagged_items.contribute_to_class(cls, 'tagged_items') + + for rel in cls._meta.local_many_to_many: + if isinstance(rel, TaggableManager) and rel.use_gfk and rel != self: + raise ValueError('You can only have one TaggableManager per model' + ' using generic relations.') def save_form_data(self, instance, value): getattr(instance, self.name).set(*value) @@ -194,52 +208,6 @@ class TaggableManager(RelatedField, Field): params = content_type_ids return extra_where, params - def _get_mm_case_path_info(self, direct=False): - pathinfos = [] - linkfield1 = self.through._meta.get_field_by_name('content_object')[0] - linkfield2 = self.through._meta.get_field_by_name(self.m2m_reverse_field_name())[0] - if direct: - join1infos, _, _, _ = linkfield1.get_reverse_path_info() - join2infos, opts, target, final = linkfield2.get_path_info() - else: - join1infos, _, _, _ = linkfield2.get_reverse_path_info() - join2infos, opts, target, final = linkfield1.get_path_info() - pathinfos.extend(join1infos) - pathinfos.extend(join2infos) - return pathinfos, opts, target, final - - def _get_gfk_case_path_info(self, direct=False): - pathinfos = [] - from_field = self.model._meta.pk - opts = self.through._meta - object_id_field = opts.get_field_by_name('object_id')[0] - linkfield = self.through._meta.get_field_by_name(self.m2m_reverse_field_name())[0] - if direct: - join1infos = [PathInfo(from_field, object_id_field, self.model._meta, opts, self, True, False)] - join2infos, opts, target, final = linkfield.get_path_info() - else: - join1infos, _, _, _ = linkfield.get_reverse_path_info() - join2infos = [PathInfo(object_id_field, from_field, opts, self.model._meta, self, True, False)] - target = from_field - final = self - opts = self.model._meta - - pathinfos.extend(join1infos) - pathinfos.extend(join2infos) - return pathinfos, opts, target, final - - def get_path_info(self): - if self.use_gfk: - return self._get_gfk_case_path_info(direct=True) - else: - return self._get_mm_case_path_info(direct=True) - - def get_reverse_path_info(self): - if self.use_gfk: - return self._get_gfk_case_path_info(direct=False) - else: - return self._get_mm_case_path_info(direct=False) - # This and all the methods till the end of class are only used in django >= 1.6 def _get_mm_case_path_info(self, direct=False): pathinfos = [] @@ -309,13 +277,51 @@ class TaggableManager(RelatedField, Field): class _TaggableManager(models.Manager): - def __init__(self, through, model, instance): + def __init__(self, through, model, instance, prefetch_cache_name): self.through = through self.model = model self.instance = instance + self.prefetch_cache_name = prefetch_cache_name + self._db = None + + def is_cached(self, instance): + return self.prefetch_cache_name in instance._prefetched_objects_cache def get_query_set(self): - return self.through.tags_for(self.model, self.instance) + try: + return self.instance._prefetched_objects_cache[self.prefetch_cache_name] + except (AttributeError, KeyError): + return self.through.tags_for(self.model, self.instance) + + def get_prefetch_query_set(self, instances, queryset = None): + if queryset is not None: + raise ValueError("Custom queryset can't be used for this lookup.") + + instance = instances[0] + from django.db import connections + db = self._db or router.db_for_read(instance.__class__, instance=instance) + + fieldname = ('object_id' if issubclass(self.through, GenericTaggedItemBase) + else 'content_object') + fk = self.through._meta.get_field(fieldname) + query = { + '%s__%s__in' % (self.through.tag_relname(), fk.name) : + set(obj._get_pk_val() for obj in instances) + } + join_table = self.through._meta.db_table + source_col = fk.column + connection = connections[db] + qn = connection.ops.quote_name + qs = self.get_query_set().using(db)._next_is_sticky().filter(**query).extra( + select = { + '_prefetch_related_val' : '%s.%s' % (qn(join_table), qn(source_col)) + } + ) + return (qs, + attrgetter('_prefetch_related_val'), + attrgetter(instance._meta.pk.name), + False, + self.prefetch_cache_name) # Django 1.6 renamed this get_queryset = get_query_set diff --git a/awx/lib/site-packages/taggit/models.py b/awx/lib/site-packages/taggit/models.py index 0335757875..a76d404c41 100644 --- a/awx/lib/site-packages/taggit/models.py +++ b/awx/lib/site-packages/taggit/models.py @@ -1,6 +1,5 @@ from __future__ import unicode_literals -import django from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.generic import GenericForeignKey from django.db import models, IntegrityError, transaction diff --git a/awx/templates/rest_framework/base.html b/awx/templates/rest_framework/base.html index e4b2062885..8efef0bfbf 100644 --- a/awx/templates/rest_framework/base.html +++ b/awx/templates/rest_framework/base.html @@ -111,7 +111,9 @@
+ {% block description %} {{ description }} + {% endblock %}
{{ request.method }} {{ request.get_full_path }}
@@ -124,7 +126,7 @@
- {% if response.status_code != 403 %} + {% if display_edit_forms %} {% if post_form or raw_data_post_form %}
@@ -153,7 +155,7 @@ {% with form=raw_data_post_form %}
- {% include "rest_framework/form.html" %} + {% include "rest_framework/raw_data_form.html" %}
@@ -190,7 +192,7 @@ {% with form=raw_data_put_or_patch_form %}
- {% include "rest_framework/form.html" %} + {% include "rest_framework/raw_data_form.html" %}
{% if raw_data_put_form %} @@ -221,9 +223,6 @@
{% block footer %} - {% endblock %} {% block script %} diff --git a/requirements/South-0.8.3.tar.gz b/requirements/South-0.8.3.tar.gz deleted file mode 100644 index 397815f0f957dd86adcae12c53e864723b4699e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97650 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 z 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�?N|!^F*y1VqoiC$US<2py_l;H%B45H~$+MS) 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

EcZAO#E%Wp6>*DWPOipb?dvg(>o|E-4kwOEWt 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

Edoe>l0u-s8pv#B9NUZNPInxp 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 X+Fsjhdu^|O-0Ob<-l>~}0GJ2>m_!t0 literal 0 HcmV?d00001 diff --git a/requirements/argparse-1.2.1.tar.gz b/requirements/argparse-1.2.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..f060222cb4de6b3cbf410bc9286f23f8d2d9f614 GIT binary patch literal 69297 zcmV(-K-|9{iwFqK^^{El17UJ!aA9(DWi2r-GA=PLbYXG;>^y68+s3Z>%$fX$y~$)K zB@%7PR?>Q^bFTAfn|l%`Q>UkArjt=AaV0UKNRr=!8M;j;n24F=GD zkB#nqg)2)^H)iZ!y4el4ul@h%#`xJst`vyGduSrn$RKh09^u{2`ux9Ktp88k$5^)PgvF*k(f zWtLco6ZkV8CV-HI9*^NYSD>=RVVCZTt0(5J*MZLyr0)g+oBIJg_@R}WJgwc?XLkX= zarBALQegSVC}ti{VGs#(r%{%gJ-rdMdu$zW7tj;VnHSBDL~~y@<3s^UKl@1<#apW{ zF3Wn(=TXdA2Z!Z{vmo>QaM8_~890L;t7We`e(N0C091C#u7=Jr^m#r{K{iE-IC?og zDTR3)tx6rq_6-LHJsxn-jOAqoQxd+<1GYCL4H*6?lMt z;D_kP05)8JE1AXsWc>`&y1xd`cE*-zx;{HPnnfOW7E!baI0lcS^^xl6$U4t}Vtl58 zkBmI>b)RFvIb%&>$da>OGj899!w&Gz*ea8IH%#V4}BOk3<+xX-= z7a0f#0-q+jj5f%j00J2%)Qqt@*(MI4Upcj7bOUhBZk9$Xkn#*1^H!5w@Q}xD3fwJu zuqHOL1S8#wC-|GtD;Z;W97i#Z1C);fO4!1`LQZm_s4@HDl^gh8KHM4^ottUK-^M!A zfZG#iSc<@MD3Az&L4}YOgb;x-H2GnH0Z9)02G~^WDNA=4<`aVH%`$>^lyS&K-jihO zbp)YKBL6_FM6o9NgJ1|W2K|#XVVqaK2iTAhxR8DTlORQvC-k5Xf3{?hTZzO6*vVzC z;y31C7+Z0iYIro53imw*DVpe5vI?RLF#9MC`%3tNI%%7^gml)*WEVsDfCy zKus0{hUiI6I6=>e;)U>a&@;?r9y=wXUIgl8 zCZL|R$^cAC@75Tj&{8kAV2dk35}5J$8rccc0{D9ogI0*}#tj!4ieLA704UxK4}?EC zl)iH~#_7Qrqk}P?9*ptqP)R{5dnm@>V2q;vK16GOh7H>EjLBmCZ(sjiy!!3(%NGCC z`tRw}#`-U=`NaC~>FKlMQ(XUzhR5I5e_!MJ4OR?x!Y=sczBSg@ee1quRF=Rp?puWn ztB(+U2uj!BZeLT}dHCJ%%q&L@vG7&OL*=wNA$kzuAW(S}%P`|gu)G5gTZn<7jR8<( z{tRXxq>6J$6k)l7;ntPatC~ldrMgv;X7f3vnL3!CP>M$V7e`neU(M*A zeSZd7LSN^#mFO!H-K0>LOrU4V^pn(sMB5Cz94O1`Z9|BMfGjW zKUvl~&O%XepG-49@Z<{~UJXx;`;l?~)VP24t>}BJ`Hz11i*EuSzW+Ofr*Hee|5N(M zKNDlc{+Igy)8Xjkw)9Y7QUN*4&r~+@za4`qZ-s^YIA%Em?N40eY<{H{9qyL1bsu$chG5UCD zCZAaHJuPLZ9l%YD!n3F(B|ertAX)7itP-SRmZz9oV#fv>(89f2aw4ESK9^)Ve#&Dk z-}E5q#gZ={|L6t@@8*?8NX4@tWn-$|Y4~ob-9dVt{H;G%1kVbELJ2L~IwqMki$mFN zSr0)v0hNWQh6oGn5OkBUz9@v!PB6blBLrDUaVa26-8f)jz^{7jP-iYxt;V*$fYk=K zd-PK7QH*We^mrg^-w*Vj1C|cY<^6k6JOeFyd=1%>3miC-3_dKPcsqV6n}Eu1qWA7y zxxxyan@%Ke&;~m8ifnuZF4izb?#_goeIH=Pzi`10)bw}M8!$j^ssPDhPXC#?0ZgP| z-eb}9(}4aC4MPQ!!}sjp#?(@@JL0=z+ufSCSQPFcYIj%bu(p-Z>faCZ_er(}|Dwj$ zV>pVgV~)!hktJvH`+PBL6pODos|ZU{`VeRQtRyvjCxr&nCGN3RvKU`PAukFJX=8g) zXaEcI9(c=nASW03ugHmk zWgtP*ELQ86e*D(I_Cu5m%yQEnz#sm)ra>8lAhH-$CY~Py*DAm`tIr#2)vsup}A8a+s%1Mxf|owa+!@HqUQe(%kY@$9%QZyyI$86_Q1XlaI{U{kfifxz^X||@QjK8!emUr^868`|L z^C;;eUMJnIh1$E&eF%YmGU?^r$?;4kOE+0gCeS-hYjcqNPc5nlGmb(~r{1n0mWdwN zcr2a-q)8^^`^caNAPA(Q2uMX1!zS5gM^F15%9T;4hb6TrOUY-^1CL|*K!*q>n3hM>~zRwD@r z8DguOrm+O-A$Avqo)4>vCYM`fyq+P$?k)NP86DnN!97%0Dy0}Kwv}I9`=wFIIggA0 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

;ChXuMhP{uiiX+ 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 LT<$4T0C)ueY3bcu literal 0 HcmV?d00001 diff --git a/requirements/billiard-3.3.0.13.tar.gz b/requirements/billiard-3.3.0.13.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..351834c148a0f7797ba7b2202aeca361a0d50b7f GIT binary patch literal 148777 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

G(7P8zXLLH88RuHl$-L2@;Irk}* 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

sWP$= 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 IOaOQa0EaTSYybcN literal 0 HcmV?d00001 diff --git a/requirements/billiard-3.3.0.6.tar.gz b/requirements/billiard-3.3.0.6.tar.gz deleted file mode 100644 index 1f6277a23d4d062c2a6fa63ce29e7e094a1179ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 146649 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

S|j}KYk6e&gcQYZDbI;mhfz~ze4 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%0DT@_|tEMG*toC0J=Ut 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 H08k15pEEb2 diff --git a/requirements/boto-2.17.0.tar.gz b/requirements/boto-2.17.0.tar.gz deleted file mode 100644 index 2d520f7461bde267121452a42d04211161425a34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5993878 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%0D)18<9cnI%B;(Ja(UJR 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࿺JwOR_Qu;6~gNGF7She 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 n8II>9A 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 z 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�$ll~oU?OQ!qh>h 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

wnpLPtFvkY)ukI-VM!w!4<k99IFrdB~SPzE& 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%0DgUP11xJfjga3REad8dnoHf;NG|jv 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

-7ZZ8a8Ce-uufo^p39P6`T49^WGJVV@$+Co zM@}wyI*zg~`!I)h5^eWR63Jk@t8`ITw@Zg5t-@~P*O(6D0cv1i$zhZ^X}yErxDptA zu*iWEjL)ufMpY_Ds+!2qa$u#}%TA}^kEL?{Car-cA{#^puaB?w2J0sO<|4$&k<3H< zQztAqMiQP<-RA;TQ-~;Ct%!o2*XiUk)JM8GY6J^MqEQN8YDAi?byv#nmTT_3X+z=hTLabuBIgR)fI*qkMx>^viGxJ3;oMcn>80NjP_C-9-A^aC* z;BPDcmyhmQ#zcAe>Ep*S`Jcq)J&^hL_V*4SAAktG_w@1Z-XD_3TlxRj(EpT=Bu9Q9 z%AXqbpLZX-`ky^?3EAp@eii-C-fkV$kKb)C`8r)JZjv|fzp~H86#hW{^;TK5RTgcP zMZc)B=wpc$73oljC}BSe~;>d z_wQYdFtAuqQI7HB33Rb5c0|!AMUMt^bL?ZH=>rX={?^8lT*?c|XD+G>xr@IQ@wa_z zb3(RO(Ok^FZ60dF4NCjN_P_s#_^~F`+wH7G+Hm`&vf$geg3F`ao``3R3^1=x>TliG$?CtOD z?#1h9Z=P!>AhhJvcD0Zt?Qm}eocW^oaASTR=pP#aqXV`;JDuGHjzN4e&W5Y={%)Wz zzG&sZketra(Xv>`!5M=j*mQY;7Q+A-T1dXU0kP^blkG_uK(p#7TP({+ojxAH<>Jrz zFbpx$$id>_!+P&jzn{bruONpQ+L2*A1a?CwjNUyd$=33k^>8VIMzw$`oMLnms9+*d zEif9ROk@&xR0~23uY~ow4hRRQ>_2Nka1hY`(=f3QWL29%3THeRrSp`7kX`>=sorP- z(Q6t0yo2E?pNt2nKM``KGS%ZBUCP=F|4_{iJIl_qF$H>49)Ry(?_lCyV7XA2Lwz%h z#3sEA@{Pb&(Qc-T8za9CDGtOn-7qUjnsA_J88={5c%B620~ zBRNg#=0K#Clad2@Ob4d;(ViVbX_a>39y1#a+K)@Ag=&ip#>bV%aDAm|zWwBcKG+@s zIq4nJ*?HF9gEPuz46TEONgXh}ktY}e#q|^0q6|ykL3aS^cakSN$)1TF)ATYU9D}*Z z7ew&g4A2eFf_1)uK5*b8WF-Xyi^@E}5%1&~R%~V<~>4)w(qxZVD42nS zLFWkLhiLK%uZa_tP@XBc3O{f&zm_jg?Gop7)#IM+)@peMn_!%#Wa`j4Y6YT9+hWo9 z1?%)IT(yR3;UPMYzsC)Tz3z*D?H|cujJe^SI=8l|n8W|fh>!6NJ;gk6w@f$b1;tM~ zjAMV-3FIKE3=;b#<3PIw%pRrGB6NSoIYBZ^E7f{U=~|XK{#E(Fv|e83(|7m~Q9p*r z$oWh;@vMV^x9%lu$@j=Bl&wIXe{(|1i*{B~5Zq$a`J|+| zy3Syat|-9=>;mS8nM^diOW+O8vm4T)pkjs|DcF^CF}mQqFlYHWaIBQP=$al6d^D~X z#q2!%9_T#ev`sAznZ?K0AqQQHbO0WPYFa5E2*EfHL1CJLKqSLSI=aL=lZ|^#D#s3O zT?BlYVIG#nO>zdL1r}Ap&Y(9TpxhY|)!7mVdNxCh(@!CsQ$Ek(w^r%E^Ya!xBl(p$ zFF7H&k-g*@1-L&{&21d7-0=>dl7t42}U)`A1ZezKI5!@YY zx?Ex^pls|wqx?TfTc((z!Z?h0<4kGcaHA-%lkt3adKM&=asFNL7Vi%^@0vOVv{#8! z`2X2^)8;mgY*DZy<{N**L`*$7901)QL{f|UvM=9zv?SY{*4853em%Mhum}{%dIC@| z3Lu5P?TGn-^P?uul9?x$TEIoJ`%-bQ8w7GadGh4h&v*6^tbRbG#T?K%t0Cg&=K91v zc;SFIr~HbS{5({j@-Zj_HF1FBEh&W-?Eb;KY&KqP9TyKcDHBLesFw68jJk>gJm2mn zBzT>6AUmTPMbDqCvc>fw^}1M?cdh|a4N&l4_FOeK;m^r0%R(`Au!3w<2eKDaOgM$a z7hy$6F{Ct9)SpslPPpPac@PHe_VVAkP>QzEQEL2EjW`5e-_}jwy6~s7^jFMt!=Ad8uvB*FgeY*$XxP z&uaMR#i9`hqFeFy`x4SSnAMvkv7GA+NVMW06q7hhhgl^U4#Dm){b;NYoM^UiUkyFW zHTI6HWQy@jz4%I`k($@|{@2-B0GGq@I6Jr9E4O}tb(H3C+0rqJdXP2v+8gC*d8m#iKYGY0+tC7{L@+9>>c+%_#=c4&z}`GawJ;r(Cx=7ZfK3Fa;ddMH@DjzW?sp)a zMTY{dR&Dx`(1@{9JRyvLC9U}Hi^XJY|8}LTXT@YzfZYodaRQH|-+fRsj*^0NxFi%F zL1tpeq&iXP1-5!21z~(0GdQ|%9ooS0?F>|U1mY@{p8oY1lYCB&jz_B$pRp|0|ahCGxYQLRP6c;8?jHi^`}H1a3KB_#iwA| zNG>YYOuroqh{89)5E3o-jEf@;N#^uQ93H4JLi|to@{? z*PQh7srKtIk+7fD?v4Nh6Ob(WWDF zYt;;*0oDjnf3}@L>I0do?DGd*f~60W&Rlx|j?SDQJotfOMvt}65-kpfetyY=7OMCMW(9vvW=c!~mFz{Kcok$w+4mnc;Qa?- zn5bR;K2F>s$(h=;IjlR_^t9cs%@VG&YrB5lb!hnePuI3}gltx4PcyvkubhRhe?;6; zA1pc0mYHJH_}2~BU}Xts)Us^vF4`DHduN;$r=dsG3;hnbqaRg2S}KfgM%h>oyQ4!N ztA2K9Gm2bxm#-I$3c6#uV?BP!H$6d?(CBZVMMd$a`=CSpJL(BJM;}nD3hFy3_hVpi1r0(l#^UTV+Ohf zd^!8ag|Sxl*&OIlH;0dl7@?}yBzv~91v=|`HjJ#xA-mUK+3C%e_T8{)Z9dbt*6O^@ z?be4Dg6LWLjz%=SW0FU!F>35P+Iz&8)#vGzBd^2XhI1rZX8ZyTq+&iON2ucTrQaSs z%Vgn4`puGFz=&86jxjJueSGDmuL-+Q0HIly+1YX|g<^HL$BTRhl~rCHzIq|5cZ2Gm zSCK9jiWLS@fP8&E9fNU}7eo`P?eqP0*hrh#14sxKOkdHMhhV3eW?V4^az0E)iZv_$ zOpnV|4#wEnNR}}Ljs5Kl^=$l8-;au6nUv{jPa6LZ$r4AWuwwUetPx?jKxTd8Z245O z(Fl+f91~n;9^_8*U}dN-qe>q$kT6D>nm`O!Tq3Tlm^a-*=9Ezg6=<;X33}bLJDE`u z*y9u9)ybm*-z()8*`x+Z2!jZHlU%altU*IhJwV!QS}y0>_I_53Da^n*pRI)7OO0}< zI9H62xJoI@!es^vUC>oZ!H7Bim;i3~odFN9Rtz~W>S0i9FU`xSj)SmK_Im;HBVH}F z-_*NlMj+Bd(5nlJnazt?HV2u}*%oxtL;%w~o381kK$rlR28EW2Iq!+>*heppTt(=+ z>X!-<$Z{5QRaosqk@h=(zD2^OzUY1eizrSG8MM75A%Xv}W&^wIv|- zPoF;K!NmBRRSYkawJ7_@3^pbz!;el+2as#M%ChI$EW zzgQjq_ZbAKr3P&RRY1lrmgsWhI1ES(<|ts-XOl}j0#?3M!^i#Lw8a6?dpT4c6cKz~ zEXd9g0p`bSWv@G9rM@L`|D76WRxis>9*CR{+TW{y$m(|RVplKba5o)lvRxac(oc4tY)$g% zQW)EEVBDYx@A`*&WJdojoUC1qJl;_@RyeJSf znSl%y3f@aIH8!Z?yqpDA=#H^SEqbH{3u>U|#&?QF%htNz1fUrC`JyzjdRgkd@g8mG z*F6{5;)NDSg%De4^3cs30_cPnE^B(1V)-YUvn z=NUyftXiXrMT`j2+ybhE%eh4qp+uE~(Z_tk2twa9R1F8`G$bX@Umt<7q)?JH`c7aR z7wE$PFh*LT0CE#d5a5lAouX!Cul zs?IyXE^|0Z8?fkfSGxkiPyzi#TCQkGWqv+oulBR$l(~1K~O(dX?^KZfYd=HCxevaHXl${}huMWVJMOP5brkLKSfS|R~87|xqaR=19 zm*`@sCnrbQLc1_Q^u`Mua>O}r@M)vK&LsI>%a#y2t*KUe3J&UKx?XZ#XaJnpJ)6Ni zdDVRX@0>#dG&mfLe3hM=@?elu0&07kCGC|p`7y}ASD^l$&Pf58~#nv7V)D?Vd&sWfefXK0NOp6 z9uq_;NKT}^={ALC9}e;4WV7e0tER!t zu-5>B{KS$$qzYk0YqGmmgCO^6K^7gvvc zG1lfsGsMY>e`D19!UQIWwq=y6y2SSP1MhtB4n(gt69;jL_L9@07zYHxX>r6H7sfN7 z6ONhyRN4zef+dvKCnIqh91;`VNRbmm5;lSWJl%aS=_qC^>!8+1YzU3nN#_hwo_C`3 z=sciDA_uoak`z!}GK9(ZOkfIF1phHJr3Q9A#OqXUq zK^rzytHkTBiI>#;i(OQqW}a0=gNxq}*4l$}n%;gY@XBf`e{F4SwJUJKJ45qny-+TZ zRt9)h==i%dhxCqN-2n8hQVkH$zatOV`w zq~r&@t_INp^owf^Md)tT{gxYEVM1Jy-uoA&9kB&nQ@C+dY2LxykuJ@3iujk&rM1G0&!|kRMvV2f zX{^Qf@I(LEMrAKV(6}(Li9)aQaI|Aa*Of<(FN8o$Cr{fOt*>|gO`N&Alr`m&UpMcQ z3ICS!|B8^pyU+i-{pj)Ip#JObll%IwpXDE1_rIm{yimNgNLPs@1oYQNP7p2r??jAa4AedSPaoB?hxDFv%^Zw$lkIhEQI~tiCjkXL@Y(QUYE0 zc{WvV#}NFNXIo>?OJjd;yB6AgXW!ubzaf)@RzyU1^-4UrVc06Cj!0#a4gL6m&W@Zf z!6Sw<{h{##&eo*TaMxp2Qxy)~YB^K!A~S;w!Z`DK-pb7T+iqbMfzMUzsu-mrdrH+P zWby%pE9ZVO0XfKTUC~B5Xd2V!_i!uJRG%a ztx5dRa=khS$wSUSf?ieYE+d|Sqw?;FfIEi)?r8B;<_e)aArB!%N9`J_GhtNTlBu5q z1Ei~X8VpQLh(p$|B9f+}EeUc{R*+@KAc}G!PwPX)CCD>48;n8c6nmHl%@Jcb&qwEaX zOc=4U&fx1WP-pP<@3GFHVhV0vWl%zUv**RKd8^BoTUXgSt1}%w$LbU)&Wp=6SLk&5 zOsiabg`aPAWx6K*nGT;5cDw7sZufJnE}d;n6)gH8 zI`87#zfdLCsapc|^%ttdTDOe*O00J(|9{r{pWi-y{AAb2|KEQ5E!zK{?%vD)zeD+d zmtEk229m^&$wnac_L-8rK_D;t31(w>N8<6j4A@~11n)Hi_nLuw&A`28KxhVZUC?Dd z(w{HV@&by4HkAea>oS|K))(*PsGxb!O`tfBQwh}AqF#IDJH3g0TNp-RAYtCM6!Y%1*UzVT0V+Ag+jmz`*hgj%VP;i+R|Io{XT^mJS0EwMW<` z>_B{jQAH3YXlKTFm$U>^>}*+HU`d;;Mb4GzoZty|xkSQ)`3EvI9K)4{s0*mxgt?C> z#SX_T8N2jsu7Ex)#_IK`2|6U&GA~9;MXbt<#yH`(3t02iyiUOAoD66*%8Y})2HuFy zVW{n%W$6N|)o>2$d@kP;s2T@#V!)7}WhTt&L=50XJDNDfpA~T&mjx{T60-IjJ^xE7 z4^W>UmAQ15q&*n1P{?c!X@TaHfk?falL?UMaXLL;nk-E?Hd|teo#n9Bl>A-L_s1!F zL;0$P@InB!P0Nq!QC&j%6;3!aoUdjJm~VE$U37dIu8OhJ7{O8gn6I?Ag8dr6YRX7a z(pjB>oloAz7Z@cQ`3tE{=}^;?<3eGItOE42x*B|O;MAQfd84Yib(*oNnz`GLwjSNr z%>A!WGq<^KtvaA}#a-{s={I3iyDE0qudaJr<#ns->$d6}Ei}AFW!~E;&3g;AdD|D~ zr4SwP9v`G-O^sb!&bEg-4s&m$?>ExaY_2%%{2x$X)z+KsU}_1@TTZ3Bkp1Y`aXawB z7lKxs-qMMlrpWdZC(=K7rFDpZI?Ep_YC1T|7H`#8@KOuz#Kr>kA@{5^3C2)U1oPhB zMgVlXZmfK&2Y)+PqDVeV#}GDqRuoW4QvddBo}nir{dk(rJHH0QPWdSjQA+OISH*HX zGO43*o4Z4Ii$s=vBqV8r?0Lk{IZ_}+i269juSJ47tQT=!`Uog z+H^P5DF|xVcm;D8Cc72_#Fo!BIWugAjl7hx6FMr(oGwLHBwLKMEH{=K$wzi{cLY*s zN@ZqEAA5&%CFK%RId(-wYA$x$gCLFlaXL92rOBtgPw%%sXp)Z=axX!dFv>mwZu}#k z>C(-S0?dEhk;$2XO7kA~)hIT&Pw|HNCqT)s^$~D6NYV-8WSc=DU)5NR2<>P9$U>;T zh_%B>-In;(O)7|AOw!@j!q;1_c82A_=7>k|+ z7$bbc0AT#O0={0bKPFAZNy2I~>dVTC3iKmZ;(qs9-#YxZ5q=$}nlISi#nyVY`Z)mGQm_jY}LOuSg#g(9b<>uEprRpb9TkV zQ~PX~b*_(lF%Hi%1h8P$(&9{QYs|E-o8t<9ZJ9}=1!k*PbYPXTE>0^UI~(`3FS`;S zKv2iWtgOK7gVBgmYbf4j!ojtvJ$KS!X#ejS9%GO6{PKXfojwK|*9kcrcr|4tZg0P_{Rf?u>57IqdwKb=4K;+VYF!rq426&Xa~s%0u+{Qk2&9tu8XR^)Y}0$ z3NqFdtt$9{*;AiEYasLYEtbsf&{{x$ID`djx7wTy4JFj>t3Te@CEIzb!x zmHK^)x3a}WLe%QFPFGvnuzB4&wBh;j!?c8;$CS4GfNQT+7mvegKu#3}r{+!g02o?O zc{4?e$Rd%mqxz+q+9h7$X78Uis;HK|L?mkjNCrk#FB)lO~pr>H?VVRMC)Y9pesFAED1q6+GN+<0$4y!Z6 z8s_b)y5ToA?Jwt4xU$b5IV`uVdMidkNZiVB0LXBlpWeMxAI|eB`h8I8JJqnwU}fvk z8rPJ#HglQ|2R+p9sC0Da;X%4)kv5a-q=_u0R>?>=Fq=kF}=*D zIaI@AONp-DG=+q$!~_>QS2dV&KY_DSKD{i)m*P>)r<`}%nL4GUf#R0p@94k=>%rXl z>F^@YE-8hOlM~KVsY^gyvBkN;jTN}LY_unHr622b+Uj)$yrbRG6T*31&|%fCZpxdb z)_yv4a~4&S$2Z9VF~zL8(0L%xl@ZEEk-gmaGrjyH{ zJWA6bT3AbqHlQWC%sB&ZtYrVu3LHblD5+kAKY70B88^Y9t_2T- zPjxvG`f6uISmgqhRyg^z(4(V%05o(`sjGz_QoD@q_DMz{fIbVnQi-r7h0CPz$lUVS zKn~?v#i-yhOI|`F!Lf^G@`{7=8(}~`>X)-|t_aFQp^W?mc{$xia%ZJ_ZT7VrZ+|j+ z(j{E`BlX$rUu2&~`8klNP1$KcuvUG)hcx9Ivc4p6ra<8=N5xdCqo|i6Z#1$sEGU#R zYde=XRx0id57Dg`tiME$bk)}5AnDlm(Mh;JF49rig;wu%w-0u(uxhyJ?OJ|2>^0cY zHK3_otnYi%_5=ACZvSa(XM1bs+m17!!R}T=+SV}W`wtsdVmZnvdP>|Ed#{0)po8Lz z*_Y+#lhV%X%n{U=2f-sB!Q}gJ`XRIDpai)8`Obf~fmamKtQwwT(x`(Mk0MEXkmN~= zO*J}-&Wp1%5Q$W;19%#0+e$y8{{%w-bo-|BYh9mrS*dHPBktC<1u*TwZtEI7(?J@z zh$AFDFY}KX{+V8tdsJdl>KuRlwFxo$>1?I|)-@0n_aE<;L%+?{>d{3REhn?GOT%sk zW(>I2LW507-3ENYQJvuOBW)b&z~uzA{UCr0is@iEH3VZHiOO$ERaxtw!ap8e6!XOv z_{fhq%el^F3_OM5cSg&(`^frIiRIV~hZCCis-YJznNiyzq7up#iVo97^-8PO&sCB2 zTjp0jYV&V7m8%^kX05YD5Et6;Py2|8{@1V$B^~nX*`srH-iA8BMs*tpqQjf%PqsO| z7+4dem6?UE;gQ%{On4CM(XQ2^N0rY25Yp1(Y;iRuT_zcCJa`&gm8_R%)NRawar8)p z1(So-s8~fC@7l^AD-$|boV5fW9l0E>mFy;uu)=u@9OUG<>-ot6$uof#3YyMH0XXmd z>DZr69&OqBWCo|J&^CE1Cq**1NaA}-Dneq}&nR`{@IsQ`igPz**`X{DN1GWHzhF*yk z&}?%SW)as4YojWcvl;qTQ{166Rtc{f3i#^jSheKft&(biGy37#s~$x_1NM^Ej)M9o z#c3{h2elG~Bk2l*Zc4O{{$1fZnsn(}twK+G$EF*4#!JUXv@@APX|^g_BlswkFPvJa zkLKAh%bnW5PC%wkLxsvtfXqYq&*13b_4DuE{I6cH0XawV;OOXO0ud-QUiN^70l3z8 z1j&q#7o0t5^5;#x9t_7hDzruq+>HyUik)L9?!Oh^ER_)N)z**w1lJI2Rs^}rni zajT*iM2MOm@qK$ec;gg@MVk-0$S|1slo(=2!mMedMY2{1ruBB(f}D!VXO4km5ngny zjJ9YR3)k(L;9OkGPl*2_ru7wG!sIPnZ5jMrM(TRjxiiymVsrS7^~ji{qYUa6LXv3k zR8~YKn-9}63%oKEZ_2+M96dWcOcbjJQ7An&1*i{LezF`Em}~oDHM_u?z5Y0qWtk&g z^)gPg#T6uh-obBopFFi$kV`eQQ$LUmaSZNCL!9~j*wJ6>?@4`ai0B@mqK+tc*87|c z8l)3ZBW(7Fh;{*}krUEUwq7bD_ewDZPP#u7#km^g*|=Da#2it-bt0I1>da;_7jFHt z7b9$baZwJ@t|^f0WUwA@$?1aX&CKZ9hFm~8aa30NXqt!6i^gGsw=@|sa85^n{LZ=vw*M0e53iOIpaabj+EixdAe8@1UnHM@m*pL5om z@6&v|oM%<@dd=3JSh2f`z&ytaNeMfx*^E19G^#gV7aRxDDcE{oAwnV-M5|-fxaE5K zxhmS-o+)x^yTc;+gZ`FTrlvROMx4|6=jWX2n4cfoGCzH*r>-p2TnbVTkA#Gw`7&7X?L%O>Pcv1A*v z$N5~1I|G9uuf50qYKhU;TL@6NiMA|i)mk6?2AL&fbN(k9vxhbjutKzfhS31qsr8ha z;k0fvn(=gO9sT5ISo;D?C;)J$1<@o84q*$S)%V0)dSBBejCAKJyR{5G0YvhWRFkOI zguVM7166R=H)T*j%|fO*R@8r&>LOfgrrGb6P`00+W4~}3{&M@aB*_^FHaHzY|3DRdjkY=-!k;y9ZR1bNOX)!XNIQRV8AbRpRf9F15?iOU6OhlIT?y-;PsCe_;b*Dw z>_vA*3GsO_h;d~%!<=#D2vR{-lI{G(IW{(B`AHb8io!U2hqpsSRxC0~eoq2LOkG9VizDDV*05)pVb)>$x({-74 zIe0VPipddaW$(2)a*H>$j%{`hKhbc29lbRj%_3CG_b&65mFYBsE`lMh<$O0{z6gz+ z@8{ynZib7v4~E&$~jCrgn6%L+&Ro8(&&1UUhAp9-N(M}xtH!Ul!pbE zeKtV5`s!^E_uEnLBLkSpcV zz)TykLg!S0Xj56zKGm88$tf64wOe5BGTa0f`BBKl)t5+*xCDnJxFh(CJAlG(5KNM( z?CHn}t|5h|j2XuS8<|5X#=xnJ8FnENTeh7tyf^|%OV2q5Y{l59Jk^0YBD+Y950qDY z{mZ=uEyI}caNV(wXAD^ry$QP0KcKIPHf3re3nE2h9;L&`>qsE0I29VbN%l(5rj zYGNDIGvhq)pO*G*Tp`w@@;7Rd$QGj&Rt=*?^dT!tSN^;x`s3ofkCm~y(0bFYW6k{_ z%g3^Wd@Q@$+tC`zkewo-trt+<@?E#iu&JFE_-Kp_wml|&f_PKw*Rob^X-$J zCx1wu+}Hp9GUu<$2i{8c_on*q+mF9}YU{u6JbCQ zV*7o?_WO$M_Z8c1#rChbE_+yG{phbpqRjfn234IoM_+iaMmp9-gQT3sEs7gDsZ(7+ zes2y^5|tg|FOVmN%$VAovxgPi_fC*yRPUUq1mCx7J8{;c%Md!t$9jqTqDFKbudd~t z{SN2CbZSIrb04*PGI`?_YnPYfWg{-*m#=H7DG??u2E! z9>SRR*PSq(ZB5nXyI5;hx6=)#E{o;*Q;SZwGWG6trmi?)XP^&E#JE26U{MT+o^AGPXmq6jb*E;gs`soO@$d_f;TtkrF7+-l8S+nW}^lF zFU$(JAptb-|BrT`K2`kx&bNx4GK_x=t)Xk&x3E1{8>BU8P_(D3L&tZoD@ zPFy{N2C6?u85lel0MHOXo7P74FRF|G&FFtmp<14fI=VRr*ueiiefsSqpZ|Nh`{r%vXyT=qix-E+*`_!HVZYy7!nGmPWJF(F(ZU6s&S;>iBT=1L0k{k?bOshPNfc9FAhLONRB>>UAlc9bv@9C$aS0-BK;H5z$U6mXwH44jV_>`Wj{$?q!7xYZaA}PZe}Q* zAtMESI`9y~Oj`TIOL5}Nj-YTRmv6(}OfR8$i<%7$e5X(w{z99iA8tkt7{mJNXiIn= zyB+yBi)~5=NwTr1FVza=+>Y4dPG_7i735gLP~ zCbLhAhqJMw`_#&b#ZV12oM?jO;)3_17Y+5CH>x;iwYouy3_Mt@lrX5{qt*A6?_c~} zl}{+gw##|8e~dwuaD2LA+PwI*lAj0m$8aEO0jdVKi#lxn0wZqrwv3eXR4k<8)#d1n9`jq$x z3*#;+BNXe@!|ck`OHJ{NGH=SloR|S>N+sptCwlaq+F6*F36wBIwySCAi2~Dd z%2@+4lB9zW_V5f6)Y_k&WvF?-(yE3^_#A1<6 zwX~;qiV%mSb5Pb?@muqJH1ZN>VSX_M@hzkIw`=8yf*@*uhR17nB3g5}!7*K%@yet< z`^CGU6$NH-Kyt(pchU*Gj=(Km?pt%P{hhw4H`n=_>3vL{JB^*ms|R{RcA{|lcym*bn}cV&SR5|(*IJD#c6@XA0d$kWlQuu-#d`6 z^)Q07V5Ewm<{acDqU?%^pQKokS@AX52$VGl+oXUz)mM3$MPck8GsR4IIk%BMX5upm z@AHwD4}x$zNCv^@ZNA^{9E``E>YCRjC2*Kiq>xhrCS_^x^PIhz8z0*0AD!%lww@~6 zMIh@SWKUOg-hE%$NU0M55`oM`vTzRoYM8$P@3Rrli3$(+-iGtzH&7r|agF&z;o)m6 zXKD;&W&4(|iv?1capv_2=#KY07Yc(P6*^63-p?RZFzN@x5YRguDmbbQCfCh z-_L2jfbK^bXurx9bY8$zWE=^v)xlKeUSe~#u+;Ji6W`D+H~UR5ff)^Hcd}=X@7G3p zt8NCOx6F~D$!-%LeIRnkL@sX`UfznktBn3QlAv<~IdOCp0<9}iwrenntE+1#b5X8Ca93~=?>(_DBIr6&5Dby?(`mnTeXD&;y+ z@W#GE<~8x8s>Ov(UIUqE)l;Jw2uN&ul};Do({t})t-gnv4BXTX>K#jPo1<74X@wHdl9Q};^Qp$WP4uxK z+#o+GZ}TYp!hoFPN+!!zLeFL92u6yPIisp0a2Poh7ng%U1s5}dIyMu8-7}NZgqjW) z#guqf4|n_xM%Yvntlc(XTT5yDrl06yX3f&otMrr4u)y2mk);M{t2x?~R8^M?c`&r3mq2^FzY` z`qAg!p}ZM=`uWQSA=6wDdVvEW-+O#(l?Zq8C=2Jow%5pCfEfao@X8XEs4Ub<^0e+% zfw1L7+l~lzqXWB17wWxh%TOxCtDO-%35?OMNV;#bz_=L zzQ*W>?0L#v6Pfyr*ksBG3$~^--fXN=t3oUFT)kYMNXPNZalzBqD(KUcmk^%5T%AXG z4#3P5VFx{G){PtxnM|^?{1d3f9CToFE*=1RkGZ|HxuElP+5bB4AC53(9Szn~kM-dYFEV3EV5uC^Uv35Z6LlxEn=COL8e+;@dYz$DQg61$TfK z>0T>$1J|L&z2sayIa5qti(@4;)^CYMySt2X@qQBuY>*o=9=JT;7p2K}NQ;^f(SP=nNU>l%7Kq$tHo$-09b>E*CK`0vi0yjc;G*mc8y{ z23fO9Q}EFd*Z&2cGOXp<>Y1XdpK$S(vvFpf#HUIYat(3tyMluah}W>0I1Cjp(yM_p z0zG0$bDiPehtHEP1%qsooj_+zCnIYhzO&@#b057R7AMIUfD2x=8vrU>&{CtWQR6&) z{1-UraW*|)u!Yi-{}l3PV7j0&1OP~nJx!8_w8%p2~9tx0Y|@C@*hH$LR=w?ABS7KgO8o^I#5(>b)S{d~J0)}e@Z z%9#w+lXY%66DzXUF(z$XQzBN=IC*{XX_09)Bd`m}xPavT)&Neq%E^S3jU29LLmK{V z6Jx$|zvkGre>Fx(_=)RE0EQ`QIHaqKqRe7`2l^2q^tg482XL^F{v>+6ola6qk0%9;`*p@buCS(Zk6e zt?CpqLQtUu599a3^DqO`hUuZEP?AI4;|%y6;%+pL;(FGA9=WYB8q9 z@Y+P3gqSIkalC81_KP)j2NhU+_gaL7;tcLqjes*$=n-PGMJU7CGww9A19cE@t_E=@ zoC7Q`9goR2uH9K^D<#r__xD1_6EvQvHMJQwgmh6n;ygJyfq_m= z$lG2CRtg<$Dcuwj9WSR2vq4lDu%XUh*YJC~EKWZ*g0m$TtzeLYpO1_uuT71hzoDm) zT^l2Em2szOLK*>v2=)yCH8=LS7fCI!@Fa07NU%a7l{Y@V7+~`0% zvg^{ux_&%e5V05Vj{sSx%odBl!2Zf=QU0`zk+BL|pjA6LdB45&Z|T-Q4z~WE!PWU62#F7fBIB*Mb&Z22=vw1!p=CgE+ZI8X{Z+&3M_ng~$N}|HBokZp=B*-Jg zb|h`pMS7X}>LM{~FF94boGBM50tw3e9C8CGdlBF6e2j^2-sYTb9a zjB`<5tI(J5R&5JSwE87nJ4L67#>Avihx&pep-YCMUGNx;=b=5NW|38qEK4n$d>e9wGJ_cW!I>J~?AMu;0HpcF$g6XCr>;%41|8ttM9BgYw20Eq&eE7ZQ z|AabjT74Yyb)nhq{Dg(kiCV(f#{5M290Gq8$`vRwo7HU6S?6dunFZ_Q zLG7k_JZ^TMoc&Ajf49i{HS>SFyF0s&y!>xFPj(;Q^MCjCfA0Ced;ag9|NGsgb%$tF zqn$o5p(DN%Ah1^Dq5vPge5#{ZZSoG)VF~w}qTeVbLJB#*S)*k7Z0HH#J^%^g0C%QY zie{9YzU(SH<+7oe#_Zw2&qqf&sMS$T#;L|0g7~|&y`%o`Au>#t*%-32{IJYN*+Wb; zHNgK0#ccm#F&S@c92F3YMVw=a1DA@FzyOMY)T{j8paTc3Ho48hjxd`yPXk{fRFcyb z#)K)#N)8g|8RdY%?>A1<;m1UgDg~<_6-+K6`I8w>I_9FfT@gEoL@l!kT*e_gfa)a? z-;Bz6NH_o-HT=9Gve7GoK0ix`5Q@2Rd_hhhi}?~#JsID$$Z(K0YX&|s+MsRITs**| ze!y-ldFf|RPB(xdapIN{3?3S>%@YvB_X$OtfkrUKDU)NyBmpAwW|pP?0P|V@*0u@W zwGX0xup8`Y4uleYaJ@A2v|_Skn5WT>j9VOKkfAu?cj`1#r=1ttWV4|ftJ7YN6^o-+ zttc`sT#XKvl1$r`I5CLd3=)c6<{%GQF$v2U*tzJ9*?|0Gv0sahLB=lQA?N=v2d-s%?KDaqG`8A9 zf=z?eYF9@^&RnE?<%F`eSuYqE@WksD93d1sFFhhGlM4etW`QM^YQ#k{&|+O>Y+V+c z+%STvy*sp&4YQQfRsB*pWf#xFbRr!uGEHOX8Jc?6f5U||`M;cviJWBI)KFdv5@+28 z_0~D4fyEdL7=8aGVnhyY!_+as^HP8DLs*4!T>r*Zv1v6KUg*O&*Gq2Oq;=C%snt)VY=|OW*cgW-m#7unvebRR2bA?W0KySvx*n8coyaVzpoFWDWaeV~Q z&`2!JJ~efJ(pRwy|MAjV=A&p?OV^1r+GH|%68&D_&%UhBNyI z)rEcB#OCJh)TF4bjwvm;c0YGo<))&nj6FPGVcWXW4V`ga@fX+YcQ00F!$XG~7RzDe zxoKTb2K#HPP_C$qA>oLB2~~Sv6Xx#b=4MMhwYsmz^K@DQ9p+n2&j?<1#nUQoQ}GBR z6uTgyO1fg2-H&9(^EBkOW&meqHBmSZE&<3O^AMF2CQg3;Nim`-N`fm)qBi5_r@9JSPj52X9(~fms!?Zav ztt~%aQ-CSx%a(I0ex@FzX;s<-2|7tj1=9PG_CEN)NyfY|)pU}SFp(@NVK7b*C|4Wr zRx`htSfrn=56h$W?Gi*cB*0!btZ%J=KUrQ&TP7_p6scXPwG=KFib$;4DvlY@X>PGW zx?B|C^$6%j7mJOV59tz@A>T`PTpBkK^%dEY%&m7N2oT6rneX3y|Ljk@JGLz5 z1?9*i%RHPn*rv{aa* zo&&(mo+oazmXZ}!3kruIhkNoVn545Au7aP^yr1=x$@`AoNaq8~c?|51*jFdwQP3nt z(8o`cF{bAX(q1UaOYb!C`9|dkTwce=C4A3Cw2szt$JW3+#&wY%0_>f+@bW{%f|hCf z`a{ecVw_Lm%AC#ma7^%*SItcc)#D7C?FCdFas*6NZ}_!;mQP3B&YpKY;NQn=#f{!? z?_r-089>sVYWLS10IQ%{$@GaJV08q#-(;zho;q7no13rwrEseTvHG#~8-M0E7XwO_aEyAx7@Jw4s3z{leT(~M zQw>jS#q&xm>W!b+&&RIa4s|w1-;b<(O*cI|R-}1b#`pH>lHULOg8qLbh2N6*Ut|5( zo$c)%FaBd^_ul{SzW(dI|KGj;-@X6e@2mbR@Kf(ZwnI^x!ZBYj=i^yAFI$#u)%@{a zNo`!E6R~<@)`qBA_>+@4eE(ID;~TkiQL=Vl4CXdcW2#@(e?1eboB-0>$-mvEk;L-* zo&j<&0Dpx_lPYDP=zd*pg1oGkCA#OMD$T!Y7qGFkA3Tq~{?OH}H)WQ-P?DwYW(lDN zk$CeFCU61&#>J{TaDt^V{Q6dx+b?Gdy4}vh&W#ptR?nG^?D{dWh1h|575xo>=Uu4> z&qrcO!C|W2d+AlVr!K(W*ZhB|2MO&X!ZIR?RrYAM_d6f-r(M>WsG*&OtG{n*bH59N zxygDGF$vLqt20uEsiz{tL@ymywexN9*RfoKp1`^B+}bTz5I18UWv=HcQ4q@JWLzcD z^n=z(l8hHQX0s6XOLq9h%#lb`Whun(R$AB4v;I~#kiIcZTh7KOh>u%@Wfeu@T6F0H zCQobwJw-DUZx^YxD3j9>u=X_ZC-+cq!A_Do-N9s3bQB^{n71I=ZhkMnT%9QHR9C1@ zr1=sh*f1dpg7KHoxfz|uWIoRcyIL9t7polU8ZTXRvwUtmbT|7A)q*7ML<$Cx%3W45 zLz}_bUY%vMrZ`;hn*D51x!Mr|3Q*hHFF04*I9h(LwnwBGo%gT4GM%6E!k)XIdNo#o zP9u}`syE6q#Dj}sJYwgDaEUhK7Ld7zq#K&0`Mhj&NDwbmO_fLcg-1O7l5#b*qzabz4|DfnfofiL%G3Z8V(04m zRhLZUth3N9o@kbSadXS+zy-5rHzO5<0R%IOQpY;QctwWquuvL4KidG0KRtcCy?vuR zE+&HuWpwGUgNW4?3j_3W$vtxjbR)2kxs-9N)LcmMq6?i1ZrJXvd8?KPbgB_U|eRClW>>ONN< zxzC(EuHp#mK`KF?jw&BiR$H!L8aSvg%bNRWaQpI{Lf%xP}s8A$JtkY^uIdrfjC4do@;8Gg<}88UI$W0;XzRjDf;V zmFQurNW=i6#LEFWZ-!!*U#V?fe|o*LAR1(I?V&0Pu<04lFu_}q1r_w~6x^g6sJ{Xa zNy$|jbaM)lT)(VZn_6o3Wz6o&m^ElYDyse&ytK%Ri0;%_3`11ql%z^URg-yd)Cq$^ zcLu(JHptvXT6Cdx4$encYH{rO5vqyCD^q^Jz_j2J2Aj9_hDs}fr*)OvpJ?hAv;DXc zx)T%C>)@xRBAk^UbG)SFSP8CxR-m*fZ}Us|*TKH?uac8)u|pGDC33DJS$C|iAE}OwAnf~Eidg9P>UnBh*Aslq30|- zL~1IK<+J(W2tF)~fkoPcSi*l6Wa}4gzR&07f*YDa?gfu)3m&nWKu$@Z^^1PDlAQ4X z%?lJLP1Q-KTb~Le?!Lj5Xf2i0si`ASifO zx2aQE2Qg}4T3KCuJsvzm(|quzUXusE#s#V2(!P@;E>c)JK7Azm~WfE#!)4hS&ChUTogko@l6tBd-f`t3U^K9%ouyAs|+; z4&U)ow=I?!0*}8r&Sn-?rz;du*aSF%Yovz^4@)lE*Ldr(1F#LC55x^3FhnYbjWhu`B zQwbEaY}yqY=vug5phq@Cdd5_-=o#1D2pGz}@YH?SuhMHqIE=rkdAViTe zRTA5x7yx)Rs?4eo!LwBcFSC_}G4m+!kL7~sk3tEULS~EY`w1$j#Jp!kfnFTPlqDUt zu8z)snwNpX8UmEF#TDfJ5P1uo;pxpD1q(K*M64+~vXZ{^4K{fqBX1SJb<~Ew7$qbc zlzpt6xabo>j26gPg^1Ni*n+#MT6aB)nP3rzBHabHfd|akJG1{+=YK9H`RRf-yiargTeoPXYYgS7s4lomDYKq z^go+U-XBiIGA|nu!GK)a9pQw}ZD2oEmEpe11fD&Q_lr zXV((BlE#&ZouZ5-ILd&FO!P$th`tI8xSMh9Ljby(qasXEqOE!WI6tP=N`5^8tO-lH zhC7WTplFN#^T%WyaISIqG#&Li%tGr^w|oJb-{NN;e>&&Ur_)2vn?9bAw-fiV9|6wB zeYTeS{4YWN7YZ!~|L|K$0@G0cclX=vCw~3k-N)bF=YRQv`CoRn+vI-<`ho`N#Zr;S z)oigWlcQA$ncRBG;dIzn&B5N!nN+~+F-LauK8wtK7Mc4jGWS*FWEz>TWa(i08tJq! z@9>*L^^HypbM)6E`(@XD+*~7B4DdtzF`JHNh2nL6InGU1Bhtm#x+%}Xv@v!${mM1y z#1eYudOv4po*Pxl4d4GoF$e9#a-QF2{nu}wJc+;mJ3Ehe9?|>%^wG}aM^ASk|J&2u zr}yvw=YIe3+5e#^z|)0a?BIdl=_RkTPw;l?*PWZ*zvB0=`28z>p9@apf|F&#_;XR} zPvy#dTx6dXSMzixbHP1gW$h%Le}ocU)RLon@w>YEW#6f9pN(@x9H@XNo9QP4Z6zVDK9Z?m@0nepU8%T z!E1Mv{PgaS^o!+6(Ya53k$aiyrKajeK|FlIDUkf~dc$-IG2y4=9t;&77Z>y5s?=dF z0vzN5zQEi;PG)2$E1szlrZ8uwy}jq>PW4EL<0n>$k_PEj4d>u4rc)O2C}OoG(rR*8 zle3yaqus23-p58d?-UP$rA7v}%it`90rghI54cvDZSSk(RXT%3>ci4Tnr^3j)B&>9 zIcI;8gP)HMmWvC^d1*6r^0QtD@CWdaL2z_YjPVgfLdd@Hq8_Rq1KVM(;0abIGq zb%>ApB|guBy|EWp1q@9_MC@8O3)mPy3UDS=cVqZ*pyNk)V)(O1b*}wYU^bL;rmHH) zvY>kuxC^TJ{{L1&P**<;efUo|I01Qn5I6NTk>Uqmmk*M&RPlqOJ{Lz)Wa%QE%`zl& z;Zb$~>lI+2Y$#U31(iPdsAZq1P^~FuJJ)nl7Z{3-2FVt&I_VTE97E+uMT<1`8fS`_ zVSSpjWb0i*p=;3gyj(8wacsb$g6`z92h)!^)f?Nk(OfD3-%I|q?UcS7(1B5N5bCr! zgsmKYVi>hO#n~~5?t*hQ;cqYb4u`N;ViWm6cwG=-cm_=7(c+N9O@57ao@kgY#mkp? zB09%u*I97SAZcW;bXIq{SDvBmUU_TOE7)3#faX@4hr&+-%-w>ITx{>XuHp zxTN_xzESFzz|sg`zE}VG5OH8$mHl#|Nc)@(iIqF){7glupu|g(pHGW9Ix?K2_y%9@ zbLp3jwh&OAdq6(BW_=FU^DC&6ePIj=I2jD`5o>tL47ibj{fWQ-<{Pk~omWLRyiqg+ zqC~_q3&cXiyXyC@$CcSBccS^)=7%K#NK^adoubD%z~$LI!wfr$uESo?3l+SD3Usob zp5^D{X#`clH)Q#*hqF~W$sbai{!BAJ@b7Z*krh9e8nk}U=)eCehB5(YF5oqz4YmXjLk$ndOef`6 z0{BKxGvo`Q9(~sfRiNL1{nRMNccXiemLfB3r(Dk9AxB13;n$#4bman_ku|e#E<{yR zq%rEWz1h90N#3vTD~E%kK;5|QzoN@#6>xNg9KIe-8edHpZI`{!eGuj(&RUo0aahBO z00~F<2z$L3<9_hm47^z(Q?TObBTkG`>Wt`gA4OEU)oYZ^yAI`9J9R}sqt+hbn{RwX zitnHrreS)IW+*FpsSe8LG0pi8M>SCX3RJGio4F#U>3sD}2?mM?eXr}LV}t7-fP1 zg?L7Vn@5nH(jYvVlI{WfT{|3a6U15yokmmi+zFmelSkV->JMVyWBa5ymgJ>g4wcbr z2XTshVr48VV)-H{S*3#t8%$!xQIHh?g7oc1O^!?f214X8irO7BD!?)D;DA?4P<>xy zv0FA@POVR=I+*1I1@Pqz9ETo`imNF)5_yp?E$L|V`UZmpPuq~14=7h5zG%^rx|=PC zv!pWrMTs+@NiBIs=kf6PzE@wb^$@xpx^4lpYDd5d5$dO@x`)O26f30jc0kZ?CqP-Q z2YYT-mHp_CveTtWX@!3@#Id?H3OV4pqH0ICt+W~J2&B(0@ufV4LRn46&_*2x0x+!{ z^E1un`oXZh!h+$V%pyNB***sD_jH{=7L@Eds`JK7&eFl6_?S(7J37@u48--0U4!tG zWKlyzFVQz$y+E_HuudJl4c^wI{BHWn9ksa1W@`e1;1{je#*v)lB;D!ssMf5KlIQrB z1Iy@aineKVD(M6&;3rf&9kGHo0Mx4pzz2fAm_M3iuX~A4`Xvgd)-l|4>PFm$h0C~v zi1}mz6D-M-Cs0l*bs>cAWzVqGWG1|pNc1?r3ifSF7(cu*dC0ZO>E?llj z6V@LCARV4+ zr@ZB4p#Ip|ZXm#lc>^)?9L7JOmfh?bnNM{*!|xOrRoBl( z)U|ok^kr;XgT1Q_*Kyq|VU}BeDb{2Ou1EVU=x*WIy|Wj`l@7-unWz9*Jp*OBX&y=| z5BlbpT9}wt3Nq$%9enJt*7%mHRgDJfmo*nJItI%ZztwI)v{PFUf7NY54zB&be4)H6 zuD)`YQ&%^K;tn?Wgi zCA2``)y<4~DHANr#Jy>6|8vg^n$Q zMw0Ff6(c!Kgv(+NJP65QTEP7wpNVgP#)Eg0uJZW&3#s4Gp9Q_1(Myffiy75oca9E% z+x`Bo4-*fe_Mr5gKUL61Cy$24vf?4RH9}f*H(XvVirlOJ^XO6UhofJGf1Y$zt8i8{ z3`o7pqC}ebeb@tw2cyae@6uvkj4_WPq}cQg#;WIX0U2kxyQx8>hbK1!cvffW;-Uq@`f-#=XcCUN%!c{7C8vy!*B~0HB4Wjk>peq-5;JE)r?_oG36Z1Ft6e$H&u!- zJ0!0N5_i!wd1zhI?v32m-rxhwpCQ~D+2J4JsnwX6_8!6zblzPZQDAI1)~hDZ#*jET zLM9yw=_nlqNO~fT8t>XP1^*!+`?jx!8GQ>bdtQ<~g(!}rrw(i|=Qlko*b)}=NOYZr zh1c#68Fi5}0-^R9uT?+GWJr;rSAwe=UoYb7HvIzmf61Ixg2%9hx{fsZb_Cu(0r zD8M11=v3JCPtWyl*@)OY;Niy)?vDa9jRI-lyb->h1o9f#zc#!CD`Y-#EhqU|Ky>RW zTWen&@0*P_?klj%_%B`wc56l17kAKYBuLc0q*sUl(?!>QXW%xbT?%?DtsUh?3|0slQP1djS^Q;Q_`z!YtgE?tsz3qO(&x#x>40`c^9lY ziZd{haZy9MFsY}$b+mV*C6%ovi{f{x?F2QQepj|0OXwB@Eh=_5`}8&|!jNA1{&#Cy zhc?zwS?!BgDWPCihr~#wYSY5cG4%MZ*DllpmE`$$Okw|09u@0jUBxYrU`dU6{tjF> zJok+o;^#G%+ir<Q&WvvE44EMvOdQ+5@p`P@d?B_ja+7CnJNSiL|^tF>2R ztASQbuck`9WPgXO+(N$;b=$9UI0%6e=4KDnx*HWfVyoO5zfwINv9a03i;iK;{HOqjHLll@;L3xjWh zXP1q$hMP5X7VK3K!Ws-GxJPd|XSHPh^0=?aaF)UJMw2^)!7QV;-p$lTSYr^9M4AX+ zq&BF$!q8j0fJCKFd846myjA_JzV6KqM~S*qgw4b&5mO%q$FOfc`5tP+@eR3Nb%AVY zLUyw%!9dvNX7Lhk$fSHl@xE8Z{38V%oGS98V@in}Q4l8E7!IDjER!y{mMa>Civ3cI z1)kx?jwLp#zt?M%$}z|n(E0pKlLDQ~CBt#*bvF2Yg#vop(XPu%tKrDL++bODF;x9; zODt_fN?pQGmuYH`qr8Y4;%NY2y|-453)chRu$Y&(0lQ~!-W?_X>($G)5QBMd2rd}H zg%@t76|jbwSEPfhsB-~Ozl&7zF1%=r_E1yZF<_LGCfA0ZUPW?4@G;!XrrJUo65>$d zZTjKaQ4i%P{Q09`W4{uuWHNX!oaevAVl63t=5L^)(MKTFe#SG%zk3Ep%DyAc39u*74cdrrh97RSFfZ zW~0&Id|oVPgKU!K;{j&u(*Z0d(_1g0UsY@1U%^dLiHxO^+!)*qOSs|1i!QRWdBdv_ z-};?g552(3+##4Lhe7JwOWLozKpo`P*>a3VWX}K9l)WhFaB>H6s^D(b*^KC7+xlEy zPm!txz4!)e@G+Rb(R_5h`zl`4wby8%yM{e6vahmT+L;<0@zd;dTCAr-=0M9ur-w4jGMiUo4E{*&@a=Hr7Er}5=nG(qfJQwW zdcVc2674rQgVSH z5ClyUxLCeDQvAv(hvQ;7y6&7dGZSa0j7$lgMaUlX9I)qWHm@uB+&H^UcL&-xPR;SN zO{`%?qH6GGrWNMr$mivs*{2mf-Q_RpU?*V67?#O2%SNTnNQsA!Nk=m9l1Ezxy3{9K zOr6SU^+rWjZq`<)Mjxx#Rp0bMMb+RJVW9syI8l8%)(fm|5eCxNS;RUBNz)ni%TEI1?nbu$$)n4;(+9iJ?_O<1_ zqNsg7oh=s+i{(Q7PeLQL*f4q8y0Pf45khNxFqgut80W)Pt(5O*71};D&N7nLG3;L@ zZ$bUzOv(BjEGDf%1qqx%2V|&Z_izeXk)*r&S0*OJWb9=xJ1k9&#O|XpoAxWk;Ye04 zqxYOn`ys$xTeng8Yq)Emw-aL=P*gK5x3Z!zp-CkgwLk%9h}IY&Hxe!)x{*k_2x`{A zB(-0NKWu#BDk@(;j|o`vqV{SP^EOdtM}MqS(3>$GCB3x=K_Fr=2XfW3hPzH@U9Dgc zO_rYx!ho`~0XQ^x-@D}TsM-c_@a$#3t^VJ&H3`e3`KT>})mF%xxqHRDsf9%WPQZg= z>?m4U4gKSAVekAEJA~kyYFcwGGpo1jhHXZ5tuRMtT$e}(~Y(c!IgLqHttH?Z*N?!!BWqxe?z1d>-7`0 z)M8%W->leX`0AE{XM?0G>zlM{{d3lW-CBUUHjsQu8i$aL&=)|uCWLMPB=Fn7;s7&9 z(oM!)PC2ldU|2*Y(4U4u@)_PDvPX_p&f4;X zW7op&Iq7`<^YNhWpHU5u(rjs8enx|Pd8-C@@$yw#+IfT5H@H_q){RDXvhb9?nu8sU zt1@2%xpTv$S&ni9LY>-W@&T!9v>YnDf&ZP3(y1DwE(v8o-6Fe;UjUtstu7a3V}fzC zo%;)JQL(}nrT|3@sEDQMzl~M26VCf*Q`&-SU5r34-Da#7kmD>*K)m)X9gg8txO;K& z8MEBnMXb}oc)i;EnRh;Yh@c^u{a4eE$Am}-Ux`3Vue*@7S?Qenc%8IZ@!Ob``9HFD zW6iUxd^*zf7BYoVa&9MU-L>v$bvtI*lzomn}8gHl8h1ycMx@<$O4B zl=bk1)r{zvwyFb#)`4!$wM2D}jt^cxKX~^%cKgtZHowe(ch?j@n-1rz8SbVf)BVdb zo3EVoYHC@vYCvt+Q)n<=>9jX^ecQ;k8ipQvH8Se{cA~G0v-D^juAQrIPLuIjL~=@& zej|2nPVA?L2GI_7{5X#250TyuMmT@AaEthBZE@a>=Z7V=-++7SqxU!q)8gnrD+jA(>f?yN>InrAz$fUw4=myKWuLuph&-$*eF{#%&r_ z%66+h4ImB3zEcdLtp<$8cAUC+d@PWoaP9pEC-Z3unc=WDt6qm+l~wldW4-ZF7kU|q zdULa;$NR0F4{qKw>>EkH5oSnpr5Npb<=Ag94jO1t8a5WrX zkJby>RM_&&n2AG(`)%XX{Wab2o$!ZqaDRiIl;(AZimZ`K`4YxNVBp}d0FqZ8TFkuiIb>5K#C$HAeZt2O;gj(!a}4m zDybqSP!C^Ojy}MqN*L+}>t*Qk>4|j2M;#s4Ux4zFw^DrpG|Z*WGzIR$V+z42SLGs` z++qy|T27YX@DJa;IC%c*MS_a=QGC-*!k2lqD zt;^%x>0B#)H)j@x;W78^AJ@(FP3uHtqol0#`Ihn(#;{YSu5*9?ZR9G{5iTw@GYJC) zFnbbupE(54jR*W35s1+kr@9ctYegQ`hdkK`x;u#Q>w?5UXIT#k^Njm2_#6>`#&nM> zjjHk8yoCIvdWPUt=;x&xw>ehvu7U@nSacV0g3*a?JMOP38t)DR0mB&NTaWu|484t$ zKShbk7?hvE_aznjm@4!buYkBCXsc6tYVK4?$T(~j->&QD4byHaZRv3_!hg={c<5E!70IG|EVCuTV0dGRc$wuzFfO4UDA%gk`BQ3k=& zDSEoXYI&j5nu7_=XhEJ>*N1;UVwEY`KeS_HnvIFi2mQ-^Z9F`vOinh*7-ku z{J84;A3u7u3+KQ4ElO#NVf0K|IYt?l{_nEs{m*~m%n*_ez8cp z!_8!OduMw~{bwh6l`n=D$q(s#nu0cEv6v~D@SOha7xVLn8+d@P`sPFIi{s6?%mDbJ@y z0>2U}_XUyh#o6Kt<@hP2Tr7(rRUaD_L-fYxvSO$X>cV69Rr277`#jjhiAI@vA6fX< zKbd-4in&n&;gAFNbb@jjCR~IZN zn;j`&ov8<0O-zLhM}-0&&PkOm3$6WtC6NXMRI^kgwA{l(1okC8EiN6OjI?yhy2<8o@6csgV@CQ?WBJw4AcoKTg08pEP9djtP^Fe|(V~z4`w5=Yw}I zlEb6q?YlRBJAD4)dGg@kNd5hwm;8Kq{NtOSjuX}5ow~w*Pu_f=9K8N}@|VNc&lQ^f zuea}B9382V-n>f=U%h>K_(FYq`1;w)pPnDS{vr8J^?d#2IC**a>hM?%d;A8c?Y? z43r~d4zeZ4z2oqs+&deKV`-W?tR2)=*!<`oPAKvaF+;4rG^>lZW*0N6bT)dc?j z>F9-B&+``tFV$!OY1Lge?{93NB1aVX%qJLqaddoSOKVaiRJ+czbF|=|6}sg+{N_-7 zv$3%O%se$IyPmH2hirkUW)*$h&=d+#b0%QXRJh8Dp}je1h4wIS6@P);@18nV_znwqpfEd~K$rf9 z^=#jK^YLnc!d2-b1s0!3$;`zF!L@C5Ds4JMQw=!&;NfR{{Nb+e=XM^Hh+{H;9CF>0ks0619f%NGsU9=>t6Pg