Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJörn Friedrich Dreyer <jfd@butonic.de>2012-08-25 02:05:07 +0400
committerJörn Friedrich Dreyer <jfd@butonic.de>2012-08-25 02:05:07 +0400
commitc8255a170c2d7449b4e7728edd2237eea71dca80 (patch)
treee5a3854ec472be9700064bc7b689b8adf7c7f692 /3rdparty
parent0c0ae928dcd483211a92303eb2b202453d02a86e (diff)
parent46d6fd15e4cc02d45079ffc688be0684e61f1434 (diff)
Merge branch 'master' of git://gitorious.org/owncloud/owncloud into oracle-support
Conflicts: 3rdparty/Sabre/CardDAV/Plugin.php 3rdparty/smb4php/smb.php apps/bookmarks/ajax/addBookmark.php apps/bookmarks/ajax/editBookmark.php apps/bookmarks/appinfo/migrate.php apps/calendar/ajax/calendar/edit.form.php apps/calendar/ajax/changeview.php apps/calendar/ajax/import/import.php apps/calendar/ajax/settings/guesstimezone.php apps/calendar/ajax/settings/setfirstday.php apps/calendar/ajax/settings/settimeformat.php apps/calendar/ajax/share/changepermission.php apps/calendar/ajax/share/share.php apps/calendar/ajax/share/unshare.php apps/calendar/appinfo/app.php apps/calendar/appinfo/remote.php apps/calendar/appinfo/update.php apps/calendar/appinfo/version apps/calendar/js/calendar.js apps/calendar/l10n/da.php apps/calendar/l10n/de.php apps/calendar/l10n/fi_FI.php apps/calendar/l10n/gl.php apps/calendar/l10n/he.php apps/calendar/l10n/hr.php apps/calendar/l10n/ja_JP.php apps/calendar/l10n/lb.php apps/calendar/l10n/lt_LT.php apps/calendar/l10n/nb_NO.php apps/calendar/l10n/pl.php apps/calendar/l10n/pt_PT.php apps/calendar/l10n/ro.php apps/calendar/l10n/ru.php apps/calendar/l10n/sv.php apps/calendar/l10n/zh_CN.php apps/calendar/l10n/zh_TW.php apps/calendar/lib/app.php apps/calendar/lib/calendar.php apps/calendar/lib/object.php apps/calendar/lib/share.php apps/calendar/templates/part.choosecalendar.rowfields.php apps/calendar/templates/part.import.php apps/calendar/templates/settings.php apps/contacts/ajax/activation.php apps/contacts/ajax/addressbook/delete.php apps/contacts/ajax/contact/add.php apps/contacts/ajax/contact/addproperty.php apps/contacts/ajax/contact/delete.php apps/contacts/ajax/contact/deleteproperty.php apps/contacts/ajax/contact/saveproperty.php apps/contacts/ajax/createaddressbook.php apps/contacts/ajax/cropphoto.php apps/contacts/ajax/currentphoto.php apps/contacts/ajax/importaddressbook.php apps/contacts/ajax/oc_photo.php apps/contacts/ajax/savecrop.php apps/contacts/ajax/selectaddressbook.php apps/contacts/ajax/updateaddressbook.php apps/contacts/ajax/uploadimport.php apps/contacts/ajax/uploadphoto.php apps/contacts/appinfo/migrate.php apps/contacts/appinfo/remote.php apps/contacts/css/contacts.css apps/contacts/import.php apps/contacts/index.php apps/contacts/js/contacts.js apps/contacts/l10n/ca.php apps/contacts/l10n/cs_CZ.php apps/contacts/l10n/da.php apps/contacts/l10n/de.php apps/contacts/l10n/el.php apps/contacts/l10n/eo.php apps/contacts/l10n/es.php apps/contacts/l10n/et_EE.php apps/contacts/l10n/eu.php apps/contacts/l10n/fa.php apps/contacts/l10n/fi_FI.php apps/contacts/l10n/fr.php apps/contacts/l10n/he.php apps/contacts/l10n/hr.php apps/contacts/l10n/hu_HU.php apps/contacts/l10n/ia.php apps/contacts/l10n/it.php apps/contacts/l10n/ja_JP.php apps/contacts/l10n/ko.php apps/contacts/l10n/lb.php apps/contacts/l10n/mk.php apps/contacts/l10n/nb_NO.php apps/contacts/l10n/nl.php apps/contacts/l10n/pl.php apps/contacts/l10n/pt_BR.php apps/contacts/l10n/pt_PT.php apps/contacts/l10n/ro.php apps/contacts/l10n/ru.php apps/contacts/l10n/sk_SK.php apps/contacts/l10n/sl.php apps/contacts/l10n/sv.php apps/contacts/l10n/th_TH.php apps/contacts/l10n/tr.php apps/contacts/l10n/zh_CN.php apps/contacts/l10n/zh_TW.php apps/contacts/lib/addressbook.php apps/contacts/lib/hooks.php apps/contacts/lib/vcard.php apps/contacts/photo.php apps/contacts/templates/part.contact.php apps/contacts/templates/part.contacts.php apps/contacts/templates/part.cropphoto.php apps/contacts/templates/part.importaddressbook.php apps/contacts/templates/part.selectaddressbook.php apps/contacts/thumbnail.php apps/files/ajax/download.php apps/files/ajax/newfile.php apps/files/ajax/timezone.php apps/files/appinfo/update.php apps/files/appinfo/version apps/files/index.php apps/files/js/fileactions.js apps/files/js/filelist.js apps/files/js/files.js apps/files/l10n/ar.php apps/files/l10n/bg_BG.php apps/files/l10n/ca.php apps/files/l10n/cs_CZ.php apps/files/l10n/da.php apps/files/l10n/de.php apps/files/l10n/el.php apps/files/l10n/eo.php apps/files/l10n/es.php apps/files/l10n/et_EE.php apps/files/l10n/eu.php apps/files/l10n/fa.php apps/files/l10n/fi_FI.php apps/files/l10n/fr.php apps/files/l10n/gl.php apps/files/l10n/he.php apps/files/l10n/hr.php apps/files/l10n/hu_HU.php apps/files/l10n/ia.php apps/files/l10n/id.php apps/files/l10n/it.php apps/files/l10n/ja_JP.php apps/files/l10n/ko.php apps/files/l10n/lb.php apps/files/l10n/lt_LT.php apps/files/l10n/mk.php apps/files/l10n/ms_MY.php apps/files/l10n/nb_NO.php apps/files/l10n/nl.php apps/files/l10n/nn_NO.php apps/files/l10n/pl.php apps/files/l10n/pt_BR.php apps/files/l10n/pt_PT.php apps/files/l10n/ro.php apps/files/l10n/ru.php apps/files/l10n/sk_SK.php apps/files/l10n/sl.php apps/files/l10n/sr.php apps/files/l10n/sr@latin.php apps/files/l10n/sv.php apps/files/l10n/th_TH.php apps/files/l10n/tr.php apps/files/l10n/uk.php apps/files/l10n/zh_CN.php apps/files/l10n/zh_TW.php apps/files_archive/js/archive.js apps/files_encryption/lib/cryptstream.php apps/files_encryption/lib/proxy.php apps/files_encryption/tests/proxy.php apps/files_external/appinfo/app.php apps/files_external/lib/smb.php apps/files_external/lib/streamwrapper.php apps/files_external/tests/config.php apps/files_external/tests/smb.php apps/files_sharing/ajax/email.php apps/files_sharing/ajax/getitem.php apps/files_sharing/ajax/setpermissions.php apps/files_sharing/ajax/share.php apps/files_sharing/ajax/toggleresharing.php apps/files_sharing/ajax/unshare.php apps/files_sharing/ajax/userautocomplete.php apps/files_sharing/js/settings.js apps/files_sharing/js/share.js apps/files_sharing/lib_share.php apps/files_sharing/settings.php apps/files_sharing/sharedstorage.php apps/files_sharing/templates/settings.php apps/files_versions/ajax/rollbackVersion.php apps/files_versions/versions.php apps/gallery/ajax/thumbnail.php apps/gallery/appinfo/app.php apps/gallery/appinfo/update.php apps/gallery/appinfo/version apps/gallery/css/styles.css apps/gallery/index.php apps/gallery/js/pictures.js apps/gallery/l10n/ca.php apps/gallery/l10n/cs_CZ.php apps/gallery/l10n/de.php apps/gallery/l10n/el.php apps/gallery/l10n/es.php apps/gallery/l10n/fi_FI.php apps/gallery/l10n/fr.php apps/gallery/l10n/it.php apps/gallery/l10n/pl.php apps/gallery/l10n/pt_PT.php apps/gallery/l10n/ru.php apps/gallery/l10n/sl.php apps/gallery/l10n/sv.php apps/gallery/l10n/th_TH.php apps/gallery/l10n/tr.php apps/gallery/l10n/zh_CN.php apps/gallery/lib/album.php apps/gallery/lib/hooks_handlers.php apps/gallery/lib/managers.php apps/gallery/lib/photo.php apps/gallery/lib/tiles.php apps/gallery/lib/tiles_test.php apps/gallery/templates/index.php apps/media/lib_ampache.php apps/media/lib_collection.php apps/media/lib_media.php apps/remoteStorage/lib_remoteStorage.php apps/tasks/ajax/addtaskform.php apps/tasks/ajax/edittask.php apps/user_ldap/appinfo/update.php apps/user_ldap/group_ldap.php apps/user_ldap/lib_ldap.php apps/user_ldap/settings.php apps/user_ldap/templates/settings.php apps/user_ldap/user_ldap.php apps/user_migrate/appinfo/app.php apps/user_migrate/templates/settings.php apps/user_webfinger/host-meta.php config/config.sample.php core/js/js.js core/l10n/da.php core/l10n/de.php core/l10n/fi_FI.php core/l10n/gl.php core/l10n/he.php core/l10n/hr.php core/l10n/id.php core/l10n/ja_JP.php core/l10n/lb.php core/l10n/lt_LT.php core/l10n/nb_NO.php core/l10n/pl.php core/l10n/pt_PT.php core/l10n/ro.php core/l10n/ru.php core/l10n/sv.php core/lostpassword/index.php core/templates/layout.user.php core/templates/login.php db_structure.xml index.php l10n/af/calendar.po l10n/af/contacts.po l10n/af/core.po l10n/af/files.po l10n/af/settings.po l10n/ar/calendar.po l10n/ar/contacts.po l10n/ar/core.po l10n/ar/files.po l10n/ar/media.po l10n/ar/settings.po l10n/bg_BG/calendar.po l10n/bg_BG/contacts.po l10n/bg_BG/core.po l10n/bg_BG/files.po l10n/bg_BG/media.po l10n/bg_BG/settings.po l10n/ca/calendar.po l10n/ca/contacts.po l10n/ca/core.po l10n/ca/files.po l10n/ca/gallery.po l10n/ca/settings.po l10n/cs_CZ/calendar.po l10n/cs_CZ/contacts.po l10n/cs_CZ/core.po l10n/cs_CZ/files.po l10n/cs_CZ/gallery.po l10n/cs_CZ/settings.po l10n/da/calendar.po l10n/da/contacts.po l10n/da/core.po l10n/da/files.po l10n/da/settings.po l10n/de/calendar.po l10n/de/contacts.po l10n/de/core.po l10n/de/files.po l10n/de/gallery.po l10n/de/settings.po l10n/el/calendar.po l10n/el/contacts.po l10n/el/core.po l10n/el/files.po l10n/el/gallery.po l10n/el/settings.po l10n/eo/calendar.po l10n/eo/contacts.po l10n/eo/core.po l10n/eo/files.po l10n/eo/media.po l10n/eo/settings.po l10n/es/calendar.po l10n/es/contacts.po l10n/es/core.po l10n/es/files.po l10n/es/gallery.po l10n/es/settings.po l10n/et_EE/calendar.po l10n/et_EE/contacts.po l10n/et_EE/core.po l10n/et_EE/files.po l10n/et_EE/settings.po l10n/eu/calendar.po l10n/eu/contacts.po l10n/eu/core.po l10n/eu/files.po l10n/eu/settings.po l10n/fa/calendar.po l10n/fa/contacts.po l10n/fa/core.po l10n/fa/files.po l10n/fa/settings.po l10n/fi_FI/calendar.po l10n/fi_FI/contacts.po l10n/fi_FI/core.po l10n/fi_FI/files.po l10n/fi_FI/gallery.po l10n/fi_FI/settings.po l10n/fr/calendar.po l10n/fr/contacts.po l10n/fr/core.po l10n/fr/files.po l10n/fr/gallery.po l10n/fr/media.po l10n/fr/settings.po l10n/gl/calendar.po l10n/gl/contacts.po l10n/gl/core.po l10n/gl/files.po l10n/gl/settings.po l10n/he/calendar.po l10n/he/contacts.po l10n/he/core.po l10n/he/files.po l10n/he/settings.po l10n/hr/calendar.po l10n/hr/contacts.po l10n/hr/core.po l10n/hr/files.po l10n/hr/settings.po l10n/hu_HU/calendar.po l10n/hu_HU/contacts.po l10n/hu_HU/core.po l10n/hu_HU/files.po l10n/hu_HU/settings.po l10n/hy/calendar.po l10n/hy/contacts.po l10n/hy/core.po l10n/hy/files.po l10n/hy/settings.po l10n/ia/calendar.po l10n/ia/contacts.po l10n/ia/core.po l10n/ia/files.po l10n/ia/settings.po l10n/id/calendar.po l10n/id/contacts.po l10n/id/core.po l10n/id/files.po l10n/id/settings.po l10n/it/calendar.po l10n/it/contacts.po l10n/it/core.po l10n/it/files.po l10n/it/gallery.po l10n/it/settings.po l10n/ja_JP/calendar.po l10n/ja_JP/contacts.po l10n/ja_JP/core.po l10n/ja_JP/files.po l10n/ja_JP/settings.po l10n/ko/calendar.po l10n/ko/contacts.po l10n/ko/core.po l10n/ko/files.po l10n/ko/settings.po l10n/lb/calendar.po l10n/lb/contacts.po l10n/lb/core.po l10n/lb/files.po l10n/lb/settings.po l10n/lt_LT/calendar.po l10n/lt_LT/contacts.po l10n/lt_LT/core.po l10n/lt_LT/files.po l10n/lt_LT/settings.po l10n/mk/calendar.po l10n/mk/contacts.po l10n/mk/core.po l10n/mk/files.po l10n/mk/settings.po l10n/ms_MY/calendar.po l10n/ms_MY/contacts.po l10n/ms_MY/core.po l10n/ms_MY/files.po l10n/ms_MY/settings.po l10n/nb_NO/calendar.po l10n/nb_NO/contacts.po l10n/nb_NO/core.po l10n/nb_NO/files.po l10n/nb_NO/settings.po l10n/nl/calendar.po l10n/nl/contacts.po l10n/nl/core.po l10n/nl/files.po l10n/nl/settings.po l10n/nn_NO/calendar.po l10n/nn_NO/contacts.po l10n/nn_NO/core.po l10n/nn_NO/files.po l10n/nn_NO/settings.po l10n/pl/calendar.po l10n/pl/contacts.po l10n/pl/core.po l10n/pl/files.po l10n/pl/gallery.po l10n/pl/settings.po l10n/pt_BR/calendar.po l10n/pt_BR/contacts.po l10n/pt_BR/core.po l10n/pt_BR/files.po l10n/pt_BR/settings.po l10n/pt_PT/calendar.po l10n/pt_PT/contacts.po l10n/pt_PT/core.po l10n/pt_PT/files.po l10n/pt_PT/gallery.po l10n/pt_PT/settings.po l10n/ro/calendar.po l10n/ro/contacts.po l10n/ro/core.po l10n/ro/files.po l10n/ro/settings.po l10n/ru/calendar.po l10n/ru/contacts.po l10n/ru/core.po l10n/ru/files.po l10n/ru/gallery.po l10n/ru/settings.po l10n/sk_SK/calendar.po l10n/sk_SK/contacts.po l10n/sk_SK/core.po l10n/sk_SK/files.po l10n/sk_SK/settings.po l10n/sl/calendar.po l10n/sl/contacts.po l10n/sl/core.po l10n/sl/files.po l10n/sl/gallery.po l10n/sl/settings.po l10n/sr/calendar.po l10n/sr/contacts.po l10n/sr/core.po l10n/sr/files.po l10n/sr/settings.po l10n/sr@latin/calendar.po l10n/sr@latin/contacts.po l10n/sr@latin/core.po l10n/sr@latin/files.po l10n/sr@latin/settings.po l10n/sv/calendar.po l10n/sv/contacts.po l10n/sv/core.po l10n/sv/files.po l10n/sv/gallery.po l10n/sv/media.po l10n/sv/settings.po l10n/templates/bookmarks.pot l10n/templates/calendar.pot l10n/templates/contacts.pot l10n/templates/core.pot l10n/templates/files.pot l10n/templates/gallery.pot l10n/templates/media.pot l10n/templates/settings.pot l10n/th_TH/calendar.po l10n/th_TH/contacts.po l10n/th_TH/core.po l10n/th_TH/files.po l10n/th_TH/gallery.po l10n/th_TH/settings.po l10n/tr/calendar.po l10n/tr/contacts.po l10n/tr/core.po l10n/tr/files.po l10n/tr/gallery.po l10n/tr/settings.po l10n/uk/calendar.po l10n/uk/contacts.po l10n/uk/core.po l10n/uk/files.po l10n/uk/media.po l10n/uk/settings.po l10n/zh_CN/calendar.po l10n/zh_CN/contacts.po l10n/zh_CN/core.po l10n/zh_CN/files.po l10n/zh_CN/gallery.po l10n/zh_CN/settings.po l10n/zh_TW/calendar.po l10n/zh_TW/contacts.po l10n/zh_TW/core.po l10n/zh_TW/files.po l10n/zh_TW/settings.po lib/app.php lib/base.php lib/connector/sabre/file.php lib/connector/sabre/locks.php lib/connector/sabre/node.php lib/db.php lib/filecache.php lib/fileproxy/quota.php lib/files.php lib/filestorage/local.php lib/filesystemview.php lib/group/database.php lib/helper.php lib/installer.php lib/json.php lib/l10n.php lib/migrate.php lib/mimetypes.fixlist.php lib/ocs.php lib/preferences.php lib/public/json.php lib/public/util.php lib/template.php lib/user.php lib/user/database.php lib/util.php lib/vcategories.php ocs/providers.php settings/admin.php settings/ajax/lostpassword.php settings/ajax/removeuser.php settings/ajax/setbackgroundjobsmode.php settings/ajax/setlanguage.php settings/ajax/setquota.php settings/ajax/togglegroups.php settings/apps.php settings/css/settings.css settings/js/apps.js settings/js/users.js settings/l10n/bg_BG.php settings/l10n/ca.php settings/l10n/cs_CZ.php settings/l10n/da.php settings/l10n/de.php settings/l10n/el.php settings/l10n/eo.php settings/l10n/es.php settings/l10n/et_EE.php settings/l10n/eu.php settings/l10n/fa.php settings/l10n/fi_FI.php settings/l10n/fr.php settings/l10n/gl.php settings/l10n/he.php settings/l10n/hr.php settings/l10n/hu_HU.php settings/l10n/it.php settings/l10n/ja_JP.php settings/l10n/ko.php settings/l10n/lt_LT.php settings/l10n/mk.php settings/l10n/ms_MY.php settings/l10n/nb_NO.php settings/l10n/nl.php settings/l10n/nn_NO.php settings/l10n/pl.php settings/l10n/pt_BR.php settings/l10n/pt_PT.php settings/l10n/ru.php settings/l10n/sk_SK.php settings/l10n/sl.php settings/l10n/sv.php settings/l10n/th_TH.php settings/l10n/tr.php settings/l10n/zh_CN.php settings/personal.php settings/templates/admin.php settings/templates/users.php
Diffstat (limited to '3rdparty')
-rw-r--r--3rdparty/Crypt_Blowfish/Blowfish.php2
-rw-r--r--3rdparty/Dropbox/API.php380
-rw-r--r--3rdparty/Dropbox/Exception.php15
-rw-r--r--3rdparty/Dropbox/Exception/Forbidden.php18
-rw-r--r--3rdparty/Dropbox/Exception/NotFound.php20
-rw-r--r--3rdparty/Dropbox/Exception/OverQuota.php20
-rw-r--r--3rdparty/Dropbox/Exception/RequestToken.php18
-rw-r--r--3rdparty/Dropbox/LICENSE.txt19
-rw-r--r--3rdparty/Dropbox/OAuth.php151
-rw-r--r--3rdparty/Dropbox/OAuth/Consumer/Dropbox.php37
-rw-r--r--3rdparty/Dropbox/OAuth/Curl.php282
-rw-r--r--3rdparty/Dropbox/README.md31
-rw-r--r--3rdparty/Dropbox/autoload.php29
-rw-r--r--3rdparty/Google/LICENSE.txt21
-rwxr-xr-x3rdparty/Google/OAuth.php751
-rwxr-xr-x3rdparty/Google/common.inc.php185
-rw-r--r--3rdparty/MDB2/Schema/Parser.php27
-rw-r--r--3rdparty/MDB2/Schema/Parser2.php27
-rw-r--r--3rdparty/MDB2/Schema/Validate.php22
-rw-r--r--3rdparty/MDB2/Schema/Writer.php16
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre.includes.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Backend/Abstract.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Backend/PDO.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Calendar.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/CalendarObject.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/CalendarQueryParser.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/CalendarQueryValidator.php39
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/CalendarRootNode.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/ICSExportPlugin.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/ICalendar.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/ICalendarObject.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Plugin.php146
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Principal/Collection.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Principal/ProxyRead.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Principal/User.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Schedule/IMip.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Schedule/IOutbox.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Schedule/Outbox.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Server.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/UserCalendars.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/Version.php2
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CalDAV/includes.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CardDAV/AddressBook.php4
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CardDAV/AddressBookQueryParser.php18
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CardDAV/AddressBookRoot.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CardDAV/Backend/Abstract.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CardDAV/Backend/PDO.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CardDAV/Card.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CardDAV/IAddressBook.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CardDAV/ICard.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CardDAV/IDirectory.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CardDAV/Plugin.php81
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CardDAV/UserAddressBooks.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CardDAV/Version.php2
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/CardDAV/includes.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Auth/Backend/Apache.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Auth/Backend/File.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Auth/Backend/PDO.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Auth/IBackend.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Auth/Plugin.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Browser/GuessContentType.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Browser/Plugin.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Browser/assets/favicon.icobin4286 -> 4286 bytes
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.pngbin7232 -> 7232 bytes
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Browser/assets/icons/calendar.pngbin4388 -> 4388 bytes
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Browser/assets/icons/card.pngbin5695 -> 5695 bytes
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Browser/assets/icons/collection.pngbin3474 -> 3474 bytes
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Browser/assets/icons/file.pngbin2837 -> 2837 bytes
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Browser/assets/icons/parent.pngbin3474 -> 3474 bytes
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Browser/assets/icons/principal.pngbin5480 -> 5480 bytes
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Client.php46
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Collection.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Directory.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/BadRequest.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/Conflict.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/ConflictingLock.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/FileNotFound.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/Forbidden.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/InsufficientStorage.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/InvalidResourceType.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/Locked.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/NotAuthenticated.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/NotFound.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/NotImplemented.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/PaymentRequired.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/PreconditionFailed.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/FS/Directory.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/FS/File.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/FS/Node.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/FSExt/Directory.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/FSExt/File.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/FSExt/Node.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/File.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/ICollection.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/IExtendedCollection.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/IFile.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/INode.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/IProperties.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/IQuota.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Locks/Backend/Abstract.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Locks/Backend/FS.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Locks/Backend/File.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Locks/Backend/PDO.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Locks/LockInfo.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Locks/Plugin.php5
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Mount/Plugin.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Node.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/ObjectTree.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Property.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Property/GetLastModified.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Property/Href.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Property/HrefList.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Property/IHref.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Property/LockDiscovery.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Property/ResourceType.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Property/Response.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Property/ResponseList.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Property/SupportedLock.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Property/SupportedReportSet.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Server.php9
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/ServerPlugin.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/SimpleCollection.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/SimpleDirectory.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/SimpleFile.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/StringUtil.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Tree.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Tree/Filesystem.php4
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/URLUtil.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/UUIDUtil.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/Version.php2
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/XMLUtil.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAV/includes.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/Exception/AceConflict.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/Exception/NoAbstract.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/IACL.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/IPrincipal.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/IPrincipalBackend.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/Plugin.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/Principal.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/PrincipalCollection.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/Property/Acl.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/Property/AclRestrictions.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/Property/Principal.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/Version.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/DAVACL/includes.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/HTTP/AWSAuth.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/HTTP/AbstractAuth.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/HTTP/BasicAuth.php2
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/HTTP/DigestAuth.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/HTTP/Request.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/HTTP/Response.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/HTTP/Util.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/HTTP/Version.php2
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/HTTP/includes.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Component.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Component/VAlarm.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Component/VCalendar.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Component/VEvent.php15
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Component/VJournal.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Component/VTodo.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/DateTimeParser.php4
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Element.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Element/DateTime.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Element/MultiDateTime.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/ElementList.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/FreeBusyGenerator.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Node.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Parameter.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/ParseException.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Property.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Property/DateTime.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Property/MultiDateTime.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Reader.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/RecurrenceIterator.php40
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/Version.php2
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/WindowsTimezoneMap.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/VObject/includes.php0
-rwxr-xr-x[-rw-r--r--]3rdparty/Sabre/autoload.php0
-rw-r--r--3rdparty/aws-sdk/README.md136
-rw-r--r--3rdparty/aws-sdk/_compatibility_test/README.md37
-rw-r--r--3rdparty/aws-sdk/_compatibility_test/sdk_compatibility.inc.php75
-rw-r--r--3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test.php789
-rwxr-xr-x3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test_cli.php186
-rw-r--r--3rdparty/aws-sdk/_docs/CHANGELOG.md1405
-rw-r--r--3rdparty/aws-sdk/_docs/CONTRIBUTORS.md64
-rw-r--r--3rdparty/aws-sdk/_docs/DYNAMODBSESSIONHANDLER.html235
-rw-r--r--3rdparty/aws-sdk/_docs/KNOWNISSUES.md65
-rw-r--r--3rdparty/aws-sdk/_docs/LICENSE.md151
-rw-r--r--3rdparty/aws-sdk/_docs/NOTICE.md444
-rw-r--r--3rdparty/aws-sdk/_docs/STREAMWRAPPER_README.html243
-rw-r--r--3rdparty/aws-sdk/_docs/WHERE_IS_THE_API_REFERENCE.md2
-rw-r--r--3rdparty/aws-sdk/authentication/signable.interface.php48
-rw-r--r--3rdparty/aws-sdk/authentication/signature_v2query.class.php163
-rw-r--r--3rdparty/aws-sdk/authentication/signature_v3json.class.php235
-rw-r--r--3rdparty/aws-sdk/authentication/signature_v3query.class.php192
-rw-r--r--3rdparty/aws-sdk/authentication/signature_v4json.class.php353
-rw-r--r--3rdparty/aws-sdk/authentication/signature_v4query.class.php345
-rw-r--r--3rdparty/aws-sdk/authentication/signer.abstract.php68
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/LICENSE25
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/README1
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/_sql/README5
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/_sql/mysql.sql7
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/_sql/pgsql.sql6
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/_sql/sqlite3.sql2
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/cacheapc.class.php126
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/cachecore.class.php160
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/cachefile.class.php189
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/cachemc.class.php183
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/cachepdo.class.php297
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/cachexcache.class.php129
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/icachecore.interface.php66
-rw-r--r--3rdparty/aws-sdk/lib/dom/ArrayToDOMDocument.php181
-rwxr-xr-x3rdparty/aws-sdk/lib/requestcore/LICENSE25
-rwxr-xr-x3rdparty/aws-sdk/lib/requestcore/README.md15
-rwxr-xr-x3rdparty/aws-sdk/lib/requestcore/cacert.pem3390
-rwxr-xr-x3rdparty/aws-sdk/lib/requestcore/requestcore.class.php1028
-rw-r--r--3rdparty/aws-sdk/lib/yaml/LICENSE19
-rw-r--r--3rdparty/aws-sdk/lib/yaml/README.markdown15
-rw-r--r--3rdparty/aws-sdk/lib/yaml/lib/sfYaml.php135
-rw-r--r--3rdparty/aws-sdk/lib/yaml/lib/sfYamlDumper.php60
-rw-r--r--3rdparty/aws-sdk/lib/yaml/lib/sfYamlInline.php442
-rw-r--r--3rdparty/aws-sdk/lib/yaml/lib/sfYamlParser.php612
-rwxr-xr-x3rdparty/aws-sdk/sdk.class.php1435
-rwxr-xr-x3rdparty/aws-sdk/services/s3.class.php3979
-rw-r--r--3rdparty/aws-sdk/utilities/array.class.php312
-rw-r--r--3rdparty/aws-sdk/utilities/batchrequest.class.php126
-rw-r--r--3rdparty/aws-sdk/utilities/complextype.class.php123
-rw-r--r--3rdparty/aws-sdk/utilities/credential.class.php157
-rw-r--r--3rdparty/aws-sdk/utilities/credentials.class.php125
-rw-r--r--3rdparty/aws-sdk/utilities/gzipdecode.class.php377
-rw-r--r--3rdparty/aws-sdk/utilities/hadoopbase.class.php67
-rw-r--r--3rdparty/aws-sdk/utilities/hadoopbootstrap.class.php127
-rw-r--r--3rdparty/aws-sdk/utilities/hadoopstep.class.php98
-rw-r--r--3rdparty/aws-sdk/utilities/info.class.php69
-rw-r--r--3rdparty/aws-sdk/utilities/json.class.php89
-rw-r--r--3rdparty/aws-sdk/utilities/manifest.class.php54
-rw-r--r--3rdparty/aws-sdk/utilities/mimetypes.class.php223
-rw-r--r--3rdparty/aws-sdk/utilities/policy.class.php134
-rw-r--r--3rdparty/aws-sdk/utilities/request.class.php70
-rw-r--r--3rdparty/aws-sdk/utilities/response.class.php29
-rw-r--r--3rdparty/aws-sdk/utilities/simplexml.class.php248
-rw-r--r--3rdparty/aws-sdk/utilities/stacktemplate.class.php52
-rw-r--r--3rdparty/aws-sdk/utilities/stepconfig.class.php91
-rwxr-xr-x3rdparty/aws-sdk/utilities/utilities.class.php399
-rw-r--r--3rdparty/mediawiki/CSSMin.php228
-rw-r--r--3rdparty/mediawiki/JavaScriptMinifier.php606
-rw-r--r--3rdparty/miniColors/GPL-LICENSE.txt278
-rw-r--r--3rdparty/miniColors/MIT-LICENSE.txt20
-rwxr-xr-x3rdparty/miniColors/css/images/colors.pngbin0 -> 12485 bytes
-rwxr-xr-x3rdparty/miniColors/css/images/trigger.pngbin0 -> 1406 bytes
-rwxr-xr-x3rdparty/miniColors/css/jquery.miniColors.css81
-rwxr-xr-x3rdparty/miniColors/js/jquery.miniColors.js580
-rwxr-xr-x3rdparty/miniColors/js/jquery.miniColors.min.js9
-rw-r--r--3rdparty/openid/class.openid.v3.php326
-rw-r--r--3rdparty/openid/phpmyid.php1707
-rw-r--r--3rdparty/when/MIT-LICENSE.txt9
-rw-r--r--3rdparty/when/When.php731
279 files changed, 26911 insertions, 896 deletions
diff --git a/3rdparty/Crypt_Blowfish/Blowfish.php b/3rdparty/Crypt_Blowfish/Blowfish.php
index a7b8948f043..4ccacb963e3 100644
--- a/3rdparty/Crypt_Blowfish/Blowfish.php
+++ b/3rdparty/Crypt_Blowfish/Blowfish.php
@@ -221,7 +221,7 @@ class Crypt_Blowfish
function decrypt($cipherText)
{
if (!is_string($cipherText)) {
- PEAR::raiseError('Chiper text must be a string', 1, PEAR_ERROR_DIE);
+ PEAR::raiseError('Cipher text must be a string', 1, PEAR_ERROR_DIE);
}
if (extension_loaded('mcrypt')) {
diff --git a/3rdparty/Dropbox/API.php b/3rdparty/Dropbox/API.php
new file mode 100644
index 00000000000..8cdce678e1c
--- /dev/null
+++ b/3rdparty/Dropbox/API.php
@@ -0,0 +1,380 @@
+<?php
+
+/**
+ * Dropbox API class
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+class Dropbox_API {
+
+ /**
+ * Sandbox root-path
+ */
+ const ROOT_SANDBOX = 'sandbox';
+
+ /**
+ * Dropbox root-path
+ */
+ const ROOT_DROPBOX = 'dropbox';
+
+ /**
+ * API URl
+ */
+ protected $api_url = 'https://api.dropbox.com/1/';
+
+ /**
+ * Content API URl
+ */
+ protected $api_content_url = 'https://api-content.dropbox.com/1/';
+
+ /**
+ * OAuth object
+ *
+ * @var Dropbox_OAuth
+ */
+ protected $oauth;
+
+ /**
+ * Default root-path, this will most likely be 'sandbox' or 'dropbox'
+ *
+ * @var string
+ */
+ protected $root;
+ protected $useSSL;
+
+ /**
+ * Constructor
+ *
+ * @param Dropbox_OAuth Dropbox_Auth object
+ * @param string $root default root path (sandbox or dropbox)
+ */
+ public function __construct(Dropbox_OAuth $oauth, $root = self::ROOT_DROPBOX, $useSSL = true) {
+
+ $this->oauth = $oauth;
+ $this->root = $root;
+ $this->useSSL = $useSSL;
+ if (!$this->useSSL)
+ {
+ throw new Dropbox_Exception('Dropbox REST API now requires that all requests use SSL');
+ }
+
+ }
+
+ /**
+ * Returns information about the current dropbox account
+ *
+ * @return stdclass
+ */
+ public function getAccountInfo() {
+
+ $data = $this->oauth->fetch($this->api_url . 'account/info');
+ return json_decode($data['body'],true);
+
+ }
+
+ /**
+ * Returns a file's contents
+ *
+ * @param string $path path
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return string
+ */
+ public function getFile($path = '', $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $result = $this->oauth->fetch($this->api_content_url . 'files/' . $root . '/' . ltrim($path,'/'));
+ return $result['body'];
+
+ }
+
+ /**
+ * Uploads a new file
+ *
+ * @param string $path Target path (including filename)
+ * @param string $file Either a path to a file or a stream resource
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return bool
+ */
+ public function putFile($path, $file, $root = null) {
+
+ $directory = dirname($path);
+ $filename = basename($path);
+
+ if($directory==='.') $directory = '';
+ $directory = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($directory));
+// $filename = str_replace('~', '%7E', rawurlencode($filename));
+ if (is_null($root)) $root = $this->root;
+
+ if (is_string($file)) {
+
+ $file = fopen($file,'rb');
+
+ } elseif (!is_resource($file)) {
+ throw new Dropbox_Exception('File must be a file-resource or a string');
+ }
+ $result=$this->multipartFetch($this->api_content_url . 'files/' .
+ $root . '/' . trim($directory,'/'), $file, $filename);
+
+ if(!isset($result["httpStatus"]) || $result["httpStatus"] != 200)
+ throw new Dropbox_Exception("Uploading file to Dropbox failed");
+
+ return true;
+ }
+
+
+ /**
+ * Copies a file or directory from one location to another
+ *
+ * This method returns the file information of the newly created file.
+ *
+ * @param string $from source path
+ * @param string $to destination path
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return stdclass
+ */
+ public function copy($from, $to, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $response = $this->oauth->fetch($this->api_url . 'fileops/copy', array('from_path' => $from, 'to_path' => $to, 'root' => $root), 'POST');
+
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Creates a new folder
+ *
+ * This method returns the information from the newly created directory
+ *
+ * @param string $path
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return stdclass
+ */
+ public function createFolder($path, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+
+ // Making sure the path starts with a /
+// $path = '/' . ltrim($path,'/');
+
+ $response = $this->oauth->fetch($this->api_url . 'fileops/create_folder', array('path' => $path, 'root' => $root),'POST');
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Deletes a file or folder.
+ *
+ * This method will return the metadata information from the deleted file or folder, if successful.
+ *
+ * @param string $path Path to new folder
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return array
+ */
+ public function delete($path, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $response = $this->oauth->fetch($this->api_url . 'fileops/delete', array('path' => $path, 'root' => $root), 'POST');
+ return json_decode($response['body']);
+
+ }
+
+ /**
+ * Moves a file or directory to a new location
+ *
+ * This method returns the information from the newly created directory
+ *
+ * @param mixed $from Source path
+ * @param mixed $to destination path
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return stdclass
+ */
+ public function move($from, $to, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $response = $this->oauth->fetch($this->api_url . 'fileops/move', array('from_path' => rawurldecode($from), 'to_path' => rawurldecode($to), 'root' => $root), 'POST');
+
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Returns file and directory information
+ *
+ * @param string $path Path to receive information from
+ * @param bool $list When set to true, this method returns information from all files in a directory. When set to false it will only return infromation from the specified directory.
+ * @param string $hash If a hash is supplied, this method simply returns true if nothing has changed since the last request. Good for caching.
+ * @param int $fileLimit Maximum number of file-information to receive
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return array|true
+ */
+ public function getMetaData($path, $list = true, $hash = null, $fileLimit = null, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+
+ $args = array(
+ 'list' => $list,
+ );
+
+ if (!is_null($hash)) $args['hash'] = $hash;
+ if (!is_null($fileLimit)) $args['file_limit'] = $fileLimit;
+
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_url . 'metadata/' . $root . '/' . ltrim($path,'/'), $args);
+
+ /* 304 is not modified */
+ if ($response['httpStatus']==304) {
+ return true;
+ } else {
+ return json_decode($response['body'],true);
+ }
+
+ }
+
+ /**
+ * A way of letting you keep up with changes to files and folders in a user's Dropbox. You can periodically call /delta to get a list of "delta entries", which are instructions on how to update your local state to match the server's state.
+ *
+ * This method returns the information from the newly created directory
+ *
+ * @param string $cursor A string that is used to keep track of your current state. On the next call pass in this value to return delta entries that have been recorded since the cursor was returned.
+ * @return stdclass
+ */
+ public function delta($cursor) {
+
+ $arg['cursor'] = $cursor;
+
+ $response = $this->oauth->fetch($this->api_url . 'delta', $arg, 'POST');
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Returns a thumbnail (as a string) for a file path.
+ *
+ * @param string $path Path to file
+ * @param string $size small, medium or large
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return string
+ */
+ public function getThumbnail($path, $size = 'small', $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_content_url . 'thumbnails/' . $root . '/' . ltrim($path,'/'),array('size' => $size));
+
+ return $response['body'];
+
+ }
+
+ /**
+ * This method is used to generate multipart POST requests for file upload
+ *
+ * @param string $uri
+ * @param array $arguments
+ * @return bool
+ */
+ protected function multipartFetch($uri, $file, $filename) {
+
+ /* random string */
+ $boundary = 'R50hrfBj5JYyfR3vF3wR96GPCC9Fd2q2pVMERvEaOE3D8LZTgLLbRpNwXek3';
+
+ $headers = array(
+ 'Content-Type' => 'multipart/form-data; boundary=' . $boundary,
+ );
+
+ $body="--" . $boundary . "\r\n";
+ $body.="Content-Disposition: form-data; name=file; filename=".rawurldecode($filename)."\r\n";
+ $body.="Content-type: application/octet-stream\r\n";
+ $body.="\r\n";
+ $body.=stream_get_contents($file);
+ $body.="\r\n";
+ $body.="--" . $boundary . "--";
+
+ // Dropbox requires the filename to also be part of the regular arguments, so it becomes
+ // part of the signature.
+ $uri.='?file=' . $filename;
+
+ return $this->oauth->fetch($uri, $body, 'POST', $headers);
+
+ }
+
+
+ /**
+ * Search
+ *
+ * Returns metadata for all files and folders that match the search query.
+ *
+ * @added by: diszo.sasil
+ *
+ * @param string $query
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @param string $path
+ * @return array
+ */
+ public function search($query = '', $root = null, $path = ''){
+ if (is_null($root)) $root = $this->root;
+ if(!empty($path)){
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ }
+ $response = $this->oauth->fetch($this->api_url . 'search/' . $root . '/' . ltrim($path,'/'),array('query' => $query));
+ return json_decode($response['body'],true);
+ }
+
+ /**
+ * Creates and returns a shareable link to files or folders.
+ *
+ * Note: Links created by the /shares API call expire after thirty days.
+ *
+ * @param type $path
+ * @param type $root
+ * @return type
+ */
+ public function share($path, $root = null) {
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_url. 'shares/'. $root . '/' . ltrim($path, '/'), array(), 'POST');
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Returns a link directly to a file.
+ * Similar to /shares. The difference is that this bypasses the Dropbox webserver, used to provide a preview of the file, so that you can effectively stream the contents of your media.
+ *
+ * Note: The /media link expires after four hours, allotting enough time to stream files, but not enough to leave a connection open indefinitely.
+ *
+ * @param type $path
+ * @param type $root
+ * @return type
+ */
+ public function media($path, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_url. 'media/'. $root . '/' . ltrim($path, '/'), array(), 'POST');
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Creates and returns a copy_ref to a file. This reference string can be used to copy that file to another user's Dropbox by passing it in as the from_copy_ref parameter on /fileops/copy.
+ *
+ * @param type $path
+ * @param type $root
+ * @return type
+ */
+ public function copy_ref($path, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_url. 'copy_ref/'. $root . '/' . ltrim($path, '/'));
+ return json_decode($response['body'],true);
+
+ }
+
+
+}
diff --git a/3rdparty/Dropbox/Exception.php b/3rdparty/Dropbox/Exception.php
new file mode 100644
index 00000000000..50cbc4c7915
--- /dev/null
+++ b/3rdparty/Dropbox/Exception.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Dropbox base exception
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+/**
+ * Base exception class
+ */
+class Dropbox_Exception extends Exception { }
diff --git a/3rdparty/Dropbox/Exception/Forbidden.php b/3rdparty/Dropbox/Exception/Forbidden.php
new file mode 100644
index 00000000000..5f0378cfc74
--- /dev/null
+++ b/3rdparty/Dropbox/Exception/Forbidden.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * Dropbox Forbidden exception
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+/**
+ * This exception is thrown when we receive the 403 forbidden response
+ */
+class Dropbox_Exception_Forbidden extends Dropbox_Exception {
+
+
+}
diff --git a/3rdparty/Dropbox/Exception/NotFound.php b/3rdparty/Dropbox/Exception/NotFound.php
new file mode 100644
index 00000000000..3deaf90d76b
--- /dev/null
+++ b/3rdparty/Dropbox/Exception/NotFound.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * Dropbox Not Found exception
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+/**
+ * This exception is thrown when a non-existant uri is accessed.
+ *
+ * Basically, this exception is used when we get back a 404.
+ */
+class Dropbox_Exception_NotFound extends Dropbox_Exception {
+
+
+}
diff --git a/3rdparty/Dropbox/Exception/OverQuota.php b/3rdparty/Dropbox/Exception/OverQuota.php
new file mode 100644
index 00000000000..86e5425dbd8
--- /dev/null
+++ b/3rdparty/Dropbox/Exception/OverQuota.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * Dropbox Over Quota exception
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+/**
+ * This exception is thrown when the operation required more space than the available quota.
+ *
+ * Basically, this exception is used when we get back a 507.
+ */
+class Dropbox_Exception_OverQuota extends Dropbox_Exception {
+
+
+}
diff --git a/3rdparty/Dropbox/Exception/RequestToken.php b/3rdparty/Dropbox/Exception/RequestToken.php
new file mode 100644
index 00000000000..5b117f2c6b0
--- /dev/null
+++ b/3rdparty/Dropbox/Exception/RequestToken.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * Dropbox RequestToken exception
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+/**
+ * This exception is thrown when an error occured during the request_token process.
+ */
+class Dropbox_Exception_RequestToken extends Dropbox_Exception {
+
+
+}
diff --git a/3rdparty/Dropbox/LICENSE.txt b/3rdparty/Dropbox/LICENSE.txt
new file mode 100644
index 00000000000..cd3512acee6
--- /dev/null
+++ b/3rdparty/Dropbox/LICENSE.txt
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Rooftop Solutions
+
+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.
diff --git a/3rdparty/Dropbox/OAuth.php b/3rdparty/Dropbox/OAuth.php
new file mode 100644
index 00000000000..905cc2da1c6
--- /dev/null
+++ b/3rdparty/Dropbox/OAuth.php
@@ -0,0 +1,151 @@
+<?php
+
+/**
+ * Dropbox OAuth
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+
+/**
+ * This class is an abstract OAuth class.
+ *
+ * It must be extended by classes who wish to provide OAuth functionality
+ * using different libraries.
+ */
+abstract class Dropbox_OAuth {
+
+ /**
+ * After a user has authorized access, dropbox can redirect the user back
+ * to this url.
+ *
+ * @var string
+ */
+ public $authorizeCallbackUrl = null;
+
+ /**
+ * Uri used to fetch request tokens
+ *
+ * @var string
+ */
+ const URI_REQUEST_TOKEN = 'https://api.dropbox.com/1/oauth/request_token';
+
+ /**
+ * Uri used to redirect the user to for authorization.
+ *
+ * @var string
+ */
+ const URI_AUTHORIZE = 'https://www.dropbox.com/1/oauth/authorize';
+
+ /**
+ * Uri used to
+ *
+ * @var string
+ */
+ const URI_ACCESS_TOKEN = 'https://api.dropbox.com/1/oauth/access_token';
+
+ /**
+ * An OAuth request token.
+ *
+ * @var string
+ */
+ protected $oauth_token = null;
+
+ /**
+ * OAuth token secret
+ *
+ * @var string
+ */
+ protected $oauth_token_secret = null;
+
+
+ /**
+ * Constructor
+ *
+ * @param string $consumerKey
+ * @param string $consumerSecret
+ */
+ abstract public function __construct($consumerKey, $consumerSecret);
+
+ /**
+ * Sets the request token and secret.
+ *
+ * The tokens can also be passed as an array into the first argument.
+ * The array must have the elements token and token_secret.
+ *
+ * @param string|array $token
+ * @param string $token_secret
+ * @return void
+ */
+ public function setToken($token, $token_secret = null) {
+
+ if (is_array($token)) {
+ $this->oauth_token = $token['token'];
+ $this->oauth_token_secret = $token['token_secret'];
+ } else {
+ $this->oauth_token = $token;
+ $this->oauth_token_secret = $token_secret;
+ }
+
+ }
+
+ /**
+ * Returns the oauth request tokens as an associative array.
+ *
+ * The array will contain the elements 'token' and 'token_secret'.
+ *
+ * @return array
+ */
+ public function getToken() {
+
+ return array(
+ 'token' => $this->oauth_token,
+ 'token_secret' => $this->oauth_token_secret,
+ );
+
+ }
+
+ /**
+ * Returns the authorization url
+ *
+ * @param string $callBack Specify a callback url to automatically redirect the user back
+ * @return string
+ */
+ public function getAuthorizeUrl($callBack = null) {
+
+ // Building the redirect uri
+ $token = $this->getToken();
+ $uri = self::URI_AUTHORIZE . '?oauth_token=' . $token['token'];
+ if ($callBack) $uri.='&oauth_callback=' . $callBack;
+ return $uri;
+ }
+
+ /**
+ * Fetches a secured oauth url and returns the response body.
+ *
+ * @param string $uri
+ * @param mixed $arguments
+ * @param string $method
+ * @param array $httpHeaders
+ * @return string
+ */
+ public abstract function fetch($uri, $arguments = array(), $method = 'GET', $httpHeaders = array());
+
+ /**
+ * Requests the OAuth request token.
+ *
+ * @return array
+ */
+ abstract public function getRequestToken();
+
+ /**
+ * Requests the OAuth access tokens.
+ *
+ * @return array
+ */
+ abstract public function getAccessToken();
+
+}
diff --git a/3rdparty/Dropbox/OAuth/Consumer/Dropbox.php b/3rdparty/Dropbox/OAuth/Consumer/Dropbox.php
new file mode 100644
index 00000000000..204a659de00
--- /dev/null
+++ b/3rdparty/Dropbox/OAuth/Consumer/Dropbox.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * HTTP OAuth Consumer
+ *
+ * Adapted from halldirector's code in
+ * http://code.google.com/p/dropbox-php/issues/detail?id=36#c5
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2011 Joe Constant / halldirector. All rights reserved.
+ * @author Joe Constant / halldirector
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+require_once 'HTTP/OAuth.php';
+require_once 'HTTP/OAuth/Consumer.php';
+
+/*
+ * This class is to help work around aomw ssl issues.
+ */
+class Dropbox_OAuth_Consumer_Dropbox extends HTTP_OAuth_Consumer
+{
+ public function getOAuthConsumerRequest()
+ {
+ if (!$this->consumerRequest instanceof HTTP_OAuth_Consumer_Request) {
+ $this->consumerRequest = new HTTP_OAuth_Consumer_Request;
+ }
+
+ // TODO: Change this and add in code to validate the SSL cert.
+ // see https://github.com/bagder/curl/blob/master/lib/mk-ca-bundle.pl
+ $this->consumerRequest->setConfig(array(
+ 'ssl_verify_peer' => false,
+ 'ssl_verify_host' => false
+ ));
+
+ return $this->consumerRequest;
+ }
+}
diff --git a/3rdparty/Dropbox/OAuth/Curl.php b/3rdparty/Dropbox/OAuth/Curl.php
new file mode 100644
index 00000000000..b75b27bb363
--- /dev/null
+++ b/3rdparty/Dropbox/OAuth/Curl.php
@@ -0,0 +1,282 @@
+<?php
+
+/**
+ * Dropbox OAuth
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2011 Daniel Huesken
+ * @author Daniel Huesken (http://www.danielhuesken.de/)
+ * @license MIT
+ */
+
+/**
+ * This class is used to sign all requests to dropbox.
+ *
+ * This specific class uses WordPress WP_Http to authenticate.
+ */
+class Dropbox_OAuth_Curl extends Dropbox_OAuth {
+
+ /**
+ *
+ * @var string ConsumerKey
+ */
+ protected $consumerKey = null;
+ /**
+ *
+ * @var string ConsumerSecret
+ */
+ protected $consumerSecret = null;
+ /**
+ *
+ * @var string ProzessCallBack
+ */
+ public $ProgressFunction = false;
+
+ /**
+ * Constructor
+ *
+ * @param string $consumerKey
+ * @param string $consumerSecret
+ */
+ public function __construct($consumerKey, $consumerSecret) {
+ if (!function_exists('curl_exec'))
+ throw new Dropbox_Exception('The PHP curl functions not available!');
+
+ $this->consumerKey = $consumerKey;
+ $this->consumerSecret = $consumerSecret;
+ }
+
+ /**
+ * Fetches a secured oauth url and returns the response body.
+ *
+ * @param string $uri
+ * @param mixed $arguments
+ * @param string $method
+ * @param array $httpHeaders
+ * @return string
+ */
+ public function fetch($uri, $arguments = array(), $method = 'GET', $httpHeaders = array()) {
+
+ $uri=str_replace('http://', 'https://', $uri); // all https, upload makes problems if not
+ if (is_string($arguments) and strtoupper($method) == 'POST') {
+ preg_match("/\?file=(.*)$/i", $uri, $matches);
+ if (isset($matches[1])) {
+ $uri = str_replace($matches[0], "", $uri);
+ $filename = $matches[1];
+ $httpHeaders=array_merge($httpHeaders,$this->getOAuthHeader($uri, array("file" => $filename), $method));
+ }
+ } else {
+ $httpHeaders=array_merge($httpHeaders,$this->getOAuthHeader($uri, $arguments, $method));
+ }
+ $ch = curl_init();
+ if (strtoupper($method) == 'POST') {
+ curl_setopt($ch, CURLOPT_URL, $uri);
+ curl_setopt($ch, CURLOPT_POST, true);
+// if (is_array($arguments))
+// $arguments=http_build_query($arguments);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $arguments);
+// $httpHeaders['Content-Length']=strlen($arguments);
+ } else {
+ curl_setopt($ch, CURLOPT_URL, $uri.'?'.http_build_query($arguments));
+ curl_setopt($ch, CURLOPT_POST, false);
+ }
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 300);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
+// curl_setopt($ch, CURLOPT_CAINFO, "rootca");
+ curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
+ //Build header
+ $headers = array();
+ foreach ($httpHeaders as $name => $value) {
+ $headers[] = "{$name}: $value";
+ }
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+ if (!ini_get('safe_mode') && !ini_get('open_basedir'))
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true );
+ if (function_exists($this->ProgressFunction) and defined('CURLOPT_PROGRESSFUNCTION')) {
+ curl_setopt($ch, CURLOPT_NOPROGRESS, false);
+ curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, $this->ProgressFunction);
+ curl_setopt($ch, CURLOPT_BUFFERSIZE, 512);
+ }
+ $response=curl_exec($ch);
+ $errorno=curl_errno($ch);
+ $error=curl_error($ch);
+ $status=curl_getinfo($ch,CURLINFO_HTTP_CODE);
+ curl_close($ch);
+
+
+ if (!empty($errorno))
+ throw new Dropbox_Exception_NotFound('Curl error: ('.$errorno.') '.$error."\n");
+
+ if ($status>=300) {
+ $body = json_decode($response,true);
+ switch ($status) {
+ // Not modified
+ case 304 :
+ return array(
+ 'httpStatus' => 304,
+ 'body' => null,
+ );
+ break;
+ case 403 :
+ throw new Dropbox_Exception_Forbidden('Forbidden.
+ This could mean a bad OAuth request, or a file or folder already existing at the target location.
+ ' . $body["error"] . "\n");
+ case 404 :
+ throw new Dropbox_Exception_NotFound('Resource at uri: ' . $uri . ' could not be found. ' .
+ $body["error"] . "\n");
+ case 507 :
+ throw new Dropbox_Exception_OverQuota('This dropbox is full. ' .
+ $body["error"] . "\n");
+ }
+ if (!empty($body["error"]))
+ throw new Dropbox_Exception_RequestToken('Error: ('.$status.') '.$body["error"]."\n");
+ }
+
+ return array(
+ 'body' => $response,
+ 'httpStatus' => $status
+ );
+ }
+
+ /**
+ * Returns named array with oauth parameters for further use
+ * @return array Array with oauth_ parameters
+ */
+ private function getOAuthBaseParams() {
+ $params['oauth_version'] = '1.0';
+ $params['oauth_signature_method'] = 'HMAC-SHA1';
+
+ $params['oauth_consumer_key'] = $this->consumerKey;
+ $tokens = $this->getToken();
+ if (isset($tokens['token']) && $tokens['token']) {
+ $params['oauth_token'] = $tokens['token'];
+ }
+ $params['oauth_timestamp'] = time();
+ $params['oauth_nonce'] = md5(microtime() . mt_rand());
+ return $params;
+ }
+
+ /**
+ * Creates valid Authorization header for OAuth, based on URI and Params
+ *
+ * @param string $uri
+ * @param array $params
+ * @param string $method GET or POST, standard is GET
+ * @param array $oAuthParams optional, pass your own oauth_params here
+ * @return array Array for request's headers section like
+ * array('Authorization' => 'OAuth ...');
+ */
+ private function getOAuthHeader($uri, $params, $method = 'GET', $oAuthParams = null) {
+ $oAuthParams = $oAuthParams ? $oAuthParams : $this->getOAuthBaseParams();
+
+ // create baseString to encode for the sent parameters
+ $baseString = $method . '&';
+ $baseString .= $this->oauth_urlencode($uri) . "&";
+
+ // OAuth header does not include GET-Parameters
+ $signatureParams = array_merge($params, $oAuthParams);
+
+ // sorting the parameters
+ ksort($signatureParams);
+
+ $encodedParams = array();
+ foreach ($signatureParams as $key => $value) {
+ $encodedParams[] = $this->oauth_urlencode($key) . '=' . $this->oauth_urlencode($value);
+ }
+
+ $baseString .= $this->oauth_urlencode(implode('&', $encodedParams));
+
+ // encode the signature
+ $tokens = $this->getToken();
+ $hash = $this->hash_hmac_sha1($this->consumerSecret.'&'.$tokens['token_secret'], $baseString);
+ $signature = base64_encode($hash);
+
+ // add signature to oAuthParams
+ $oAuthParams['oauth_signature'] = $signature;
+
+ $oAuthEncoded = array();
+ foreach ($oAuthParams as $key => $value) {
+ $oAuthEncoded[] = $key . '="' . $this->oauth_urlencode($value) . '"';
+ }
+
+ return array('Authorization' => 'OAuth ' . implode(', ', $oAuthEncoded));
+ }
+
+ /**
+ * Requests the OAuth request token.
+ *
+ * @return void
+ */
+ public function getRequestToken() {
+ $result = $this->fetch(self::URI_REQUEST_TOKEN, array(), 'POST');
+ if ($result['httpStatus'] == "200") {
+ $tokens = array();
+ parse_str($result['body'], $tokens);
+ $this->setToken($tokens['oauth_token'], $tokens['oauth_token_secret']);
+ return $this->getToken();
+ } else {
+ throw new Dropbox_Exception_RequestToken('We were unable to fetch request tokens. This likely means that your consumer key and/or secret are incorrect.');
+ }
+ }
+
+ /**
+ * Requests the OAuth access tokens.
+ *
+ * This method requires the 'unauthorized' request tokens
+ * and, if successful will set the authorized request tokens.
+ *
+ * @return void
+ */
+ public function getAccessToken() {
+ $result = $this->fetch(self::URI_ACCESS_TOKEN, array(), 'POST');
+ if ($result['httpStatus'] == "200") {
+ $tokens = array();
+ parse_str($result['body'], $tokens);
+ $this->setToken($tokens['oauth_token'], $tokens['oauth_token_secret']);
+ return $this->getToken();
+ } else {
+ throw new Dropbox_Exception_RequestToken('We were unable to fetch request tokens. This likely means that your consumer key and/or secret are incorrect.');
+ }
+ }
+
+ /**
+ * Helper function to properly urlencode parameters.
+ * See http://php.net/manual/en/function.oauth-urlencode.php
+ *
+ * @param string $string
+ * @return string
+ */
+ private function oauth_urlencode($string) {
+ return str_replace('%E7', '~', rawurlencode($string));
+ }
+
+ /**
+ * Hash function for hmac_sha1; uses native function if available.
+ *
+ * @param string $key
+ * @param string $data
+ * @return string
+ */
+ private function hash_hmac_sha1($key, $data) {
+ if (function_exists('hash_hmac') && in_array('sha1', hash_algos())) {
+ return hash_hmac('sha1', $data, $key, true);
+ } else {
+ $blocksize = 64;
+ $hashfunc = 'sha1';
+ if (strlen($key) > $blocksize) {
+ $key = pack('H*', $hashfunc($key));
+ }
+
+ $key = str_pad($key, $blocksize, chr(0x00));
+ $ipad = str_repeat(chr(0x36), $blocksize);
+ $opad = str_repeat(chr(0x5c), $blocksize);
+ $hash = pack('H*', $hashfunc(( $key ^ $opad ) . pack('H*', $hashfunc(($key ^ $ipad) . $data))));
+
+ return $hash;
+ }
+ }
+
+
+} \ No newline at end of file
diff --git a/3rdparty/Dropbox/README.md b/3rdparty/Dropbox/README.md
new file mode 100644
index 00000000000..54e05db762b
--- /dev/null
+++ b/3rdparty/Dropbox/README.md
@@ -0,0 +1,31 @@
+Dropbox-php
+===========
+
+This PHP library allows you to easily integrate dropbox with PHP.
+
+The following PHP extension is required:
+
+* json
+
+The library makes use of OAuth. At the moment you can use either of these libraries:
+
+[PHP OAuth extension](http://pecl.php.net/package/oauth)
+[PEAR's HTTP_OAUTH package](http://pear.php.net/package/http_oauth)
+
+The extension is recommended, but if you can't install php extensions you should go for the pear package.
+Installing
+----------
+
+ pear channel-discover pear.dropbox-php.com
+ pear install dropbox-php/Dropbox-alpha
+
+Documentation
+-------------
+Check out the [documentation](http://www.dropbox-php.com/docs).
+
+Questions?
+----------
+
+[Dropbox-php Mailing list](http://groups.google.com/group/dropbox-php)
+[Official Dropbox developer forum](http://forums.dropbox.com/forum.php?id=5)
+
diff --git a/3rdparty/Dropbox/autoload.php b/3rdparty/Dropbox/autoload.php
new file mode 100644
index 00000000000..5388ea6334a
--- /dev/null
+++ b/3rdparty/Dropbox/autoload.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file registers a new autoload function using spl_autoload_register.
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+/**
+ * Autoloader function
+ *
+ * @param $className string
+ * @return void
+ */
+function Dropbox_autoload($className) {
+
+ if(strpos($className,'Dropbox_')===0) {
+
+ include dirname(__FILE__) . '/' . str_replace('_','/',substr($className,8)) . '.php';
+
+ }
+
+}
+
+spl_autoload_register('Dropbox_autoload');
+
diff --git a/3rdparty/Google/LICENSE.txt b/3rdparty/Google/LICENSE.txt
new file mode 100644
index 00000000000..8891c7ddc90
--- /dev/null
+++ b/3rdparty/Google/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2007 Andy Smith
+
+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.
diff --git a/3rdparty/Google/OAuth.php b/3rdparty/Google/OAuth.php
new file mode 100755
index 00000000000..c7e75dd8266
--- /dev/null
+++ b/3rdparty/Google/OAuth.php
@@ -0,0 +1,751 @@
+<?php
+// vim: foldmethod=marker
+
+/* Generic exception class
+ */
+class OAuthException extends Exception {/*{{{*/
+ // pass
+}/*}}}*/
+
+class OAuthConsumer {/*{{{*/
+ public $key;
+ public $secret;
+
+ public function __construct($key, $secret, $callback_url=NULL) {/*{{{*/
+ $this->key = $key;
+ $this->secret = $secret;
+ $this->callback_url = $callback_url;
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthToken {/*{{{*/
+ // access tokens and request tokens
+ public $key;
+ public $secret;
+
+ /**
+ * key = the token
+ * secret = the token secret
+ */
+ function __construct($key, $secret) {/*{{{*/
+ $this->key = $key;
+ $this->secret = $secret;
+ }/*}}}*/
+
+ /**
+ * generates the basic string serialization of a token that a server
+ * would respond to request_token and access_token calls with
+ */
+ function to_string() {/*{{{*/
+ return "oauth_token=" . OAuthUtil::urlencodeRFC3986($this->key) .
+ "&oauth_token_secret=" . OAuthUtil::urlencodeRFC3986($this->secret);
+ }/*}}}*/
+
+ function __toString() {/*{{{*/
+ return $this->to_string();
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthSignatureMethod {/*{{{*/
+ public function check_signature(&$request, $consumer, $token, $signature) {
+ $built = $this->build_signature($request, $consumer, $token);
+ return $built == $signature;
+ }
+}/*}}}*/
+
+class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {/*{{{*/
+ function get_name() {/*{{{*/
+ return "HMAC-SHA1";
+ }/*}}}*/
+
+ public function build_signature($request, $consumer, $token, $privKey=NULL) {/*{{{*/
+ $base_string = $request->get_signature_base_string();
+ $request->base_string = $base_string;
+
+ $key_parts = array(
+ $consumer->secret,
+ ($token) ? $token->secret : ""
+ );
+
+ $key_parts = array_map(array('OAuthUtil','urlencodeRFC3986'), $key_parts);
+ $key = implode('&', $key_parts);
+
+ return base64_encode( hash_hmac('sha1', $base_string, $key, true));
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod {/*{{{*/
+ public function get_name() {/*{{{*/
+ return "RSA-SHA1";
+ }/*}}}*/
+
+ protected function fetch_public_cert(&$request) {/*{{{*/
+ // not implemented yet, ideas are:
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
+ // (2) fetch via http using a url provided by the requester
+ // (3) some sort of specific discovery code based on request
+ //
+ // either way should return a string representation of the certificate
+ throw Exception("fetch_public_cert not implemented");
+ }/*}}}*/
+
+ protected function fetch_private_cert($privKey) {//&$request) {/*{{{*/
+ // not implemented yet, ideas are:
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
+ //
+ // either way should return a string representation of the certificate
+ throw Exception("fetch_private_cert not implemented");
+ }/*}}}*/
+
+ public function build_signature(&$request, $consumer, $token, $privKey) {/*{{{*/
+ $base_string = $request->get_signature_base_string();
+
+ // Fetch the private key cert based on the request
+ //$cert = $this->fetch_private_cert($consumer->privKey);
+
+ //Pull the private key ID from the certificate
+ //$privatekeyid = openssl_get_privatekey($cert);
+
+ // hacked in
+ if ($privKey == '') {
+ $fp = fopen($GLOBALS['PRIV_KEY_FILE'], "r");
+ $privKey = fread($fp, 8192);
+ fclose($fp);
+ }
+ $privatekeyid = openssl_get_privatekey($privKey);
+
+ //Check the computer signature against the one passed in the query
+ $ok = openssl_sign($base_string, $signature, $privatekeyid);
+
+ //Release the key resource
+ openssl_free_key($privatekeyid);
+
+ return base64_encode($signature);
+ } /*}}}*/
+
+ public function check_signature(&$request, $consumer, $token, $signature) {/*{{{*/
+ $decoded_sig = base64_decode($signature);
+
+ $base_string = $request->get_signature_base_string();
+
+ // Fetch the public key cert based on the request
+ $cert = $this->fetch_public_cert($request);
+
+ //Pull the public key ID from the certificate
+ $publickeyid = openssl_get_publickey($cert);
+
+ //Check the computer signature against the one passed in the query
+ $ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
+
+ //Release the key resource
+ openssl_free_key($publickeyid);
+
+ return $ok == 1;
+ } /*}}}*/
+}/*}}}*/
+
+class OAuthRequest {/*{{{*/
+ private $parameters;
+ private $http_method;
+ private $http_url;
+ // for debug purposes
+ public $base_string;
+ public static $version = '1.0';
+
+ function __construct($http_method, $http_url, $parameters=NULL) {/*{{{*/
+ @$parameters or $parameters = array();
+ $this->parameters = $parameters;
+ $this->http_method = $http_method;
+ $this->http_url = $http_url;
+ }/*}}}*/
+
+
+ /**
+ * attempt to build up a request from what was passed to the server
+ */
+ public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) {/*{{{*/
+ $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https';
+ @$http_url or $http_url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
+ @$http_method or $http_method = $_SERVER['REQUEST_METHOD'];
+
+ $request_headers = OAuthRequest::get_headers();
+
+ // let the library user override things however they'd like, if they know
+ // which parameters to use then go for it, for example XMLRPC might want to
+ // do this
+ if ($parameters) {
+ $req = new OAuthRequest($http_method, $http_url, $parameters);
+ }
+ // next check for the auth header, we need to do some extra stuff
+ // if that is the case, namely suck in the parameters from GET or POST
+ // so that we can include them in the signature
+ else if (@substr($request_headers['Authorization'], 0, 5) == "OAuth") {
+ $header_parameters = OAuthRequest::split_header($request_headers['Authorization']);
+ if ($http_method == "GET") {
+ $req_parameters = $_GET;
+ }
+ else if ($http_method = "POST") {
+ $req_parameters = $_POST;
+ }
+ $parameters = array_merge($header_parameters, $req_parameters);
+ $req = new OAuthRequest($http_method, $http_url, $parameters);
+ }
+ else if ($http_method == "GET") {
+ $req = new OAuthRequest($http_method, $http_url, $_GET);
+ }
+ else if ($http_method == "POST") {
+ $req = new OAuthRequest($http_method, $http_url, $_POST);
+ }
+ return $req;
+ }/*}}}*/
+
+ /**
+ * pretty much a helper function to set up the request
+ */
+ public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {/*{{{*/
+ @$parameters or $parameters = array();
+ $defaults = array("oauth_version" => OAuthRequest::$version,
+ "oauth_nonce" => OAuthRequest::generate_nonce(),
+ "oauth_timestamp" => OAuthRequest::generate_timestamp(),
+ "oauth_consumer_key" => $consumer->key);
+ $parameters = array_merge($defaults, $parameters);
+
+ if ($token) {
+ $parameters['oauth_token'] = $token->key;
+ }
+
+ // oauth v1.0a
+ /*if (isset($_REQUEST['oauth_verifier'])) {
+ $parameters['oauth_verifier'] = $_REQUEST['oauth_verifier'];
+ }*/
+
+
+ return new OAuthRequest($http_method, $http_url, $parameters);
+ }/*}}}*/
+
+ public function set_parameter($name, $value) {/*{{{*/
+ $this->parameters[$name] = $value;
+ }/*}}}*/
+
+ public function get_parameter($name) {/*{{{*/
+ return $this->parameters[$name];
+ }/*}}}*/
+
+ public function get_parameters() {/*{{{*/
+ return $this->parameters;
+ }/*}}}*/
+
+ /**
+ * Returns the normalized parameters of the request
+ *
+ * This will be all (except oauth_signature) parameters,
+ * sorted first by key, and if duplicate keys, then by
+ * value.
+ *
+ * The returned string will be all the key=value pairs
+ * concated by &.
+ *
+ * @return string
+ */
+ public function get_signable_parameters() {/*{{{*/
+ // Grab all parameters
+ $params = $this->parameters;
+
+ // Remove oauth_signature if present
+ if (isset($params['oauth_signature'])) {
+ unset($params['oauth_signature']);
+ }
+
+ // Urlencode both keys and values
+ $keys = array_map(array('OAuthUtil', 'urlencodeRFC3986'), array_keys($params));
+ $values = array_map(array('OAuthUtil', 'urlencodeRFC3986'), array_values($params));
+ $params = array_combine($keys, $values);
+
+ // Sort by keys (natsort)
+ uksort($params, 'strnatcmp');
+
+if(isset($params['title']) && isset($params['title-exact'])) {
+ $temp = $params['title-exact'];
+ $title = $params['title'];
+
+ unset($params['title']);
+ unset($params['title-exact']);
+
+ $params['title-exact'] = $temp;
+ $params['title'] = $title;
+}
+
+ // Generate key=value pairs
+ $pairs = array();
+ foreach ($params as $key=>$value ) {
+ if (is_array($value)) {
+ // If the value is an array, it's because there are multiple
+ // with the same key, sort them, then add all the pairs
+ natsort($value);
+ foreach ($value as $v2) {
+ $pairs[] = $key . '=' . $v2;
+ }
+ } else {
+ $pairs[] = $key . '=' . $value;
+ }
+ }
+
+ // Return the pairs, concated with &
+ return implode('&', $pairs);
+ }/*}}}*/
+
+ /**
+ * Returns the base string of this request
+ *
+ * The base string defined as the method, the url
+ * and the parameters (normalized), each urlencoded
+ * and the concated with &.
+ */
+ public function get_signature_base_string() {/*{{{*/
+ $parts = array(
+ $this->get_normalized_http_method(),
+ $this->get_normalized_http_url(),
+ $this->get_signable_parameters()
+ );
+
+ $parts = array_map(array('OAuthUtil', 'urlencodeRFC3986'), $parts);
+
+ return implode('&', $parts);
+ }/*}}}*/
+
+ /**
+ * just uppercases the http method
+ */
+ public function get_normalized_http_method() {/*{{{*/
+ return strtoupper($this->http_method);
+ }/*}}}*/
+
+/**
+ * parses the url and rebuilds it to be
+ * scheme://host/path
+ */
+ public function get_normalized_http_url() {
+ $parts = parse_url($this->http_url);
+
+ $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http';
+ $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80');
+ $host = (isset($parts['host'])) ? strtolower($parts['host']) : '';
+ $path = (isset($parts['path'])) ? $parts['path'] : '';
+
+ if (($scheme == 'https' && $port != '443')
+ || ($scheme == 'http' && $port != '80')) {
+ $host = "$host:$port";
+ }
+ return "$scheme://$host$path";
+ }
+
+ /**
+ * builds a url usable for a GET request
+ */
+ public function to_url() {/*{{{*/
+ $out = $this->get_normalized_http_url() . "?";
+ $out .= $this->to_postdata();
+ return $out;
+ }/*}}}*/
+
+ /**
+ * builds the data one would send in a POST request
+ */
+ public function to_postdata() {/*{{{*/
+ $total = array();
+ foreach ($this->parameters as $k => $v) {
+ $total[] = OAuthUtil::urlencodeRFC3986($k) . "=" . OAuthUtil::urlencodeRFC3986($v);
+ }
+ $out = implode("&", $total);
+ return $out;
+ }/*}}}*/
+
+ /**
+ * builds the Authorization: header
+ */
+ public function to_header() {/*{{{*/
+ $out ='Authorization: OAuth ';
+ $total = array();
+
+ /*
+ $sig = $this->parameters['oauth_signature'];
+ unset($this->parameters['oauth_signature']);
+ uksort($this->parameters, 'strnatcmp');
+ $this->parameters['oauth_signature'] = $sig;
+ */
+
+ foreach ($this->parameters as $k => $v) {
+ if (substr($k, 0, 5) != "oauth") continue;
+ $out .= OAuthUtil::urlencodeRFC3986($k) . '="' . OAuthUtil::urlencodeRFC3986($v) . '", ';
+ }
+ $out = substr_replace($out, '', strlen($out) - 2);
+
+ return $out;
+ }/*}}}*/
+
+ public function __toString() {/*{{{*/
+ return $this->to_url();
+ }/*}}}*/
+
+
+ public function sign_request($signature_method, $consumer, $token, $privKey=NULL) {/*{{{*/
+ $this->set_parameter("oauth_signature_method", $signature_method->get_name());
+ $signature = $this->build_signature($signature_method, $consumer, $token, $privKey);
+ $this->set_parameter("oauth_signature", $signature);
+ }/*}}}*/
+
+ public function build_signature($signature_method, $consumer, $token, $privKey=NULL) {/*{{{*/
+ $signature = $signature_method->build_signature($this, $consumer, $token, $privKey);
+ return $signature;
+ }/*}}}*/
+
+ /**
+ * util function: current timestamp
+ */
+ private static function generate_timestamp() {/*{{{*/
+ return time();
+ }/*}}}*/
+
+ /**
+ * util function: current nonce
+ */
+ private static function generate_nonce() {/*{{{*/
+ $mt = microtime();
+ $rand = mt_rand();
+
+ return md5($mt . $rand); // md5s look nicer than numbers
+ }/*}}}*/
+
+ /**
+ * util function for turning the Authorization: header into
+ * parameters, has to do some unescaping
+ */
+ private static function split_header($header) {/*{{{*/
+ // this should be a regex
+ // error cases: commas in parameter values
+ $parts = explode(",", $header);
+ $out = array();
+ foreach ($parts as $param) {
+ $param = ltrim($param);
+ // skip the "realm" param, nobody ever uses it anyway
+ if (substr($param, 0, 5) != "oauth") continue;
+
+ $param_parts = explode("=", $param);
+
+ // rawurldecode() used because urldecode() will turn a "+" in the
+ // value into a space
+ $out[$param_parts[0]] = rawurldecode(substr($param_parts[1], 1, -1));
+ }
+ return $out;
+ }/*}}}*/
+
+ /**
+ * helper to try to sort out headers for people who aren't running apache
+ */
+ private static function get_headers() {/*{{{*/
+ if (function_exists('apache_request_headers')) {
+ // we need this to get the actual Authorization: header
+ // because apache tends to tell us it doesn't exist
+ return apache_request_headers();
+ }
+ // otherwise we don't have apache and are just going to have to hope
+ // that $_SERVER actually contains what we need
+ $out = array();
+ foreach ($_SERVER as $key => $value) {
+ if (substr($key, 0, 5) == "HTTP_") {
+ // this is chaos, basically it is just there to capitalize the first
+ // letter of every word that is not an initial HTTP and strip HTTP
+ // code from przemek
+ $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
+ $out[$key] = $value;
+ }
+ }
+ return $out;
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthServer {/*{{{*/
+ protected $timestamp_threshold = 300; // in seconds, five minutes
+ protected $version = 1.0; // hi blaine
+ protected $signature_methods = array();
+
+ protected $data_store;
+
+ function __construct($data_store) {/*{{{*/
+ $this->data_store = $data_store;
+ }/*}}}*/
+
+ public function add_signature_method($signature_method) {/*{{{*/
+ $this->signature_methods[$signature_method->get_name()] =
+ $signature_method;
+ }/*}}}*/
+
+ // high level functions
+
+ /**
+ * process a request_token request
+ * returns the request token on success
+ */
+ public function fetch_request_token(&$request) {/*{{{*/
+ $this->get_version($request);
+
+ $consumer = $this->get_consumer($request);
+
+ // no token required for the initial token request
+ $token = NULL;
+
+ $this->check_signature($request, $consumer, $token);
+
+ $new_token = $this->data_store->new_request_token($consumer);
+
+ return $new_token;
+ }/*}}}*/
+
+ /**
+ * process an access_token request
+ * returns the access token on success
+ */
+ public function fetch_access_token(&$request) {/*{{{*/
+ $this->get_version($request);
+
+ $consumer = $this->get_consumer($request);
+
+ // requires authorized request token
+ $token = $this->get_token($request, $consumer, "request");
+
+ $this->check_signature($request, $consumer, $token);
+
+ $new_token = $this->data_store->new_access_token($token, $consumer);
+
+ return $new_token;
+ }/*}}}*/
+
+ /**
+ * verify an api call, checks all the parameters
+ */
+ public function verify_request(&$request) {/*{{{*/
+ $this->get_version($request);
+ $consumer = $this->get_consumer($request);
+ $token = $this->get_token($request, $consumer, "access");
+ $this->check_signature($request, $consumer, $token);
+ return array($consumer, $token);
+ }/*}}}*/
+
+ // Internals from here
+ /**
+ * version 1
+ */
+ private function get_version(&$request) {/*{{{*/
+ $version = $request->get_parameter("oauth_version");
+ if (!$version) {
+ $version = 1.0;
+ }
+ if ($version && $version != $this->version) {
+ throw new OAuthException("OAuth version '$version' not supported");
+ }
+ return $version;
+ }/*}}}*/
+
+ /**
+ * figure out the signature with some defaults
+ */
+ private function get_signature_method(&$request) {/*{{{*/
+ $signature_method =
+ @$request->get_parameter("oauth_signature_method");
+ if (!$signature_method) {
+ $signature_method = "PLAINTEXT";
+ }
+ if (!in_array($signature_method,
+ array_keys($this->signature_methods))) {
+ throw new OAuthException(
+ "Signature method '$signature_method' not supported try one of the following: " . implode(", ", array_keys($this->signature_methods))
+ );
+ }
+ return $this->signature_methods[$signature_method];
+ }/*}}}*/
+
+ /**
+ * try to find the consumer for the provided request's consumer key
+ */
+ private function get_consumer(&$request) {/*{{{*/
+ $consumer_key = @$request->get_parameter("oauth_consumer_key");
+ if (!$consumer_key) {
+ throw new OAuthException("Invalid consumer key");
+ }
+
+ $consumer = $this->data_store->lookup_consumer($consumer_key);
+ if (!$consumer) {
+ throw new OAuthException("Invalid consumer");
+ }
+
+ return $consumer;
+ }/*}}}*/
+
+ /**
+ * try to find the token for the provided request's token key
+ */
+ private function get_token(&$request, $consumer, $token_type="access") {/*{{{*/
+ $token_field = @$request->get_parameter('oauth_token');
+ $token = $this->data_store->lookup_token(
+ $consumer, $token_type, $token_field
+ );
+ if (!$token) {
+ throw new OAuthException("Invalid $token_type token: $token_field");
+ }
+ return $token;
+ }/*}}}*/
+
+ /**
+ * all-in-one function to check the signature on a request
+ * should guess the signature method appropriately
+ */
+ private function check_signature(&$request, $consumer, $token) {/*{{{*/
+ // this should probably be in a different method
+ $timestamp = @$request->get_parameter('oauth_timestamp');
+ $nonce = @$request->get_parameter('oauth_nonce');
+
+ $this->check_timestamp($timestamp);
+ $this->check_nonce($consumer, $token, $nonce, $timestamp);
+
+ $signature_method = $this->get_signature_method($request);
+
+ $signature = $request->get_parameter('oauth_signature');
+ $valid_sig = $signature_method->check_signature(
+ $request,
+ $consumer,
+ $token,
+ $signature
+ );
+
+ if (!$valid_sig) {
+ throw new OAuthException("Invalid signature");
+ }
+ }/*}}}*/
+
+ /**
+ * check that the timestamp is new enough
+ */
+ private function check_timestamp($timestamp) {/*{{{*/
+ // verify that timestamp is recentish
+ $now = time();
+ if ($now - $timestamp > $this->timestamp_threshold) {
+ throw new OAuthException("Expired timestamp, yours $timestamp, ours $now");
+ }
+ }/*}}}*/
+
+ /**
+ * check that the nonce is not repeated
+ */
+ private function check_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
+ // verify that the nonce is uniqueish
+ $found = $this->data_store->lookup_nonce($consumer, $token, $nonce, $timestamp);
+ if ($found) {
+ throw new OAuthException("Nonce already used: $nonce");
+ }
+ }/*}}}*/
+
+
+
+}/*}}}*/
+
+class OAuthDataStore {/*{{{*/
+ function lookup_consumer($consumer_key) {/*{{{*/
+ // implement me
+ }/*}}}*/
+
+ function lookup_token($consumer, $token_type, $token) {/*{{{*/
+ // implement me
+ }/*}}}*/
+
+ function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
+ // implement me
+ }/*}}}*/
+
+ function fetch_request_token($consumer) {/*{{{*/
+ // return a new token attached to this consumer
+ }/*}}}*/
+
+ function fetch_access_token($token, $consumer) {/*{{{*/
+ // return a new access token attached to this consumer
+ // for the user associated with this token if the request token
+ // is authorized
+ // should also invalidate the request token
+ }/*}}}*/
+
+}/*}}}*/
+
+
+/* A very naive dbm-based oauth storage
+ */
+class SimpleOAuthDataStore extends OAuthDataStore {/*{{{*/
+ private $dbh;
+
+ function __construct($path = "oauth.gdbm") {/*{{{*/
+ $this->dbh = dba_popen($path, 'c', 'gdbm');
+ }/*}}}*/
+
+ function __destruct() {/*{{{*/
+ dba_close($this->dbh);
+ }/*}}}*/
+
+ function lookup_consumer($consumer_key) {/*{{{*/
+ $rv = dba_fetch("consumer_$consumer_key", $this->dbh);
+ if ($rv === FALSE) {
+ return NULL;
+ }
+ $obj = unserialize($rv);
+ if (!($obj instanceof OAuthConsumer)) {
+ return NULL;
+ }
+ return $obj;
+ }/*}}}*/
+
+ function lookup_token($consumer, $token_type, $token) {/*{{{*/
+ $rv = dba_fetch("${token_type}_${token}", $this->dbh);
+ if ($rv === FALSE) {
+ return NULL;
+ }
+ $obj = unserialize($rv);
+ if (!($obj instanceof OAuthToken)) {
+ return NULL;
+ }
+ return $obj;
+ }/*}}}*/
+
+ function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
+ return dba_exists("nonce_$nonce", $this->dbh);
+ }/*}}}*/
+
+ function new_token($consumer, $type="request") {/*{{{*/
+ $key = md5(time());
+ $secret = time() + time();
+ $token = new OAuthToken($key, md5(md5($secret)));
+ if (!dba_insert("${type}_$key", serialize($token), $this->dbh)) {
+ throw new OAuthException("doooom!");
+ }
+ return $token;
+ }/*}}}*/
+
+ function new_request_token($consumer) {/*{{{*/
+ return $this->new_token($consumer, "request");
+ }/*}}}*/
+
+ function new_access_token($token, $consumer) {/*{{{*/
+
+ $token = $this->new_token($consumer, 'access');
+ dba_delete("request_" . $token->key, $this->dbh);
+ return $token;
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthUtil {/*{{{*/
+ public static function urlencodeRFC3986($string) {/*{{{*/
+ return str_replace('%7E', '~', rawurlencode($string));
+ }/*}}}*/
+
+ public static function urldecodeRFC3986($string) {/*{{{*/
+ return rawurldecode($string);
+ }/*}}}*/
+}/*}}}*/
+
+?> \ No newline at end of file
diff --git a/3rdparty/Google/common.inc.php b/3rdparty/Google/common.inc.php
new file mode 100755
index 00000000000..57185cdc4d8
--- /dev/null
+++ b/3rdparty/Google/common.inc.php
@@ -0,0 +1,185 @@
+<?php
+/* Copyright (c) 2009 Google Inc.
+ *
+ * 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.
+ *
+ * Author: Eric Bidelman <e.bidelman@google.com>
+ */
+
+$PRIV_KEY_FILE = '/path/to/your/rsa_private_key.pem';
+
+// OAuth library - http://oauth.googlecode.com/svn/code/php/
+require_once('OAuth.php');
+
+// Google's accepted signature methods
+$hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
+$rsa_method = new OAuthSignatureMethod_RSA_SHA1();
+$SIG_METHODS = array($rsa_method->get_name() => $rsa_method,
+ $hmac_method->get_name() => $hmac_method);
+
+/**
+ * Makes an HTTP request to the specified URL
+ *
+ * @param string $http_method The HTTP method (GET, POST, PUT, DELETE)
+ * @param string $url Full URL of the resource to access
+ * @param array $extraHeaders (optional) Additional headers to include in each
+ * request. Elements are header/value pair strings ('Host: example.com')
+ * @param string $postData (optional) POST/PUT request body
+ * @param bool $returnResponseHeaders True if resp. headers should be returned.
+ * @return string Response body from the server
+ */
+function send_signed_request($http_method, $url, $extraHeaders=null,
+ $postData=null, $returnResponseHeaders=true) {
+ $curl = curl_init($url);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_FAILONERROR, false);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+
+ // Return request headers in the reponse
+// curl_setopt($curl, CURLINFO_HEADER_OUT, true);
+
+ // Return response headers ni the response?
+ if ($returnResponseHeaders) {
+ curl_setopt($curl, CURLOPT_HEADER, true);
+ }
+
+ $headers = array();
+ //$headers[] = 'GData-Version: 2.0'; // use GData v2 by default
+ if (is_array($extraHeaders)) {
+ $headers = array_merge($headers, $extraHeaders);
+ }
+
+ // Setup default curl options for each type of HTTP request.
+ // This is also a great place to add additional headers for each request.
+ switch($http_method) {
+ case 'GET':
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ break;
+ case 'POST':
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($curl, CURLOPT_POST, 1);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
+ break;
+ case 'PUT':
+ $headers[] = 'If-Match: *';
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
+ break;
+ case 'DELETE':
+ $headers[] = 'If-Match: *';
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method);
+ break;
+ default:
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ }
+
+ // Execute the request. If an error occures, fill the response body with it.
+ $response = curl_exec($curl);
+ if (!$response) {
+ $response = curl_error($curl);
+ }
+
+ // Add server's response headers to our response body
+ $response = curl_getinfo($curl, CURLINFO_HEADER_OUT) . $response;
+
+ curl_close($curl);
+
+ return $response;
+}
+
+/**
+* Takes XML as a string and returns it nicely indented
+*
+* @param string $xml The xml to beautify
+* @param boolean $html_output True if returned XML should be escaped for HTML.
+* @return string The beautified xml
+*/
+function xml_pretty_printer($xml, $html_output=false) {
+ $xml_obj = new SimpleXMLElement($xml);
+ $level = 2;
+
+ // Get an array containing each XML element
+ $xml = explode("\n", preg_replace('/>\s*</', ">\n<", $xml_obj->asXML()));
+
+ // Hold current indentation level
+ $indent = 0;
+
+ $pretty = array();
+
+ // Shift off opening XML tag if present
+ if (count($xml) && preg_match('/^<\?\s*xml/', $xml[0])) {
+ $pretty[] = array_shift($xml);
+ }
+
+ foreach ($xml as $el) {
+ if (preg_match('/^<([\w])+[^>\/]*>$/U', $el)) {
+ // opening tag, increase indent
+ $pretty[] = str_repeat(' ', $indent) . $el;
+ $indent += $level;
+ } else {
+ if (preg_match('/^<\/.+>$/', $el)) {
+ $indent -= $level; // closing tag, decrease indent
+ }
+ if ($indent < 0) {
+ $indent += $level;
+ }
+ $pretty[] = str_repeat(' ', $indent) . $el;
+ }
+ }
+
+ $xml = implode("\n", $pretty);
+ return $html_output ? htmlentities($xml) : $xml;
+}
+
+/**
+ * Joins key/value pairs by $inner_glue and each pair together by $outer_glue.
+ *
+ * Example: implode_assoc('=', '&', array('a' => 1, 'b' => 2)) === 'a=1&b=2'
+ *
+ * @param string $inner_glue What to implode each key/value pair with
+ * @param string $outer_glue What to impode each key/value string subset with
+ * @param array $array Associative array of query parameters
+ * @return string Urlencoded string of query parameters
+ */
+function implode_assoc($inner_glue, $outer_glue, $array) {
+ $output = array();
+ foreach($array as $key => $item) {
+ $output[] = $key . $inner_glue . urlencode($item);
+ }
+ return implode($outer_glue, $output);
+}
+
+/**
+ * Explodes a string of key/value url parameters into an associative array.
+ * This method performs the compliment operations of implode_assoc().
+ *
+ * Example: explode_assoc('=', '&', 'a=1&b=2') === array('a' => 1, 'b' => 2)
+ *
+ * @param string $inner_glue What each key/value pair is joined with
+ * @param string $outer_glue What each set of key/value pairs is joined with.
+ * @param array $array Associative array of query parameters
+ * @return array Urlencoded string of query parameters
+ */
+function explode_assoc($inner_glue, $outer_glue, $params) {
+ $tempArr = explode($outer_glue, $params);
+ foreach($tempArr as $val) {
+ $pos = strpos($val, $inner_glue);
+ $key = substr($val, 0, $pos);
+ $array2[$key] = substr($val, $pos + 1, strlen($val));
+ }
+ return $array2;
+}
+
+?> \ No newline at end of file
diff --git a/3rdparty/MDB2/Schema/Parser.php b/3rdparty/MDB2/Schema/Parser.php
index cfd0c37d8a3..3c4345661b1 100644
--- a/3rdparty/MDB2/Schema/Parser.php
+++ b/3rdparty/MDB2/Schema/Parser.php
@@ -147,33 +147,6 @@ class MDB2_Schema_Parser extends XML_Parser
}
/**
- * PHP 4 compatible constructor
- *
- * @param array $variables mixed array with user defined schema
- * variables
- * @param bool $fail_on_invalid_names array with reserved words per RDBMS
- * @param array $structure multi dimensional array with
- * database schema and data
- * @param array $valid_types information of all valid fields
- * types
- * @param bool $force_defaults if true sets a default value to
- * field when not explicit
- * @param int $max_identifiers_length maximum allowed size for entities
- * name
- *
- * @return void
- *
- * @access public
- * @static
- */
- function MDB2_Schema_Parser($variables, $fail_on_invalid_names = true,
- $structure = false, $valid_types = array(), $force_defaults = true,
- $max_identifiers_length = null
- ) {
- $this->__construct($variables, $fail_on_invalid_names, $structure, $valid_types, $force_defaults);
- }
-
- /**
* Triggered when reading a XML open tag <element>
*
* @param resource $xp xml parser resource
diff --git a/3rdparty/MDB2/Schema/Parser2.php b/3rdparty/MDB2/Schema/Parser2.php
index b415b4a336e..f27dffbabf9 100644
--- a/3rdparty/MDB2/Schema/Parser2.php
+++ b/3rdparty/MDB2/Schema/Parser2.php
@@ -144,33 +144,6 @@ class MDB2_Schema_Parser2 extends XML_Unserializer
}
/**
- * PHP 4 compatible constructor
- *
- * @param array $variables mixed array with user defined schema
- * variables
- * @param bool $fail_on_invalid_names array with reserved words per RDBMS
- * @param array $structure multi dimensional array with
- * database schema and data
- * @param array $valid_types information of all valid fields
- * types
- * @param bool $force_defaults if true sets a default value to
- * field when not explicit
- * @param int $max_identifiers_length maximum allowed size for entities
- * name
- *
- * @return void
- *
- * @access public
- * @static
- */
- function MDB2_Schema_Parser2($variables, $fail_on_invalid_names = true,
- $structure = false, $valid_types = array(), $force_defaults = true,
- $max_identifiers_length = null
- ) {
- $this->__construct($variables, $fail_on_invalid_names, $structure, $valid_types, $force_defaults);
- }
-
- /**
* Main method. Parses XML Schema File.
*
* @return bool|error object
diff --git a/3rdparty/MDB2/Schema/Validate.php b/3rdparty/MDB2/Schema/Validate.php
index 4cff175576f..4a8e0d27bac 100644
--- a/3rdparty/MDB2/Schema/Validate.php
+++ b/3rdparty/MDB2/Schema/Validate.php
@@ -108,28 +108,6 @@ class MDB2_Schema_Validate
$this->max_identifiers_length = $max_identifiers_length;
}
- /**
- * PHP 4 compatible constructor
- *
- * @param bool $fail_on_invalid_names array with reserved words per RDBMS
- * @param array $valid_types information of all valid fields
- * types
- * @param bool $force_defaults if true sets a default value to
- * field when not explicit
- * @param int $max_identifiers_length maximum allowed size for entities
- * name
- *
- * @return void
- *
- * @access public
- * @static
- */
- function MDB2_Schema_Validate($fail_on_invalid_names = true, $valid_types = array(),
- $force_defaults = true, $max_identifiers_length = null
- ) {
- $this->__construct($fail_on_invalid_names, $valid_types, $force_defaults);
- }
-
// }}}
// {{{ raiseError()
diff --git a/3rdparty/MDB2/Schema/Writer.php b/3rdparty/MDB2/Schema/Writer.php
index 70a03168de6..3eaa39a2071 100644
--- a/3rdparty/MDB2/Schema/Writer.php
+++ b/3rdparty/MDB2/Schema/Writer.php
@@ -82,22 +82,6 @@ class MDB2_Schema_Writer
$this->valid_types = $valid_types;
}
- /**
- * PHP 4 compatible constructor
- *
- * @param array $valid_types information of all valid fields
- * types
- *
- * @return void
- *
- * @access public
- * @static
- */
- function MDB2_Schema_Writer($valid_types = array())
- {
- $this->__construct($valid_types);
- }
-
// }}}
// {{{ raiseError()
diff --git a/3rdparty/Sabre.includes.php b/3rdparty/Sabre.includes.php
index c1334373663..c1334373663 100644..100755
--- a/3rdparty/Sabre.includes.php
+++ b/3rdparty/Sabre.includes.php
diff --git a/3rdparty/Sabre/CalDAV/Backend/Abstract.php b/3rdparty/Sabre/CalDAV/Backend/Abstract.php
index 7aba1d69ffe..7aba1d69ffe 100644..100755
--- a/3rdparty/Sabre/CalDAV/Backend/Abstract.php
+++ b/3rdparty/Sabre/CalDAV/Backend/Abstract.php
diff --git a/3rdparty/Sabre/CalDAV/Backend/PDO.php b/3rdparty/Sabre/CalDAV/Backend/PDO.php
index ddacf940c74..ddacf940c74 100644..100755
--- a/3rdparty/Sabre/CalDAV/Backend/PDO.php
+++ b/3rdparty/Sabre/CalDAV/Backend/PDO.php
diff --git a/3rdparty/Sabre/CalDAV/Calendar.php b/3rdparty/Sabre/CalDAV/Calendar.php
index 623df2dd1b8..623df2dd1b8 100644..100755
--- a/3rdparty/Sabre/CalDAV/Calendar.php
+++ b/3rdparty/Sabre/CalDAV/Calendar.php
diff --git a/3rdparty/Sabre/CalDAV/CalendarObject.php b/3rdparty/Sabre/CalDAV/CalendarObject.php
index 72f0a578d16..72f0a578d16 100644..100755
--- a/3rdparty/Sabre/CalDAV/CalendarObject.php
+++ b/3rdparty/Sabre/CalDAV/CalendarObject.php
diff --git a/3rdparty/Sabre/CalDAV/CalendarQueryParser.php b/3rdparty/Sabre/CalDAV/CalendarQueryParser.php
index bd0d343382f..bd0d343382f 100644..100755
--- a/3rdparty/Sabre/CalDAV/CalendarQueryParser.php
+++ b/3rdparty/Sabre/CalDAV/CalendarQueryParser.php
diff --git a/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php b/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php
index 1bb6b5d53fa..8f674840e87 100644..100755
--- a/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php
+++ b/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php
@@ -294,6 +294,7 @@ class Sabre_CalDAV_CalendarQueryValidator {
// in the VALARM component code, so this is a hack, and an
// expensive one too.
if ($component->parent->name === 'VEVENT' && $component->parent->RRULE) {
+
// Fire up the iterator!
$it = new Sabre_VObject_RecurrenceIterator($component->parent->parent, (string)$component->parent->UID);
while($it->valid()) {
@@ -303,15 +304,37 @@ class Sabre_CalDAV_CalendarQueryValidator {
// one is the first to trigger. Based on this, we can
// determine if we can 'give up' expanding events.
$firstAlarm = null;
- foreach($expandedEvent->VALARM as $expandedAlarm) {
- $effectiveTrigger = $expandedAlarm->getEffectiveTriggerTime();
- if (!$firstAlarm || $effectiveTrigger < $firstAlarm) {
- $firstAlarm = $effectiveTrigger;
- }
- if ($expandedAlarm->isInTimeRange($start, $end)) {
- return true;
+ if ($expandedEvent->VALARM !== null) {
+ foreach($expandedEvent->VALARM as $expandedAlarm) {
+
+ $effectiveTrigger = $expandedAlarm->getEffectiveTriggerTime();
+ if ($expandedAlarm->isInTimeRange($start, $end)) {
+ return true;
+ }
+
+ if ((string)$expandedAlarm->TRIGGER['VALUE'] === 'DATE-TIME') {
+ // This is an alarm with a non-relative trigger
+ // time, likely created by a buggy client. The
+ // implication is that every alarm in this
+ // recurring event trigger at the exact same
+ // time. It doesn't make sense to traverse
+ // further.
+ } else {
+ // We store the first alarm as a means to
+ // figure out when we can stop traversing.
+ if (!$firstAlarm || $effectiveTrigger < $firstAlarm) {
+ $firstAlarm = $effectiveTrigger;
+ }
+ }
}
-
+ }
+ if (is_null($firstAlarm)) {
+ // No alarm was found.
+ //
+ // Or technically: No alarm that will change for
+ // every instance of the recurrence was found,
+ // which means we can assume there was no match.
+ return false;
}
if ($firstAlarm > $end) {
return false;
diff --git a/3rdparty/Sabre/CalDAV/CalendarRootNode.php b/3rdparty/Sabre/CalDAV/CalendarRootNode.php
index 3907913cc78..3907913cc78 100644..100755
--- a/3rdparty/Sabre/CalDAV/CalendarRootNode.php
+++ b/3rdparty/Sabre/CalDAV/CalendarRootNode.php
diff --git a/3rdparty/Sabre/CalDAV/ICSExportPlugin.php b/3rdparty/Sabre/CalDAV/ICSExportPlugin.php
index ec42b406b2f..ec42b406b2f 100644..100755
--- a/3rdparty/Sabre/CalDAV/ICSExportPlugin.php
+++ b/3rdparty/Sabre/CalDAV/ICSExportPlugin.php
diff --git a/3rdparty/Sabre/CalDAV/ICalendar.php b/3rdparty/Sabre/CalDAV/ICalendar.php
index 15d51ebcf79..15d51ebcf79 100644..100755
--- a/3rdparty/Sabre/CalDAV/ICalendar.php
+++ b/3rdparty/Sabre/CalDAV/ICalendar.php
diff --git a/3rdparty/Sabre/CalDAV/ICalendarObject.php b/3rdparty/Sabre/CalDAV/ICalendarObject.php
index 280f982a310..280f982a310 100644..100755
--- a/3rdparty/Sabre/CalDAV/ICalendarObject.php
+++ b/3rdparty/Sabre/CalDAV/ICalendarObject.php
diff --git a/3rdparty/Sabre/CalDAV/Plugin.php b/3rdparty/Sabre/CalDAV/Plugin.php
index d7d1d970518..c56ab384844 100644..100755
--- a/3rdparty/Sabre/CalDAV/Plugin.php
+++ b/3rdparty/Sabre/CalDAV/Plugin.php
@@ -49,23 +49,23 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
/**
* The email handler for invites and other scheduling messages.
- *
- * @var Sabre_CalDAV_Schedule_IMip
+ *
+ * @var Sabre_CalDAV_Schedule_IMip
*/
protected $imipHandler;
/**
* Sets the iMIP handler.
*
- * iMIP = The email transport of iCalendar scheduling messages. Setting
- * this is optional, but if you want the server to allow invites to be sent
+ * iMIP = The email transport of iCalendar scheduling messages. Setting
+ * this is optional, but if you want the server to allow invites to be sent
* out, you must set a handler.
*
- * Specifically iCal will plain assume that the server supports this. If
- * the server doesn't, iCal will display errors when inviting people to
+ * Specifically iCal will plain assume that the server supports this. If
+ * the server doesn't, iCal will display errors when inviting people to
* events.
*
- * @param Sabre_CalDAV_Schedule_IMip $imipHandler
+ * @param Sabre_CalDAV_Schedule_IMip $imipHandler
* @return void
*/
public function setIMipHandler(Sabre_CalDAV_Schedule_IMip $imipHandler) {
@@ -672,6 +672,42 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
}
+ if ($vobj->name !== 'VCALENDAR') {
+ throw new Sabre_DAV_Exception_UnsupportedMediaType('This collection can only support iCalendar objects.');
+ }
+
+ $foundType = null;
+ $foundUID = null;
+ foreach($vobj->getComponents() as $component) {
+ switch($component->name) {
+ case 'VTIMEZONE' :
+ continue 2;
+ case 'VEVENT' :
+ case 'VTODO' :
+ case 'VJOURNAL' :
+ if (is_null($foundType)) {
+ $foundType = $component->name;
+ if (!isset($component->UID)) {
+ throw new Sabre_DAV_Exception_BadRequest('Every ' . $component->name . ' component must have an UID');
+ }
+ $foundUID = (string)$component->UID;
+ } else {
+ if ($foundType !== $component->name) {
+ throw new Sabre_DAV_Exception_BadRequest('A calendar object must only contain 1 component. We found a ' . $component->name . ' as well as a ' . $foundType);
+ }
+ if ($foundUID !== (string)$component->UID) {
+ throw new Sabre_DAV_Exception_BadRequest('Every ' . $component->name . ' in this object must have identical UIDs');
+ }
+ }
+ break;
+ default :
+ throw new Sabre_DAV_Exception_BadRequest('You are not allowed to create components of type: ' . $component->name . ' here');
+
+ }
+ }
+ if (!$foundType)
+ throw new Sabre_DAV_Exception_BadRequest('iCalendar object must contain at least 1 of VEVENT, VTODO or VJOURNAL');
+
}
/**
@@ -687,12 +723,12 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
if (!$originator) {
throw new Sabre_DAV_Exception_BadRequest('The Originator: header must be specified when making POST requests');
- }
+ }
if (!$recipients) {
throw new Sabre_DAV_Exception_BadRequest('The Recipient: header must be specified when making POST requests');
- }
+ }
- if (!preg_match('/^mailto:(.*)@(.*)$/', $originator)) {
+ if (!preg_match('/^mailto:(.*)@(.*)$/i', $originator)) {
throw new Sabre_DAV_Exception_BadRequest('Originator must start with mailto: and must be valid email address');
}
$originator = substr($originator,7);
@@ -701,14 +737,14 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
foreach($recipients as $k=>$recipient) {
$recipient = trim($recipient);
- if (!preg_match('/^mailto:(.*)@(.*)$/', $recipient)) {
+ if (!preg_match('/^mailto:(.*)@(.*)$/i', $recipient)) {
throw new Sabre_DAV_Exception_BadRequest('Recipients must start with mailto: and must be valid email address');
}
$recipient = substr($recipient, 7);
$recipients[$k] = $recipient;
}
- // We need to make sure that 'originator' matches one of the email
+ // We need to make sure that 'originator' matches one of the email
// addresses of the selected principal.
$principal = $outboxNode->getOwner();
$props = $this->server->getProperties($principal,array(
@@ -724,7 +760,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
throw new Sabre_DAV_Exception_Forbidden('The addresses specified in the Originator header did not match any addresses in the owners calendar-user-address-set header');
}
- try {
+ try {
$vObject = Sabre_VObject_Reader::read($this->server->httpRequest->getBody(true));
} catch (Sabre_VObject_ParseException $e) {
throw new Sabre_DAV_Exception_BadRequest('The request body must be a valid iCalendar object. Parse error: ' . $e->getMessage());
@@ -749,9 +785,10 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
}
if (in_array($method, array('REQUEST','REPLY','ADD','CANCEL')) && $componentType==='VEVENT') {
- $this->iMIPMessage($originator, $recipients, $vObject);
+ $result = $this->iMIPMessage($originator, $recipients, $vObject);
$this->server->httpResponse->sendStatus(200);
- $this->server->httpResponse->sendBody('Messages sent');
+ $this->server->httpResponse->setHeader('Content-Type','application/xml');
+ $this->server->httpResponse->sendBody($this->generateScheduleResponse($result));
} else {
throw new Sabre_DAV_Exception_NotImplemented('This iTIP method is currently not implemented');
}
@@ -760,18 +797,83 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
/**
* Sends an iMIP message by email.
- *
- * @param string $originator
- * @param array $recipients
- * @param Sabre_VObject_Component $vObject
- * @return void
+ *
+ * This method must return an array with status codes per recipient.
+ * This should look something like:
+ *
+ * array(
+ * 'user1@example.org' => '2.0;Success'
+ * )
+ *
+ * Formatting for this status code can be found at:
+ * https://tools.ietf.org/html/rfc5545#section-3.8.8.3
+ *
+ * A list of valid status codes can be found at:
+ * https://tools.ietf.org/html/rfc5546#section-3.6
+ *
+ * @param string $originator
+ * @param array $recipients
+ * @param Sabre_VObject_Component $vObject
+ * @return array
*/
protected function iMIPMessage($originator, array $recipients, Sabre_VObject_Component $vObject) {
if (!$this->imipHandler) {
- throw new Sabre_DAV_Exception_NotImplemented('No iMIP handler is setup on this server.');
+ $resultStatus = '5.2;This server does not support this operation';
+ } else {
+ $this->imipHandler->sendMessage($originator, $recipients, $vObject);
+ $resultStatus = '2.0;Success';
}
- $this->imipHandler->sendMessage($originator, $recipients, $vObject);
+
+ $result = array();
+ foreach($recipients as $recipient) {
+ $result[$recipient] = $resultStatus;
+ }
+
+ return $result;
+
+
+ }
+
+ /**
+ * Generates a schedule-response XML body
+ *
+ * The recipients array is a key->value list, containing email addresses
+ * and iTip status codes. See the iMIPMessage method for a description of
+ * the value.
+ *
+ * @param array $recipients
+ * @return string
+ */
+ public function generateScheduleResponse(array $recipients) {
+
+ $dom = new DOMDocument('1.0','utf-8');
+ $dom->formatOutput = true;
+ $xscheduleResponse = $dom->createElement('cal:schedule-response');
+ $dom->appendChild($xscheduleResponse);
+
+ foreach($this->server->xmlNamespaces as $namespace=>$prefix) {
+
+ $xscheduleResponse->setAttribute('xmlns:' . $prefix, $namespace);
+
+ }
+
+ foreach($recipients as $recipient=>$status) {
+ $xresponse = $dom->createElement('cal:response');
+
+ $xrecipient = $dom->createElement('cal:recipient');
+ $xrecipient->appendChild($dom->createTextNode($recipient));
+ $xresponse->appendChild($xrecipient);
+
+ $xrequestStatus = $dom->createElement('cal:request-status');
+ $xrequestStatus->appendChild($dom->createTextNode($status));
+ $xresponse->appendChild($xrequestStatus);
+
+ $xscheduleResponse->appendChild($xresponse);
+
+ }
+
+ return $dom->saveXML();
}
diff --git a/3rdparty/Sabre/CalDAV/Principal/Collection.php b/3rdparty/Sabre/CalDAV/Principal/Collection.php
index abbefa5567a..abbefa5567a 100644..100755
--- a/3rdparty/Sabre/CalDAV/Principal/Collection.php
+++ b/3rdparty/Sabre/CalDAV/Principal/Collection.php
diff --git a/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php b/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php
index 4b3f035634a..4b3f035634a 100644..100755
--- a/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php
+++ b/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php
diff --git a/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php b/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php
index dd0c2e86edd..dd0c2e86edd 100644..100755
--- a/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php
+++ b/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php
diff --git a/3rdparty/Sabre/CalDAV/Principal/User.php b/3rdparty/Sabre/CalDAV/Principal/User.php
index 8453b877a73..8453b877a73 100644..100755
--- a/3rdparty/Sabre/CalDAV/Principal/User.php
+++ b/3rdparty/Sabre/CalDAV/Principal/User.php
diff --git a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php
index 2ea078d7dac..2ea078d7dac 100644..100755
--- a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php
+++ b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php
diff --git a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php
index 1d848dd5cf6..1d848dd5cf6 100644..100755
--- a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php
+++ b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php
diff --git a/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php b/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php
index 24e84d4c17d..24e84d4c17d 100644..100755
--- a/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php
+++ b/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php
diff --git a/3rdparty/Sabre/CalDAV/Schedule/IMip.php b/3rdparty/Sabre/CalDAV/Schedule/IMip.php
index 37e75fcc4a7..37e75fcc4a7 100644..100755
--- a/3rdparty/Sabre/CalDAV/Schedule/IMip.php
+++ b/3rdparty/Sabre/CalDAV/Schedule/IMip.php
diff --git a/3rdparty/Sabre/CalDAV/Schedule/IOutbox.php b/3rdparty/Sabre/CalDAV/Schedule/IOutbox.php
index 46d77514bc0..46d77514bc0 100644..100755
--- a/3rdparty/Sabre/CalDAV/Schedule/IOutbox.php
+++ b/3rdparty/Sabre/CalDAV/Schedule/IOutbox.php
diff --git a/3rdparty/Sabre/CalDAV/Schedule/Outbox.php b/3rdparty/Sabre/CalDAV/Schedule/Outbox.php
index 014c37230d1..014c37230d1 100644..100755
--- a/3rdparty/Sabre/CalDAV/Schedule/Outbox.php
+++ b/3rdparty/Sabre/CalDAV/Schedule/Outbox.php
diff --git a/3rdparty/Sabre/CalDAV/Server.php b/3rdparty/Sabre/CalDAV/Server.php
index 325e3d80a7f..325e3d80a7f 100644..100755
--- a/3rdparty/Sabre/CalDAV/Server.php
+++ b/3rdparty/Sabre/CalDAV/Server.php
diff --git a/3rdparty/Sabre/CalDAV/UserCalendars.php b/3rdparty/Sabre/CalDAV/UserCalendars.php
index b8d3f0573fa..b8d3f0573fa 100644..100755
--- a/3rdparty/Sabre/CalDAV/UserCalendars.php
+++ b/3rdparty/Sabre/CalDAV/UserCalendars.php
diff --git a/3rdparty/Sabre/CalDAV/Version.php b/3rdparty/Sabre/CalDAV/Version.php
index 939e903c89f..ace9901c089 100644..100755
--- a/3rdparty/Sabre/CalDAV/Version.php
+++ b/3rdparty/Sabre/CalDAV/Version.php
@@ -14,7 +14,7 @@ class Sabre_CalDAV_Version {
/**
* Full version number
*/
- const VERSION = '1.6.2';
+ const VERSION = '1.6.4';
/**
* Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/CalDAV/includes.php b/3rdparty/Sabre/CalDAV/includes.php
index 1ecb870a0e1..1ecb870a0e1 100644..100755
--- a/3rdparty/Sabre/CalDAV/includes.php
+++ b/3rdparty/Sabre/CalDAV/includes.php
diff --git a/3rdparty/Sabre/CardDAV/AddressBook.php b/3rdparty/Sabre/CardDAV/AddressBook.php
index 3b381e1eea3..12297175a85 100644..100755
--- a/3rdparty/Sabre/CardDAV/AddressBook.php
+++ b/3rdparty/Sabre/CardDAV/AddressBook.php
@@ -108,7 +108,9 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
*/
public function createFile($name,$vcardData = null) {
- $vcardData = stream_get_contents($vcardData);
+ if (is_resource($vcardData)) {
+ $vcardData = stream_get_contents($vcardData);
+ }
// Converting to UTF-8, if needed
$vcardData = Sabre_DAV_StringUtil::ensureUTF8($vcardData);
diff --git a/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php b/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php
index 85a4963127b..46bb8ff18dd 100644..100755
--- a/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php
+++ b/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php
@@ -9,7 +9,7 @@
* @package Sabre
* @subpackage CardDAV
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_CardDAV_AddressBookQueryParser {
@@ -88,12 +88,22 @@ class Sabre_CardDAV_AddressBookQueryParser {
if (is_nan($limit)) $limit = null;
$filter = $this->xpath->query('/card:addressbook-query/card:filter');
- if ($filter->length !== 1) {
+
+ // According to the CardDAV spec there needs to be exactly 1 filter
+ // element. However, KDE 4.8.2 contains a bug that will encode 0 filter
+ // elements, so this is a workaround for that.
+ //
+ // See: https://bugs.kde.org/show_bug.cgi?id=300047
+ if ($filter->length === 0) {
+ $test = null;
+ $filter = null;
+ } elseif ($filter->length === 1) {
+ $filter = $filter->item(0);
+ $test = $this->xpath->evaluate('string(@test)', $filter);
+ } else {
throw new Sabre_DAV_Exception_BadRequest('Only one filter element is allowed');
}
- $filter = $filter->item(0);
- $test = $this->xpath->evaluate('string(@test)', $filter);
if (!$test) $test = self::TEST_ANYOF;
if ($test !== self::TEST_ANYOF && $test !== self::TEST_ALLOF) {
throw new Sabre_DAV_Exception_BadRequest('The test attribute must either hold "anyof" or "allof"');
diff --git a/3rdparty/Sabre/CardDAV/AddressBookRoot.php b/3rdparty/Sabre/CardDAV/AddressBookRoot.php
index 9d37b15f08e..9d37b15f08e 100644..100755
--- a/3rdparty/Sabre/CardDAV/AddressBookRoot.php
+++ b/3rdparty/Sabre/CardDAV/AddressBookRoot.php
diff --git a/3rdparty/Sabre/CardDAV/Backend/Abstract.php b/3rdparty/Sabre/CardDAV/Backend/Abstract.php
index e4806b7161f..e4806b7161f 100644..100755
--- a/3rdparty/Sabre/CardDAV/Backend/Abstract.php
+++ b/3rdparty/Sabre/CardDAV/Backend/Abstract.php
diff --git a/3rdparty/Sabre/CardDAV/Backend/PDO.php b/3rdparty/Sabre/CardDAV/Backend/PDO.php
index 413a77f3bcc..413a77f3bcc 100644..100755
--- a/3rdparty/Sabre/CardDAV/Backend/PDO.php
+++ b/3rdparty/Sabre/CardDAV/Backend/PDO.php
diff --git a/3rdparty/Sabre/CardDAV/Card.php b/3rdparty/Sabre/CardDAV/Card.php
index d7c66333837..d7c66333837 100644..100755
--- a/3rdparty/Sabre/CardDAV/Card.php
+++ b/3rdparty/Sabre/CardDAV/Card.php
diff --git a/3rdparty/Sabre/CardDAV/IAddressBook.php b/3rdparty/Sabre/CardDAV/IAddressBook.php
index 2bc275bcf74..2bc275bcf74 100644..100755
--- a/3rdparty/Sabre/CardDAV/IAddressBook.php
+++ b/3rdparty/Sabre/CardDAV/IAddressBook.php
diff --git a/3rdparty/Sabre/CardDAV/ICard.php b/3rdparty/Sabre/CardDAV/ICard.php
index a17299316c1..a17299316c1 100644..100755
--- a/3rdparty/Sabre/CardDAV/ICard.php
+++ b/3rdparty/Sabre/CardDAV/ICard.php
diff --git a/3rdparty/Sabre/CardDAV/IDirectory.php b/3rdparty/Sabre/CardDAV/IDirectory.php
index 22d4afeb24a..22d4afeb24a 100644..100755
--- a/3rdparty/Sabre/CardDAV/IDirectory.php
+++ b/3rdparty/Sabre/CardDAV/IDirectory.php
diff --git a/3rdparty/Sabre/CardDAV/Plugin.php b/3rdparty/Sabre/CardDAV/Plugin.php
index 095769feddc..96def6dd96b 100644..100755
--- a/3rdparty/Sabre/CardDAV/Plugin.php
+++ b/3rdparty/Sabre/CardDAV/Plugin.php
@@ -52,6 +52,8 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
$server->subscribeEvent('report', array($this,'report'));
$server->subscribeEvent('onHTMLActionsPanel', array($this,'htmlActionsPanel'));
$server->subscribeEvent('onBrowserPostAction', array($this,'browserPostAction'));
+ $server->subscribeEvent('beforeWriteContent', array($this, 'beforeWriteContent'));
+ $server->subscribeEvent('beforeCreateFile', array($this, 'beforeCreateFile'));
/* Namespaces */
$server->xmlNamespaces[self::NS_CARDDAV] = 'card';
@@ -152,7 +154,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
$val = stream_get_contents($val);
// Taking out \r to not screw up the xml output
- $returnedProperties[200][$addressDataProp] = str_replace("\r","", $val);
+ //$returnedProperties[200][$addressDataProp] = str_replace("\r","", $val);
// The stripping of \r breaks the Mail App in OSX Mountain Lion
// this is fixed in master, but not backported. /Tanghus
$returnedProperties[200][$addressDataProp] = $val;
@@ -287,6 +289,81 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
}
/**
+ * This method is triggered before a file gets updated with new content.
+ *
+ * This plugin uses this method to ensure that Card nodes receive valid
+ * vcard data.
+ *
+ * @param string $path
+ * @param Sabre_DAV_IFile $node
+ * @param resource $data
+ * @return void
+ */
+ public function beforeWriteContent($path, Sabre_DAV_IFile $node, &$data) {
+
+ if (!$node instanceof Sabre_CardDAV_ICard)
+ return;
+
+ $this->validateVCard($data);
+
+ }
+
+ /**
+ * This method is triggered before a new file is created.
+ *
+ * This plugin uses this method to ensure that Card nodes receive valid
+ * vcard data.
+ *
+ * @param string $path
+ * @param resource $data
+ * @param Sabre_DAV_ICollection $parentNode
+ * @return void
+ */
+ public function beforeCreateFile($path, &$data, Sabre_DAV_ICollection $parentNode) {
+
+ if (!$parentNode instanceof Sabre_CardDAV_IAddressBook)
+ return;
+
+ $this->validateVCard($data);
+
+ }
+
+ /**
+ * Checks if the submitted iCalendar data is in fact, valid.
+ *
+ * An exception is thrown if it's not.
+ *
+ * @param resource|string $data
+ * @return void
+ */
+ protected function validateVCard(&$data) {
+
+ // If it's a stream, we convert it to a string first.
+ if (is_resource($data)) {
+ $data = stream_get_contents($data);
+ }
+
+ // Converting the data to unicode, if needed.
+ $data = Sabre_DAV_StringUtil::ensureUTF8($data);
+
+ try {
+
+ $vobj = Sabre_VObject_Reader::read($data);
+
+ } catch (Sabre_VObject_ParseException $e) {
+
+ throw new Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid vcard data. Parse error: ' . $e->getMessage());
+
+ }
+
+ if ($vobj->name !== 'VCARD') {
+ throw new Sabre_DAV_Exception_UnsupportedMediaType('This collection can only support vcard objects.');
+ }
+
+ }
+
+
+ /**
* This function handles the addressbook-query REPORT
*
* This report is used by the client to filter an addressbook based on a
@@ -365,6 +442,8 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
$vcard = Sabre_VObject_Reader::read($vcardData);
+ if (!$filters) return true;
+
foreach($filters as $filter) {
$isDefined = isset($vcard->{$filter['name']});
diff --git a/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php b/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php
index 36d9306e7aa..36d9306e7aa 100644..100755
--- a/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php
+++ b/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php
diff --git a/3rdparty/Sabre/CardDAV/UserAddressBooks.php b/3rdparty/Sabre/CardDAV/UserAddressBooks.php
index 3f11fb11238..3f11fb11238 100644..100755
--- a/3rdparty/Sabre/CardDAV/UserAddressBooks.php
+++ b/3rdparty/Sabre/CardDAV/UserAddressBooks.php
diff --git a/3rdparty/Sabre/CardDAV/Version.php b/3rdparty/Sabre/CardDAV/Version.php
index 811b929e397..d0623f0d3e8 100644..100755
--- a/3rdparty/Sabre/CardDAV/Version.php
+++ b/3rdparty/Sabre/CardDAV/Version.php
@@ -16,7 +16,7 @@ class Sabre_CardDAV_Version {
/**
* Full version number
*/
- const VERSION = '1.6.1';
+ const VERSION = '1.6.3';
/**
* Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/CardDAV/includes.php b/3rdparty/Sabre/CardDAV/includes.php
index c3b8c04b077..c3b8c04b077 100644..100755
--- a/3rdparty/Sabre/CardDAV/includes.php
+++ b/3rdparty/Sabre/CardDAV/includes.php
diff --git a/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php b/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php
index 1e89b84f9a1..1e89b84f9a1 100644..100755
--- a/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php
+++ b/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php
diff --git a/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php b/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php
index 9833928b976..9833928b976 100644..100755
--- a/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php
+++ b/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php
diff --git a/3rdparty/Sabre/DAV/Auth/Backend/Apache.php b/3rdparty/Sabre/DAV/Auth/Backend/Apache.php
index d4294ea4d86..d4294ea4d86 100644..100755
--- a/3rdparty/Sabre/DAV/Auth/Backend/Apache.php
+++ b/3rdparty/Sabre/DAV/Auth/Backend/Apache.php
diff --git a/3rdparty/Sabre/DAV/Auth/Backend/File.php b/3rdparty/Sabre/DAV/Auth/Backend/File.php
index de308d64a67..de308d64a67 100644..100755
--- a/3rdparty/Sabre/DAV/Auth/Backend/File.php
+++ b/3rdparty/Sabre/DAV/Auth/Backend/File.php
diff --git a/3rdparty/Sabre/DAV/Auth/Backend/PDO.php b/3rdparty/Sabre/DAV/Auth/Backend/PDO.php
index eac18a23fbb..eac18a23fbb 100644..100755
--- a/3rdparty/Sabre/DAV/Auth/Backend/PDO.php
+++ b/3rdparty/Sabre/DAV/Auth/Backend/PDO.php
diff --git a/3rdparty/Sabre/DAV/Auth/IBackend.php b/3rdparty/Sabre/DAV/Auth/IBackend.php
index 5be5d1bc93d..5be5d1bc93d 100644..100755
--- a/3rdparty/Sabre/DAV/Auth/IBackend.php
+++ b/3rdparty/Sabre/DAV/Auth/IBackend.php
diff --git a/3rdparty/Sabre/DAV/Auth/Plugin.php b/3rdparty/Sabre/DAV/Auth/Plugin.php
index 55a4e391674..55a4e391674 100644..100755
--- a/3rdparty/Sabre/DAV/Auth/Plugin.php
+++ b/3rdparty/Sabre/DAV/Auth/Plugin.php
diff --git a/3rdparty/Sabre/DAV/Browser/GuessContentType.php b/3rdparty/Sabre/DAV/Browser/GuessContentType.php
index b6c00d461cb..b6c00d461cb 100644..100755
--- a/3rdparty/Sabre/DAV/Browser/GuessContentType.php
+++ b/3rdparty/Sabre/DAV/Browser/GuessContentType.php
diff --git a/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php b/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php
index 15884887641..15884887641 100644..100755
--- a/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php
+++ b/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php
diff --git a/3rdparty/Sabre/DAV/Browser/Plugin.php b/3rdparty/Sabre/DAV/Browser/Plugin.php
index 09bbdd2ae02..09bbdd2ae02 100644..100755
--- a/3rdparty/Sabre/DAV/Browser/Plugin.php
+++ b/3rdparty/Sabre/DAV/Browser/Plugin.php
diff --git a/3rdparty/Sabre/DAV/Browser/assets/favicon.ico b/3rdparty/Sabre/DAV/Browser/assets/favicon.ico
index 2b2c10a22cc..2b2c10a22cc 100644..100755
--- a/3rdparty/Sabre/DAV/Browser/assets/favicon.ico
+++ b/3rdparty/Sabre/DAV/Browser/assets/favicon.ico
Binary files differ
diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png b/3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png
index c9acc84172d..c9acc84172d 100644..100755
--- a/3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png
+++ b/3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png
Binary files differ
diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png b/3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png
index 3ecd6a800a0..3ecd6a800a0 100644..100755
--- a/3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png
+++ b/3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png
Binary files differ
diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/card.png b/3rdparty/Sabre/DAV/Browser/assets/icons/card.png
index 2ce954866d8..2ce954866d8 100644..100755
--- a/3rdparty/Sabre/DAV/Browser/assets/icons/card.png
+++ b/3rdparty/Sabre/DAV/Browser/assets/icons/card.png
Binary files differ
diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/collection.png b/3rdparty/Sabre/DAV/Browser/assets/icons/collection.png
index 156fa64fd50..156fa64fd50 100644..100755
--- a/3rdparty/Sabre/DAV/Browser/assets/icons/collection.png
+++ b/3rdparty/Sabre/DAV/Browser/assets/icons/collection.png
Binary files differ
diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/file.png b/3rdparty/Sabre/DAV/Browser/assets/icons/file.png
index 3b98551cec3..3b98551cec3 100644..100755
--- a/3rdparty/Sabre/DAV/Browser/assets/icons/file.png
+++ b/3rdparty/Sabre/DAV/Browser/assets/icons/file.png
Binary files differ
diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/parent.png b/3rdparty/Sabre/DAV/Browser/assets/icons/parent.png
index 156fa64fd50..156fa64fd50 100644..100755
--- a/3rdparty/Sabre/DAV/Browser/assets/icons/parent.png
+++ b/3rdparty/Sabre/DAV/Browser/assets/icons/parent.png
Binary files differ
diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/principal.png b/3rdparty/Sabre/DAV/Browser/assets/icons/principal.png
index f8988f828e6..f8988f828e6 100644..100755
--- a/3rdparty/Sabre/DAV/Browser/assets/icons/principal.png
+++ b/3rdparty/Sabre/DAV/Browser/assets/icons/principal.png
Binary files differ
diff --git a/3rdparty/Sabre/DAV/Client.php b/3rdparty/Sabre/DAV/Client.php
index a8320dd9782..9a428765e90 100644..100755
--- a/3rdparty/Sabre/DAV/Client.php
+++ b/3rdparty/Sabre/DAV/Client.php
@@ -11,7 +11,7 @@
* @package Sabre
* @subpackage DAVClient
* @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_DAV_Client {
@@ -24,6 +24,28 @@ class Sabre_DAV_Client {
protected $proxy;
/**
+ * Basic authentication
+ */
+ const AUTH_BASIC = 1;
+
+ /**
+ * Digest authentication
+ */
+ const AUTH_DIGEST = 2;
+
+ /**
+ * The authentication type we're using.
+ *
+ * This is a bitmask of AUTH_BASIC and AUTH_DIGEST.
+ *
+ * If DIGEST is used, the client makes 1 extra request per request, to get
+ * the authentication tokens.
+ *
+ * @var int
+ */
+ protected $authType;
+
+ /**
* Constructor
*
* Settings are provided through the 'settings' argument. The following
@@ -46,7 +68,7 @@ class Sabre_DAV_Client {
'baseUri',
'userName',
'password',
- 'proxy'
+ 'proxy',
);
foreach($validSettings as $validSetting) {
@@ -55,6 +77,12 @@ class Sabre_DAV_Client {
}
}
+ if (isset($settings['authType'])) {
+ $this->authType = $settings['authType'];
+ } else {
+ $this->authType = self::AUTH_BASIC | self::AUTH_DIGEST;
+ }
+
$this->propertyMap['{DAV:}resourcetype'] = 'Sabre_DAV_Property_ResourceType';
}
@@ -252,9 +280,6 @@ class Sabre_DAV_Client {
);
switch ($method) {
- case 'PUT':
- $curlSettings[CURLOPT_PUT] = true;
- break;
case 'HEAD' :
// do not read body with HEAD requests (this is neccessary because cURL does not ignore the body with HEAD
@@ -285,8 +310,15 @@ class Sabre_DAV_Client {
$curlSettings[CURLOPT_PROXY] = $this->proxy;
}
- if ($this->userName) {
- $curlSettings[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC | CURLAUTH_DIGEST;
+ if ($this->userName && $this->authType) {
+ $curlType = 0;
+ if ($this->authType & self::AUTH_BASIC) {
+ $curlType |= CURLAUTH_BASIC;
+ }
+ if ($this->authType & self::AUTH_DIGEST) {
+ $curlType |= CURLAUTH_DIGEST;
+ }
+ $curlSettings[CURLOPT_HTTPAUTH] = $curlType;
$curlSettings[CURLOPT_USERPWD] = $this->userName . ':' . $this->password;
}
diff --git a/3rdparty/Sabre/DAV/Collection.php b/3rdparty/Sabre/DAV/Collection.php
index 776c22531b2..776c22531b2 100644..100755
--- a/3rdparty/Sabre/DAV/Collection.php
+++ b/3rdparty/Sabre/DAV/Collection.php
diff --git a/3rdparty/Sabre/DAV/Directory.php b/3rdparty/Sabre/DAV/Directory.php
index 6db8febc02e..6db8febc02e 100644..100755
--- a/3rdparty/Sabre/DAV/Directory.php
+++ b/3rdparty/Sabre/DAV/Directory.php
diff --git a/3rdparty/Sabre/DAV/Exception.php b/3rdparty/Sabre/DAV/Exception.php
index a2cd6cf5820..a2cd6cf5820 100644..100755
--- a/3rdparty/Sabre/DAV/Exception.php
+++ b/3rdparty/Sabre/DAV/Exception.php
diff --git a/3rdparty/Sabre/DAV/Exception/BadRequest.php b/3rdparty/Sabre/DAV/Exception/BadRequest.php
index b198648a754..b198648a754 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/BadRequest.php
+++ b/3rdparty/Sabre/DAV/Exception/BadRequest.php
diff --git a/3rdparty/Sabre/DAV/Exception/Conflict.php b/3rdparty/Sabre/DAV/Exception/Conflict.php
index 6b0bd1fad73..6b0bd1fad73 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/Conflict.php
+++ b/3rdparty/Sabre/DAV/Exception/Conflict.php
diff --git a/3rdparty/Sabre/DAV/Exception/ConflictingLock.php b/3rdparty/Sabre/DAV/Exception/ConflictingLock.php
index 6121868e69e..6121868e69e 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/ConflictingLock.php
+++ b/3rdparty/Sabre/DAV/Exception/ConflictingLock.php
diff --git a/3rdparty/Sabre/DAV/Exception/FileNotFound.php b/3rdparty/Sabre/DAV/Exception/FileNotFound.php
index d76e400c93b..d76e400c93b 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/FileNotFound.php
+++ b/3rdparty/Sabre/DAV/Exception/FileNotFound.php
diff --git a/3rdparty/Sabre/DAV/Exception/Forbidden.php b/3rdparty/Sabre/DAV/Exception/Forbidden.php
index 20b1056e31b..20b1056e31b 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/Forbidden.php
+++ b/3rdparty/Sabre/DAV/Exception/Forbidden.php
diff --git a/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php b/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php
index 1a15089b0a3..1a15089b0a3 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php
+++ b/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php
diff --git a/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php b/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php
index 2230f1d0811..2230f1d0811 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php
+++ b/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php
diff --git a/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php b/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php
index 80ab7aff65a..80ab7aff65a 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php
+++ b/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php
diff --git a/3rdparty/Sabre/DAV/Exception/Locked.php b/3rdparty/Sabre/DAV/Exception/Locked.php
index 976365ac1f8..976365ac1f8 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/Locked.php
+++ b/3rdparty/Sabre/DAV/Exception/Locked.php
diff --git a/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php b/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php
index 31875751505..31875751505 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php
+++ b/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php
diff --git a/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php b/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php
index 87ca624429f..87ca624429f 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php
+++ b/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php
diff --git a/3rdparty/Sabre/DAV/Exception/NotFound.php b/3rdparty/Sabre/DAV/Exception/NotFound.php
index 2b9da560d23..2b9da560d23 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/NotFound.php
+++ b/3rdparty/Sabre/DAV/Exception/NotFound.php
diff --git a/3rdparty/Sabre/DAV/Exception/NotImplemented.php b/3rdparty/Sabre/DAV/Exception/NotImplemented.php
index d017a19f559..d017a19f559 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/NotImplemented.php
+++ b/3rdparty/Sabre/DAV/Exception/NotImplemented.php
diff --git a/3rdparty/Sabre/DAV/Exception/PaymentRequired.php b/3rdparty/Sabre/DAV/Exception/PaymentRequired.php
index 4982f45a4b5..4982f45a4b5 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/PaymentRequired.php
+++ b/3rdparty/Sabre/DAV/Exception/PaymentRequired.php
diff --git a/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php b/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php
index 213e9c52317..213e9c52317 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php
+++ b/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php
diff --git a/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php b/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php
index e86800f3038..e86800f3038 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php
+++ b/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php
diff --git a/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php b/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php
index 29ee3654a7e..29ee3654a7e 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php
+++ b/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php
diff --git a/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php b/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php
index 9a4693b21a8..9a4693b21a8 100644..100755
--- a/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php
+++ b/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php
diff --git a/3rdparty/Sabre/DAV/FS/Directory.php b/3rdparty/Sabre/DAV/FS/Directory.php
index 3af2d755583..3af2d755583 100644..100755
--- a/3rdparty/Sabre/DAV/FS/Directory.php
+++ b/3rdparty/Sabre/DAV/FS/Directory.php
diff --git a/3rdparty/Sabre/DAV/FS/File.php b/3rdparty/Sabre/DAV/FS/File.php
index 6a8039fe303..6a8039fe303 100644..100755
--- a/3rdparty/Sabre/DAV/FS/File.php
+++ b/3rdparty/Sabre/DAV/FS/File.php
diff --git a/3rdparty/Sabre/DAV/FS/Node.php b/3rdparty/Sabre/DAV/FS/Node.php
index 1283e9d0fdc..1283e9d0fdc 100644..100755
--- a/3rdparty/Sabre/DAV/FS/Node.php
+++ b/3rdparty/Sabre/DAV/FS/Node.php
diff --git a/3rdparty/Sabre/DAV/FSExt/Directory.php b/3rdparty/Sabre/DAV/FSExt/Directory.php
index 540057183b3..540057183b3 100644..100755
--- a/3rdparty/Sabre/DAV/FSExt/Directory.php
+++ b/3rdparty/Sabre/DAV/FSExt/Directory.php
diff --git a/3rdparty/Sabre/DAV/FSExt/File.php b/3rdparty/Sabre/DAV/FSExt/File.php
index b93ce5aee21..b93ce5aee21 100644..100755
--- a/3rdparty/Sabre/DAV/FSExt/File.php
+++ b/3rdparty/Sabre/DAV/FSExt/File.php
diff --git a/3rdparty/Sabre/DAV/FSExt/Node.php b/3rdparty/Sabre/DAV/FSExt/Node.php
index 68ca06beb7e..68ca06beb7e 100644..100755
--- a/3rdparty/Sabre/DAV/FSExt/Node.php
+++ b/3rdparty/Sabre/DAV/FSExt/Node.php
diff --git a/3rdparty/Sabre/DAV/File.php b/3rdparty/Sabre/DAV/File.php
index 3126bd8d364..3126bd8d364 100644..100755
--- a/3rdparty/Sabre/DAV/File.php
+++ b/3rdparty/Sabre/DAV/File.php
diff --git a/3rdparty/Sabre/DAV/ICollection.php b/3rdparty/Sabre/DAV/ICollection.php
index 4626038a66e..4626038a66e 100644..100755
--- a/3rdparty/Sabre/DAV/ICollection.php
+++ b/3rdparty/Sabre/DAV/ICollection.php
diff --git a/3rdparty/Sabre/DAV/IExtendedCollection.php b/3rdparty/Sabre/DAV/IExtendedCollection.php
index 6ec345f9a62..6ec345f9a62 100644..100755
--- a/3rdparty/Sabre/DAV/IExtendedCollection.php
+++ b/3rdparty/Sabre/DAV/IExtendedCollection.php
diff --git a/3rdparty/Sabre/DAV/IFile.php b/3rdparty/Sabre/DAV/IFile.php
index 478f822ae71..478f822ae71 100644..100755
--- a/3rdparty/Sabre/DAV/IFile.php
+++ b/3rdparty/Sabre/DAV/IFile.php
diff --git a/3rdparty/Sabre/DAV/INode.php b/3rdparty/Sabre/DAV/INode.php
index c57d3923105..c57d3923105 100644..100755
--- a/3rdparty/Sabre/DAV/INode.php
+++ b/3rdparty/Sabre/DAV/INode.php
diff --git a/3rdparty/Sabre/DAV/IProperties.php b/3rdparty/Sabre/DAV/IProperties.php
index 38eaab16dad..38eaab16dad 100644..100755
--- a/3rdparty/Sabre/DAV/IProperties.php
+++ b/3rdparty/Sabre/DAV/IProperties.php
diff --git a/3rdparty/Sabre/DAV/IQuota.php b/3rdparty/Sabre/DAV/IQuota.php
index 3fe4c4eced4..3fe4c4eced4 100644..100755
--- a/3rdparty/Sabre/DAV/IQuota.php
+++ b/3rdparty/Sabre/DAV/IQuota.php
diff --git a/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php b/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php
index 127e643a2b9..127e643a2b9 100644..100755
--- a/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php
+++ b/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php
diff --git a/3rdparty/Sabre/DAV/Locks/Backend/FS.php b/3rdparty/Sabre/DAV/Locks/Backend/FS.php
index 02cab87fc82..02cab87fc82 100644..100755
--- a/3rdparty/Sabre/DAV/Locks/Backend/FS.php
+++ b/3rdparty/Sabre/DAV/Locks/Backend/FS.php
diff --git a/3rdparty/Sabre/DAV/Locks/Backend/File.php b/3rdparty/Sabre/DAV/Locks/Backend/File.php
index c33f963514b..c33f963514b 100644..100755
--- a/3rdparty/Sabre/DAV/Locks/Backend/File.php
+++ b/3rdparty/Sabre/DAV/Locks/Backend/File.php
diff --git a/3rdparty/Sabre/DAV/Locks/Backend/PDO.php b/3rdparty/Sabre/DAV/Locks/Backend/PDO.php
index acce80638ec..acce80638ec 100644..100755
--- a/3rdparty/Sabre/DAV/Locks/Backend/PDO.php
+++ b/3rdparty/Sabre/DAV/Locks/Backend/PDO.php
diff --git a/3rdparty/Sabre/DAV/Locks/LockInfo.php b/3rdparty/Sabre/DAV/Locks/LockInfo.php
index 9df014a4281..9df014a4281 100644..100755
--- a/3rdparty/Sabre/DAV/Locks/LockInfo.php
+++ b/3rdparty/Sabre/DAV/Locks/LockInfo.php
diff --git a/3rdparty/Sabre/DAV/Locks/Plugin.php b/3rdparty/Sabre/DAV/Locks/Plugin.php
index fd956950b8a..035b3a63863 100644..100755
--- a/3rdparty/Sabre/DAV/Locks/Plugin.php
+++ b/3rdparty/Sabre/DAV/Locks/Plugin.php
@@ -292,7 +292,10 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
$this->server->tree->getNodeForPath($uri);
// We need to call the beforeWriteContent event for RFC3744
- $this->server->broadcastEvent('beforeWriteContent',array($uri));
+ // Edit: looks like this is not used, and causing problems now.
+ //
+ // See Issue 222
+ // $this->server->broadcastEvent('beforeWriteContent',array($uri));
} catch (Sabre_DAV_Exception_NotFound $e) {
diff --git a/3rdparty/Sabre/DAV/Mount/Plugin.php b/3rdparty/Sabre/DAV/Mount/Plugin.php
index b37a90ae993..b37a90ae993 100644..100755
--- a/3rdparty/Sabre/DAV/Mount/Plugin.php
+++ b/3rdparty/Sabre/DAV/Mount/Plugin.php
diff --git a/3rdparty/Sabre/DAV/Node.php b/3rdparty/Sabre/DAV/Node.php
index 070b7176afd..070b7176afd 100644..100755
--- a/3rdparty/Sabre/DAV/Node.php
+++ b/3rdparty/Sabre/DAV/Node.php
diff --git a/3rdparty/Sabre/DAV/ObjectTree.php b/3rdparty/Sabre/DAV/ObjectTree.php
index bce51463900..bce51463900 100644..100755
--- a/3rdparty/Sabre/DAV/ObjectTree.php
+++ b/3rdparty/Sabre/DAV/ObjectTree.php
diff --git a/3rdparty/Sabre/DAV/Property.php b/3rdparty/Sabre/DAV/Property.php
index 1cfada3236c..1cfada3236c 100644..100755
--- a/3rdparty/Sabre/DAV/Property.php
+++ b/3rdparty/Sabre/DAV/Property.php
diff --git a/3rdparty/Sabre/DAV/Property/GetLastModified.php b/3rdparty/Sabre/DAV/Property/GetLastModified.php
index bd63f573140..bd63f573140 100644..100755
--- a/3rdparty/Sabre/DAV/Property/GetLastModified.php
+++ b/3rdparty/Sabre/DAV/Property/GetLastModified.php
diff --git a/3rdparty/Sabre/DAV/Property/Href.php b/3rdparty/Sabre/DAV/Property/Href.php
index dac564f24d7..dac564f24d7 100644..100755
--- a/3rdparty/Sabre/DAV/Property/Href.php
+++ b/3rdparty/Sabre/DAV/Property/Href.php
diff --git a/3rdparty/Sabre/DAV/Property/HrefList.php b/3rdparty/Sabre/DAV/Property/HrefList.php
index 7a52272e885..7a52272e885 100644..100755
--- a/3rdparty/Sabre/DAV/Property/HrefList.php
+++ b/3rdparty/Sabre/DAV/Property/HrefList.php
diff --git a/3rdparty/Sabre/DAV/Property/IHref.php b/3rdparty/Sabre/DAV/Property/IHref.php
index 5c0409064cb..5c0409064cb 100644..100755
--- a/3rdparty/Sabre/DAV/Property/IHref.php
+++ b/3rdparty/Sabre/DAV/Property/IHref.php
diff --git a/3rdparty/Sabre/DAV/Property/LockDiscovery.php b/3rdparty/Sabre/DAV/Property/LockDiscovery.php
index 2ded5649a44..2ded5649a44 100644..100755
--- a/3rdparty/Sabre/DAV/Property/LockDiscovery.php
+++ b/3rdparty/Sabre/DAV/Property/LockDiscovery.php
diff --git a/3rdparty/Sabre/DAV/Property/ResourceType.php b/3rdparty/Sabre/DAV/Property/ResourceType.php
index f6269611e54..f6269611e54 100644..100755
--- a/3rdparty/Sabre/DAV/Property/ResourceType.php
+++ b/3rdparty/Sabre/DAV/Property/ResourceType.php
diff --git a/3rdparty/Sabre/DAV/Property/Response.php b/3rdparty/Sabre/DAV/Property/Response.php
index 88afbcfb26d..88afbcfb26d 100644..100755
--- a/3rdparty/Sabre/DAV/Property/Response.php
+++ b/3rdparty/Sabre/DAV/Property/Response.php
diff --git a/3rdparty/Sabre/DAV/Property/ResponseList.php b/3rdparty/Sabre/DAV/Property/ResponseList.php
index cae923afbf9..cae923afbf9 100644..100755
--- a/3rdparty/Sabre/DAV/Property/ResponseList.php
+++ b/3rdparty/Sabre/DAV/Property/ResponseList.php
diff --git a/3rdparty/Sabre/DAV/Property/SupportedLock.php b/3rdparty/Sabre/DAV/Property/SupportedLock.php
index 4e3aaf23a1a..4e3aaf23a1a 100644..100755
--- a/3rdparty/Sabre/DAV/Property/SupportedLock.php
+++ b/3rdparty/Sabre/DAV/Property/SupportedLock.php
diff --git a/3rdparty/Sabre/DAV/Property/SupportedReportSet.php b/3rdparty/Sabre/DAV/Property/SupportedReportSet.php
index e62699f3b5a..e62699f3b5a 100644..100755
--- a/3rdparty/Sabre/DAV/Property/SupportedReportSet.php
+++ b/3rdparty/Sabre/DAV/Property/SupportedReportSet.php
diff --git a/3rdparty/Sabre/DAV/Server.php b/3rdparty/Sabre/DAV/Server.php
index 50b190e8fab..0dfac8b0c71 100644..100755
--- a/3rdparty/Sabre/DAV/Server.php
+++ b/3rdparty/Sabre/DAV/Server.php
@@ -215,7 +215,7 @@ class Sabre_DAV_Server {
$DOM->appendChild($error);
$error->appendChild($DOM->createElement('s:exception',get_class($e)));
- $error->appendChild($DOM->createElement('s:message',htmlentities($e->getMessage())));
+ $error->appendChild($DOM->createElement('s:message',$e->getMessage()));
if ($this->debugExceptions) {
$error->appendChild($DOM->createElement('s:file',$e->getFile()));
$error->appendChild($DOM->createElement('s:line',$e->getLine()));
@@ -1784,7 +1784,14 @@ class Sabre_DAV_Server {
$etag = $node->getETag();
if ($etag===$ifMatchItem) {
$haveMatch = true;
+ } else {
+ // Evolution has a bug where it sometimes prepends the "
+ // with a \. This is our workaround.
+ if (str_replace('\\"','"', $ifMatchItem) === $etag) {
+ $haveMatch = true;
+ }
}
+
}
if (!$haveMatch) {
throw new Sabre_DAV_Exception_PreconditionFailed('An If-Match header was specified, but none of the specified the ETags matched.','If-Match');
diff --git a/3rdparty/Sabre/DAV/ServerPlugin.php b/3rdparty/Sabre/DAV/ServerPlugin.php
index 131863d13fb..131863d13fb 100644..100755
--- a/3rdparty/Sabre/DAV/ServerPlugin.php
+++ b/3rdparty/Sabre/DAV/ServerPlugin.php
diff --git a/3rdparty/Sabre/DAV/SimpleCollection.php b/3rdparty/Sabre/DAV/SimpleCollection.php
index 4acf971caa5..4acf971caa5 100644..100755
--- a/3rdparty/Sabre/DAV/SimpleCollection.php
+++ b/3rdparty/Sabre/DAV/SimpleCollection.php
diff --git a/3rdparty/Sabre/DAV/SimpleDirectory.php b/3rdparty/Sabre/DAV/SimpleDirectory.php
index 621222ebc53..621222ebc53 100644..100755
--- a/3rdparty/Sabre/DAV/SimpleDirectory.php
+++ b/3rdparty/Sabre/DAV/SimpleDirectory.php
diff --git a/3rdparty/Sabre/DAV/SimpleFile.php b/3rdparty/Sabre/DAV/SimpleFile.php
index 58330d6861d..58330d6861d 100644..100755
--- a/3rdparty/Sabre/DAV/SimpleFile.php
+++ b/3rdparty/Sabre/DAV/SimpleFile.php
diff --git a/3rdparty/Sabre/DAV/StringUtil.php b/3rdparty/Sabre/DAV/StringUtil.php
index b126a94c825..b126a94c825 100644..100755
--- a/3rdparty/Sabre/DAV/StringUtil.php
+++ b/3rdparty/Sabre/DAV/StringUtil.php
diff --git a/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php b/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php
index 36096e67775..36096e67775 100644..100755
--- a/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php
+++ b/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php
diff --git a/3rdparty/Sabre/DAV/Tree.php b/3rdparty/Sabre/DAV/Tree.php
index 50216394155..50216394155 100644..100755
--- a/3rdparty/Sabre/DAV/Tree.php
+++ b/3rdparty/Sabre/DAV/Tree.php
diff --git a/3rdparty/Sabre/DAV/Tree/Filesystem.php b/3rdparty/Sabre/DAV/Tree/Filesystem.php
index 85a9ee317be..40580ae366f 100644..100755
--- a/3rdparty/Sabre/DAV/Tree/Filesystem.php
+++ b/3rdparty/Sabre/DAV/Tree/Filesystem.php
@@ -42,9 +42,9 @@ class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree {
$realPath = $this->getRealPath($path);
if (!file_exists($realPath)) throw new Sabre_DAV_Exception_NotFound('File at location ' . $realPath . ' not found');
if (is_dir($realPath)) {
- return new Sabre_DAV_FS_Directory($path);
+ return new Sabre_DAV_FS_Directory($realPath);
} else {
- return new Sabre_DAV_FS_File($path);
+ return new Sabre_DAV_FS_File($realPath);
}
}
diff --git a/3rdparty/Sabre/DAV/URLUtil.php b/3rdparty/Sabre/DAV/URLUtil.php
index 794665a44f6..794665a44f6 100644..100755
--- a/3rdparty/Sabre/DAV/URLUtil.php
+++ b/3rdparty/Sabre/DAV/URLUtil.php
diff --git a/3rdparty/Sabre/DAV/UUIDUtil.php b/3rdparty/Sabre/DAV/UUIDUtil.php
index f0eebe598e5..f0eebe598e5 100644..100755
--- a/3rdparty/Sabre/DAV/UUIDUtil.php
+++ b/3rdparty/Sabre/DAV/UUIDUtil.php
diff --git a/3rdparty/Sabre/DAV/Version.php b/3rdparty/Sabre/DAV/Version.php
index 5e5d15e4039..274646240ab 100644..100755
--- a/3rdparty/Sabre/DAV/Version.php
+++ b/3rdparty/Sabre/DAV/Version.php
@@ -14,7 +14,7 @@ class Sabre_DAV_Version {
/**
* Full version number
*/
- const VERSION = '1.6.2';
+ const VERSION = '1.6.4';
/**
* Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/DAV/XMLUtil.php b/3rdparty/Sabre/DAV/XMLUtil.php
index 60eff3b159a..60eff3b159a 100644..100755
--- a/3rdparty/Sabre/DAV/XMLUtil.php
+++ b/3rdparty/Sabre/DAV/XMLUtil.php
diff --git a/3rdparty/Sabre/DAV/includes.php b/3rdparty/Sabre/DAV/includes.php
index 6a4890677ea..6a4890677ea 100644..100755
--- a/3rdparty/Sabre/DAV/includes.php
+++ b/3rdparty/Sabre/DAV/includes.php
diff --git a/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php b/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php
index e05b7749805..e05b7749805 100644..100755
--- a/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php
+++ b/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php
diff --git a/3rdparty/Sabre/DAVACL/Exception/AceConflict.php b/3rdparty/Sabre/DAVACL/Exception/AceConflict.php
index 4b9f93b0036..4b9f93b0036 100644..100755
--- a/3rdparty/Sabre/DAVACL/Exception/AceConflict.php
+++ b/3rdparty/Sabre/DAVACL/Exception/AceConflict.php
diff --git a/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php b/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php
index 9b055dd9709..9b055dd9709 100644..100755
--- a/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php
+++ b/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php
diff --git a/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php b/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php
index f44e3e32281..f44e3e32281 100644..100755
--- a/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php
+++ b/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php
diff --git a/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php b/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php
index 8d1e38ca1b4..8d1e38ca1b4 100644..100755
--- a/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php
+++ b/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php
diff --git a/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php b/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php
index 3b5d012d7fa..3b5d012d7fa 100644..100755
--- a/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php
+++ b/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php
diff --git a/3rdparty/Sabre/DAVACL/IACL.php b/3rdparty/Sabre/DAVACL/IACL.php
index 003e6993483..003e6993483 100644..100755
--- a/3rdparty/Sabre/DAVACL/IACL.php
+++ b/3rdparty/Sabre/DAVACL/IACL.php
diff --git a/3rdparty/Sabre/DAVACL/IPrincipal.php b/3rdparty/Sabre/DAVACL/IPrincipal.php
index fc7605bf625..fc7605bf625 100644..100755
--- a/3rdparty/Sabre/DAVACL/IPrincipal.php
+++ b/3rdparty/Sabre/DAVACL/IPrincipal.php
diff --git a/3rdparty/Sabre/DAVACL/IPrincipalBackend.php b/3rdparty/Sabre/DAVACL/IPrincipalBackend.php
index e798bf890c0..e798bf890c0 100644..100755
--- a/3rdparty/Sabre/DAVACL/IPrincipalBackend.php
+++ b/3rdparty/Sabre/DAVACL/IPrincipalBackend.php
diff --git a/3rdparty/Sabre/DAVACL/Plugin.php b/3rdparty/Sabre/DAVACL/Plugin.php
index 5c828c6d97b..5c828c6d97b 100644..100755
--- a/3rdparty/Sabre/DAVACL/Plugin.php
+++ b/3rdparty/Sabre/DAVACL/Plugin.php
diff --git a/3rdparty/Sabre/DAVACL/Principal.php b/3rdparty/Sabre/DAVACL/Principal.php
index 51c6658afd6..51c6658afd6 100644..100755
--- a/3rdparty/Sabre/DAVACL/Principal.php
+++ b/3rdparty/Sabre/DAVACL/Principal.php
diff --git a/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php b/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php
index a76b4a9d727..a76b4a9d727 100644..100755
--- a/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php
+++ b/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php
diff --git a/3rdparty/Sabre/DAVACL/PrincipalCollection.php b/3rdparty/Sabre/DAVACL/PrincipalCollection.php
index c3e4cb83f23..c3e4cb83f23 100644..100755
--- a/3rdparty/Sabre/DAVACL/PrincipalCollection.php
+++ b/3rdparty/Sabre/DAVACL/PrincipalCollection.php
diff --git a/3rdparty/Sabre/DAVACL/Property/Acl.php b/3rdparty/Sabre/DAVACL/Property/Acl.php
index 05e1a690b3c..05e1a690b3c 100644..100755
--- a/3rdparty/Sabre/DAVACL/Property/Acl.php
+++ b/3rdparty/Sabre/DAVACL/Property/Acl.php
diff --git a/3rdparty/Sabre/DAVACL/Property/AclRestrictions.php b/3rdparty/Sabre/DAVACL/Property/AclRestrictions.php
index a8b054956dd..a8b054956dd 100644..100755
--- a/3rdparty/Sabre/DAVACL/Property/AclRestrictions.php
+++ b/3rdparty/Sabre/DAVACL/Property/AclRestrictions.php
diff --git a/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php b/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php
index 94a29640615..94a29640615 100644..100755
--- a/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php
+++ b/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php
diff --git a/3rdparty/Sabre/DAVACL/Property/Principal.php b/3rdparty/Sabre/DAVACL/Property/Principal.php
index c36328a58e0..c36328a58e0 100644..100755
--- a/3rdparty/Sabre/DAVACL/Property/Principal.php
+++ b/3rdparty/Sabre/DAVACL/Property/Principal.php
diff --git a/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php b/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php
index 276d57ae093..276d57ae093 100644..100755
--- a/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php
+++ b/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php
diff --git a/3rdparty/Sabre/DAVACL/Version.php b/3rdparty/Sabre/DAVACL/Version.php
index 9950f748741..9950f748741 100644..100755
--- a/3rdparty/Sabre/DAVACL/Version.php
+++ b/3rdparty/Sabre/DAVACL/Version.php
diff --git a/3rdparty/Sabre/DAVACL/includes.php b/3rdparty/Sabre/DAVACL/includes.php
index 28fa3eed225..28fa3eed225 100644..100755
--- a/3rdparty/Sabre/DAVACL/includes.php
+++ b/3rdparty/Sabre/DAVACL/includes.php
diff --git a/3rdparty/Sabre/HTTP/AWSAuth.php b/3rdparty/Sabre/HTTP/AWSAuth.php
index fb8245c8cbf..fb8245c8cbf 100644..100755
--- a/3rdparty/Sabre/HTTP/AWSAuth.php
+++ b/3rdparty/Sabre/HTTP/AWSAuth.php
diff --git a/3rdparty/Sabre/HTTP/AbstractAuth.php b/3rdparty/Sabre/HTTP/AbstractAuth.php
index 3bccabcd1c1..3bccabcd1c1 100644..100755
--- a/3rdparty/Sabre/HTTP/AbstractAuth.php
+++ b/3rdparty/Sabre/HTTP/AbstractAuth.php
diff --git a/3rdparty/Sabre/HTTP/BasicAuth.php b/3rdparty/Sabre/HTTP/BasicAuth.php
index a747cc6a31b..f90ed24f5d8 100644..100755
--- a/3rdparty/Sabre/HTTP/BasicAuth.php
+++ b/3rdparty/Sabre/HTTP/BasicAuth.php
@@ -46,7 +46,7 @@ class Sabre_HTTP_BasicAuth extends Sabre_HTTP_AbstractAuth {
if (strpos(strtolower($auth),'basic')!==0) return false;
- return explode(':', base64_decode(substr($auth, 6)));
+ return explode(':', base64_decode(substr($auth, 6)),2);
}
diff --git a/3rdparty/Sabre/HTTP/DigestAuth.php b/3rdparty/Sabre/HTTP/DigestAuth.php
index ee7f05c08ed..ee7f05c08ed 100644..100755
--- a/3rdparty/Sabre/HTTP/DigestAuth.php
+++ b/3rdparty/Sabre/HTTP/DigestAuth.php
diff --git a/3rdparty/Sabre/HTTP/Request.php b/3rdparty/Sabre/HTTP/Request.php
index 4746ef77704..4746ef77704 100644..100755
--- a/3rdparty/Sabre/HTTP/Request.php
+++ b/3rdparty/Sabre/HTTP/Request.php
diff --git a/3rdparty/Sabre/HTTP/Response.php b/3rdparty/Sabre/HTTP/Response.php
index ffe9bda2082..ffe9bda2082 100644..100755
--- a/3rdparty/Sabre/HTTP/Response.php
+++ b/3rdparty/Sabre/HTTP/Response.php
diff --git a/3rdparty/Sabre/HTTP/Util.php b/3rdparty/Sabre/HTTP/Util.php
index 67bdd489e1e..67bdd489e1e 100644..100755
--- a/3rdparty/Sabre/HTTP/Util.php
+++ b/3rdparty/Sabre/HTTP/Util.php
diff --git a/3rdparty/Sabre/HTTP/Version.php b/3rdparty/Sabre/HTTP/Version.php
index 23dc7f8a7a1..e6b4f7e5358 100644..100755
--- a/3rdparty/Sabre/HTTP/Version.php
+++ b/3rdparty/Sabre/HTTP/Version.php
@@ -14,7 +14,7 @@ class Sabre_HTTP_Version {
/**
* Full version number
*/
- const VERSION = '1.6.2';
+ const VERSION = '1.6.4';
/**
* Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/HTTP/includes.php b/3rdparty/Sabre/HTTP/includes.php
index 9d34bf3a8be..9d34bf3a8be 100644..100755
--- a/3rdparty/Sabre/HTTP/includes.php
+++ b/3rdparty/Sabre/HTTP/includes.php
diff --git a/3rdparty/Sabre/VObject/Component.php b/3rdparty/Sabre/VObject/Component.php
index b78a26133fa..b78a26133fa 100644..100755
--- a/3rdparty/Sabre/VObject/Component.php
+++ b/3rdparty/Sabre/VObject/Component.php
diff --git a/3rdparty/Sabre/VObject/Component/VAlarm.php b/3rdparty/Sabre/VObject/Component/VAlarm.php
index ebb4a9b18f6..ebb4a9b18f6 100644..100755
--- a/3rdparty/Sabre/VObject/Component/VAlarm.php
+++ b/3rdparty/Sabre/VObject/Component/VAlarm.php
diff --git a/3rdparty/Sabre/VObject/Component/VCalendar.php b/3rdparty/Sabre/VObject/Component/VCalendar.php
index f3be29afdbb..f3be29afdbb 100644..100755
--- a/3rdparty/Sabre/VObject/Component/VCalendar.php
+++ b/3rdparty/Sabre/VObject/Component/VCalendar.php
diff --git a/3rdparty/Sabre/VObject/Component/VEvent.php b/3rdparty/Sabre/VObject/Component/VEvent.php
index 4cc1e36d7d6..d6b910874d0 100644..100755
--- a/3rdparty/Sabre/VObject/Component/VEvent.php
+++ b/3rdparty/Sabre/VObject/Component/VEvent.php
@@ -42,14 +42,15 @@ class Sabre_VObject_Component_VEvent extends Sabre_VObject_Component {
$effectiveStart = $this->DTSTART->getDateTime();
if (isset($this->DTEND)) {
+
+ // The DTEND property is considered non inclusive. So for a 3 day
+ // event in july, dtstart and dtend would have to be July 1st and
+ // July 4th respectively.
+ //
+ // See:
+ // http://tools.ietf.org/html/rfc5545#page-54
$effectiveEnd = $this->DTEND->getDateTime();
- // If this was an all-day event, we should just increase the
- // end-date by 1. Otherwise the event will last until the second
- // the date changed, by increasing this by 1 day the event lasts
- // all of the last day as well.
- if ($this->DTSTART->getDateType() == Sabre_VObject_Element_DateTime::DATE) {
- $effectiveEnd->modify('+1 day');
- }
+
} elseif (isset($this->DURATION)) {
$effectiveEnd = clone $effectiveStart;
$effectiveEnd->add( Sabre_VObject_DateTimeParser::parseDuration($this->DURATION) );
diff --git a/3rdparty/Sabre/VObject/Component/VJournal.php b/3rdparty/Sabre/VObject/Component/VJournal.php
index 22b3ec921e5..22b3ec921e5 100644..100755
--- a/3rdparty/Sabre/VObject/Component/VJournal.php
+++ b/3rdparty/Sabre/VObject/Component/VJournal.php
diff --git a/3rdparty/Sabre/VObject/Component/VTodo.php b/3rdparty/Sabre/VObject/Component/VTodo.php
index 79d06298d7f..79d06298d7f 100644..100755
--- a/3rdparty/Sabre/VObject/Component/VTodo.php
+++ b/3rdparty/Sabre/VObject/Component/VTodo.php
diff --git a/3rdparty/Sabre/VObject/DateTimeParser.php b/3rdparty/Sabre/VObject/DateTimeParser.php
index 1e2d54ef3a9..23a4bb69916 100644..100755
--- a/3rdparty/Sabre/VObject/DateTimeParser.php
+++ b/3rdparty/Sabre/VObject/DateTimeParser.php
@@ -125,6 +125,9 @@ class Sabre_VObject_DateTimeParser {
}
+ if ($duration==='P') {
+ $duration = 'PT0S';
+ }
$iv = new DateInterval($duration);
if ($invert) $iv->invert = true;
@@ -150,6 +153,7 @@ class Sabre_VObject_DateTimeParser {
}
$newDur = ($matches['plusminus']==='-'?'-':'+') . trim($newDur);
+ if ($newDur === '+') { $newDur = '+0 seconds'; };
return $newDur;
}
diff --git a/3rdparty/Sabre/VObject/Element.php b/3rdparty/Sabre/VObject/Element.php
index e20ff0b353c..e20ff0b353c 100644..100755
--- a/3rdparty/Sabre/VObject/Element.php
+++ b/3rdparty/Sabre/VObject/Element.php
diff --git a/3rdparty/Sabre/VObject/Element/DateTime.php b/3rdparty/Sabre/VObject/Element/DateTime.php
index 5e5eb7ab6f2..5e5eb7ab6f2 100644..100755
--- a/3rdparty/Sabre/VObject/Element/DateTime.php
+++ b/3rdparty/Sabre/VObject/Element/DateTime.php
diff --git a/3rdparty/Sabre/VObject/Element/MultiDateTime.php b/3rdparty/Sabre/VObject/Element/MultiDateTime.php
index 8a12ced94a8..8a12ced94a8 100644..100755
--- a/3rdparty/Sabre/VObject/Element/MultiDateTime.php
+++ b/3rdparty/Sabre/VObject/Element/MultiDateTime.php
diff --git a/3rdparty/Sabre/VObject/ElementList.php b/3rdparty/Sabre/VObject/ElementList.php
index 7e508db20f0..7e508db20f0 100644..100755
--- a/3rdparty/Sabre/VObject/ElementList.php
+++ b/3rdparty/Sabre/VObject/ElementList.php
diff --git a/3rdparty/Sabre/VObject/FreeBusyGenerator.php b/3rdparty/Sabre/VObject/FreeBusyGenerator.php
index 1c96a64a004..1c96a64a004 100644..100755
--- a/3rdparty/Sabre/VObject/FreeBusyGenerator.php
+++ b/3rdparty/Sabre/VObject/FreeBusyGenerator.php
diff --git a/3rdparty/Sabre/VObject/Node.php b/3rdparty/Sabre/VObject/Node.php
index d89e01b56c6..d89e01b56c6 100644..100755
--- a/3rdparty/Sabre/VObject/Node.php
+++ b/3rdparty/Sabre/VObject/Node.php
diff --git a/3rdparty/Sabre/VObject/Parameter.php b/3rdparty/Sabre/VObject/Parameter.php
index 2e39af5f78a..2e39af5f78a 100644..100755
--- a/3rdparty/Sabre/VObject/Parameter.php
+++ b/3rdparty/Sabre/VObject/Parameter.php
diff --git a/3rdparty/Sabre/VObject/ParseException.php b/3rdparty/Sabre/VObject/ParseException.php
index 1b5e95bf16e..1b5e95bf16e 100644..100755
--- a/3rdparty/Sabre/VObject/ParseException.php
+++ b/3rdparty/Sabre/VObject/ParseException.php
diff --git a/3rdparty/Sabre/VObject/Property.php b/3rdparty/Sabre/VObject/Property.php
index ce74fe3865b..ce74fe3865b 100644..100755
--- a/3rdparty/Sabre/VObject/Property.php
+++ b/3rdparty/Sabre/VObject/Property.php
diff --git a/3rdparty/Sabre/VObject/Property/DateTime.php b/3rdparty/Sabre/VObject/Property/DateTime.php
index fe2372caa81..fe2372caa81 100644..100755
--- a/3rdparty/Sabre/VObject/Property/DateTime.php
+++ b/3rdparty/Sabre/VObject/Property/DateTime.php
diff --git a/3rdparty/Sabre/VObject/Property/MultiDateTime.php b/3rdparty/Sabre/VObject/Property/MultiDateTime.php
index ae53ab6a617..ae53ab6a617 100644..100755
--- a/3rdparty/Sabre/VObject/Property/MultiDateTime.php
+++ b/3rdparty/Sabre/VObject/Property/MultiDateTime.php
diff --git a/3rdparty/Sabre/VObject/Reader.php b/3rdparty/Sabre/VObject/Reader.php
index eea73fa3dce..eea73fa3dce 100644..100755
--- a/3rdparty/Sabre/VObject/Reader.php
+++ b/3rdparty/Sabre/VObject/Reader.php
diff --git a/3rdparty/Sabre/VObject/RecurrenceIterator.php b/3rdparty/Sabre/VObject/RecurrenceIterator.php
index 833aa091ab7..740270dd8f0 100644..100755
--- a/3rdparty/Sabre/VObject/RecurrenceIterator.php
+++ b/3rdparty/Sabre/VObject/RecurrenceIterator.php
@@ -337,6 +337,8 @@ class Sabre_VObject_RecurrenceIterator implements Iterator {
$this->endDate = clone $this->startDate;
if (isset($this->baseEvent->DURATION)) {
$this->endDate->add(Sabre_VObject_DateTimeParser::parse($this->baseEvent->DURATION->value));
+ } elseif ($this->baseEvent->DTSTART->getDateType()===Sabre_VObject_Property_DateTime::DATE) {
+ $this->endDate->modify('+1 day');
}
}
$this->currentDate = clone $this->startDate;
@@ -561,7 +563,7 @@ class Sabre_VObject_RecurrenceIterator implements Iterator {
*/
public function fastForward(DateTime $dt) {
- while($this->valid() && $this->getDTEnd() < $dt) {
+ while($this->valid() && $this->getDTEnd() <= $dt) {
$this->next();
}
@@ -823,9 +825,40 @@ class Sabre_VObject_RecurrenceIterator implements Iterator {
*/
protected function nextYearly() {
+ $currentMonth = $this->currentDate->format('n');
+ $currentYear = $this->currentDate->format('Y');
+ $currentDayOfMonth = $this->currentDate->format('j');
+
+ // No sub-rules, so we just advance by year
if (!$this->byMonth) {
+
+ // Unless it was a leap day!
+ if ($currentMonth==2 && $currentDayOfMonth==29) {
+
+ $counter = 0;
+ do {
+ $counter++;
+ // Here we increase the year count by the interval, until
+ // we hit a date that's also in a leap year.
+ //
+ // We could just find the next interval that's dividable by
+ // 4, but that would ignore the rule that there's no leap
+ // year every year that's dividable by a 100, but not by
+ // 400. (1800, 1900, 2100). So we just rely on the datetime
+ // functions instead.
+ $nextDate = clone $this->currentDate;
+ $nextDate->modify('+ ' . ($this->interval*$counter) . ' years');
+ } while ($nextDate->format('n')!=2);
+ $this->currentDate = $nextDate;
+
+ return;
+
+ }
+
+ // The easiest form
$this->currentDate->modify('+' . $this->interval . ' years');
return;
+
}
$currentMonth = $this->currentDate->format('n');
@@ -877,8 +910,8 @@ class Sabre_VObject_RecurrenceIterator implements Iterator {
} else {
- // no byDay or byMonthDay, so we can just loop through the
- // months.
+ // These are the 'byMonth' rules, if there are no byDay or
+ // byMonthDay sub-rules.
do {
$currentMonth++;
@@ -888,6 +921,7 @@ class Sabre_VObject_RecurrenceIterator implements Iterator {
}
} while (!in_array($currentMonth, $this->byMonth));
$this->currentDate->setDate($currentYear, $currentMonth, $currentDayOfMonth);
+
return;
}
diff --git a/3rdparty/Sabre/VObject/Version.php b/3rdparty/Sabre/VObject/Version.php
index 00110febc07..9ee03d87118 100644..100755
--- a/3rdparty/Sabre/VObject/Version.php
+++ b/3rdparty/Sabre/VObject/Version.php
@@ -14,7 +14,7 @@ class Sabre_VObject_Version {
/**
* Full version number
*/
- const VERSION = '1.3.2';
+ const VERSION = '1.3.4';
/**
* Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/VObject/WindowsTimezoneMap.php b/3rdparty/Sabre/VObject/WindowsTimezoneMap.php
index 5e1cc5d479b..5e1cc5d479b 100644..100755
--- a/3rdparty/Sabre/VObject/WindowsTimezoneMap.php
+++ b/3rdparty/Sabre/VObject/WindowsTimezoneMap.php
diff --git a/3rdparty/Sabre/VObject/includes.php b/3rdparty/Sabre/VObject/includes.php
index 0177a8f1ba6..0177a8f1ba6 100644..100755
--- a/3rdparty/Sabre/VObject/includes.php
+++ b/3rdparty/Sabre/VObject/includes.php
diff --git a/3rdparty/Sabre/autoload.php b/3rdparty/Sabre/autoload.php
index c7b537d83d3..c7b537d83d3 100644..100755
--- a/3rdparty/Sabre/autoload.php
+++ b/3rdparty/Sabre/autoload.php
diff --git a/3rdparty/aws-sdk/README.md b/3rdparty/aws-sdk/README.md
new file mode 100644
index 00000000000..7e55f76b3b2
--- /dev/null
+++ b/3rdparty/aws-sdk/README.md
@@ -0,0 +1,136 @@
+# AWS SDK for PHP
+
+The AWS SDK for PHP enables developers to build solutions for Amazon Simple Storage Service (Amazon S3),
+Amazon Elastic Compute Cloud (Amazon EC2), Amazon SimpleDB, and more. With the AWS SDK for PHP, developers
+can get started in minutes with a single, downloadable package.
+
+The SDK features:
+
+* **AWS PHP Libraries:** Build PHP applications on top of APIs that take the complexity out of coding directly
+ against a web service interface. The toolkit provides APIs that hide much of the lower-level implementation.
+* **Code Samples:** Practical examples for how to use the toolkit to build applications.
+* **Documentation:** Complete SDK reference documentation with samples demonstrating how to use the SDK.
+* **PEAR package:** The ability to install the AWS SDK for PHP as a PEAR package.
+* **SDK Compatibility Test:** Includes both an HTML-based and a CLI-based SDK Compatibility Test that you can
+ run on your server to determine whether or not your PHP environment meets the minimum requirements.
+
+For more information about the AWS SDK for PHP, including a complete list of supported services, see
+[aws.amazon.com/sdkforphp](http://aws.amazon.com/sdkforphp).
+
+
+## Signing up for Amazon Web Services
+
+Before you can begin, you must sign up for each service you want to use.
+
+To sign up for a service:
+
+* Go to the home page for the service. You can find a list of services on
+ [aws.amazon.com/products](http://aws.amazon.com/products).
+* Click the Sign Up button on the top right corner of the page. If you don't already have an AWS account, you
+ are prompted to create one as part of the sign up process.
+* Follow the on-screen instructions.
+* AWS sends you a confirmation e-mail after the sign-up process is complete. At any time, you can view your
+ current account activity and manage your account by going to [aws.amazon.com](http://aws.amazon.com) and
+ clicking "Your Account".
+
+
+## Source
+The source tree for includes the following files and directories:
+
+* `_compatibility_test` -- Includes both an HTML-based and a CLI-based SDK Compatibility Test that you can
+ run on your server to determine whether or not your PHP environment meets the minimum requirements.
+* `_docs` -- Informational documents, the contents of which should be fairly self-explanatory.
+* `_samples` -- Code samples that you can run out of the box.
+* `extensions` -- Extra code that can be used to enhance usage of the SDK, but isn't a service class or a
+ third-party library.
+* `lib` -- Contains any third-party libraries that the SDK depends on. The licenses for these projects will
+ always be Apache 2.0-compatible.
+* `services` -- Contains the service-specific classes that communicate with AWS. These classes are always
+ prefixed with `Amazon`.
+* `utilities` -- Contains any utility-type methods that the SDK uses. Includes extensions to built-in PHP
+ classes, as well as new functionality that is entirely custom. These classes are always prefixed with `CF`.
+* `README` -- The document you're reading right now.
+* `config-sample.inc.php` -- A sample configuration file that should be filled out and renamed to `config.inc.php`.
+* `sdk.class.php` -- The SDK loader that you would include in your projects. Contains the base functionality
+ that the rest of the SDK depends on.
+
+
+## Minimum Requirements in a nutshell
+
+* You are at least an intermediate-level PHP developer and have a basic understanding of object-oriented PHP.
+* You have a valid AWS account, and you've already signed up for the services you want to use.
+* The PHP interpreter, version 5.2 or newer. PHP 5.2.17 or 5.3.x is highly recommended for use with the AWS SDK for PHP.
+* The cURL PHP extension (compiled with the [OpenSSL](http://openssl.org) libraries for HTTPS support).
+* The ability to read from and write to the file system via [file_get_contents()](http://php.net/file_get_contents) and [file_put_contents()](http://php.net/file_put_contents).
+
+If you're not sure whether your PHP environment meets these requirements, run the
+[SDK Compatibility Test](http://github.com/amazonwebservices/aws-sdk-for-php/tree/master/_compatibility_test/) script
+included in the SDK download.
+
+
+## Installation
+
+### Via GitHub
+
+[Git](http://git-scm.com) is an extremely fast, efficient, distributed version control system ideal for the
+collaborative development of software. [GitHub](http://github.com/amazonwebservices) is the best way to
+collaborate with others. Fork, send pull requests and manage all your public and private git repositories.
+We believe that GitHub is the ideal service for working collaboratively with the open source PHP community.
+
+Git is primarily a command-line tool. GitHub provides instructions for installing Git on
+[Mac OS X](http://help.github.com/mac-git-installation/), [Windows](http://help.github.com/win-git-installation/),
+and [Linux](http://help.github.com/linux-git-installation/). If you're unfamiliar with Git, there are a variety
+of resources on the net that will help you learn more:
+
+* [Git Immersion](http://gitimmersion.com) is a guided tour that walks through the fundamentals of Git, inspired
+ by the premise that to know a thing is to do it.
+* The [PeepCode screencast on Git](https://peepcode.com/products/git) ($12) will teach you how to install and
+ use Git. You'll learn how to create a repository, use branches, and work with remote repositories.
+* [Git Reference](http://gitref.org) is meant to be a quick reference for learning and remembering the most
+ important and commonly used Git commands.
+* [Git Ready](http://gitready.com) provides a collection of Git tips and tricks.
+* If you want to dig even further, I've [bookmarked other Git references](http://pinboard.in/u:skyzyx/t:git).
+
+If you're comfortable working with Git and/or GitHub, you can pull down the source code as follows:
+
+ git clone git://github.com/amazonwebservices/aws-sdk-for-php.git AWSSDKforPHP
+ cd ./AWSSDKforPHP
+
+### Via PEAR
+
+[PEAR](http://pear.php.net) stands for the _PHP Extension and Application Repository_ and is a framework and
+distribution system for reusable PHP components. It is the PHP equivalent to package management software such as
+[MacPorts](http://macports.org) and [Homebrew](https://github.com/mxcl/homebrew) for Mac OS X,
+[Yum](http://fedoraproject.org/wiki/Tools/yum) and [Apt](http://wiki.debian.org/Apt) for GNU/Linux,
+[RubyGems](http://rubygems.org) for Ruby, [Easy Install](http://packages.python.org/distribute/easy_install.html)
+for Python, [Maven](http://maven.apache.org) for Java, and [NPM](http://npm.mape.me) for Node.js.
+
+PEAR packages are very easy to install, and are available in your PHP environment path so that they are accessible
+to any PHP project. PEAR packages are not specific to your project, but rather to the machine that they're
+installed on.
+
+From the command-line, you can install the SDK with PEAR as follows:
+
+ pear channel-discover pear.amazonwebservices.com
+ pear install aws/sdk
+
+You may need to use `sudo` for the above commands. Once the SDK has been installed via PEAR, you can load it into
+your project with:
+
+ require_once 'AWSSDKforPHP/sdk.class.php';
+
+### Configuration
+
+1. Copy the contents of [config-sample.inc.php](https://github.com/amazonwebservices/aws-sdk-for-php/raw/master/config-sample.inc.php)
+ and add your credentials as instructed in the file.
+2. Move your file to `~/.aws/sdk/config.inc.php`.
+3. Make sure that `getenv('HOME')` points to your user directory. If not you'll need to set
+ `putenv('HOME=<your-user-directory>')`.
+
+
+## Additional Information
+
+* AWS SDK for PHP: <http://aws.amazon.com/sdkforphp>
+* Documentation: <http://docs.amazonwebservices.com/AWSSDKforPHP/latest/>
+* License: <http://aws.amazon.com/apache2.0/>
+* Discuss: <http://aws.amazon.com/forums>
diff --git a/3rdparty/aws-sdk/_compatibility_test/README.md b/3rdparty/aws-sdk/_compatibility_test/README.md
new file mode 100644
index 00000000000..9e2f2d89409
--- /dev/null
+++ b/3rdparty/aws-sdk/_compatibility_test/README.md
@@ -0,0 +1,37 @@
+# Compatibility Test
+
+## Via your web browser
+
+1. Upload `sdk_compatibility_test.php` to the web-accessible root of your website.
+For example, if your website is `www.example.com`, upload it so that you can get
+to it at `www.example.com/sdk_compatibility_test.php`
+
+2. Open your web browser and go to the page you just uploaded.
+
+
+## Via the command line
+
+### Windows
+
+1. Upload `sdk_compatibility_test_cli.php` to your server via SFTP.
+
+2. SSH/RDP into the machine, and find the directory where you uploaded the test.
+
+3. Run the test, and review the results:
+
+ php .\sdk_compatibility_test_cli.php
+
+
+### Non-Windows (Mac or *nix)
+
+1. Upload `sdk_compatibility_test_cli.php` to your server via SFTP.
+
+2. SSH into the machine, and find the directory where you uploaded the test.
+
+3. Set the executable bit:
+
+ chmod +x ./sdk_compatibility_test_cli.php
+
+4. Run the test, and review the results:
+
+ ./sdk_compatibility_test_cli.php
diff --git a/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility.inc.php b/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility.inc.php
new file mode 100644
index 00000000000..c17ec33d72e
--- /dev/null
+++ b/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility.inc.php
@@ -0,0 +1,75 @@
+<?php
+
+define('REQUIREMENTS_ALL_MET', 100);
+define('REQUIREMENTS_MIN_MET', 10);
+define('REQUIREMENTS_NOT_MET', 0);
+
+// Required
+$php_ok = (function_exists('version_compare') && version_compare(phpversion(), '5.2.0', '>='));
+$simplexml_ok = extension_loaded('simplexml');
+$dom_ok = extension_loaded('dom');
+$json_ok = (extension_loaded('json') && function_exists('json_encode') && function_exists('json_decode'));
+$spl_ok = extension_loaded('spl');
+$pcre_ok = extension_loaded('pcre');
+$curl_ok = false;
+if (function_exists('curl_version'))
+{
+ $curl_version = curl_version();
+ $curl_ok = (function_exists('curl_exec') && in_array('https', $curl_version['protocols'], true));
+}
+$file_ok = (function_exists('file_get_contents') && function_exists('file_put_contents'));
+
+// Optional, but recommended
+$openssl_ok = (extension_loaded('openssl') && function_exists('openssl_sign'));
+$zlib_ok = extension_loaded('zlib');
+
+// Optional
+$apc_ok = extension_loaded('apc');
+$xcache_ok = extension_loaded('xcache');
+$memcached_ok = extension_loaded('memcached');
+$memcache_ok = extension_loaded('memcache');
+$mc_ok = ($memcache_ok || $memcached_ok);
+$pdo_ok = extension_loaded('pdo');
+$pdo_sqlite_ok = extension_loaded('pdo_sqlite');
+$sqlite2_ok = extension_loaded('sqlite');
+$sqlite3_ok = extension_loaded('sqlite3');
+$sqlite_ok = ($pdo_ok && $pdo_sqlite_ok && ($sqlite2_ok || $sqlite3_ok));
+
+// Other
+$int64_ok = (PHP_INT_MAX === 9223372036854775807);
+$ini_memory_limit = get_ini('memory_limit');
+$ini_open_basedir = get_ini('open_basedir');
+$ini_safe_mode = get_ini('safe_mode');
+$ini_zend_enable_gc = get_ini('zend.enable_gc');
+
+if ($php_ok && $int64_ok && $curl_ok && $simplexml_ok && $dom_ok && $spl_ok && $json_ok && $pcre_ok && $file_ok && $openssl_ok && $zlib_ok && ($apc_ok || $xcache_ok || $mc_ok || $sqlite_ok))
+{
+ $compatiblity = REQUIREMENTS_ALL_MET;
+}
+elseif ($php_ok && $curl_ok && $simplexml_ok && $dom_ok && $spl_ok && $json_ok && $pcre_ok && $file_ok)
+{
+ $compatiblity = REQUIREMENTS_MIN_MET;
+}
+else
+{
+ $compatiblity = REQUIREMENTS_NOT_MET;
+}
+
+function get_ini($config)
+{
+ $cfg_value = ini_get($config);
+
+ if ($cfg_value === false || $cfg_value === '' || $cfg_value === 0)
+ {
+ return false;
+ }
+ elseif ($cfg_value === true || $cfg_value === '1' || $cfg_value === 1)
+ {
+ return true;
+ }
+}
+
+function is_windows()
+{
+ return strtolower(substr(PHP_OS, 0, 3)) === 'win';
+}
diff --git a/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test.php b/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test.php
new file mode 100644
index 00000000000..b36a38ab35e
--- /dev/null
+++ b/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test.php
@@ -0,0 +1,789 @@
+<?php
+if (isset($_GET['logopng']))
+{
+ $data = <<<IMAGE
+iVBORw0KGgoAAAANSUhEUgAAASwAAABwCAYAAACkRk1NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz
+AAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAAAU
+dEVYdENyZWF0aW9uIFRpbWUAOS80LzEwZyhWjQAAGJpJREFUeNrtnQ2wXEWVgJvwjKksP2MKMAKV
+HXbZIqUgU1CLWBtkLLZc1IU3CK4ssDAEFVlhM7qIyhYwiqALCqOFIkbNGDSsSszsqllA1zfhT0SX
+DD8aFgJv+DU/JG9CfpYErNluc+6m35m+ffvvvrkz75yqU8mbudO3b9/u755z+txuxkhISEhISEhI
+SEgyJa8tnlvgWgUtZqxuOa4lqFtF1JXuGAnJ9AJUHgZ/g2uHa1ehTYBEoQ/1K3KtcW3F1K3Ntc61
+LK6F7igJyfABqgyDvB0DAZ12AG6VNAABFl4FINl10BYATlhiObrjJCSDBajIjdJZKT4qWzg5h/qZ
+WHg+2syie0tCQqKGwYoUIBCnq23AAKBaPUV1mwBok9VFQjIAVtZ5AK+JwCAY47rIxz0EsC5KAV7i
+WpdwHaVeQEIyuAAbhYHsCq8VAMBcCnXzhdc4QYqEZHBg1IR4kFFMyQJexpCCmJmIa3XQ50WIedVM
+Zhwt4CUgdaNFmVFQv0Y9hoSk/8CSB3PDdMpfgte4DaTA5YxmHicFzhXAUgXsS5ZurSuk8KRDk3oM
+CUm2gIWn/IOkI0iQauisnwRg4XQJI3gZ1q9gMDNKwCIhyTCwVPAqWJSdN4GUI7BUuV5WqRISpEzz
+ywhYJCQDAizsminjShp3Kk1gdWPc2pwmXuaSBEvAIiEZQGDJWkTleaUWBAKWEjCQEBqsPBISEgIW
+AYuEhISARcAiISFgEbBISEgIWAQsEhISApa7UqY7CQkBa2CAVaUeQ0JCwCJgkZCQELAIWCQkBCwC
+FgkJCQGLgEVCQkLAImCRkBCwCFgkJCQELAIWCQkJAYuARUJCwCJgkZCQELAIWCQkJNkE1jgqq+C5
+L2JoYFWox5CQ9BdYJc/dnn2Blbibjce+iCGAtdp341cSEpLw4MLbYqUJLOMttzzh5QqsFQQpEpLh
+hJcpsJwh5QEvG2Cltjs1CUnWB3wRD+SM1a8AdcwFgJcOWMEhZQmvJGCNEaRIpqtFUlLsZOy0X16K
+sSrVHnwN081SJXit1gBrDMBR7OO1jgJgawpgUUyKZFpCKtp/r2ETBA61k7IhXKJNTDsWm6VWLbZz
+p4FPQpJxV6rqukmo6WakASDaDFS/YFvBk5CQ9NeVCqkdVzg4bLfuWr9MuLYkJCR6GNwIweNuyhoF
+qE+0tKgWoZhSWjoBsalR6hkkJIMBr9BwCDaLlhK8CFIkJEMALx84GEPKNaAN9TvPMYPd2NKDwH5q
+LuLIjL1zXItcK1yrSMXn+am87+J8cF6hBYffR78t9qG9SlPdXinfi6LPvQhUh4JUh3y/YGQVEDeE
+l/juKsPyJgX2Fd83bWJehkmgVhCFwH5LldYQCApigLW4dg20DcfnLQd2VaM5xbFtxbk7XOvy8TED
+qxFTd3GN5QCQqli2V812gME5mgG1YQMa6Be1hOtsQj1zDuCJ6wsVRT3qcO/j+kN+qoGlms0rGQ7m
+CA5jptP+usB5DLCcAvYIXmMekIpNHPUceDXDQRenVYunc2I50JE7Buft4MEH19MwrHfL1kqQ2quT
+dnvB+bopaDWlftHBoEk4h/Y+oX5j2h/K/QJWkNk8xXmKJrN7BsDqKhJBvWfzLGYfiwFgVYixYFy0
+HgJYFrDqgRYMspbDIMtbtFcrUHu1TCySfgArQL9oGl5bMwlYUBfb85f6DSwVvIzhEJMN3w0MLGd4
+OaZIFD1hlfe0ElRaCwCspsvgh/JdLcWmocURur3qWQOWwwPDGciGwHIBZ8fWPU0TWEZwcIFUQGCp
+suyD1i8AsFopDYaCB7B8nupVz3oXfQZXiuedMmA5Wqg6bXi2acXj3JWsAiv1FTg9gZVK/XyAJfz8
+lAaC1mowAFY/taapd6kf7dUHYNVSOFfFA1g+D7AWAWt4gNUytFjyCDYmv2sPKLCantZVDbVXwfB3
+HZ/AtKO7lI8JERgFtaW0gqqB+xjrnqVotU4K2hOwBhhYhh2zrHEZ2q4dxRJYdRgQNccnbfR70wHf
+0VyzU3tZPBy84y0W7lMl5vd1F3ffMCheDQCshpTy0A7hbhOwBgNYRZ8AtGGsKOcJrIJHbKWFLQjT
+maaU2quc9sCymEBpekBZ5zLXXaxuC2CVHfsDAWtILKyWi7VgAZ2ix2/rnnG3gqsF4dhelbTaK7CL
+H5u+Ydi2ec8YX8ERWPV+PQgIWBmJYSkGVPRaSSWAheYLrKJHALrlY+lY5GIVobxU28uwPqazo6XQ
+FpKlhVZ1BFbBoz9UCVhDBqwUXEovYCWcu+3hthT7EaRNE1gWSZUNz3Y1yVPr2JZhAKyO5zlTBdYE
+ASs7wFK80FuHDtbqI7CaI+4JkakCS2qvcqj2MjhfeyRAEqVvQrArfAx+00yrP4QAVpOA1T9gQaym
+ArMxvpnOrsDqDAqwpJefGwFeb3IBVm0kTGJqMYRrZeLeOfymRsAiYKlAVR+ZguztADNufQfWVLZX
+gPSQWqCyTIBVd5j99QIOAWuaAcvz1YdpByxw9zpT1V4ay65jmN6Rm0JgVW2vk4BFwLKBVX0kvSzj
+oQNWinC3BVbDJ72DgEXAGuZ3CTsQKylDx86lPEuYSWBZvEsYLSQXpL086lG16AsELAJWphNHTV2K
+Wh/SGjIHLJv2UrlgoYDlm81OwCJgDSqwTGaXKn3Kw8oisCo+AzogsJojHtnsnrlcIdIauqGBQ8Ca
+HsBKmoJv9zFxNIvAavWrvRziZ2XHPhFigUMCFgErLLAMV2pIyn0pTzNg+a5nVfIBVqhs9oQ6ekHZ
+8EHYHDZgVT2z3UMCYUXG67faZSuyEPEKw9nFoQBWoPaqeQLLdQXQDrRXNWmNc8N7mkuIi6bxLmF2
+gSUN5FHYRHRiioGwAna2yWW0fsa7AaUFLIsAdIWAZWx56NaLqgZMnejEbTNmaAWWPK3uwlACywMO
+LkAwgpRB/cazWD/HAdjwnAmKXTVhSIHVChB7anvAzkXLDg+ipsd9aacBnMwByxJepkAwhgDsJ5g3
+rF8B9hscn6r6pQSsuKeh7TrwlSEAlmn8qOjR1jqXKc0loXMObmHZEcrlaQcsA3jpgGADqWjz0qZi
+U9eCBbxs6jeWFqQcYg3y2t3RWll1RxekMA2C7tG1Vj3bS/WuXZrAKjpMyET5ZkVwI02us+2xpvtw
+AAtZQNGOygX03ZgFpGz2BbTa1FWCq6p+XjGplGaEUtsRZkCB1ZjC9mr0C1gpxMxMYl/TC1ieoPPd
+FxDvi5gfhGtPeYuvpFjJIAJrKnf6qfYTWCk80OppAmeogQWuXhkA001JW+BOFjIOLd9OWTaYri8P
+Qx6W4XlN2qvq0F46NyvaRaYkuaKRqxbtFtRyAFaozVTrBv2QgKWB1ZIAq5ra5EmVMgys3Ij7FuCl
+BPB1hvDlZ9dB3JFBFFP/TpzbpIBUxeHVm2hhxqbFWum+0Kob1o2AlWKe15SmIEwRtGwsh6Zi+yzc
+sdueW9X7Aqvsce6OQXvVA7dXJ6G9amApFQPOEtcN3w3MOcS02klJqpbxQV9gVdgwSQB4DRSkNJ24
+prj5bSlTOulp3ICBkDMYBBVpQ0yshYTfFzS/rRicX3fukmF75aX26ni0V8PWWurjg62isbg6cC1l
+h7J197NqcD+9fp81GDVtAuIArxsNkkBtUiT+P7DPSEiGQADYUbwsRy0SFliqgLgJvOQk0Amwwkxe
+28lJgf2O7mVqEhISEh2wnOBlcJ6cyewj3REvmc31QK5voKYgmY7A6rpmsUPZqmz4LgErFbmG6wau
+W+HfedQkwWQG13O5rgE9m5ok+8AygpcEqVaI9bVIjOXHXLuSvoeaJJj8GddXpLYVD4UjqFkGB1hT
+tiAgibGsJGClJl9CbSv0FGoWAhYBi4CVRZnDdZPUti+z3fFCEgIWCQErk7If11u4fp2agoBFwCJg
+kZAQsAZQ5nO9nO0OoovZvse43s71Aq4HOAJLTI6czvVUrkdynRmgngdx/dMArpG4JtGHjuU6bAmW
+oo1EmsnrPMqYy/VdcN/28ShHTBzMI2ANN7D+iu2exv4t12Wa40a53s11jOtZmuMENO7kegdX/IrL
+/mx3asILrDfAG+kTXBdaAOtvuK7l2pE+38ZVLFf8dw7tIcq7B+q4GeI6W7g+znU517dw3dugHDHw
+ylx/zfVZqNME1xe53g9toxvkZ3A9h+vBXPeCzy7m+ijUZ5zrvvD5J7neB/UuG9TtMK5LoT2jd+xE
+WkMVyl/N9TLN74/i+hVoE9H2T3N9jutd0DdmGcbMLoW+Jx5aO6C918F1HGvYzlWpP70C7bwT6nSd
+1EZ/lIPnHFDm2kQqPqvB//NwXDH6joCVLfmBNNB3wUBRyf3ScaJTjyiOEZ/9r3TcF6XvZsGA36mB
+VVfqeGcaAEuU/7KmHHE9N1hYQT/huj2hbuL77yaUdQiAfVdC3e6MsbgE1F+F40R7/gW0HS7v43D8
+i9JnG8Ha1Mld0vF/gM9yAI2udF4se8EDqYXucxed/46E8x8HD0hdX9iZ0M7HAOiS+tJ6+QELIKpy
+bYNWJTh1xd9wXF3+m4CVHbkYWSfLYwbgk9Ix68BVwnIydJAuWAGyhXWbooM+A+f7BXR0+TtRp7cl
+AGtnwt8RGC4zaId7DDq/fJ4vayyH31uU9ZDCfV0qff8S11tjri0C1n3o808ngFmu35gErO3ooYHl
+eAOgR78dA4say59D3zBtn9sUD8f5YLWaliEs2wXI0vqjdYX+7gDEcgArAlYGgXUkuBfRzX1Rccz7
+EVCEVXOu4rgrpCfvBohNRE/UHagT3Q6xD9lNeRgd83gCsOSnurBKTgIXB8PvNa6Ha9rgVMVA/B3X
+xVy/wPU/wV3Bg3Kewg28QwHMu+EcZ8BA3oaOuVYDrC2Kc++Ez6NBuAhZPPdrrvU0qX3ENXzYEFiH
+Iis76gfiem8GV162dkXi6T8pYNlSPJiEZftutju7/lfIknxVESL4maI9xO++yXbPcD7JJifBdsFl
+TQJWZFXVAF5NAlY2g+6y9STAkkffq5IK64py5Cf9g1Js5CH027jtsMSgaKO6HJ8ArE0KGB2rAKRu
+qn4MHbtSEYeZCxYhPk6WhWiwCVBeqDjfpZLLFw3aA2KA9Qfkji6DwS0f/1aweuXBGRd8riNL+WBD
+YC1ClriwcE5Ex1yPjmmhIPo1CCTbwSrH8m1kUa6VytkXrE45Xnk+ineNQPxvAt2Lv04AlnAPWwCt
+OgEru8Bagp5WH9bEr2QLZCayLmTL5ibJnXwZxUaO0dTlixowrlRYL+8ziM1FlmNcMPgFdP3HxRz3
+dmkgiXOvQt//Cp1zVUzgeCbEAeVjL4sBljzg4t7vmwUxIRmA5yiOez2yYtdI3yUB62H03eWK8l+H
+Hk6bJSDtB1aYfE1LYq5nNopP7YJZxMhal/vZU4bxWdHv3msArAoAq0TAyi6wFqIn479J3x2k6Ghd
+iIPI75qdInWyrWxPysEV6HfPxgTsI1mABs46DbB+l+DqTiBr7a0xx76EgPXOmONmwGzpVxXHFFBs
+5hWYTdO5obI1dl8CsFYk3MOvo+OXxwSqn5eO+awhsI5Cv9scE5+KZjfljPnPS/1jK3L1kmb/5Ov5
+AXw+itrtSQCxSgQk/4XrJyB2JruEBaHo7zzEr4ryZwSs7MnhyBV7nu2ZSh+VgrTbpEEpOvSHUPxK
+DhRHs18/QR3vFxCwj9N3INB0ARQqYH0l4bqeQ8cvijluHB13vxR/M5V/VABdJ/OQ5bmR7UlzWKqw
+JJPyi96F2u1Z1pvTdKkU61qHJjV0wKqgGNk9mnrMRX1pKXx+C7qm3yRczwmoPmsk6G5GbXMp88vf
+ypYQsIzkURRbiAbs51CQVY6V3Cr9/t6YGNXjikDtRo2+hOIX2yAgrwJW0lLGOAC+2CCuI7uQPwdX
+bQHTJ7QKaSgmDD6o0UuQRbYVYngqYD0tPUCYxi2cQLE9HGNaJX0/jr7TAesbhuCP5GRot49wfTN8
+9iAq496E9rkStc8mcKVnIgsugtYasMLOAotwNgFruIH1NTR4TofPH5A+F0mQjyCXbBYM5rXS51+K
+Cei7qADW0THASno151Z0/PdjjjsMYkRxdRDtsR4GnQgcz0+YcHDVY2OAdZvhPfwvjQWKU1OWWQDr
+TnQ/XHaBesKzbTZBeELIlxOO7YCFK/rLeQNnfRGwjORs9ERbAjMyckBaDNZr0WzU0chtFIP7A1K5
+L3p21B2SO4SBdWrCNWHLoKE59iLFkztON4AFMDMmKO2qb4sB1rcM7+H5bHLKxNPSd/8gxRi3wD0z
+Bdbd6NpH+wSsg6XyHjD83S7og0cTsIYLWIdCB49u9CNgwWyQOsxJAKPNUqf+KJj/cpLeG6Vy26gD
+fQbiE6aa0wTdkyysGwwC0bKcCYDeZTAQXkUxPOz6boRBaqq/kcC8VDODqJP9UWB7o+SSLUEza4dY
+AKsZAFjPKGJ8bQt9QOHm3YwmTHT6HNPn4mUKWPUMAWs8w031axQ4v5ZNTgTdF2C0Cc3ejKHBMEMq
+839Qx/m8R/0wsE5POB7Hpr5neB6R+/VVcHm3aQAm7mU0i4QTIm/2uE4MrEssfvtLNnnGU/z2T+Ba
+cHa7i0u4Faw1W8H94MxAfTYH3sESiMNOsPhXfpazQRFY1ngR7MQ81cAah513Chlvpn9FwfFHFbM6
+M5B5vxZZZt9AZeJljW8NCKxywvE/Qsdf43je46Bt1ikGwUVwzO3o85/2CVjyTGAXXFXRf6O0BPHd
+hZbAwjltVyfUQUxSLET35xFUxg0p9eE54AksY71vPKyD7wcuCG8LLxdgDQqkZDkDmdhyIFp+d+6b
+yO2IYl+iw+MVEq5WWCU6mQ1PSzF1fhMKcGNgfTuhLOymvduzfeaiyQW5Dtcx8xwx2YU7LDCwjlDE
+DT/H9mT+i0F7pCWwPsV6U1Pi5E1gZa+HvvSjGKD/h8G1HKhwXW3kBIV1/HY2yGIIL1NgDSKkZDmA
+TU4QjF6jWI8C6adJkNqBXBC8+oBoCzkpdTtDL6Iq4khyJ/uZBlhrNeW8mU3OcxLXcFAMhH4Mg1wM
+sKMS2ujqGDfzJOSK7Ig5nwzmh+CcImfqqkDAYqw3RUWOH/03U68VpgNWCYUBhJU2SxP436KYMLiQ
+9b6QrEsgFvG8NdA+T0kupEjYfQz6yG8T2mEG682xG55FHzXw0gFr0CGF5UGF2/MMsgT2Z+o37p+P
+KRO7A+uZOhFyHnRO+djrNcDapoljLWe9yaAq+Rg6Trxeo1uHaTFT53bNYb0rCCzWlPNJNvm9ujUB
+gYVfb5JdxJs0saA4YOWQZbmdxS9DhFMgzpTurfy6jZi0+KCFWxw9uNqojI8ntAV2C49nwygAr6sA
+SBhYY7ADdHEIL/0aBYhUT7LHmHopEJWcznpXQxCD+yPQkXNgweEZHzFjd6gGWNG09QL0VD0XWXW6
+dw4LyEoUbvC1McceznpXWrgoxlWOrCzVYoRFNnk2T+iVAYG1AFnKslVzogOwGOtNEXmM9c66XYLa
+XZQhL1J4N+tNIlY9cD6K2kfcv7NiHhjPQXuq5Ep0TZuY/RsMJBmXU1jvqzGqGa/Pst4lPj6gKfen
+TL2ulEiR+D3rXYjvNcXTc6XCXY0G4kpwz1ax3sXlxOB6vaZu9yog+CTA+xywJm5gva/6dBBQD0QD
+NrIyxJT8h8DaaCjaVwykfQICazbrfbk6SiXYxxFYf6mAtZj5uwWgvIJNXmdL/B6vyzWf9S77IsB0
+B5Tx93D/8DGPSy7ofLZnzTX5PtwJ/eU0cEvvUjwU7qXhPXyyD4pXiM5wgeK4k5GJjwcvljkKMOiS
+/aoK10wG1jJFh4xbITQp/6agCKab5GF9RlHW2QpoJWVlnxAw6B7J1xTn+nfN8SYL+H1M4WJFuXX4
+M9W7gnuB1bPTon1eUFhFCy3LiMCYp+E9nPIQeiqrBvy+yO1Ya1j29Sw5KznOfVspuVri7ft/Vjz1
+8fuAJxjWa36MGxX3utB1msDzBcwsa35DjEuEgXWxwz18L+vdZ/B8zfH7sd4JFJXcyPTLUgvr9p6E
+h8QXEu6bbFnFxYYvYuYrlz7F1OtukQyJCBiI4PsvwdJhmoEppq1/yPasV2QiYpaqAgNTTJGLd+C+
+Y1CGeL2iyXYvFyJbR6sArC/BIBUzQ3XmtoPK5eDqbGeTZyt3wFNaBH+PMShHDNifQxmvIijvhDaL
+i6ecA4NxA0PrOFmIsJi+C23xBLhMSe/UidQVsQGFSCC+IuaYvWHwi+TTdaDRDKvIx7vaME4kZnEf
+hrbZhSy7DliIcwzaOLrGLQqLStxH8V7rm2hIk2RNhLXzRhZmG60Z0MmLXP8WBugRHuWJcspsd3qA
+yWzyCFzLkZ7nTVNEHQ+BazvZ8Lri7ts7wZV+D9vzKpFtGW+BuogyFjAKrpOQkJCQkJCQkJCQkJCE
+l/8Df+8XDp+g0JUAAAAASUVORK5CYII=
+IMAGE;
+
+
+ header('Content-type: image/png');
+ echo base64_decode($data);
+ exit;
+}
+elseif (isset($_GET['background']))
+{
+ $data = <<<IMAGE
+R0lGODlhMAEeAeYAAP///8ni6cTf5+72+PD3+c3k6+nz9ufy9ev099Pn7bnZ48bg6LfY4uHv8/r8
+/f3+/v7//7bX4cjh6fj7/Mvj6vz9/rva4+z19/X6+/f7/Pn8/fb6+7jZ4vv9/bra473b5Lzb5LXX
+4b7c5b/c5e31+NTo7tvs8dfq7/H3+bjY4tnq79Hm7c/l69nr8PL4+t7t8sDd5cLe5uPw9Nvr8Mri
+6fP4+tLn7er099Hm7O/2+dDm7OTw9OXx9Nbp7tbp7+Lv8+Du8szj6sXg57bY4d3s8djq7+jz9tzs
+8cPe58fh6M7k68Pf5+by9fz+/sDd5vT5+vT5+97t8bbY4trr8P7+/v7+/+Pw8+Xx9dXo7sHe5vH4
++fP5+sHd5t/u8s/l7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5
+BAAAAAAALAAAAAAwAR4BAAf/gCGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnp+goaKNEaWm
+p6ipqqusra6vsLGys7S1tre4ubq7vL2+v8DBwsPExbBDyMnKy8zNzs/Q0dLT1NXW19jZ2tvc3d7K
+UuHi4+Tl5ufo6err7O3u7/Dx8vP09fb34wz6+/z9/v8AAwocSLCgwYMIEypcyLChw4cQI0qcSLGi
+xYsYM2osmKKjx48gQ4ocSbKkyZMoU6pcybKly5cwY8qc+ZGDzZs4c+rcybOnz59AgwodSrSo0aNI
+kypdyrSp06dQo0qdSrWq1aAKsmrdyrWr169gw4odS7as2bNo06pdy7at27dw/+PKnUu3rt27ePOS
+9cC3r9+/gAMLHky4sOHDiBMrXsy4sePHkCNLnky5suXLmDNr3sz5sIXPoEOLHk26tOnTqFOrXs26
+tevXsGPLnk27tu3buHPr3s27t+/fqkEIH068uPHjyJMrX868ufPn0KNLn069uvXr2LNr3869u/fv
+4MOLb/6hvPnz6NOrX8++vfv38OPLn0+/vv37+PPr38+/v///AAYo4IAEFgifCAgmqOCCDDbo4IMQ
+RijhhBRWaOGFGGao4YYcdujhhyCGKOKIJJZo4okoTjjCiiy26OKLMMYo44w01mjjjTjmqOOOPPbo
+449ABinkkEQWaeSRSCap5P+SNsLg5JNQRinllFRWaeWVWGap5ZZcdunll2CGKeaYZELpxJlopqnm
+mmy26eabcMYp55x01mnnnXjmqeeefPaZJheABirooIQWauihiCaq6KKMNuroo5BGKumklFZqqaBZ
+ZKrpppx26umnoIYq6qiklmrqqaimquqqrLbq6qubxiDrrLTWauutuOaq66689urrr8AGK+ywxBZr
+7LHI0orEssw26+yz0EYr7bTUVmvttdhmq+223Hbr7bfghtvsEuSWa+656Kar7rrstuvuu/DGK++8
+9NZr77345quvuQL06++/AAcs8MAEF2zwwQgnrPDCDDfs8MMQRyzxxBRXbPH/xRhnrPHGHHeMsBAg
+hyzyyCSXbPLJKKes8sost+zyyzDHLPPMNNdss8gL5Kzzzjz37PPPQAct9NBEF2300UgnrfTSTDft
+9NNQRy311FRXbfXVWGdNdBJcd+3112CHLfbYZJdt9tlop6322my37fbbcMctt9cS1G333Xjnrffe
+fPft99+ABy744IQXbvjhiCeu+OKMN+7445BHLvnklFcOeACYZ6755px37vnnoIcu+uikl2766ain
+rvrqrLfu+uuwxy777LTXbvvtuI9Ow+689+7778AHL/zwxBdv/PHIJ6/88sw37/zz0EffOwXUV2/9
+9dhnr/323Hfv/ffghy/+//jkl2/++einr/767Lfv/vvwxy///PR/H8T9+Oev//789+///wAMoAAH
+SMACGvCACEygAhfIwAbmrwAQjKAEJ0jBClrwghjMoAY3yMEOevCDIAyhCEdIwhKa8IQoTKEKV8jC
+FrrwhTDcoBJmSMMa2vCGOMyhDnfIwx768IdADKIQh0jEIhrxiEhMYg1ZwMQmOvGJUIyiFKdIxSpa
+8YpYzKIWt8jFLnrxi2AMoxid6IUymvGMaEyjGtfIxja68Y1wjKMc50jHOtrxjnjMox73eEYd+PGP
+gAykIAdJyEIa8pCITKQiF8nIRjrykZCMpCQnSUlA4uCSmMykJjfJyU568v+ToAylKEdJylKa8pSo
+TKUqV8nKVmZyBbCMpSxnScta2vKWuMylLnfJy1768pfADKYwh0nMYhpTljZIpjKXycxmOvOZ0Iym
+NKdJzWpa85rYzKY2t8nNbnrzm8tMgDjHSc5ymvOc6EynOtfJzna6853wjKc850nPetrznvjMpz73
+yc9++vOfAA2oQNtZgoIa9KAITahCF8rQhjr0oRCNqEQnStGKWvSiGM2oRjd6UCx49KMgDalIR0rS
+kpr0pChNqUpXytKWuvSlMI2pTGdKU5D24KY4zalOd8rTnvr0p0ANqlCHStSiGvWoSE2qUpfK1Kbm
+1AdQjapUp0rVqlr1qlj/zapWt8rVrnr1q2ANq1jHStaymlWqJ0irWtfK1ra69a1wjatc50rXutr1
+rnjNq173yte++vWvay2CYAdL2MIa9rCITaxiF8vYxjr2sZCNrGQnS9nKWvaymCWsCjbL2c569rOg
+Da1oR0va0pr2tKhNrWpXy9rWuva1sI1tZ1tA29ra9ra4za1ud8vb3vr2t8ANrnCHS9ziGve4yE2u
+cm07heY697nQja50p0vd6lr3utjNrna3y93ueve74A2veMf73BmY97zoTa9618ve9rr3vfCNr3zn
+S9/62ve++M2vfvfLX/Sa4L8ADrCAB0zgAhv4wAhOsIIXzOAGO/jBEI6w/4QnTOEKB/gIGM6whjfM
+4Q57+MMgDrGIR0ziEpv4xChOsYpXzOIWu1jDRIixjGdM4xrb+MY4zrGOd8zjHvv4x0AOspCHTOQi
+G/nIM46CkpfM5CY7+clQjrKUp0zlKlv5yljOspa3zOUue/nLYGbyC8ZM5jKb+cxoTrOa18zmNrv5
+zXCOs5znTOc62/nOeM5zmbvA5z77+c+ADrSgB03oQhv60IhOtKIXzehGO/rRkI60pP0MhEpb+tKY
+zrSmN83pTnv606AOtahHTepSm/rUqE61qld96Qa4+tWwjrWsZ03rWtv61rjOta53zete+/rXwA62
+sIdN7GIb+9jITrayl//N7GY7O9c/iLa0p03talv72tjOtra3ze1ue/vb4A63uMdN7nKb+9zTtoK6
+183udrv73fCOt7znTe962/ve+M63vvfN7377+98AZ7cMBk7wghv84AhPuMIXzvCGO/zhEI+4xCdO
+8Ypb/OIYz3jBd8Dxjnv84yAPuchHTvKSm/zkKE+5ylfO8pa7/OUwj7nMPc6Dmtv85jjPuc53zvOe
++/znQA+60IdO9KIb/ehIT7rSl37zKzj96VCPutSnTvWqW/3qWM+61rfO9a57/etgD7vYx052qDPh
+7GhPu9rXzva2u/3tcI+73OdO97rb/e54z7ve9873vqf9AIAPvOAHT/j/whv+8IhPvOIXz/jGO/7x
+kI+85CdP+cpb/vKYz7zmN8/5znv+86BfvBFGT/rSm/70qE+96lfP+ta7/vWwj73sZ0/72tv+9rjP
+fekNwPve+/73wA++8IdP/OIb//jIT77yl8/85jv/+dCPvvSnT/3qW//62M++9rfP/ePf4PvgD7/4
+x0/+8pv//OhPv/rXz/72u//98I+//OdP//qHHwH4z7/+98///vv//wAYgAI4gARYgAZ4gAiYgAq4
+gAzYgA74gBAYgRI4gRRYgRZ4gRg4gBewgRzYgR74gSAYgiI4giRYgiZ4giiYgiq4gizYgi74gjAY
+gzI4gzRYgzZ4gziY/4M6uIMmSAI++INAGIRCOIREWIRGeIRImIRKuIRM2IRO+IRQGIVSOIVUCIQD
+cIVYmIVauIVc2IVe+IVgGIZiOIZkWIZmeIZomIZquIZs2IZu+IZwGIdyOId0WId2eIdimAN6uId8
+2Id++IeAGIiCOIiEWIiGeIiImIiKuIiM2IiO+IiQyIcEMImUWImWeImYmImauImc2Ime+ImgGIqi
+OIqkWIqmeIqomIqquIqs2Iqu+IqwGIuyOIueiAK2eIu4mIu6uIu82Iu++IvAGIzCOIzEWIzGeIzI
+mIzKuIzMiIta8IzQGI3SOI3UWI3WeI3YmI3auI3c2I3e+I3gGI7iOP+O5FiO0egC6JiO6riO7NiO
+7viO8BiP8jiP9FiP9niP+JiP+riP/NiP/qiONRCQAjmQBFmQBnmQCJmQCrmQDNmQDvmQEBmREjmR
+FFmRFnmRA7kFGrmRHNmRHvmRIBmSIjmSJFmSJnmSKJmSKrmSLNmSLvmSMMmRTzCTNFmTNnmTOJmT
+OrmTPNmTPvmTQBmUQjmURFmURnmUSJmUNQkFTNmUTvmUUBmVUjmVVFmVVnmVWJmVWrmVXNmVXvmV
+YBmWYumUGFCWZnmWaJmWarmWbNmWbvmWcBmXcjmXdFmXdnmXeJmXermXfNmXfvmXgBmYgjmYhFmY
+cLkBiJmYirmYjNn/mI75mJAZmZI5mZRZmZZ5mZiZmZq5mZzZmZ75maAZmqI5mqRZmqZ5mqg5mRmw
+mqzZmq75mrAZm7I5m7RZm7Z5m7iZm7q5m7zZm775m8AZnMI5nMRZnMZ5nMiZnMq5nLY5Ac75nNAZ
+ndI5ndRZndZ5ndiZndq5ndzZnd75neAZnuI5nuRZnuZ5nuiZnuq5nuzZnu6ZnRoQn/I5n/RZn/Z5
+n/iZn/q5n/zZn/75nwAaoAI6oARaoAZ6oAiaoAq6oAzaoA76oBAaofzpABRaoRZ6oRiaoRq6oRza
+oR76oSAaoiI6oiRaoiZ6oiiaoiq6oizaoi76ojAaozI6ozT6oR1w/6M4mqM6uqM82qM++qNAGqRC
+OqREWqRGeqRImqRKuqRM2qRO+qRQGqVSOqVUWqVWeqVCWgFauqVc2qVe+qVgGqZiOqZkWqZmeqZo
+mqZquqZs2qZu+qZwGqdyOqd0Wqd2eqd4mqd6WqZN0Kd++qeAGqiCOqiEWqiGeqiImqiKuqiM2qiO
++qiQGqmSOql/+gCWeqmYmqmauqmc2qme+qmgGqqiOqqkWqqmeqqomqqquqqs2qqu+qqwGquyOqu0
+Wqu2GqpUkKu6uqu82qu++qvAGqzCOqzEWqzGeqzImqzKuqzM2qzO+qy7WgXSOq3UWq3Weq3Ymq3a
+uq3c2q3e+q3gGv+u4jqu5Fqu5nqu6EqtELCu7Nqu7vqu8Bqv8jqv9Fqv9nqv+Jqv+rqv/Nqv/vqv
+ABuwAjuwBFuwBnuwCJuwCruw9goADvuwEBuxEjuxFFuxFnuxGJuxGruxHNuxHvuxIBuyIjuyJFuy
+JnuyKJuyKruyLNuyLvuyMBuzMjuzNFuzNnuzOJuzOruzPNuzPvuzQBu0Qju0RFu0Rnu0SJu0Sru0
+TNu0Tvu0UBu1Uju1VFu1Vnu1WJu1Wru1XNu1Xvu1YBu2Yju2ZFu2Znu2aJu2aru2bNu2bvu2cBu3
+cju3dFu3dnu3eJu3eru3fNu3fvu3gBu4gju4hFu4hnu4iJu4irv/uIzbuI77uJAbuZI7uZRbuZZ7
+uZibuZq7uZzbuZ77uaAbuqI7uqRbuqZ7uqibuqq7uqzbuq77urAbu7I7u7Rbu7Z7u7ibu7q7u7zb
+u777u8AbvMI7vMRbvMZ7vMibvMq7vMzbvM77vNAbvdI7vdRbvdZ7vdibvdq7vdzbvd77veAbvuI7
+vuRbvuZ7vuibvuq7vuzbvu77vvAbv/I7v/Rbv/Z7v/ibv/q7v/zbv/77vwAcwAI8wARcwAZ8wAic
+wAq8wAzcwA78wBAcwRI8wRRcwRZ8wRicwRq8wRzcwR78wSAcwiI8wiRcwiZ8wiicwiq8wizcwi78
+wjAcwzI8wzRcFcM2fMM4nMM6vMM83MM+/MNArLmBAAA7
+IMAGE;
+
+ header('Content-type: image/gif');
+ echo base64_decode($data);
+ exit;
+}
+elseif (isset($_GET['loader']))
+{
+ $data = <<<IMAGE
+R0lGODlhEAALAPQAAP///wBmzNro9tDi9Ory+gZpzQBmzC6B1YKz5WCf3rrV8CJ60kqS2oq452Sh
+377X8SZ80wRozE6U2+bv+djn9vT4/DiH19zp9/L2+7bS76DF68re8+70+gAAAAAAAAAAACH/C05F
+VFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCwAAACwAAAAA
+EAALAAAFLSAgjmRpnqSgCuLKAq5AEIM4zDVw03ve27ifDgfkEYe04kDIDC5zrtYKRa2WQgAh+QQJ
+CwAAACwAAAAAEAALAAAFJGBhGAVgnqhpHIeRvsDawqns0qeN5+y967tYLyicBYE7EYkYAgAh+QQJ
+CwAAACwAAAAAEAALAAAFNiAgjothLOOIJAkiGgxjpGKiKMkbz7SN6zIawJcDwIK9W/HISxGBzdHT
+uBNOmcJVCyoUlk7CEAAh+QQJCwAAACwAAAAAEAALAAAFNSAgjqQIRRFUAo3jNGIkSdHqPI8Tz3V5
+5zuaDacDyIQ+YrBH+hWPzJFzOQQaeavWi7oqnVIhACH5BAkLAAAALAAAAAAQAAsAAAUyICCOZGme
+1rJY5kRRk7hI0mJSVUXJtF3iOl7tltsBZsNfUegjAY3I5sgFY55KqdX1GgIAIfkECQsAAAAsAAAA
+ABAACwAABTcgII5kaZ4kcV2EqLJipmnZhWGXaOOitm2aXQ4g7P2Ct2ER4AMul00kj5g0Al8tADY2
+y6C+4FIIACH5BAkLAAAALAAAAAAQAAsAAAUvICCOZGme5ERRk6iy7qpyHCVStA3gNa/7txxwlwv2
+isSacYUc+l4tADQGQ1mvpBAAIfkECQsAAAAsAAAAABAACwAABS8gII5kaZ7kRFGTqLLuqnIcJVK0
+DeA1r/u3HHCXC/aKxJpxhRz6Xi0ANAZDWa+kEAA7AAAAAAAAAAAA
+IMAGE;
+ header('Content-type: image/gif');
+ echo base64_decode($data);
+ exit;
+}
+elseif (isset($_GET['ssl_check']))
+{
+ header('Content-type: text/plain; charset=utf-8');
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, 'https://email.us-east-1.amazonaws.com');
+ curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
+ curl_setopt($ch, CURLOPT_HEADER, false);
+ curl_setopt($ch, CURLOPT_NOBODY, true);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 5184000);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 120);
+ curl_setopt($ch, CURLOPT_NOSIGNAL, true);
+ curl_setopt($ch, CURLOPT_USERAGENT, 'aws-sdk-php/compat-www');
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
+ curl_setopt($ch, CURLOPT_VERBOSE, true);
+
+ curl_exec($ch);
+ echo (curl_getinfo($ch, CURLINFO_SSL_VERIFYRESULT) === 0) ? 'false' : 'true';
+ curl_close($ch);
+
+ exit;
+}
+
+// Include the compatibility test logic
+require dirname(__FILE__) . DIRECTORY_SEPARATOR . 'sdk_compatibility.inc.php';
+
+header('Content-type: text/html; charset=UTF-8');
+
+?><!DOCTYPE html>
+
+<html lang="en">
+<head>
+<title>AWS SDK for PHP: Environment Compatibility Test</title>
+<meta name="ROBOTS" content="NOINDEX, NOFOLLOW, NOARCHIVE" />
+
+<script type="text/javascript" charset="utf-8">
+/*!
+ * Reqwest! A x-browser general purpose XHR connection manager
+ * copyright Dustin Diaz 2011
+ * https://github.com/ded/reqwest
+ * license MIT
+ */
+!function(window){function serial(a){var b=a.name;if(a.disabled||!b)return"";b=enc(b);switch(a.tagName.toLowerCase()){case"input":switch(a.type){case"reset":case"button":case"image":case"file":return"";case"checkbox":case"radio":return a.checked?b+"="+(a.value?enc(a.value):!0)+"&":"";default:return b+"="+(a.value?enc(a.value):"")+"&"}break;case"textarea":return b+"="+enc(a.value)+"&";case"select":return b+"="+enc(a.options[a.selectedIndex].value)+"&"}return""}function enc(a){return encodeURIComponent(a)}function reqwest(a,b){return new Reqwest(a,b)}function init(o,fn){function error(a){o.error&&o.error(a),complete(a)}function success(resp){o.timeout&&clearTimeout(self.timeout)&&(self.timeout=null);var r=resp.responseText;if(r)switch(type){case"json":resp=window.JSON?window.JSON.parse(r):eval("("+r+")");break;case"js":resp=eval(r);break;case"html":resp=r}fn(resp),o.success&&o.success(resp),complete(resp)}function complete(a){o.complete&&o.complete(a)}this.url=typeof o=="string"?o:o.url,this.timeout=null;var type=o.type||setType(this.url),self=this;fn=fn||function(){},o.timeout&&(this.timeout=setTimeout(function(){self.abort(),error()},o.timeout)),this.request=getRequest(o,success,error)}function setType(a){return/\.json$/.test(a)?"json":/\.jsonp$/.test(a)?"jsonp":/\.js$/.test(a)?"js":/\.html?$/.test(a)?"html":/\.xml$/.test(a)?"xml":"js"}function Reqwest(a,b){this.o=a,this.fn=b,init.apply(this,arguments)}function getRequest(a,b,c){if(a.type!="jsonp"){var f=xhr();f.open(a.method||"GET",typeof a=="string"?a:a.url,!0),setHeaders(f,a),f.onreadystatechange=readyState(f,b,c),a.before&&a.before(f),f.send(a.data||null);return f}var d=doc.createElement("script");window[getCallbackName(a)]=generalCallback,d.type="text/javascript",d.src=a.url,d.async=!0;var e=function(){a.success&&a.success(lastValue),lastValue=undefined,head.removeChild(d)};d.onload=e,d.onreadystatechange=function(){/^loaded|complete$/.test(d.readyState)&&e()},head.appendChild(d)}function generalCallback(a){lastValue=a}function getCallbackName(a){var b=a.jsonpCallback||"callback";if(a.url.slice(-(b.length+2))==b+"=?"){var c="reqwest_"+uniqid++;a.url=a.url.substr(0,a.url.length-1)+c;return c}var d=new RegExp(b+"=([\\w]+)");return a.url.match(d)[1]}function setHeaders(a,b){var c=b.headers||{};c.Accept=c.Accept||"text/javascript, text/html, application/xml, text/xml, */*",b.crossOrigin||(c["X-Requested-With"]=c["X-Requested-With"]||"XMLHttpRequest");if(b.data){c["Content-type"]=c["Content-type"]||"application/x-www-form-urlencoded";for(var d in c)c.hasOwnProperty(d)&&a.setRequestHeader(d,c[d],!1)}}function readyState(a,b,c){return function(){a&&a.readyState==4&&(twoHundo.test(a.status)?b(a):c(a))}}var v=window.v;!v&&typeof require!="undefined"&&(v=require("valentine"));var twoHundo=/^20\d$/,doc=document,byTag="getElementsByTagName",head=doc[byTag]("head")[0],xhr="XMLHttpRequest"in window?function(){return new XMLHttpRequest}:function(){return new ActiveXObject("Microsoft.XMLHTTP")},uniqid=0,lastValue;Reqwest.prototype={abort:function(){this.request.abort()},retry:function(){init.call(this,this.o,this.fn)}},reqwest.serialize=function(a){var b=a[byTag]("input"),c=a[byTag]("select"),d=a[byTag]("textarea");return(v(b).chain().toArray().map(serial).value().join("")+v(c).chain().toArray().map(serial).value().join("")+v(d).chain().toArray().map(serial).value().join("")).replace(/&$/,"")},reqwest.serializeArray=function(a){for(var b=this.serialize(a).split("&"),c=0,d=b.length,e=[],f;c<d;c++)b[c]&&(f=b[c].split("="))&&e.push({name:f[0],value:f[1]});return e};var old=window.reqwest;reqwest.noConflict=function(){window.reqwest=old;return this},window.reqwest=reqwest}(this)
+</script>
+
+<style type="text/css">
+body {
+ font:14px/1.4em "Helvetica Neue", Helvetica, "Lucida Grande", Roboto, "Droid Sans", Ubuntu, Verdana, Arial, Clean, Sans, sans-serif;
+ letter-spacing:0px;
+ color:#333;
+ margin:0;
+ padding:0;
+ background:#fff url(<?php echo pathinfo(__FILE__, PATHINFO_BASENAME); ?>?background) repeat-x top left;
+}
+
+div#site {
+ width:650px;
+ margin:20px auto 0 auto;
+}
+
+a {
+ color: #326EA1;
+ text-decoration: underline;
+ padding: 1px 2px;
+ -webkit-transition: background-color 0.15s;
+ -webkit-transition: color 0.15s;
+ -moz-transition: background-color 0.15s;
+ -moz-transition: color 0.15s;
+ transition: background-color 0.15s;
+ transition: color 0.15s;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+}
+
+a:hover, a.hover {
+ color: #fff;
+ background-color: #333;
+ text-decoration: none;
+ padding: 1px 2px;
+}
+
+p {
+ margin:0;
+ padding:5px 0;
+}
+
+em {
+ font-style:normal;
+ background-color:#ffc;
+}
+
+ul, ol {
+ margin:10px 0 10px 20px;
+ padding:0 0 0 15px;
+}
+
+ul li, ol li {
+ margin:0 0 4px 0;
+ padding:0 0 0 3px;
+}
+
+h2 {
+ font-size:18px;
+ padding:0;
+ margin:0 0 10px 0;
+}
+
+h3 {
+ font-size:16px;
+ padding:0;
+ margin:20px 0 5px 0;
+}
+
+h4 {
+ font-size:14px;
+ padding:0;
+ margin:15px 0 5px 0;
+}
+
+pre, code {
+ font-family: "Panic Sans", "Bitstream Vera Sans Mono", Monaco, Consolas, "Andale Mono", monospace;
+ background-color: #F0F0F0;
+ border-radius: 3px 3px 3px 3px;
+ padding: 0 3px;
+ font-size: 1em;
+}
+
+em strong {
+ text-transform: uppercase;
+}
+
+table.chart {
+ border-collapse:collapse;
+}
+
+table.chart th {
+ background-color:#eee;
+ padding:2px 3px;
+ border:1px solid #fff;
+}
+
+table.chart td {
+ text-align:center;
+ padding:2px 3px;
+ border:1px solid #eee;
+}
+
+table.chart tr.enabled td {
+ /* Leave this alone */
+}
+
+table.chart tr.disabled td,
+table.chart tr.disabled td a {
+ color:#999;
+ font-style:italic;
+}
+
+table.chart tr.disabled td a {
+ text-decoration:underline;
+}
+
+div.chunk {
+ margin:0;
+ padding:10px;
+ border-bottom:1px solid #ccc;
+}
+
+div.important {
+ background-color:#ffc;
+}
+
+div.ok {
+ background-color:#cfc;
+}
+
+div.error {
+ background-color:#fcc;
+}
+
+div.important h3 {
+ margin: 7px 0 5px 0;
+}
+
+.footnote,
+.footnote a {
+ font:12px/1.4em "Helvetica Neue", Helvetica, "Lucida Grande", Verdana, Arial, Clean, Sans, sans-serif;
+ color:#aaa;
+}
+
+.footnote em {
+ background-color:transparent;
+ font-style:italic;
+}
+</style>
+
+</head>
+
+<body>
+
+<div id="site">
+ <div id="content">
+
+ <div class="chunk">
+ <h2 style="text-align:center;"><img src="<?php echo pathinfo(__FILE__, PATHINFO_BASENAME); ?>?logopng" alt="SDK Compatibility Test" title="SDK Compatibility Test" /></h2>
+
+ <h3>Minimum Requirements</h3>
+ <table cellpadding="0" cellspacing="0" border="0" width="100%" class="chart">
+ <thead>
+ <tr>
+ <th>Test</th>
+ <th>Should Be</th>
+ <th>What You Have</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="<?php echo ($php_ok) ? 'enabled' : 'disabled'; ?>">
+ <td>PHP</td>
+ <td>5.2 or newer</td>
+ <td><?php echo phpversion(); ?></td>
+ </tr>
+ <tr class="<?php echo ($curl_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/curl">cURL</a></td>
+ <td>7.15.0 or newer, with SSL</td>
+ <td><?php echo ($curl_ok) ? ($curl_version['version'] . ' (' . $curl_version['ssl_version'] . ')') : ($curl_version['version'] . (in_array('https', $curl_version['protocols'], true) ? ' (with ' . $curl_version['ssl_version'] . ')' : ' (without SSL)')); ?></td>
+ </tr>
+ <tr class="<?php echo ($simplexml_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/simplexml">SimpleXML</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($simplexml_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($dom_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/dom">DOM</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($dom_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($spl_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/spl">SPL</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($spl_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($json_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/json">JSON</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($json_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($pcre_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/pcre">PCRE</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($pcre_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($file_ok) ? 'enabled' : 'disabled'; ?>">
+ <td>File System <a href="http://php.net/file_get_contents">Read</a>/<a href="http://php.net/file_put_contents">Write</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($file_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>Optional Extensions</h3>
+ <table cellpadding="0" cellspacing="0" border="0" width="100%" class="chart">
+ <thead>
+ <tr>
+ <th>Test</th>
+ <th>Would Like To Be</th>
+ <th>What You Have</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="<?php echo ($openssl_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/openssl">OpenSSL</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($openssl_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($zlib_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/zlib">Zlib</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($zlib_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($apc_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/apc">APC</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($apc_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($xcache_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://xcache.lighttpd.net">XCache</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($xcache_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($memcache_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/memcache">Memcache</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($memcache_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($memcached_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/memcached">Memcached</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($memcached_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($pdo_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/pdo">PDO</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($pdo_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($pdo_sqlite_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/pdo-sqlite">PDO-SQLite</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($pdo_sqlite_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($sqlite2_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/sqlite">SQLite 2</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($sqlite2_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($sqlite3_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/sqlite3">SQLite 3</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($sqlite3_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>Settings for php.ini</h3>
+ <table cellpadding="0" cellspacing="0" border="0" width="100%" class="chart">
+ <thead>
+ <tr>
+ <th>Test</th>
+ <th>Would Like To Be</th>
+ <th>What You Have</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="<?php echo (!$ini_open_basedir) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/open_basedir">open_basedir</a></td>
+ <td>off</td>
+ <td><?php echo ($ini_open_basedir) ? 'on' : 'off'; ?></td>
+ </tr>
+ <tr class="<?php echo (!$ini_safe_mode) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/safe_mode">safe_mode</a></td>
+ <td>off</td>
+ <td><?php echo ($ini_safe_mode) ? 'on' : 'off'; ?></td>
+ </tr>
+ <tr class="<?php echo ($ini_zend_enable_gc) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/zend.enable_gc">zend.enable_gc</a></td>
+ <td>on</td>
+ <td><?php echo ($ini_zend_enable_gc) ? 'on' : 'off'; ?></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>Other</h3>
+ <table cellpadding="0" cellspacing="0" border="0" width="100%" class="chart">
+ <thead>
+ <tr>
+ <th>Test</th>
+ <th>Would Like To Be</th>
+ <th>What You Have</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="<?php echo ($int64_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="https://aws.amazon.com/amis/4158">Architecture</a></td>
+ <td>64-bit</td>
+ <td><?php echo ($int64_ok) ? '64-bit' : '32-bit'; ?><?php if (is_windows()): ?>
+ (<a href="#win64">why?</a>)
+ <?php endif; ?></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <br>
+ </div>
+
+ <?php if ($compatiblity == REQUIREMENTS_ALL_MET): ?>
+ <div class="chunk important ok">
+ <h3>Bottom Line: Yes, you can!</h3>
+ <p>Your PHP environment is ready to go, and can take advantage of all possible features!</p>
+ </div>
+ <div class="chunk">
+ <h3>What's Next?</h3>
+ <p>You can download the latest version of the <a href="http://aws.amazon.com/sdkforphp"><strong>AWS SDK for PHP</strong></a> and install it by <a href="http://aws.amazon.com/articles/4261">following the instructions</a>. Also, check out our library of <a href="http://aws.amazon.com/articles/4262">screencasts and tutorials</a>.</p>
+ <p>Take the time to read <a href="http://aws.amazon.com/articles/4261">"Getting Started"</a> to make sure you're prepared to use the AWS SDK for PHP. No seriously, read it.</p>
+ </div>
+ <?php elseif ($compatiblity == REQUIREMENTS_MIN_MET): ?>
+ <div class="chunk important ok">
+ <h3>Bottom Line: Yes, you can!</h3>
+ <p>Your PHP environment is ready to go! <i>There are a couple of minor features that you won't be able to take advantage of, but nothing that's a show-stopper.</i></p>
+ </div>
+ <div class="chunk">
+ <h3>What's Next?</h3>
+ <p>You can download the latest version of the <a href="http://aws.amazon.com/sdkforphp"><strong>AWS SDK for PHP</strong></a> and install it by <a href="http://aws.amazon.com/articles/4261">following the instructions</a>. Also, check out our library of <a href="http://aws.amazon.com/articles/4262">screencasts and tutorials</a>.</p>
+ <p>Take the time to read <a href="http://aws.amazon.com/articles/4261">"Getting Started"</a> to make sure you're prepared to use the AWS SDK for PHP. No seriously, read it.</p>
+ </div>
+ <?php else: ?>
+ <div class="chunk important error">
+ <h3>Bottom Line: We're sorry&hellip;</h3>
+ <p>Your PHP environment does not support the minimum requirements for the <strong>AWS SDK for PHP</strong>.</p>
+ </div>
+ <div class="chunk">
+ <h3>What's Next?</h3>
+ <p>If you're using a shared hosting plan, it may be a good idea to contact your web host and ask them to install a more recent version of PHP and relevant extensions.</p>
+ <p>If you have control over your PHP environment, we recommended that you upgrade your PHP environment. Check out the "Set Up Your Environment" section of the <a href="http://aws.amazon.com/articles/4261">Getting Started Guide</a> for more information.</p>
+ </div>
+ <?php endif; ?>
+
+ <?php if ($compatiblity >= REQUIREMENTS_MIN_MET): ?>
+ <div class="chunk">
+ <h3>Recommended settings for config.inc.php</h3>
+ <p>Based on your particular server configuration, the following settings are recommended.</p>
+ <br>
+ <table cellpadding="0" cellspacing="0" border="0" width="100%" class="chart">
+ <thead>
+ <tr>
+ <th>Configuration Setting</th>
+ <th>Recommended Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><code>default_cache_config</code></td>
+ <?php if ($apc_ok): ?>
+ <td><code>apc</code></td>
+ <?php elseif ($xcache_ok): ?>
+ <td><code>xcache</code></td>
+ <?php elseif ($file_ok): ?>
+ <td>Any valid, server-writable file system path</td>
+ <?php endif; ?>
+ </tr>
+ <tr>
+ <td><code>certificate_authority</code></td>
+ <?php if (is_windows()): ?>
+ <td id="ssl_check"><code>true</code></td>
+ <?php else: ?>
+ <td id="ssl_check"><img src="<?php echo pathinfo(__FILE__, PATHINFO_BASENAME); ?>?loader" alt="Loading..."></td>
+ <?php endif; ?>
+ </tr>
+ </tbody>
+ </table>
+ <br>
+ </div>
+ <?php endif; ?>
+
+ <div class="chunk">
+ <h3>Give me the details!</h3>
+ <?php if ($compatiblity >= REQUIREMENTS_MIN_MET): ?>
+ <ol>
+ <li><em>Your environment meets the minimum requirements for using the <strong>AWS SDK for PHP</strong>!</em></li>
+
+ <?php if (version_compare(PHP_VERSION, '5.3.0') < 0): ?>
+ <li>You're still running <strong>PHP <?php echo PHP_VERSION; ?></strong>. The PHP 5.2 family is no longer supported by the PHP team, and future versions of the AWS SDK for PHP will <i>require</i> PHP 5.3 or newer.</li>
+ <?php endif; ?>
+
+ <?php if ($openssl_ok): ?>
+ <li>The <a href="http://php.net/openssl">OpenSSL</a> extension is installed. This will allow you to use <a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html">CloudFront Private URLs</a> and decrypt Microsoft&reg; Windows&reg; instance passwords.</li>
+ <?php endif; ?>
+
+ <?php if ($zlib_ok): ?>
+ <li>The <a href="http://php.net/zlib">Zlib</a> extension is installed. The SDK will request gzipped data whenever possible.</li>
+ <?php endif; ?>
+
+ <?php if (!$int64_ok): ?>
+ <li>You're running on a <strong>32-bit</strong> system. This means that PHP does not correctly handle files larger than 2GB (this is a <a href="http://www.google.com/search?q=php+2gb+32-bit">well-known PHP issue</a>). For more information, please see: <a href="http://docs.php.net/manual/en/function.filesize.php#refsect1-function.filesize-returnvalues">PHP filesize: Return values</a>.</li>
+ <?php if (is_windows()): ?>
+ <li id="win64"><em>Note that PHP on Microsoft® Windows® <a href="http://j.mp/php64win">does not support 64-bit integers at all</a>, even if both the hardware and PHP are 64-bit.</em></li>
+ <?php endif; ?>
+ <?php endif; ?>
+
+ <?php if ($ini_open_basedir || $ini_safe_mode): ?>
+ <li>You have <a href="http://php.net/open_basedir">open_basedir</a> or <a href="http://php.net/safe_mode">safe_mode</a> enabled in your <code>php.ini</code> file. Sometimes PHP behaves strangely when these settings are enabled. Disable them if you can.</li>
+ <?php endif; ?>
+
+ <?php if (!$ini_zend_enable_gc): ?>
+ <li>The PHP garbage collector (available in PHP 5.3+) is not enabled in your <code>php.ini</code> file. Enabling <a href="http://php.net/zend.enable_gc">zend.enable_gc</a> will provide better memory management in the PHP core.</li>
+ <?php endif; ?>
+
+ <?php
+ $storage_types = array();
+ if ($file_ok) { $storage_types[] = '<a href="http://php.net/file_put_contents">The file system</a>'; }
+ if ($apc_ok) { $storage_types[] = '<a href="http://php.net/apc">APC</a>'; }
+ if ($xcache_ok) { $storage_types[] = '<a href="http://xcache.lighttpd.net">XCache</a>'; }
+ if ($sqlite_ok && $sqlite3_ok) { $storage_types[] = '<a href="http://php.net/sqlite3">SQLite 3</a>'; }
+ elseif ($sqlite_ok && $sqlite2_ok) { $storage_types[] = '<a href="http://php.net/sqlite">SQLite 2</a>'; }
+ if ($memcached_ok) { $storage_types[] = '<a href="http://php.net/memcached">Memcached</a>'; }
+ elseif ($memcache_ok) { $storage_types[] = '<a href="http://php.net/memcache">Memcache</a>'; }
+ ?>
+ <li>Storage types available for response caching: <?php echo implode(', ', $storage_types); ?></li>
+ </ol>
+
+ <?php if (!$openssl_ok && !$zlib_ok): ?>
+ <p class="footnote"><strong>NOTE:</strong> You're missing the <a href="http://php.net/openssl">OpenSSL</a> extension, which means that you won't be able to take advantage of <a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html">CloudFront Private URLs</a> or decrypt Microsoft&reg; Windows&reg; instance passwords. You're also missing the <a href="http://php.net/zlib">Zlib</a> extension, which means that the SDK will be unable to request gzipped data from Amazon and you won't be able to take advantage of compression with the <i>response caching</i> feature.</p>
+ <?php elseif (!$zlib_ok): ?>
+ <p class="footnote"><strong>NOTE:</strong> You're missing the <a href="http://php.net/zlib">Zlib</a> extension, which means that the SDK will be unable to request gzipped data from Amazon and you won't be able to take advantage of compression with the <i>response caching</i> feature.</p>
+ <?php elseif (!$openssl_ok): ?>
+ <p class="footnote"><strong>NOTE:</strong> You're missing the <a href="http://php.net/openssl">OpenSSL</a> extension, which means that you won't be able to take advantage of <a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html">CloudFront Private URLs</a> or decrypt Microsoft&reg; Windows&reg; instance passwords.</p>
+ <?php endif; ?>
+
+ <?php else: ?>
+ <ol>
+ <?php if (!$php_ok): ?>
+ <li><strong>PHP:</strong> You are running an unsupported version of PHP.</li>
+ <?php endif; ?>
+
+ <?php if (!$curl_ok): ?>
+ <li><strong>cURL:</strong> The <a href="http://php.net/curl">cURL</a> extension is not available. Without cURL, the SDK cannot connect to &mdash; or authenticate with &mdash; Amazon's services.</li>
+ <?php endif; ?>
+
+ <?php if (!$simplexml_ok): ?>
+ <li><strong>SimpleXML:</strong> The <a href="http://php.net/simplexml">SimpleXML</a> extension is not available. Without SimpleXML, the SDK cannot parse the XML responses from Amazon's services.</li>
+ <?php endif; ?>
+
+ <?php if (!$dom_ok): ?>
+ <li><strong>DOM:</strong> The <a href="http://php.net/dom">DOM</a> extension is not available. Without DOM, the SDK cannot transliterate JSON responses from Amazon's services into the common SimpleXML-based pattern used throughout the SDK.</li>
+ <?php endif; ?>
+
+ <?php if (!$spl_ok): ?>
+ <li><strong>SPL:</strong> <a href="http://php.net/spl">Standard PHP Library</a> support is not available. Without SPL support, the SDK cannot autoload the required PHP classes.</li>
+ <?php endif; ?>
+
+ <?php if (!$json_ok): ?>
+ <li><strong>JSON:</strong> <a href="http://php.net/json">JSON</a> support is not available. AWS leverages JSON heavily in many of its services.</li>
+ <?php endif; ?>
+
+ <?php if (!$pcre_ok): ?>
+ <li><strong>PCRE:</strong> Your PHP installation doesn't support Perl-Compatible Regular Expressions (PCRE). Without PCRE, the SDK cannot do any filtering via regular expressions.</li>
+ <?php endif; ?>
+
+ <?php if (!$file_ok): ?>
+ <li><strong>File System Read/Write:</strong> The <a href="http://php.net/file_get_contents">file_get_contents()</a> and/or <a href="http://php.net/file_put_contents">file_put_contents()</a> functions have been disabled. Without them, the SDK cannot read from, or write to, the file system.</li>
+ <?php endif; ?>
+ </ol>
+ <?php endif; ?>
+ </div>
+
+ <div class="chunk">
+ <p class="footnote"><strong>NOTE</strong>: Passing this test does not guarantee that the AWS SDK for PHP will run on your web server &mdash; it only ensures that the requirements have been addressed.</p>
+ </div>
+ </div>
+
+</div>
+
+<?php if (!is_windows()): ?>
+<script type="text/javascript" charset="utf-8">
+reqwest('<?php echo pathinfo(__FILE__, PATHINFO_BASENAME); ?>?ssl_check', function(resp) {
+ $sslCheck = document.getElementById('ssl_check');
+ $sslCheck.innerHTML = '';
+ $sslCheck.innerHTML = '<code>' + resp + '</code>';
+});
+</script>
+<?php endif; ?>
+
+</body>
+</html>
diff --git a/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test_cli.php b/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test_cli.php
new file mode 100755
index 00000000000..a6632d89787
--- /dev/null
+++ b/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test_cli.php
@@ -0,0 +1,186 @@
+#! /usr/bin/env php
+<?php
+
+//Prevent script from being called via browser
+if (PHP_SAPI !== 'cli')
+{
+ die('ERROR: You may only run the compatibility test from the command line.');
+}
+
+// Include the compatibility test logic
+require dirname(__FILE__) . DIRECTORY_SEPARATOR . 'sdk_compatibility.inc.php';
+
+// CLI display
+function success($s = 'Yes')
+{
+ return is_windows() ? $s : "\033[1;37m\033[42m " . $s . " \033[0m";
+}
+
+function info($s = 'Info')
+{
+ return is_windows() ? $s : "\033[1;37m\033[44m " . $s . " \033[0m";
+}
+
+function failure($s = 'No ')
+{
+ return is_windows() ? $s : "\033[1;37m\033[41m " . $s . " \033[0m";
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+echo PHP_EOL;
+
+echo info('AWS SDK for PHP') . PHP_EOL;
+echo 'PHP Environment Compatibility Test (CLI)' . PHP_EOL;
+echo '----------------------------------------' . PHP_EOL;
+echo PHP_EOL;
+
+echo 'PHP 5.2 or newer............ ' . ($php_ok ? (success() . ' ' . phpversion()) : failure()) . PHP_EOL;
+echo '64-bit architecture......... ' . ($int64_ok ? success() : failure()) . (is_windows() ? ' (see note below)' : '') . PHP_EOL;
+echo 'cURL with SSL............... ' . ($curl_ok ? (success() . ' ' . $curl_version['version'] . ' (' . $curl_version['ssl_version'] . ')') : failure($curl_version['version'] . (in_array('https', $curl_version['protocols'], true) ? ' (with ' . $curl_version['ssl_version'] . ')' : ' (without SSL)'))) . PHP_EOL;
+echo 'Standard PHP Library........ ' . ($spl_ok ? success() : failure()) . PHP_EOL;
+echo 'SimpleXML................... ' . ($simplexml_ok ? success() : failure()) . PHP_EOL;
+echo 'DOM......................... ' . ($dom_ok ? success() : failure()) . PHP_EOL;
+echo 'JSON........................ ' . ($json_ok ? success() : failure()) . PHP_EOL;
+echo 'PCRE........................ ' . ($pcre_ok ? success() : failure()) . PHP_EOL;
+echo 'File system read/write...... ' . ($file_ok ? success() : failure()) . PHP_EOL;
+echo 'OpenSSL extension........... ' . ($openssl_ok ? success() : failure()) . PHP_EOL;
+echo 'Zlib........................ ' . ($zlib_ok ? success() : failure()) . PHP_EOL;
+echo 'APC......................... ' . ($apc_ok ? success() : failure()) . PHP_EOL;
+echo 'XCache...................... ' . ($xcache_ok ? success() : failure()) . PHP_EOL;
+echo 'Memcache.................... ' . ($memcache_ok ? success() : failure()) . PHP_EOL;
+echo 'Memcached................... ' . ($memcached_ok ? success() : failure()) . PHP_EOL;
+echo 'PDO......................... ' . ($pdo_ok ? success() : failure()) . PHP_EOL;
+echo 'SQLite 2.................... ' . ($sqlite2_ok ? success() : failure()) . PHP_EOL;
+echo 'SQLite 3.................... ' . ($sqlite3_ok ? success() : failure()) . PHP_EOL;
+echo 'PDO-SQLite driver........... ' . ($pdo_sqlite_ok ? success() : failure()) . PHP_EOL;
+echo 'open_basedir disabled....... ' . (!$ini_open_basedir ? success() : failure()) . PHP_EOL;
+echo 'safe_mode disabled.......... ' . (!$ini_safe_mode ? success() : failure()) . PHP_EOL;
+echo 'Garbage Collector enabled... ' . ($ini_zend_enable_gc ? success() : failure()) . PHP_EOL;
+
+// Test SSL cert
+if (!is_windows())
+{
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, 'https://email.us-east-1.amazonaws.com');
+ curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
+ curl_setopt($ch, CURLOPT_HEADER, false);
+ curl_setopt($ch, CURLOPT_NOBODY, true);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 5184000);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 120);
+ curl_setopt($ch, CURLOPT_NOSIGNAL, true);
+ curl_setopt($ch, CURLOPT_USERAGENT, 'aws-sdk-php/compat-cli');
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
+ curl_setopt($ch, CURLOPT_VERBOSE, false);
+ curl_exec($ch);
+ $ssl_result = !(curl_getinfo($ch, CURLINFO_SSL_VERIFYRESULT) === 0);
+ curl_close($ch);
+
+ echo 'Valid SSL certificate....... ' . ($ssl_result ? failure() : success()) . PHP_EOL;
+}
+else
+{
+ $ssl_result = false;
+ echo 'Valid SSL certificate....... ' . failure() . ' (will use the bundled certificate instead)' . PHP_EOL;
+}
+
+echo PHP_EOL;
+
+echo '----------------------------------------' . PHP_EOL;
+echo PHP_EOL;
+
+if ($compatiblity >= REQUIREMENTS_MIN_MET)
+{
+ echo success('Your environment meets the minimum requirements for using the AWS SDK for PHP!') . PHP_EOL . PHP_EOL;
+ if (version_compare(PHP_VERSION, '5.3.0') < 0) { echo '* You\'re still running PHP ' . PHP_VERSION . '. The PHP 5.2 family is no longer supported' . PHP_EOL . ' by the PHP team, and future versions of the AWS SDK for PHP will *require*' . PHP_EOL . ' PHP 5.3 or newer.' . PHP_EOL . PHP_EOL; }
+ if ($openssl_ok) { echo '* The OpenSSL extension is installed. This will allow you to use CloudFront' . PHP_EOL . ' Private URLs and decrypt Windows instance passwords.' . PHP_EOL . PHP_EOL; }
+ if ($zlib_ok) { echo '* The Zlib extension is installed. The SDK will request gzipped data' . PHP_EOL . ' whenever possible.' . PHP_EOL . PHP_EOL; }
+ if (!$int64_ok) { echo '* You\'re running on a 32-bit system. This means that PHP does not correctly' . PHP_EOL . ' handle files larger than 2GB (this is a well-known PHP issue).' . PHP_EOL . PHP_EOL; }
+ if (!$int64_ok && is_windows()) { echo '* Note that PHP on Microsoft(R) Windows(R) does not support 64-bit integers' . PHP_EOL . ' at all, even if both the hardware and PHP are 64-bit. http://j.mp/php64win' . PHP_EOL . PHP_EOL; }
+
+ if ($ini_open_basedir || $ini_safe_mode) { echo '* You have open_basedir or safe_mode enabled in your php.ini file. Sometimes' . PHP_EOL . ' PHP behaves strangely when these settings are enabled. Disable them if you can.' . PHP_EOL . PHP_EOL; }
+ if (!$ini_zend_enable_gc) { echo '* The PHP garbage collector (available in PHP 5.3+) is not enabled in your' . PHP_EOL . ' php.ini file. Enabling zend.enable_gc will provide better memory management' . PHP_EOL . ' in the PHP core.' . PHP_EOL . PHP_EOL; }
+
+ $storage_types = array();
+ if ($file_ok) { $storage_types[] = 'The file system'; }
+ if ($apc_ok) { $storage_types[] = 'APC'; }
+ if ($xcache_ok) { $storage_types[] = 'XCache'; }
+ if ($sqlite_ok && $sqlite3_ok) { $storage_types[] = 'SQLite 3'; }
+ elseif ($sqlite_ok && $sqlite2_ok) { $storage_types[] = 'SQLite 2'; }
+ if ($memcached_ok) { $storage_types[] = 'Memcached'; }
+ elseif ($memcache_ok) { $storage_types[] = 'Memcache'; }
+ echo '* Storage types available for response caching:' . PHP_EOL . ' ' . implode(', ', $storage_types) . PHP_EOL . PHP_EOL;
+
+ if (!$openssl_ok) { echo '* You\'re missing the OpenSSL extension, which means that you won\'t be able' . PHP_EOL . ' to take advantage of CloudFront Private URLs or Windows password decryption.' . PHP_EOL . PHP_EOL; }
+ if (!$zlib_ok) { echo '* You\'re missing the Zlib extension, which means that the SDK will be unable' . PHP_EOL . ' to request gzipped data from Amazon and you won\'t be able to take advantage' . PHP_EOL . ' of compression with the response caching feature.' . PHP_EOL . PHP_EOL; }
+}
+else
+{
+ if (!$php_ok) { echo '* ' . failure('PHP:') . ' You are running an unsupported version of PHP.' . PHP_EOL . PHP_EOL; }
+ if (!$curl_ok) { echo '* ' . failure('cURL:') . ' The cURL extension is not available. Without cURL, the SDK cannot' . PHP_EOL . ' connect to -- or authenticate with -- Amazon\'s services.' . PHP_EOL . PHP_EOL; }
+ if (!$simplexml_ok) { echo '* ' . failure('SimpleXML:') . ': The SimpleXML extension is not available. Without SimpleXML,' . PHP_EOL . ' the SDK cannot parse the XML responses from Amazon\'s services.' . PHP_EOL . PHP_EOL; }
+ if (!$dom_ok) { echo '* ' . failure('DOM:') . ': The DOM extension is not available. Without DOM, the SDK' . PHP_EOL . ' Without DOM, the SDK cannot transliterate JSON responses from Amazon\'s' . PHP_EOL . ' services into the common SimpleXML-based pattern used throughout the SDK.' . PHP_EOL . PHP_EOL; }
+ if (!$spl_ok) { echo '* ' . failure('SPL:') . ' Standard PHP Library support is not available. Without SPL support,' . PHP_EOL . ' the SDK cannot autoload the required PHP classes.' . PHP_EOL . PHP_EOL; }
+ if (!$json_ok) { echo '* ' . failure('JSON:') . ' JSON support is not available. AWS leverages JSON heavily in many' . PHP_EOL . ' of its services.' . PHP_EOL . PHP_EOL; }
+ if (!$pcre_ok) { echo '* ' . failure('PCRE:') . ' Your PHP installation doesn\'t support Perl-Compatible Regular' . PHP_EOL . ' Expressions (PCRE). Without PCRE, the SDK cannot do any filtering via' . PHP_EOL . ' regular expressions.' . PHP_EOL . PHP_EOL; }
+ if (!$file_ok) { echo '* ' . failure('File System Read/Write:') . ' The file_get_contents() and/or file_put_contents()' . PHP_EOL . ' functions have been disabled. Without them, the SDK cannot read from,' . PHP_EOL . ' or write to, the file system.' . PHP_EOL . PHP_EOL; }
+}
+
+echo '----------------------------------------' . PHP_EOL;
+echo PHP_EOL;
+
+if ($compatiblity === REQUIREMENTS_ALL_MET)
+{
+ echo success('Bottom Line: Yes, you can!') . PHP_EOL;
+ echo PHP_EOL;
+ echo 'Your PHP environment is ready to go, and can take advantage of all possible features!' . PHP_EOL;
+
+ echo PHP_EOL;
+ echo info('Recommended settings for config.inc.php') . PHP_EOL;
+ echo PHP_EOL;
+
+ echo "CFCredentials::set(array(" . PHP_EOL;
+ echo " '@default' => array(" . PHP_EOL;
+ echo " 'key' => 'aws-key'," . PHP_EOL;
+ echo " 'secret' => 'aws-secret'," . PHP_EOL;
+ echo " 'default_cache_config' => ";
+ if ($apc_ok) echo success('\'apc\'');
+ elseif ($xcache_ok) echo success('\'xcache\'');
+ elseif ($file_ok) echo success('\'/path/to/cache/folder\'');
+ echo "," . PHP_EOL;
+ echo " 'certificate_authority' => " . success($ssl_result ? 'true' : 'false') . PHP_EOL;
+ echo " )" . PHP_EOL;
+ echo "));" . PHP_EOL;
+}
+elseif ($compatiblity === REQUIREMENTS_MIN_MET)
+{
+ echo success('Bottom Line: Yes, you can!') . PHP_EOL;
+ echo PHP_EOL;
+ echo 'Your PHP environment is ready to go! There are a couple of minor features that' . PHP_EOL . 'you won\'t be able to take advantage of, but nothing that\'s a show-stopper.' . PHP_EOL;
+
+ echo PHP_EOL;
+ echo info('Recommended settings for config.inc.php') . PHP_EOL;
+ echo PHP_EOL;
+
+ echo "CFCredentials::set(array(" . PHP_EOL;
+ echo " '@default' => array(" . PHP_EOL;
+ echo " 'key' => 'aws-key'," . PHP_EOL;
+ echo " 'secret' => 'aws-secret'," . PHP_EOL;
+ echo " 'default_cache_config' => ";
+ if ($apc_ok) echo success('\'apc\'');
+ elseif ($xcache_ok) echo success('\'xcache\'');
+ elseif ($file_ok) echo success('\'/path/to/cache/folder\'');
+ echo "," . PHP_EOL;
+ echo " 'certificate_authority' => " . ($ssl_result ? 'false' : 'true') . PHP_EOL;
+ echo " )" . PHP_EOL;
+ echo "));" . PHP_EOL;
+}
+else
+{
+ echo failure('Bottom Line: We\'re sorry...') . PHP_EOL;
+ echo 'Your PHP environment does not support the minimum requirements for the ' . PHP_EOL . 'AWS SDK for PHP.' . PHP_EOL;
+}
+
+echo PHP_EOL;
diff --git a/3rdparty/aws-sdk/_docs/CHANGELOG.md b/3rdparty/aws-sdk/_docs/CHANGELOG.md
new file mode 100644
index 00000000000..52db66f4f6f
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/CHANGELOG.md
@@ -0,0 +1,1405 @@
+# Changelog: 1.5.6.2 "Gershwin"
+Code name for Apple's never-released successor to the never-released Copeland. <http://en.wikipedia.org/wiki/Gershwin_operating_system>
+
+Launched Tuesday, May 29th, 2012.
+
+## Services
+### AmazonDynamoDB
+- **Fixed:** STS credentials were not always being cached correctly.
+
+----
+
+# Changelog: 1.5.6.1 "Gershwin"
+Code name for Apple's never-released successor to the never-released Copeland. <http://en.wikipedia.org/wiki/Gershwin_operating_system>
+
+Launched Tuesday, May 24th, 2012.
+
+## Services
+### AmazonDynamoDB
+- **Fixed:** STS credentials were not always being cached correctly.
+
+----
+
+# Changelog: 1.5.6 "Gershwin"
+Code name for Apple's never-released successor to the never-released Copeland. <http://en.wikipedia.org/wiki/Gershwin_operating_system>
+
+Launched Tuesday, May 15th, 2012.
+
+## Services
+### AmazonSES
+- **New:** Support for domain verification has been added to the SDK, which enables customers to verify an entire email domain.
+- **New:** Requests to this service are now signed with Signature V4.
+
+----
+
+# Changelog: 1.5.5 "Fishhead"
+Code name for the Apple II File Mangement Utility. <http://applemuseum.bott.org/sections/codenames.html>
+
+Launched Wednesday, May 9, 2012.
+
+## Services
+### AmazonCloudFormation
+* **New:** Requests to this service are now signed with Signature V4.
+
+### AmazonCloudFront
+* **New:** Updated the supported API version to `2012-03-15`.
+
+### AmazonDynamoDB
+* **New:** Support for the US West (Northern California), US West (Oregon), Asia Pacific "Southeast" (Signapore) endpoints have been added.
+
+### AmazonElasticBeanstalk
+* **New:** Support for the new Asia Pacific "Northeast" (Japan) endpoint has been added.
+
+### AmazonStorageGateway
+* **New:** Support for the AWS Storage Gateway service has been added to the SDK.
+
+---
+
+# Changelog: 1.5.4 "Enterprise"
+Code name for Mac OS X Server 1.0 (Rhapsody CR1). <http://en.wikipedia.org/wiki/Rhapsody_(operating_system)>
+
+Launched Thursday, April 19, 2012.
+
+## Bug fixes and enhancements
+* [PHP SDK Bug - Memory leak](https://forums.aws.amazon.com/thread.jspa?threadID=72310)
+* [Does update_object work in 1.5.3?](https://forums.aws.amazon.com/thread.jspa?threadID=89297)
+* [The value of CURLOPT_SSL_VERIFYHOST](https://forums.aws.amazon.com/thread.jspa?threadID=86186)
+* [PHP SDK BUG: s3.class.php Line 2396 on 1.5.2](https://forums.aws.amazon.com/thread.jspa?threadID=86779)
+* [first create_bucket(), then get_bucket_list()](https://forums.aws.amazon.com/thread.jspa?messageID=318885)
+* [Issue with AmazonS3::get_object_list() max-keys](https://forums.aws.amazon.com/thread.jspa?threadID=85878)
+* [Correct the "Bottom line" minimum requirements check](https://github.com/amazonwebservices/aws-sdk-for-php/pull/23)
+* [S3 PHP SDK: copy_object() fails to update the header](http://stackoverflow.com/questions/7677837/s3-php-sdk-copy-object-fails-to-update-the-header)
+* [Adds the following utility methods to simplexml.class.php](https://github.com/amazonwebservices/aws-sdk-for-php/pull/22)
+* [Adding the ability to name a 'rule' for Object Expiration (suggested tweak)](https://forums.aws.amazon.com/thread.jspa?messageID=328023)
+
+## Runtime
+* **New:** Support for Signature Version 4 has been added to the SDK. Signature Version 4 is now the default authentication method for AWS Identity and Access Management, AWS Security Token Service and Amazon CloudSearch.
+
+## Services
+### AmazonCloudFront
+* **New:** Support for a Minimum TTL of zero has been added to the SDK.
+
+### AmazonCloudSearch
+* **New:** Support for Amazon CloudSearch has been added to the SDK. This includes only the Configuration API.
+
+### AmazonDynamoDB
+* **New:** Support for BatchWriteItem API has been added to the SDK.
+* **New:** Support for the European (Ireland) endpoint has been added.
+* **New:** Support for the Asia Pacific "Northeast" (Tokyo) endpoint has been added.
+* **New:** Amazon DynamoDB Session Handler has been added to the SDK.
+* **New:** A simplified interface for adding attributes has been added to the SDK.
+
+### AmazonEC2
+* **New:** The new "m1.medium" instance type is now supported.
+* **New:** Amazon EBS support for Volume Status and Volume Attributes have been added to the SDK.
+* **New:** Amazon EBS support for Conversion Tasks has been added to the SDK.
+* **New:** Amazon EC2 support for the Report Instance Status feature has been added to the SDK.
+* **New:** Amazon VPC support for Network Interfaces has been added to the SDK.
+* **Fixed:** Various parameter fixes have been applied.
+
+### AmazonIAM
+* **New:** Support for Password Policies and the ability to change passwords has been added to the SDK.
+
+### AmazonS3
+* **New:** Support for pre-signed URLs using temporary credentials has been added to the SDK.
+* **New:** Support for setting a custom name to Lifecycle (i.e., Object Expiration) rules has been added to the SDK.
+* **New:** Support for pre-signed URLs with https has been added to the SDK.
+* **Fixed:** Resolved an issue where setting a custom XML parsing class was not being respected.
+* **Fixed:** Resolved an issue where the `get_object_list()` method would return an incorrect number of entries.
+* **Fixed:** Resolved an issue where `update_object()` was attempting to COPY instead of REPLACE.
+* **Fixed:** Resolved an issue stemming from using path-style URLs, `create_bucket()` + `list_bucket()` and the EU-West region.
+* **Fixed:** Resolved an issue where XML responses were not being parsed consistently.
+* **Fixed:** Resolved an issue where Private Streaming URLs contained a double-encoded signature.
+* **Fixed:** The `Expect: 100-continue` HTTP header is now only sent during `create_object()` and `upload_part()` requests.
+
+## Utilities
+### CFRuntime
+* **Fixed:** Resolved an issue where `CURLOPT_SSL_VERIFYHOST` was not set strictly enough.
+* **Fixed:** The `Expect: 100-continue` HTTP header is no longer set on every request.
+
+### CFSimpleXML
+* **New:** Support for `matches()`, `starts_with()` and `ends_with()` methods have been added to the SDK. (Thanks [Wil Moore III](https://github.com/wilmoore)!)
+
+## Compatibility Test
+* **New:** SDK Compatibility Test pages are marked up as to not be indexed by search engines. (Thanks [Eric Caron](http://www.ericcaron.com)!)
+* **Fixed:** Duplicate code between the CLI and web versions of the SDK has been refactored. (Thanks [Jimmy Berry](https://github.com/boombatower)!)
+
+---
+
+# Changelog: 1.5.3 "Darwin"
+UNIX foundation upon which Mac OS X, Apple TV, and iOS are based. <http://en.wikipedia.org/wiki/Darwin_operating_system>
+
+Launched Wednesday, Tuesday, February 21, 2012.
+
+## Bug fixes and enhancements
+* [Fixing Issue with set_distribution_config](https://github.com/amazonwebservices/aws-sdk-for-php/pull/20)
+
+## Services
+### AmazonCloudFront
+* **Fixed:** Resolved an issue where the `set_distribution_config()` method could fail to satisfy an API constraint when using a custom origin server. (Thanks [zoxa](https://github.com/zoxa)!)
+
+### AmazonSWF
+* **New:** Support for the new Amazon Simple Workflow Service has been added to the SDK.
+
+----
+
+# Changelog: 1.5.2 "Copland"
+Code name for Apple's never-released successor to System 7. <http://en.wikipedia.org/wiki/Copland_(operating_system)>
+
+Launched Wednesday, Febraury 1, 2012.
+
+## Bug fixes and enhancements
+* [SSL Cert on PHP SDK 1.5.0.1 ](https://forums.aws.amazon.com/thread.jspa?threadID=84947)
+* [Stream Wrapper need a buffer !](https://forums.aws.amazon.com/thread.jspa?threadID=85436)
+* [Fixing Issue with set_distribution_config](https://github.com/amazonwebservices/aws-sdk-for-php/pull/20)
+* [[Bug] SDK Autoloader Interferes with PHPExcel Autoloader](https://forums.aws.amazon.com/thread.jspa?threadID=85239)
+* [get_object query does not always return the same content type](https://forums.aws.amazon.com/thread.jspa?threadID=84148)
+* [AWSSDKforPHP/authentication/swift_transport_esmtp_signature_handler.class.p ](https://forums.aws.amazon.com/thread.jspa?threadID=85087)
+
+## Runtime
+* **New:** Updated the CA Root Certificates file to version 1.81.
+* **Fixed:** Resolved an issue in the autoloader where the matching logic was too aggressive in certain cases, causing subsequent autoloaders to never trigger.
+
+## Services
+### AmazonAS
+* **New:** Support for Auto Scaling Resource Tagging has been added to the SDK.
+
+### AmazonS3
+* **Fixed:** Resolved an issue where `delete_all_objects()` and `delete_all_object_versions()` was being limited to 1000 items.
+* **Fixed:** Resolved an issue where `delete_bucket()` would fail to delete a bucket with the "force" option enabled if the bucket contained more than 1000 items.
+* **Fixed:** Resolved an issue where JSON documents stored in Amazon S3 would be parsed into a native PHP object when retrieved.
+
+## Utilities
+### S3StreamWrapper
+* **New:** Support for multiple stream wrappers (e.g., one per region) has been added to the SDK.
+* **Fixed:** Writes to Amazon S3 are now buffered, resolving issues with pushing more than 8k of data at a time.
+
+### CFJSON
+* **Fixed:** The JSON-to-XML conversion code is now substantially more robust and better handles encoded characters.
+
+### CacheCore
+* **Changed:** Formerly, attempting to cache to a file system location that didn't exist or was not writable by the PHP process would fail silently. This behavior has been changed to throw a `CacheFile_Exception`.
+
+----
+
+# Changelog: 1.5.1 "Blue"
+Code name for Macintosh System 7. <http://en.wikipedia.org/wiki/System_7>
+
+Launched Wednesday, January 18, 2012.
+
+## Bug fixes and enhancements
+* [Documentation patch](https://github.com/amazonwebservices/aws-sdk-for-php/pull/13)
+* [Removed duplicate comment line.](https://github.com/amazonwebservices/aws-sdk-for-php/pull/17)
+* [CFRuntime credentials handling issue](https://forums.aws.amazon.com/thread.jspa?messageID=310388)
+* [PHP 5.2 bug in AWS SDK for PHP 1.5.x](https://forums.aws.amazon.com/thread.jspa?messageID=311543)
+* [[Bug] Custom Curl Opts Lost During Retry](https://forums.aws.amazon.com/thread.jspa?threadID=84835)
+* [json_last_error doesn't exist before php v 5.3.0](https://github.com/amazonwebservices/aws-sdk-for-php/pull/12)
+* [XML still being parsed when use_cache_flow is false](https://github.com/amazonwebservices/aws-sdk-for-php/pull/15)
+* [Bug ssl_verification option not respected for AmazonS3 ](https://forums.aws.amazon.com/thread.jspa?threadID=83710)
+* [[Bug] Compatibility test for Garbage Collector enabled should use ini_get](https://forums.aws.amazon.com/thread.jspa?threadID=84156)
+
+## Runtime
+* **Fixed:** Corrected an issue where calling `AmazonS3->get_object()` would continue to parse the content if caching was being leveraged. (Thanks [Eric Caron](http://www.ericcaron.com)!)
+* **Fixed:** The autoloader now returns `false` for any class it doesn't match, allowing subsequent autoloaders to catch the class name. (Thanks [Eric Caron](http://www.ericcaron.com)!)
+* **Fixed:** An issue that caused CloudWatch to fail to decompress gzipped data correctly has been resolved.
+* **Fixed:** Resolved an issue with passing explicit credentials without requiring a config file or a `CFCredentials` declaration.
+* **Fixed:** Resolved an issue which causes custom cURL options to be unset from the payload when retrying.
+
+## Services
+### AmazonAS
+* **New:** Support for Amazon SNS notifications and Tagging have been added to the SDK.
+
+### AmazonCloudFront
+* **Fixed:** Resolved an issue with disabling SSL verification.
+* **Fixed:** Resolved an issue where `AmazonCloudFront` were throwing warnings in `E_STRICT` mode.
+
+### AmazonCloudWatch
+* **Fixed:** Resolved an issue with decompressing gzipped data.
+
+### AmazonDynamoDB
+* **New:** Support for Amazon DynamoDB has been added to the SDK.
+* **New:** Amazon DynamoDB requires a default cache configuration to be set in the credential set, otherwise it will not function properly.
+
+### AmazonS3
+* **Fixed:** Resolved an issue with disabling SSL verification.
+* **Fixed:** Resolved multiple documentation issues. (Thanks [Aizat Faiz](http://aizatto.com) and [Jason Ardell](http://ardell.posterous.com/)!)
+* **Fixed:** Resolved an issue where `AmazonS3` were throwing warnings in `E_STRICT` mode.
+
+### AmazonSNS
+* **New:** Support for Short Messaging Service (SMS) endpoints has been added to the SDK.
+* **New:** Support for Subscription Attributes has been added to the SDK.
+
+## Utilities
+### CFJSON
+* **Fixed:** Support for the handling of JSON nulls in PHP 5.2 has been improved. (Thanks [David Chan](http://www.chandeeland.org)!)
+
+## Compatibility Test
+* **Fixed:** The SDK compatibility test now uses `ini_get()` instead of `get_cfg_var()` and `get_cfg_ini()` for more accurate test results.
+
+
+----
+
+# Changelog: 1.5 "Allegro"
+Code name for Mac OS 8.5. <http://en.wikipedia.org/wiki/Mac_OS_8#Mac_OS_8.5>
+
+Launched Wednesday, December 14, 2011
+
+## Credentials
+* !! BACKWARDS-INCOMPATIBLE CHANGE !! - The function signature of all service constructors has changed. Instead of passing a key and secret as the first and second parameters, the constructor now accepts a hash (associative array) containing `key` and `secret` keys. Please see the API reference documentation
+
+## Runtime
+* !! BACKWARDS-INCOMPATIBLE CHANGE !! - The function signature of all service constructors has changed. Instead of passing a key and secret as the first and second parameters, the constructor now accepts a hash (associative array) containing `key` and `secret` keys. If you are explicitly passing a key and secret to the constructor, you will need to change your code. If you are simply inheriting your default credentials from a config file, you don't need to make any changes beyond upgrading your config file to the new 1.5 format. Please see the API reference documentation for more information.
+* !! BACKWARDS-INCOMPATIBLE CHANGE !! - The method by which the `config.inc.php` file maintains its list of credentials has been re-factored and updated to support managing multiple sets of credentials in a single location (e.g., development, staging, production).
+* !! BACKWARDS-INCOMPATIBLE CHANGE !! - The `init()` method has been renamed to `factory()` to better reflect what it actually does.
+* !! BACKWARDS-INCOMPATIBLE CHANGE !! - The `adjust_offset()` method has been removed. Instead, please ensure that the machine's time is set correctly using an [NTP server](https://secure.wikimedia.org/wikipedia/en/wiki/Network_Time_Protocol).
+* !! BACKWARDS-INCOMPATIBLE CHANGE !! - In version 1.4 we enabled a mode where -- for services that supported it -- a set of temporary credentials were fetched and cached before the first request. This functionality has been reverted. The use of short-term credentials must be explicitly enabled by instantiating the `AmazonSTS` class and passing those credentials into the service constructor.
+* **New:** Improved the user directory lookup for the config file.
+* **Changed:** Made `set_region()` an alias of `set_hostname()`.
+
+## Services
+### AmazonAS
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+
+### AmazonCloudFormation
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+* **New:** Support for cost estimation of CloudFormation templates has been added to the SDK.
+
+### AmazonCloudWatch
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+
+### AmazonEC2
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+* **New:** Support for 24x7 Reserved Instances has been added to the SDK. For more information, please see [New Amazon EC2 Reserved Instance Options Now Available](https://aws.amazon.com/about-aws/whats-new/2011/12/01/New-Amazon-EC2-Reserved-Instances-Options-Now-Available/).
+* **New:** Support for VPC Spot Instances has been added to the SDK. For more information, please see [Announcing Amazon EC2 Spot Integration with Amazon VPC](https://aws.amazon.com/about-aws/whats-new/2011/10/11/announcing-amazon-ec2-spot-integration-with-amazon-vpc/).
+* **New:** Support for VPC Everywhere has been added to the SDK. For more information, please see [Amazon VPC Generally Available in Multiple AZs in All Regions](https://aws.amazon.com/about-aws/whats-new/2011/08/03/Announcing-VPC-GA/).
+* **New:** Instance Type-related constants have been added to the SDK: `INSTANCE_MICRO`, `INSTANCE_SMALL`, `INSTANCE_LARGE`, `INSTANCE_XLARGE`, `INSTANCE_HIGH_MEM_XLARGE`, `INSTANCE_HIGH_MEM_2XLARGE`, `INSTANCE_HIGH_MEM_4XLARGE`, `INSTANCE_HIGH_CPU_MEDIUM`, `INSTANCE_HIGH_CPU_XLARGE`, `INSTANCE_CLUSTER_4XLARGE`, `INSTANCE_CLUSTER_8XLARGE`, `INSTANCE_CLUSTER_GPU_XLARGE`.
+
+### AmazonElastiCache
+* **New:** Support for US-West 1 (California), EU-West (Ireland), Asia Pacific Southeast (Singapore), and Asia Pacific Northeast (Tokyo) regions has been added to the SDK. For more information, please see [Amazon ElastiCache is now available in four additional AWS Regions and as a CloudFormation template](https://aws.amazon.com/about-aws/whats-new/2011/12/05/amazon-elasticache-new-regions/).
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`
+
+### AmazonElasticBeanstalk
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`
+
+### AmazonELB
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+* **New:** Support for ELBs running in VPC has been added to the SDK. For more information, please see [Announcing Elastic Load Balancing in Amazon VPC](https://aws.amazon.com/about-aws/whats-new/2011/11/21/announcing-elastic-load-balancing-in-amazon-vpc/).
+
+### AmazonEMR
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+* **New:** Support for EMR AMI Versioning, new Hadoop and Pig versions, and EMR running in VPC has been added to the SDK. For more information, please see [Amazon Elastic MapReduce Announces Support for New Hadoop and Pig Versions, AMI Versioning, and Amazon VPC](https://aws.amazon.com/about-aws/whats-new/2011/12/11/amazon-elastic-mapreduce-ami-versioning-vpc/).
+
+### AmazonIAM
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`
+
+### AmazonImportExport
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`
+
+### AmazonRDS
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+
+### AmazonS3
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+* **New:** Support for an S3 Stream Wrapper has been added to the SDK. This enables users to read/write to Amazon S3 as though it were the local file system.
+**Fixed:** The `get_object()` method no longer attempts to parse XML/JSON content.
+**Fixed:** Simplified S3 region logic. Now uses fully-qualified domain names across the board.
+
+### AmazonSES
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`
+
+### AmazonSDB
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+
+### AmazonSNS
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+
+### AmazonSQS
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+
+### AmazonSTS
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`
+
+
+----
+
+# Changelog: 1.4.8 "Zanarkand"
+<http://finalfantasy.wikia.com/wiki/Zanarkand>
+
+Launched Wednesday, December 7, 2011
+
+## Services
+### AmazonCloudFront
+* **Fixed:** Merged in a pull request contributed by Ben Lumley: <https://github.com/amazonwebservices/aws-sdk-for-php/pull/11>
+
+### AmazonEC2
+* **Fixed:** Resolved an issue where `set_region()` was not setting the correct endpoint for the region.
+
+### AmazonS3
+* **New:** Support for S3-side multi-object delete has been added to the SDK as the `delete_objects()` method. The implementations of `delete_all_objects()` and `delete_all_object_versions()` have been updated to use this new functionality.
+* **Changed:** XML and JSON responses from `get_object()` are no longer parsed. The raw XML and JSON string content is now returned.
+
+
+----
+
+# Changelog: 1.4.7 "Yuna"
+<http://finalfantasy.wikia.com/wiki/Yuna>
+
+Launched Wednesday, November 9, 2011
+
+## Service Classes
+### AmazonAS
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+### AmazonCloudFormation
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+### AmazonCloudWatch
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+* **New:** Support for the US GovCloud region has been added to the SDK.
+
+### AmazonEC2
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+* **New:** Support for the US GovCloud region has been added to the SDK.
+
+### AmazonELB
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+### AmazonEMR
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+### AmazonIAM
+* **New:** Support for the US GovCloud region has been added to the SDK.
+
+### AmazonRDS
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+### AmazonS3
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+* **Fixed:** Resolved an issue where certain bits of metadata were not maintained during a copy operation. <https://forums.aws.amazon.com/thread.jspa?threadID=77630>
+* **Fixed:** Resolved an issue where an unsuccessful lookup of an existing content-type would throw a warning. <https://forums.aws.amazon.com/thread.jspa?threadID=78121>
+* **Fixed:** Resolved an issue where an exception would be thrown when a filesize lookup was attempted on an object that didn't exist. <https://forums.aws.amazon.com/thread.jspa?threadID=78197>
+
+### AmazonSDB
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+### AmazonSNS
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+### AmazonSQS
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+
+----
+
+# Changelog: 1.4.6 "Xezat"
+<http://finalfantasy.wikia.com/wiki/Xezat>
+
+Launched Thursday, November 3, 2011
+
+## Service Classes
+### AmazonIAM
+* **New:** Support for a virtual MFA device. A virtual MFA device uses a software application that can generate six-digit authentication codes that are Open AuTHentication Time-based One-Time Password (OATHTOTP)-compatible. The software application can run on any mobile hardware device, including a smartphone.
+
+
+----
+
+# Changelog: 1.4.5 "Weiss"
+<http://finalfantasy.wikia.com/wiki/Weiss>
+
+Launched Friday, October 21, 2011
+
+## Service Classes
+### AmazonSQS
+* **New:** Support for delayed queues and batch operations has been added to the SDK.
+
+
+----
+
+# Changelog: 1.4.4 "Vaan"
+<http://finalfantasy.wikia.com/wiki/Vaan>
+
+Launched Tuesday, October 12, 2011
+
+## Runtime
+* **Fixed:** Resolved an issue where a segmentation fault is triggererd when there are multiple autoloaders in the stack and one of them doesn't return a value.
+
+## Service Classes
+### AmazonS3
+* **New:** Support for server-side encryption has been added to the SDK.
+
+
+----
+
+# Changelog: 1.4.3 "Ultros"
+<http://finalfantasy.wikia.com/wiki/Ultros>
+
+Launched Friday, September 30, 2011
+
+## Service Classes
+### AmazonCloudFormation
+* **New:** Support for new features in CloudFormation have been added to the SDK.
+
+### AmazonS3
+* **Fixed:** Setting the default cache configuration no longer causes authentication errors in `AmazonS3`.
+
+
+----
+
+# Changelog: 1.4.2.1 "Tiamat, Part II"
+<http://finalfantasy.wikia.com/wiki/Tiamat>
+
+Launched Wednesday, September 7, 2011
+
+## Utility Classes
+### RequestCore
+* **Fixed:** RequestCore has updated the `cacert.pem` file from Mozilla. This update revokes trust from the DigiNotar and Staat der Nederlanden root certificates.
+
+
+----
+
+# Changelog: 1.4.2 "Tiamat"
+<http://finalfantasy.wikia.com/wiki/Tiamat>
+
+Launched Thursday, September 1, 2011
+
+## Service Classes
+### AmazonEC2
+* **Fixed:** Requests made to Amazon EC2 now use the correct API version (2011-07-15).
+
+### AmazonELB
+* **New:** A pre-defined set of ciphers may now be used for SSL termination at the Elastic Load Balancer.
+* **New:** Application servers can now accept secure communication from the corresponding Elastic Load Balancer.
+* **New:** In cases where HTTPS is required for all traffic entering the back-end server, Elastic Load Balancing can now perform health checks using HTTPS.
+* **New:** White list of public keys can now be associated with back-end servers. Elastic Load Balancing authenticates back-end servers with the public keys in the white list and communicates only with back-end servers that pass this authentication check.
+
+## Utility Classes
+### RequestCore
+* **Fixed:** RequestCore has updated the `cacert.pem` file from Mozilla. This update revokes trust from the DigiNotar root certificate.
+
+
+----
+
+# Changelog: 1.4.1 "Sephiroth"
+<http://finalfantasy.wikia.com/wiki/Sephiroth>
+
+Launched Tuesday, August 23, 2011
+
+## Service Classes
+### AmazonElastiCache
+* **New:** Support for Amazon ElastiCache has been added to the SDK.
+
+### AmazonEMR
+* **New:** Support for Hadoop Bootstrap Actions has been added to the SDK.
+* **New:** Support for Amazon Elastic MapReduce on Spot Instances has been added to the SDK.
+* **New:** Support for Termination Protection has been added to the SDK.
+* **Changed:** For the <code>add_instance_groups()</code> method, the <code>$instance_groups</code> and <code>$job_flow_id</code> parameters have been reversed.
+
+## Utility Classes
+### CFHadoopBootstrap
+* **New:** The `CFHadoopBootstrap` class has been added to the SDK. Simplifies the process of working with Hadoop system and daemon configurations in Amazon EMR.
+* **New:** This class extends from the `CFHadoopBase` class.
+
+
+----
+
+# Changelog: 1.4 "Rikku"
+<http://finalfantasy.wikia.com/wiki/Rikku>
+
+Launched Wednesday, August 3, 2011
+
+## Bug fixes and enhancements
+
+## Service Classes
+### AmazonEC2
+* **New:** Support for Session-Based Authentication (SBA) leveraging Amazon Secure Token Service (STS) has been added to the SDK.
+
+### AmazonS3
+* **New:** Support for Session-Based Authentication (SBA) leveraging Amazon Secure Token Service (STS) has been added to the SDK.
+
+### AmazonSNS
+* **New:** Support for Session-Based Authentication (SBA) leveraging Amazon Secure Token Service (STS) has been added to the SDK.
+
+### AmazonSQS
+* **New:** Support for Session-Based Authentication (SBA) leveraging Amazon Secure Token Service (STS) has been added to the SDK.
+
+### AmazonSTS
+* **New:** Support for the Amazon Secure Token Service (STS) has been added to the SDK.
+
+## Utility Classes
+### CFRuntime
+* **New:** The following anonymous datapoints are now collected in aggregate so that we can make more informed decisions about future SDK features: `memory_limit`, `date.timezone`, `open_basedir`, `safe_mode`, `zend.enable_gc`.
+
+## Compatibility Test
+* **New:** Support for verifying the installed SSL certificate has been added to the compatibility test.
+* **New:** Support for verifying the status of `open_basedir` and `safe_mode` has been added to the compatibility test.
+* **New:** Support for verifying the status of the PHP 5.3 garbage collector has been added to the compatibility test.
+* **New:** The compatibility test now recommends optimal values for the `AWS_CERTIFICATE_AUTHORITY` and `AWS_DEFAULT_CACHE_CONFIG` configuration options based on the system's configuration.
+
+
+----
+
+# Changelog: 1.3.7 "Quistis"
+<http://finalfantasy.wikia.com/wiki/Quistis_Trepe>
+
+Launched Monday, July 25, 2011
+
+## Bug fixes and enhancements
+* Addressed minor bug fixes reported via the feedback form in the API Reference.
+
+## Service Classes
+### AmazonAS
+* **Changed:** Introduced backwards-incompatible changes to the <code>put_scheduled_update_group_action()</code> method.
+
+
+----
+
+# Changelog: 1.3.6 "Penelo"
+<http://finalfantasy.wikia.com/wiki/Penelo>
+
+Launched Tuesday, July 12, 2011
+
+## Bug fixes and enhancements
+* [[Bug Report] rawurlencode error when using SES and curlopts](https://forums.aws.amazon.com/thread.jspa?threadID=68484)
+
+## Service Classes
+### AmazonCloudFormation
+* **New:** Support for the `list_stacks()` method has been added to the SDK.
+
+### AmazonElasticBeanstalk
+* **New:** Support for the `swap_environment_cnames()` method has been added to the SDK.
+
+### AmazonS3
+* **Fixed:** Additional information about maximum open connections has been added to the `create_mpu_object()` method.
+
+## Compatibility Test
+* **New:** Now tests whether the system is 64- or 32-bit.
+
+
+----
+
+# Changelog: 1.3.5 "Occuria"
+<http://finalfantasy.wikia.com/wiki/Occuria>
+
+Launched Tuesday, June 21, 2011
+
+## Service Classes
+### AmazonS3
+* **New:** Support for S3 copy part has been added to the SDK.
+
+
+----
+
+# Changelog: 1.3.4 "Nero"
+<http://finalfantasy.wikia.com/wiki/Nero>
+
+Launched Tuesday, June 7, 2011
+
+## Bug fixes and enhancements
+* [Bug in PHP SDK](https://forums.aws.amazon.com/thread.jspa?threadID=67502)
+* [cURL error: SSL certificate problem (60) with aws-sdk-for-php 1.3.3](https://forums.aws.amazon.com/thread.jspa?threadID=68349)
+
+
+## Service Classes
+### AmazonEC2
+* **New:** Support for Local Availability Zone Pricing has been added to the SDK.
+
+### AmazonELB
+* **New:** Elastic Load Balancing provides a special Amazon EC2 security group that you can use to ensure that a back-end Amazon EC2 instance receives traffic only from its load balancer.
+
+### AmazonRDS
+* **New:** Support for Oracle databases has been added to the SDK.
+
+
+## Utility Classes
+### CFArray
+* **New:** Added the init() method which simplifies the process of instantiating and chaining a class.
+* **New:** Added support for associative arrays to `each()`, `map()` and `filter()`.
+
+### CFRequest
+* **New:** Now supports the `AWS_CERTIFICATE_AUTHORITY` configuration option.
+
+
+----
+
+# Changelog: 1.3.3 "Moogle"
+<http://finalfantasy.wikia.com/wiki/Moogle>
+
+Launched Tuesday, May 10, 2011
+
+## Bug fixes and enhancements
+* [Bug in AmazonCloudFront::get_private_object_url](https://forums.aws.amazon.com/thread.jspa?threadID=64004)
+* [SDK 1.3.2 - Call to undefined function json_last_error()](https://forums.aws.amazon.com/thread.jspa?threadID=64767)
+* [CURLOPT_FOLLOWLOCATION cannot be activated when in safe_mode or an open_basedir](https://forums.aws.amazon.com/thread.jspa?threadID=61333)
+
+
+## Service Classes
+### AmazonCloudFront
+* **Fixed:** Resolved an issue where the expires value for `get_private_object_url()` only accepted a string instead of a string or integer.
+
+### AmazonCloudWatch
+* **New:** Support for CloudWatch custom user metrics has been added to the SDK.
+
+
+## Extensions
+### S3BrowserUpload
+* **New:** Added the `S3BrowserUpload` class to the SDK. This class assists in generating the correct HTML/XHTML markup for uploading files to S3 via an HTML <form> element.
+
+
+## Utility Classes
+### CFArray
+* **New:** Added the `init()` method which simplifies the process of instantiating and chaining a class.
+
+### CFHadoopBase
+* **New:** The `CFHadoopBase` class has been extracted out of `CFHadoopStep` as a shared library.
+
+### CFHadoopStep
+* **New:** The `CFHadoopBase` class has been extracted out of `CFHadoopStep` as a shared library.
+* **New:** This class now extends from the `CFHadoopBase` class.
+
+### CFJSON
+* **Fixed:** Resolved an issue where a PHP 5.3-specific function was being used.
+
+### CFPolicy
+* **New:** Added the init() method which simplifies the process of instantiating and chaining a class.
+
+### CFSimpleXML
+* **New:** Added the init() method which simplifies the process of instantiating and chaining a class.
+
+### RequestCore
+* **Fixed:** Improvements to running in PHP environments with open_basedir enabled.
+* **Fixed:** RequestCore now uses an up-to-date `cacert.pem` file from Mozilla instead of the Certificate Authority that libcurl or libopenssl was compiled with, which should resolve certain issues with making SSL connections to AWS services.
+
+
+----
+
+# Changelog: 1.3.2 "Luna"
+<http://finalfantasy.wikia.com/wiki/Luna_Wolf>
+
+Launched Tuesday, April 5, 2011
+
+## New Features & Highlights (Summary)
+* Support for Dedicated Instances within a Virtual Private Cloud on single-tenant hardware has been added to the SDK.
+* Bug fixes and enhancements:
+ * [AmazonCloudWatch get_metric_statistics returns gzipped body](https://forums.aws.amazon.com/thread.jspa?threadID=62625)
+
+
+## Service Classes
+### AmazonCloudWatch
+* **Fixed:** Worked around an issue where when CloudWatch sends back `Content-Encoding: gzip`, it really means `deflate`. When CloudWatch sends back `Content-Encoding: deflate`, it really means the data isn't encoded at all.
+
+### AmazonEC2
+* **New:** Support for Dedicated Instances within a Virtual Private Cloud on single-tenant hardware has been added to the SDK.
+
+
+----
+
+# Changelog: 1.3.1 "Kraken"
+<http://finalfantasy.wikia.com/wiki/Kraken>
+
+Launched Friday, March 25, 2011
+
+## New Features & Highlights (Summary)
+* Fixed issues with Signature v3 authentication (SES).
+* Added gzip decoding.
+* Added support for converting data to more alternate formats.
+* Bug fixes and enhancements:
+ * [Cannot send email](https://forums.aws.amazon.com/thread.jspa?threadID=62833)
+ * [AmazonCloudWatch get_metric_statistics returns gzipped body](https://forums.aws.amazon.com/thread.jspa?threadID=62625)
+
+
+## Utility Classes
+### CFArray
+* **New:** The `to_json()` and `to_yaml()` methoda have been added to the class.
+
+### CFGzipDecode
+* **New:** Handles a variety of primary and edge cases around gzip/deflate decoding in PHP.
+
+### CFRuntime
+* **New:** Gzip decoding has been added to the SDK.
+* **Fixed:** The previous release contained a regression in the Signature v3 support that affected AmazonSES. This has been resolved.
+* **Fixed:** Completed support for Signature v3 over HTTP connections.
+
+### CFSimpleXML
+* **New:** The `to_stdClass()` and `to_yaml()` methoda have been added to the class.
+
+
+----
+
+# Changelog: 1.3 "Jecht"
+<http://finalfantasy.wikia.com/wiki/Jecht>
+
+Launched Tuesday, March 15, 2011
+
+## New Features & Highlights (Summary)
+* Support for VPC Internet Access has been added to the SDK.
+* Bug fixes and enhancements:
+ * [AmazonEC2::register_image issue](https://forums.aws.amazon.com/thread.jspa?threadID=52499)
+ * [Automatic Parseing of XML objects](https://forums.aws.amazon.com/thread.jspa?threadID=61882)
+
+## Service Classes
+### AmazonEC2
+* **New:** Support for VPC Internet Access has been added to the SDK.
+* **Fixed:** The `$image_location` parameter in the `register_image()` method is no longer required. This is a backwards-incompatible change.
+
+### AmazonS3
+* **Fixed:** Resolved an issue in `get_object()` where using the `lastmodified` and `etag` parameters required both to be set before taking effect. They can now be set independently from each other.
+
+
+## Utility classes
+### CFArray
+* **Changed:** The `reduce()` method has been renamed to `filter()`. `reduce()` is now simply an alias for `filter()`.
+
+### CFJSON
+* **New:** Simplifies the task of normalizing XML and JSON responses as `CFSimpleXML` objects.
+
+### CFRuntime
+* **New:** Preliminary support for Signature v3 over HTTP has been added to the SDK. This is useful for debugging Signature v3 issues over non-HTTPS connections.
+* **Changed:** Classes that use the shared authentication method (i.e., NOT `AmazonS3` or `AmazonCloudFront`) will automatically convert JSON service responses into a `CFSimpleXML` object.
+* **Changed:** Formerly, the SDK would attempt to sniff the content to determine the type. Now, the SDK will check the HTTP response headers for `text/xml`, `application/xml` or `application/json` to determine whether or not to parse the content. If the HTTP response headers are not available, the SDK will still attempt content sniffing.
+
+### CFSimpleXML
+* **New:** The `to_json()` method has been added to the class.
+
+### CFUtilities
+* **New:** The `is_json()` method has been added to the class.
+
+
+----
+
+# Changelog: 1.2.6 "Ifrit"
+<http://finalfantasy.wikia.com/wiki/Ifrit>
+
+Launched Wednesday, March 2, 2011
+
+## New Features & Highlights (Summary)
+* **New:** Support for the new Asia Pacific "Northeast" (Japan) endpoint has been added for all relevant services.
+* **New:** Support for registering callback functions for read/write streams has been added to the SDK. Includes a runnable sample.
+* **Fixed:** Improvements to avoid triggering warnings when PHP is in Safe Mode.
+
+
+## Service Classes
+### AmazonAS
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonCloudFormation
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonCloudWatch
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonEC2
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonELB
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonRDS
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonS3
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+* **New:** Added support for `ap-northeast-1` as a location constraint when creating a new bucket.
+
+### AmazonSDB
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonSNS
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonSQS
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+## Utility classes
+### CFRuntime
+* **New:** Support for registering callback functions for read/write streams has been added to the SDK.
+* **New:** Future-proofed for future regional endpoints.
+
+### RequestCore
+* **New:** Support for registering callback functions for read/write streams has been added to the SDK.
+* **Fixed:** Improvements to avoid triggering warnings when PHP is in Safe Mode.
+
+## Samples
+* **New:** A sample demonstrating how to add a command-line progress bar for S3 transfers has been added to the SDK.
+
+
+----
+
+# Changelog: 1.2.5 "Heidegger"
+<http://finalfantasy.wikia.com/wiki/Heidegger>
+
+Launched Thursday, February 24, 2011
+
+## New Features & Highlights (Summary)
+* Support for AWS CloudFormation has been added to the SDK.
+* Bug fixes and enhancements:
+ * [PHP API change_content_type() broken](https://forums.aws.amazon.com/thread.jspa?threadID=59532)
+ * [Bug setting OriginAccessIdentity for a Cloudfront distribution config](https://forums.aws.amazon.com/thread.jspa?threadID=60989)
+
+## Service Classes
+### AmazonCloudFormation
+* **New:** Support for AWS CloudFormation has been added to the SDK.
+
+### AmazonCloudFront
+* **Fixed:** Issues around `update_xml_config()` have been resolved.
+
+### AmazonS3
+* **Fixed:** Issues around `change_content_type()` have been resolved.
+
+
+----
+
+# Changelog: 1.2.4 "Goltanna"
+<http://finalfantasy.wikia.com/wiki/Druksmald_Goltanna>
+
+Launched Wednesday, February 16, 2011
+
+## New Features & Highlights (Summary)
+* Support for IAM account aliases and server certificates has been added to the SDK.
+* Support for Amazon S3 Website Configuration has been added to the SDK.
+* Documentation updates for Amazon RDS and AWS Import/Export.
+* Updated all documentation blocks to adhere to the PHPDoc format. This enables a greater number of tools to take advantage of the SDK documentation.
+* Rolled out a major update to the SDK API Reference.
+
+## Service Classes
+### AmazonIAM
+* **New:** Support for IAM account aliases and server certificates has been added to the SDK.
+
+### AmazonImportExport
+* **New:** Documentation has been updated to note the new US West region support.
+
+### AmazonRDS
+* **New:** Documentation has been updated to note the new support for MySQL 5.5.
+
+### AmazonS3
+* **New:** Support for Amazon S3 Website Configuration has been added to the SDK.
+
+
+----
+
+# Changelog: 1.2.3 "Fayth"
+<http://finalfantasy.wikia.com/wiki/Fayth>
+
+Launched Tuesday, January 25, 2010
+
+## New Features & Highlights (Summary)
+* Support for Amazon Simple Email Service has been added to the SDK.
+
+## Service Classes
+### AmazonSES
+* **New:** Support for Amazon Simple Email Service has been added to the SDK.
+
+
+----
+
+# Changelog: 1.2.2 "Esper"
+<http://finalfantasy.wikia.com/wiki/Esper>
+
+Launched Tuesday, January 18, 2011
+
+## New Features & Highlights (Summary)
+* Support for Amazon Elastic Beanstalk has been added to the SDK.
+* Bug fixes and enhancements:
+ * [AWS PHP S3 Library is not working out of the box](https://forums.aws.amazon.com/thread.jspa?threadID=55174)
+ * [Problem with create_mpu_object() and streaming_read_callback() in S3](https://forums.aws.amazon.com/thread.jspa?threadID=54541)
+ * [Integrated Uranium235's GitHub contributions](https://github.com/Uranium235/aws-sdk-for-php/compare/Streaming)
+
+## Service Classes
+### AmazonElasticBeanstalk
+* **New:** Support for AWS Elastic Beanstalk has been added to the SDK.
+
+### AmazonS3
+* **Fixed:** Major improvements to transferring data over streams.
+
+## Utility classes
+###RequestCore
+* **New:** Upgraded to version 1.4.
+* **Fixed:** Major improvements to transferring data over streams.
+
+
+----
+
+# Changelog: 1.2.1 "Dio"
+<http://finalfantasy.wikia.com/wiki/Dio>
+
+Launched Friday, January 14, 2011
+
+
+## New Features & Highlights (Summary)
+* Support for S3 Response Headers has been added to the SDK.
+* Bug fixes and enhancements:
+ * [copy_object failed between regions](https://forums.aws.amazon.com/thread.jspa?threadID=56893)
+ * [Possible S3 bug with multiple buckets?](https://forums.aws.amazon.com/thread.jspa?threadID=56561)
+
+## Service Classes
+### AmazonS3
+* **New:** Support for S3 Response Headers has been added to the SDK.
+* **New:** Documentation for Amazon S3 has been updated to include large object support details.
+* **New:** The `abort_multipart_uploads_by_date()` method has been added to the SDK, which aborts multipart uploads that were initiated before a specific date.
+* **Fixed:** Resolved an issue where the resource prefix wasn't being reset correctly.
+
+## Utility classes
+### CFArray
+* **New:** Instantiating the class without passing an array will use an empty array instead.
+* **New:** Added the `compress()` method which removes null values from the array.
+* **New:** Added the `reindex()` method which reindexes all array elements starting at zero.
+
+## Compatibility Test
+* **New:** The command-line compatibility test now color-codes the responses.
+
+
+----
+
+# Changelog: 1.2 "Cloud"
+<http://finalfantasy.wikia.com/wiki/Cloud_Strife>
+
+Launched Friday, December 3, 2010
+
+
+## New Features & Highlights (Summary)
+* Support for Amazon AutoScaling, Amazon Elastic MapReduce, and Amazon Import/Export Service has been added to the SDK.
+* Support for metric alarms has been added to Amazon CloudWatch.
+* Support for batch deletion has been added to Amazon SimpleDB.
+* Bug fixes and enhancements:
+ * [EU Region DNS problem](https://forums.aws.amazon.com/thread.jspa?threadID=53028)
+ * [[SimpleDB] Conditional PUT](https://forums.aws.amazon.com/thread.jspa?threadID=55884)
+ * [Suggestions for the PHP SDK](https://forums.aws.amazon.com/thread.jspa?threadID=55210)
+ * [Updating a distribution config](https://forums.aws.amazon.com/thread.jspa?threadID=54888)
+ * [Problem with curlopt parameter in S3](https://forums.aws.amazon.com/thread.jspa?threadID=54532)
+ * [AmazonS3::get_object_list() doesn't consider max-keys option](https://forums.aws.amazon.com/thread.jspa?threadID=55169)
+
+## Base/Runtime class
+* **New:** Added support for an alternate approach to instantiating classes which allows for method chaining (PHP 5.3+).
+* **Changed:** Moved `CHANGELOG.md`, `CONTRIBUTORS.md`, `LICENSE.md` and `NOTICE.md` into a new `_docs` folder.
+* **Changed:** Renamed the `samples` directory to `_samples`.
+* **Changed:** Changed the permissions for the SDK files from `0755` to `0644`.
+* **Fixed:** Resolved an issue where attempting to merge cURL options would fail.
+
+## Service Classes
+### AmazonAS
+* **New:** Support for the Amazon AutoScaling Service has been added to the SDK.
+
+### AmazonCloudFront
+* **Fixed:** Resolved an issue where the incorrect formatting of an XML element prevented the ability to update the list of trusted signers.
+
+### AmazonCloudWatch
+* **New:** Support for the Amazon CloudWatch `2010-08-01` service release expands Amazon's cloud monitoring offerings with custom alarms.
+* **Changed:** The changes made to the `get_metric_statistics()` method are backwards-incompatible with the previous release. The `Namespace` and `Period` parameters are now required and the parameter order has changed.
+
+### AmazonEMR
+* **New:** Support for the Amazon Elastic MapReduce Service has been added to the SDK.
+
+### AmazonImportExport
+* **New:** Support for the Amazon Import/Export Service has been added to the SDK.
+
+### AmazonS3
+* **Fixed:** Resolved an issue in the `create_bucket()` method that caused the regional endpoint to be reset to US-Standard.
+* **Fixed:** Resolved an issue in the `get_object_list()` method where the `max-keys` parameter was ignored.
+
+### AmazonSDB
+* **New:** Support for `BatchDeleteAttributes` has been added to the SDK.
+* **Fixed:** Resolved an issue where the `Expected` condition was not respected by `put_attributes()` or `delete_attributes()`.
+
+
+## Utility classes
+### CFComplexType
+* **New:** You can now assign a `member` parameter to prefix all list identifiers.
+* **Changed:** The `option_group()` method is now `public` instead of `private`.
+* **Changed:** Rewrote the `to_query_string()` method to avoid the use of PHP's `http_build_query()` function because it uses `urlencode()` internally instead of `rawurlencode()`.
+
+### CFHadoopStep
+* **New:** Simplifies the process of working with Hadoop steps in Amazon EMR.
+
+### CFManifest
+* **New:** Simplifies the process of constructing YAML manifest documents for Amazon Import/Export Service.
+
+### CFStepConfig
+* **New:** Simplifies the process of working with step configuration in Amazon EMR.
+
+
+## Third-party Libraries
+### CacheCore
+* **Changed:** The `generate_timestamp()` method is now `protected` instead of `private`.
+
+
+----
+
+# Changelog: 1.1 "Barret"
+<http://finalfantasy.wikia.com/wiki/Barret_Wallace>
+
+Launched Wednesday, November 10, 2010
+
+
+## New Features & Highlights (Summary)
+* Support for Amazon ELB, Amazon RDS and Amazon VPC has been added to the SDK.
+* Support for the Amazon S3 multipart upload feature has been added to the SDK. This feature enables developers upload large objects in a series of requests for improved upload reliability.
+* Support for the Amazon CloudFront custom origin (2010-11-01 release) feature has been added to the SDK. This feature enables developers to use custom domains as sources for Amazon CloudFront distributions.
+* The `AmazonS3` class now supports reading from and writing to open file resources in addition to the already-supported file system paths.
+* You can now seek to a specific byte-position within a file or file resource and begin streaming from that point when uploading or downloading objects.
+* The methods `get_bucket_filesize()`, `get_object_list()`, `delete_all_objects()` and `delete_all_object_versions()` are no longer limited to 1000 entries and will work correctly for all entries.
+* Requests that have errors at the cURL level now throw exceptions containing the error message and error code returned by cURL.
+* Bug fixes and enhancements:
+ * [Bug in Samples](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52748)
+ * [EU Region DNS problem](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=53028)
+ * [AmazonS3 get_bucket_object_count](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52976)
+ * [S3: get_object_list() fatal error](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=53418)
+ * [S3 get_object_metadata() problems](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=54244)
+ * [Bug in authenticate in sdk.class.php](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=53117)
+ * [How to use Prefix with "get_object_list"?](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52987)
+ * [SignatureDoesNotMatch with utf-8 in SimpleDB](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52798)
+ * [Suggestion for the PHP SDK concerning streaming](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52787)
+ * [get_bucket_filesize only returns filesize for first 1000 objects](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=53786)
+
+
+## Base/Runtime class
+* **Changed:** Port numbers other than 80 and 443 are now part of the signature.
+* **Changed:** When putting UTF-8 characters via HTTP `POST`, a `SignatureDoesNotMatch` error would be returned. This was resolved by specifying the character set in the `Content-Type` header.
+
+
+## Service Classes
+### AmazonCloudFront
+* **New:** Support for the Amazon CloudFront non-S3 origin feature (2010-11-01 release) has been added to the SDK. This feature enables developers to use non-S3 domains as sources for Amazon CloudFront distributions.
+
+### AmazonEC2
+* **New:** Support for Amazon Virtual Private Cloud has been added to the SDK.
+
+### AmazonELB
+* **New:** Support for Amazon Elastic Load Balancing Service has been added to the SDK.
+
+### AmazonIAM
+* **Fixed:** Removed `set_region()` as IAM only supports a single endpoint.
+
+### AmazonRDS
+* **New:** Support for Amazon Relational Database Service has been added to the SDK.
+
+### AmazonS3
+* **New:** Support for the Amazon S3 multipart upload feature has been added to the SDK. This feature enables developers upload large objects in a series of requests for improved upload reliability.
+* **New:** The `fileUpload` and `fileDownload` options now support reading from and writing to open file resources in addition to the already-supported file system paths.
+* **Fixed:** In Amazon S3, requests directly to the eu-west endpoint must use the path-style URI. The set_region() method now takes this into account.
+* **Fixed:** As of version 1.0.1, CFSimpleXML extends SimpleXMLIterator instead of SimpleXMLElement. This prevented the `__call()` magic method from firing when `get_object_list()` was used.
+* **Fixed:** The `preauth` option for the `get_object_list()` method has been removed from the documentation as it is not supported.
+* **Fixed:** The methods `get_bucket_filesize()`, `get_object_list()`, `delete_all_objects()` and `delete_all_object_versions()` are no longer limited to 1000 entries and will work correctly for all entries.
+* **Fixed:** Using `delete_bucket()` to force-delete a bucket now works correctly for buckets with more than 1000 versions.
+* **Fixed:** The response from the `get_object_metadata()` method now includes all supported HTTP headers, including metadata stored in `x-amz-meta-` headers.
+* **Fixed:** Previously, if the `get_object_metadata()` method was called on a non-existant object, metadata for the alphabetically-next object would be returned.
+
+### AmazonSQS
+* **New:** The `get_queue_arn()` method has been added to the `AmazonSQS` class, which converts a queue URI to a queue ARN.
+
+
+## Utility classes
+### CFSimpleXML
+* **New:** Added `to_string()` and `to_array()` methods.
+
+
+## Third-party Libraries
+### RequestCore
+* **New:** Upgraded to version 1.3.
+* **New:** Added `set_seek_position()` for seeking to a byte-position in a file or file resource before starting an upload.
+* **New:** Added support for reading from and writing to open file resources.
+* **Fixed:** Improved the reporting for cURL errors.
+
+
+## Compatibility Test
+* **Fixed:** Fixed the links to the Getting Started Guide.
+
+
+----
+
+# Changelog: 1.0.1 "Aeris"
+<http://finalfantasy.wikia.com/wiki/Aerith_Gainsborough>
+
+Launched Tuesday, October 12, 2010
+
+
+## New Features & Highlights (Summary)
+* Improved support for running XPath queries against the service response bodies.
+* Added support for request retries and exponential backoff.
+* Added support for HTTP request/response header logging.
+* Bug fixes and enhancements:
+ * [Bug in Samples](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52748)
+ * [Can't set ACL on object using the SDK](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52305)
+ * [Range requests for S3 - status codes 200, 206](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52738)
+ * [S3 change_storage_redundancy() function clears public-read ACL](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52652)
+
+
+## Base/Runtime class
+* **New:** Added support for request retries and exponential backoff for all `500` and `503` HTTP status codes.
+* **New:** Added the `enable_debug_mode()` method to enable HTTP request/response header logging to `STDERR`.
+
+
+## Service Classes
+### AmazonS3
+* **Fixed:** Lots of tweaks to the documentation.
+* **Fixed:** The `change_content_type()`, `change_storage_redundancy()`, `set_object_acl()`, and `update_object()` methods now respect the existing content-type, storage redundancy, and ACL settings when updating.
+* **New:** Added the `get_object_metadata()` method has been added as a singular interface for obtaining all available metadata for an object.
+
+
+## Utility Classes
+### CFArray
+* **New:** Added the `each()` method which accepts a callback function to execute for each entry in the array. Works similarly to [jQuery's each()](http://api.jquery.com/each).
+* **New:** Added the `map()` method which accepts a callback function to execute for each entry in the array. Works similarly to [jQuery's map()](http://api.jquery.com/map).
+* **New:** Added the `reduce()` method which accepts a callback function to execute for each entry in the array. Works similarly to [DomCrawler reduce()](http://github.com/symfony/symfony/blob/master/src/Symfony/Component/DomCrawler/Crawler.php) from the [Symfony 2](http://symfony-reloaded.org) Preview Release.
+* **New:** Added the `first()` and `last()` methods to return the first and last nodes in the array, respectively.
+
+### CFInfo
+* **New:** Retrieves information about the current installation of the AWS SDK for PHP.
+
+### CFSimpleXML
+* **New:** Added the `query()` method, which allows for XPath queries while the results are wrapped in a `CFArray` response.
+* **New:** Added the `parent()` method, which allows for traversing back up the document tree.
+* **New:** Added the `stringify()` method, which typecasts the value as a string.
+* **New:** Added the `is()` and `contains()` methods, which allow for testing whether the XML value is or contains a given value, respectively.
+* **Changed:** Now extends the `SimpleXMLIterator` class, which in-turn extends the `SimpleXMLElement` class. This adds new iterator methods to the `CFSimpleXML` class.
+
+
+## Third-party Libraries
+### CacheCore
+* **New:** Upgraded to version 1.2.
+* **New:** Added a static `init` method that allows for chainable cache initialization (5.3+).
+
+### RequestCore
+* **New:** Added `206` as a successful status code (i.e., Range GET).
+
+
+## Compatibility Test
+* **Fixed:** Some of the links in the compatibility test were missing. These have been fixed.
+
+
+----
+
+# Changelog: AWS SDK for PHP 1.0
+
+Launched Tuesday, September 28, 2010
+
+This is a complete list of changes since we forked from the CloudFusion 2.5.x trunk build.
+
+
+## New Features & Highlights (Summary)
+* The new file to include is `sdk.class.php` rather than `cloudfusion.class.php`.
+* Because of the increased reliance on [JSON](http://json.org) across AWS services, the minimum supported version is now PHP 5.2 ([Released in November 2006](http://www.php.net/ChangeLog-5.php#5.2.0); Justified by these [WordPress usage statistics](http://wpdevel.wordpress.com/2010/07/09/suggest-topics-for-the-july-15-2010-dev/comment-page-1/#comment-8542) and the fact that [PHP 5.2 has been end-of-life'd](http://www.php.net/archive/2010.php#id2010-07-22-1) in favor of 5.3).
+* Up-to-date service support for [EC2](http://aws.amazon.com/ec2), [S3](http://aws.amazon.com/s3), [SQS](http://aws.amazon.com/sqs), [SimpleDB](http://aws.amazon.com/simpledb), [CloudWatch](http://aws.amazon.com/cloudwatch), and [CloudFront](http://aws.amazon.com/cloudfront).
+* Added service support for [SNS](http://aws.amazon.com/sns).
+* Limited testing for third-party API-compatible services such as [Eucalyptus](http://open.eucalyptus.com), [Walrus](http://open.eucalyptus.com) and [Google Storage](http://sandbox.google.com/storage).
+* Improved the consistency of setting complex data types across services. (Required some backwards-incompatible changes.)
+* Added new APIs and syntactic sugar for SimpleXML responses, batch requests and response caching.
+* Moved away from _global_ constants in favor of _class_ constants.
+* Minor, but notable improvements to the monkey patching support.
+* Added a complete list of bug fix and patch contributors. Give credit where credit is due. ;)
+
+**Note: ALL backwards-incompatible changes are noted below. Please review the changes if you are upgrading.** We're making a small number of backwards-incompatible changes in order to improve the consistency across services. We're making these changes _now_ so that we can ensure that future versions will always be backwards-compatible with the next major version change.
+
+
+## File structure
+The package file structure has been refined in a few ways:
+
+* All service-specific classes are inside the `/services/` directory.
+* All utility-specific classes are inside the `/utilities/` directory.
+* All third-party classes are inside the `/lib/` directory.
+
+
+## Base/Runtime class
+* **Fixed:** Resolved issues: [#206](http://code.google.com/p/tarzan-aws/issues/detail?id=206).
+* **New:** The following global constants have been added: `CFRUNTIME_NAME`, `CFRUNTIME_VERSION`, `CFRUNTIME_BUILD`, `CFRUNTIME_URL`, and `CFRUNTIME_USERAGENT`
+* **New:** Now supports camelCase versions of the snake_case method names. (e.g. `getObjectList()` will get translated to `get_object_list()` behind the scenes.)
+* **New:** Added `set_resource_prefix()` and `allow_hostname_override()` (in addition to `set_hostname()`) to support third-party, API-compatible services.
+* **New:** Added new caching APIs: `cache()` and `delete_cache()`, which work differently from the methods they replace. See docs for more information.
+* **New:** Added new batch request APIs, `batch()` and `CFBatchRequest` which are intended to replace the old `returnCurlHandle` optional parameter.
+* **New:** Will look for the `config.inc.php` file first in the same directory (`./config.inc.php`), and then fallback to `~/.aws/sdk/config.inc.php`.
+* **Changed:** Renamed the `CloudFusion` base class to `CFRuntime`.
+* **Changed:** `CloudFusion_Exception` has been renamed as `CFRuntime_Exception`.
+* **Changed:** Renamed the `CloudFusion::$enable_ssl` property to `CFRuntime::$use_ssl`.
+* **Changed:** Renamed the `CloudFusion::$set_proxy` property to `CFRuntime::$proxy`.
+* **Changed:** `CFRuntime::disable_ssl()` no longer takes any parameters. Once SSL is off, it is always off for that class instance.
+* **Changed:** All date-related constants are now class constants of the `CFUtilities` class (e.g. `CFUtilities::DATE_FORMAT_ISO8601`).
+ * Use `CFUtilities::konst()` if you're extending classes and need to do something such as `$this->util::DATE_FORMAT_ISO8601` but keep getting the `T_PAAMAYIM_NEKUDOTAYIMM` error.
+* **Changed:** All `x-cloudfusion-` and `x-tarzan-` HTTP headers are now `x-aws-`.
+* **Changed:** `CloudFusion::autoloader()` is now in its own separate class: `CFLoader::autoloader()`. This prevents it from being incorrectly inherited by extending classes.
+* **Changed:** `RequestCore`, `ResponseCore` and `SimpleXMLElement` are now extended by `CFRequest`, `CFResponse` and `CFSimpleXML`, respectively. These new classes are now used by default.
+* **Changed:** Changes to monkey patching:
+ * You must now extend `CFRequest` instead of `RequestCore`, and then pass that class name to `set_request_class()`.
+ * You must now extend `CFResponse` instead of `ResponseCore`, and then pass that class name to `set_response_class()`.
+ * You can now monkey patch `CFSimpleXML` (extended from `SimpleXMLElement`) with `set_parser_class()`.
+ * You can now monkey patch `CFBatchRequest` with `set_batch_class()`.
+ * No changes for monkey patching `CFUtilities` with `set_utilities_class()`.
+* **Removed:** Removed ALL existing _global_ constants and replaced them with _class_ constants.
+* **Removed:** Removed `cache_response()` and `delete_cache_response()`.
+
+
+## Service classes
+
+### AmazonCloudFront
+* **Fixed:** Resolved issues: [#124](http://code.google.com/p/tarzan-aws/issues/detail?id=124), [#225](http://code.google.com/p/tarzan-aws/issues/detail?id=225), [#229](http://code.google.com/p/tarzan-aws/issues/detail?id=229), [#232](http://code.google.com/p/tarzan-aws/issues/detail?id=232), [#239](http://code.google.com/p/tarzan-aws/issues/detail?id=239).
+* **Fixed:** Fixed an issue where `AmazonCloudFront` sent a `RequestCore` user agent in requests.
+* **New:** Class is now up-to-date with the [2010-07-15](http://docs.amazonwebservices.com/AmazonCloudFront/2010-07-15/APIReference/) API release.
+* **New:** Added _class_ constants for deployment states: `STATE_INPROGRESS` and `STATE_DEPLOYED`.
+* **New:** Now supports streaming distributions.
+* **New:** Now supports HTTPS (as well as HTTPS-only) access.
+* **New:** Now supports Origin Access Identities. Added `create_oai()`, `list_oais()`, `get_oai()`, `delete_oai()`, `generate_oai_xml()` and `update_oai_xml()`.
+* **New:** Now supports private (signed) URLs. Added `get_private_object_url()`.
+* **New:** Now supports default root objects.
+* **New:** Now supports invalidation.
+* **New:** Added `get_distribution_list()`, `get_streaming_distribution_list()` and `get_oai_list()` which return simplified arrays of identifiers.
+* **Changed:** Replaced all of the remaining `CDN_*` constants with _class_ constants.
+
+### AmazonCloudWatch
+* **New:** Added new _class_ constants: `DEFAULT_URL`, `REGION_US_E1`, `REGION_US_W1`, `REGION_EU_W1`, and `REGION_APAC_SE1`.
+* **New:** Now supports the _Northern California_, _European_ and _Asia-Pacific_ regions.
+* **New:** The _global_ `CW_DEFAULT_URL` constant has been replaced by `AmazonCloudFront::DEFAULT_URL`.
+
+### AmazonEC2
+* **Fixed:** Resolved issues: [#124](http://code.google.com/p/tarzan-aws/issues/detail?id=124), [#131](http://code.google.com/p/tarzan-aws/issues/detail?id=131), [#138](http://code.google.com/p/tarzan-aws/issues/detail?id=138), [#139](http://code.google.com/p/tarzan-aws/issues/detail?id=139), [#154](http://code.google.com/p/tarzan-aws/issues/detail?id=154), [#173](http://code.google.com/p/tarzan-aws/issues/detail?id=173), [#200](http://code.google.com/p/tarzan-aws/issues/detail?id=200), [#233](http://code.google.com/p/tarzan-aws/issues/detail?id=233).
+* **New:** Class is now up-to-date with the [2010-06-15](http://docs.amazonwebservices.com/AWSEC2/2010-06-15/APIReference/) API release.
+* **New:** Now supports [Paid AMIs](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=865&categoryID=87).
+* **New:** Now supports [Multiple instance types](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=992&categoryID=87).
+* **New:** Now supports [Elastic IPs](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1344&categoryID=87).
+* **New:** Now supports [Availability Zones](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1344&categoryID=87).
+* **New:** Now supports [Elastic Block Store](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1665&categoryID=87).
+* **New:** Now supports [Windows instances](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1765&categoryID=87).
+* **New:** Now supports the [European region](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1926&categoryID=87).
+* **New:** Now supports the _Northern California_ and _Asia-Pacific_ regions.
+* **New:** Now supports [Reserved instances](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=2213&categoryID=87).
+* **New:** Now supports [Shared snapshots](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=2843&categoryID=87).
+* **New:** Now supports [EBS AMIs](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=3105&categoryID=87).
+* **New:** Now supports [Spot instances](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=3215&categoryID=87).
+* **New:** Now supports [Cluster Compute Instances](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=3965&categoryID=87).
+* **New:** Now supports [Placement Groups](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=3965&categoryID=87).
+* **New:** Added new _class_ constants for regions: `REGION_US_E1`, `REGION_US_W1`, `REGION_EU_W1`, `REGION_APAC_SE1`.
+* **New:** Added new _class_ constants for run-state codes: `STATE_PENDING`, `STATE_RUNNING`, `STATE_SHUTTING_DOWN`, `STATE_TERMINATED`, `STATE_STOPPING`, `STATE_STOPPED`.
+* **New:** Added support for decrypting the Administrator password for Microsoft Windows instances.
+* **New:** Instead of needing to pass `Parameter.0`, `Parameter.1`, ...`Parameter.n` individually to certain methods, you can now reliably pass a string for a single value or an indexed array for a list of values.
+* **New:** Limited tested has been done with the Eucalyptus EC2-clone.
+* **Changed:** The `$account_id` parameter has been removed from the constructor.
+* **Changed:** The _global_ `EC2_LOCATION_US` and `EC2_LOCATION_EU` constants have been replaced.
+* **Changed:** The `set_locale()` method has been renamed to `set_region()`. It accepts any of the region constants.
+
+### AmazonIAM
+* **New:** Up-to-date with the [2010-03-31](http://docs.amazonwebservices.com/sns/2010-03-31/api/) API release.
+
+### AmazonS3
+* **Fixed:** Resolved issues: [#31](http://code.google.com/p/tarzan-aws/issues/detail?id=31), [#72](http://code.google.com/p/tarzan-aws/issues/detail?id=72), [#123](http://code.google.com/p/tarzan-aws/issues/detail?id=123), [#156](http://code.google.com/p/tarzan-aws/issues/detail?id=156), [#199](http://code.google.com/p/tarzan-aws/issues/detail?id=199), [#201](http://code.google.com/p/tarzan-aws/issues/detail?id=201), [#203](http://code.google.com/p/tarzan-aws/issues/detail?id=203), [#207](http://code.google.com/p/tarzan-aws/issues/detail?id=207), [#208](http://code.google.com/p/tarzan-aws/issues/detail?id=208), [#209](http://code.google.com/p/tarzan-aws/issues/detail?id=209), [#210](http://code.google.com/p/tarzan-aws/issues/detail?id=210), [#212](http://code.google.com/p/tarzan-aws/issues/detail?id=212), [#216](http://code.google.com/p/tarzan-aws/issues/detail?id=216), [#217](http://code.google.com/p/tarzan-aws/issues/detail?id=217), [#226](http://code.google.com/p/tarzan-aws/issues/detail?id=226), [#228](http://code.google.com/p/tarzan-aws/issues/detail?id=228), [#234](http://code.google.com/p/tarzan-aws/issues/detail?id=234), [#235](http://code.google.com/p/tarzan-aws/issues/detail?id=235).
+* **Fixed:** Fixed an issue where `AmazonS3` sent a `RequestCore` user agent in requests.
+* **New:** Now supports the _Northern California_ and _Asia-Pacific_ regions.
+* **New:** Now supports the new _EU (Ireland)_ REST endpoint.
+* **New:** Now supports MFA Delete.
+* **New:** Now supports Conditional Copy.
+* **New:** Now supports Reduced Redundancy Storage (RRS). Added `change_storage_redundancy()`.
+* **New:** Now supports Object Versioning. Added `enable_versioning()`, `disable_versioning`, `get_versioning_status()`, and `list_bucket_object_versions()`.
+* **New:** Now supports Bucket Policies. Added `set_bucket_policy()`, `get_bucket_policy()`, and `delete_bucket_policy()`.
+* **New:** Now supports Bucket Notifications. Added `create_bucket_notification()`, `get_bucket_notifications()`, and `delete_bucket_notification()`.
+* **New:** Added _class_ constants for regions: `REGION_US_E1`, `REGION_US_W1`, `REGION_EU_W1`, `REGION_APAC_SE1`.
+* **New:** Added _class_ constants for storage types: `STORAGE_STANDARD` and `STORAGE_REDUCED`.
+* **New:** Enhanced `create_object()` with the ability to upload a file from the file system.
+* **New:** Enhanced `get_object()` with the ability to download a file to the file system.
+* **New:** Enhanced `get_bucket_list()` and `get_object_list()` with performance improvements.
+* **New:** Enhanced all GET operations with the ability to generate pre-authenticated URLs. This is the same feature as `get_object_url()` has had, applied to all GET operations.
+* **New:** Limited testing with Walrus, the Eucalyptus S3-clone.
+* **New:** Limited testing with Google Storage.
+* **Changed:** Replaced all of the remaining `S3_*` constants with _class_ constants: `self::ACL_*`, `self::GRANT_*`, `self::USERS_*`, and `self::PCRE_ALL`.
+* **Changed:** Changed the function signature for `create_object()`. The filename is now passed as the second parameter, while the remaining options are now passed as the third parameter. This behavior now matches all of the other object-related methods.
+* **Changed:** Changed the function signature for `head_object()`, `delete_object()`, and `get_object_acl()`. The methods now accept optional parameters as the third parameter instead of simply `returnCurlHandle`.
+* **Changed:** Changed the function signature for `get_object_url()` and `get_torrent_url()`. Instead of passing a number of seconds until the URL expires, you now pass a string that `strtotime()` understands (including `60 seconds`).
+* **Changed:** Changed the function signature for `get_object_url()`. Instead of passing a boolean value for `$torrent`, the last parameter is now an `$opt` variable which allows you to set `torrent` and `method` parameters.
+* **Changed:** Changed how `returnCurlHandle` is used. Instead of passing `true` as the last parameter to most methods, you now need to explicitly set `array('returnCurlHandle' => true)`. This behavior is consistent with the implementation in other classes.
+* **Changed:** Optional parameter names changed in `list_objects()`: `maxKeys` is now `max-keys`.
+* **Changed:** `get_bucket_locale()` is now called `get_bucket_region()`, and returns the response body as a _string_ for easier comparison with class constants.
+* **Changed:** `get_bucket_size()` is now called `get_bucket_object_count()`. Everything else about it is identical.
+* **Changed:** `head_bucket()` is now called `get_bucket_headers()`. Everything else about it is identical.
+* **Changed:** `head_object()` is now called `get_object_headers()`. Everything else about it is identical.
+* **Changed:** `create_bucket()` has two backward-incompatible changes:
+ * Method now **requires** the region (formerly _locale_) to be set.
+ * Method takes an `$acl` parameter so that the ACL can be set directly when creating a new bucket.
+* **Changed:** Bucket names are now validated. Creating a new bucket now requires the more stringent DNS-valid guidelines, while the process of reading existing buckets follows the looser path-style guidelines. This change also means that the reading of path-style bucket names is now supported, when previously they weren’t.
+* **Removed:** Removed `store_remote_file()` because its intended usage repeatedly confused users, and had potential for misuse. If you were using it to upload from the local file system, you should be using `create_object` instead.
+* **Removed:** Removed `copy_bucket()`, `replace_bucket()`, `duplicate_object()`, `move_object()`, and `rename_object()` because only a small number of users used them, and they weren't very robust anyway.
+* **Removed:** Removed `get_bucket()` because it was just an alias for `list_objects()` anyway. Use the latter from now on -- it's identical.
+
+### AmazonSDB
+* **Fixed:** Resolved issues: [#205](http://code.google.com/p/tarzan-aws/issues/detail?id=205).
+* **New:** Class is now up-to-date with the [2009-04-15](http://docs.amazonwebservices.com/AmazonSimpleDB/2009-04-15/DeveloperGuide/) API release.
+* **Changed:** Changed the function signatures for `get_attributes()` and `delete_attributes()` to improve consistency.
+
+### AmazonSNS
+* **New:** Up-to-date with the [2010-03-31](http://docs.amazonwebservices.com/sns/2010-03-31/api/) API release.
+
+### AmazonSQS
+* **Fixed:** Resolved issues: [#137](http://code.google.com/p/tarzan-aws/issues/detail?id=137), [#213](http://code.google.com/p/tarzan-aws/issues/detail?id=213), [#219](http://code.google.com/p/tarzan-aws/issues/detail?id=219), [#220](http://code.google.com/p/tarzan-aws/issues/detail?id=220), [#221](http://code.google.com/p/tarzan-aws/issues/detail?id=221), [#222](http://code.google.com/p/tarzan-aws/issues/detail?id=222).
+* **Fixed:** In CloudFusion 2.5, neither `add_permission()` nor `remove_permission()` were functional. They are now working.
+* **New:** Now supports the _Northern California_ and _Asia-Pacific_ regions.
+* **New:** Now supports the new _US-East (N. Virginia)_ endpoint.
+* **New:** Now supports the new _EU (Ireland)_ endpoint.
+* **New:** Added new _class_ constants for regions: `REGION_US_E1`, `REGION_US_W1`, `REGION_EU_W1`, and `REGION_APAC_SE1`.
+* **Changed:** Because we now support multiple region endpoints, queue names alone are no longer sufficient for referencing your queues. As such, you must now use a full-queue URL instead of just the queue name.
+* **Changed:** The _global_ `SQS_LOCATION_US` and `SQS_LOCATION_EU` constants have been replaced.
+* **Changed:** Renamed `set_locale()` as `set_region()`. It accepts any of the region constants.
+* **Changed:** Changed the function signature for `list_queues()`. See the updated API reference.
+* **Changed:** Changed the function signature for `set_queue_attributes()`. See the updated API reference.
+* **Changed:** Changed how `returnCurlHandle` is used. Instead of passing `true` as the last parameter to most methods, you now need to explicitly set `array('returnCurlHandle' => true)`. This behavior is consistent with the implementation in other classes.
+* **Changed:** Function signature changed in `get_queue_attributes()`. The `$attribute_name` parameter is now passed as a value in the `$opt` parameter.
+
+### AmazonSQSQueue
+* **Removed:** `AmazonSQSQueue` was a simple wrapper around the AmazonSDB class. It generally failed as an object-centric approach to working with SQS, and as such, has been eliminated. Use the `AmazonSQS` class instead.
+
+
+## Utility Classes
+### CFArray
+* **New:** Extends `ArrayObject`.
+* **New:** Simplified typecasting of SimpleXML nodes to native types (e.g. integers, strings).
+
+### CFBatchRequest
+* **New:** Provides a higher-level API for executing batch requests.
+
+### CFComplexType
+* **New:** Used internally by several classes to handle various complex data-types (e.g. single or multiple values, `Key.x.Subkey.y.Value` combinations).
+* **New:** Introduces a way to convert between JSON, YAML, and the PHP equivalent of Lists and Maps (nested associative arrays).
+
+### CFRequest
+* **New:** Sets some project-specific settings and passes them to the lower-level RequestCore.
+
+### CFResponse
+* **New:** No additional changes from the base `ResponseCore` class.
+
+### CFPolicy
+* **New:** Used for constructing Base64-encoded, JSON policy documents to be passed around to other methods.
+
+### CFSimpleXML
+* **New:** Extends `SimpleXMLElement`.
+* **New:** Simplified node retrieval. All SimpleXML-based objects (e.g. `$response->body`) now have magic methods that allow you to quickly retrieve nodes with the same name
+ * e.g. `$response->body->Name()` will return an array of all SimpleXML nodes that match the `//Name` XPath expression.
+
+### CFUtilities
+* **Fixed:** `to_query_string()` now explicitly passes a `&` character to `http_build_query()` to avoid configuration issues with MAMP/WAMP/XAMP installations.
+* **Fixed:** `convert_response_to_array()` has been fixed to correctly return an all-array response under both PHP 5.2 and 5.3. Previously, PHP 5.3 returned a mix of `array`s and `stdClass` objects.
+* **New:** Added `konst()` to retrieve the value of a class constant, while avoiding the `T_PAAMAYIM_NEKUDOTAYIM` error. Misspelled because `const` is a reserved word.
+* **New:** Added `is_base64()` to determine whether or not a string is Base64-encoded data.
+* **New:** Added `decode_uhex()` to decode `\uXXXX` entities back into their unicode equivalents.
+* **Changed:** Changed `size_readable()`. Now supports units up to exabytes.
+* **Changed:** Moved the `DATE_FORMAT_*` _global_ constants into this class as _class_ constants.
+* **Removed:** Removed `json_encode_php51()` now that the minimum required version is PHP 5.2 (which includes the JSON extension by default).
+* **Removed:** Removed `hex_to_base64()`.
+
+
+## Third-party Libraries
+### CacheCore
+* **New:** Upgraded to version 1.1.1.
+* **New:** Now supports both the [memcache](http://php.net/memcache) extension, but also the newer, faster [memcached](http://php.net/memcached) extension. Prefers `memcached` if both are installed.
+* **Deprecated:** Support for MySQL and PostgreSQL as storage mechanisms has been **deprecated**. Since they're using PDO, they'll continue to function (as we're maintaining SQLite support via PDO), but we recommend migrating to using APC, XCache, Memcache or SQLite if you'd like to continue using response caching.
+* New BSD licensed
+* <http://github.com/skyzyx/cachecore>
+
+### RequestCore
+* **New:** Upgraded to version 1.2.
+* **New:** Now supports streaming up and down.
+* **New:** Now supports "rolling" requests for better scalability.
+* New BSD licensed
+* <http://github.com/skyzyx/requestcore>
diff --git a/3rdparty/aws-sdk/_docs/CONTRIBUTORS.md b/3rdparty/aws-sdk/_docs/CONTRIBUTORS.md
new file mode 100644
index 00000000000..3523bf6723c
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/CONTRIBUTORS.md
@@ -0,0 +1,64 @@
+# Contributors
+
+## AWS SDK for PHP Contributors
+
+Contributions were provided under the Apache 2.0 License, as appropriate.
+
+The following people have provided ideas, support and bug fixes:
+
+* [arech8](http://developer.amazonwebservices.com/connect/profile.jspa?userID=154435) (bug fixes)
+* [Aizat Faiz](http://aizatto.com) (bug fixes)
+* [Ben Lumley](http://github.com/benlumley) (bug fixes)
+* [David Chan](http://www.chandeeland.org) (bug fixes)
+* [Eric Caron](http://www.ericcaron.com) (bug fixes)
+* [Jason Ardell](http://ardell.posterous.com/) (bug fixes)
+* [Jeremy Archuleta](http://code.google.com/u/jeremy.archuleta/) (bug fixes)
+* [Jimmy Berry](http://blog.boombatower.com/) (bug fixes, patches)
+* [Paul Voegler](mailto:voegler@gmx.de) (bug fixes, bug reports, patches)
+* [Peter Bowen](http://github.com/pzb) (feedback, bug reports)
+* [zoxa](https://github.com/zoxa) (bug fixes)
+
+
+## CloudFusion/CacheCore/RequestCore Contributors
+
+Contributions were provided under the New BSD License, as appropriate.
+
+The following people have provided ideas, support and bug fixes:
+
+* [Aaron Collegeman](http://blog.aaroncollegeman.com) (bug fixes)
+* [Alex Schenkel](http://code.google.com/u/alex.schenkel/) (bug fixes)
+* [Andrzej Bednarczyk](http://kreo-consulting.com) (bug fixes)
+* [bprater](http://code.google.com/u/bprater/) (bug fixes)
+* [castoware](http://code.google.com/u/castoware/) (bug fixes)
+* [Chris Chen](http://github.com/chrischen) (bug fixes, patches, support)
+* [Chris Mytton](http://hecticjeff.net) (bug fixes)
+* [evgen.dm](http://code.google.com/u/evgen.dm/) (bug fixes)
+* [gafitescu](http://code.google.com/u/gafitescu/) (bug fixes)
+* [Gary Richardson](http://code.google.com/u/gary.richardson/) (bug fixes)
+* [Gil Hildebrand](http://squidoo.com) (bug fixes)
+* [Guilherme Blanco](http://blog.bisna.com) (bug fixes)
+* [hammjazz](http://code.google.com/u/hammjazz/) (bug fixes)
+* [HelloBunty](http://code.google.com/u/HelloBunty/) (bug fixes)
+* [inputrequired](http://code.google.com/u/inputrequired/) (bug fixes)
+* [Ivo Beckers](http://infopractica.nl) (bug fixes)
+* [Jason Litka](http://jasonlitka.com) (bug fixes, patches)
+* [Jeremy Archuleta](http://code.google.com/u/jeremy.archuleta/) (bug fixes)
+* [John Beales](http://johnbeales.com) (bug fixes)
+* [John Parker](http://code.google.com/u/john3parker/) (bug fixes)
+* [Jon Cianciullo](http://code.google.com/u/jon.cianciullo/) (bug fixes)
+* [kris0476](http://code.google.com/u/kris0476/) (bug fixes)
+* [Matt Terenzio](http://jour.nali.st/blog) (bug fixes, patches)
+* [Mike Jetter](http://mbjetter.com) (bug fixes)
+* [Morten Blinksbjerg Nielsen](http://mbn.dk) (bug fixes)
+* [nathell](http://code.google.com/u/nathell/) (bug fixes)
+* [nickgsuperstar](http://code.google.com/u/nickgsuperstar/) (bug fixes)
+* [ofpichon](http://code.google.com/u/ofpichon/) (bug fixes)
+* [Otavio Ferreira](http://otaviofff.me) (bug fixes)
+* [Paul Voegler](mailto:voegler@gmx.de) (bug fixes, bug reports, patches)
+* [Steve Brozosky](http://code.google.com/u/@UBZWSlJVBxhHXAN1/) (bug fixes)
+* [Steve Chu](http://stevechu.org) (bug fixes)
+* [tommusic](http://code.google.com/u/tommusic/) (bug fixes)
+* [Tyler Hall](http://clickontyler.com) (bug fixes)
+* [webcentrica.co.uk](http://code.google.com/u/@VhBQQldUBBBEXAF1/) (bug fixes)
+* [worden341](http://github.com/worden341) (bug fixes)
+* [yakkyjunk](http://code.google.com/u/yakkyjunk/) (bug fixes)
diff --git a/3rdparty/aws-sdk/_docs/DYNAMODBSESSIONHANDLER.html b/3rdparty/aws-sdk/_docs/DYNAMODBSESSIONHANDLER.html
new file mode 100644
index 00000000000..8b1545db50a
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/DYNAMODBSESSIONHANDLER.html
@@ -0,0 +1,235 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+ <title>README</title>
+ <style type="text/css" media="screen">
+ body {
+ font: 18px/1.5em 'Book Antiqua', 'Palatino Linotype', Palatino, 'Minion Pro', Cambria, Georgia, serif;
+ padding: 50px 10%;
+ max-width: 1000px;
+ margin: 0 auto;
+ color: #080000;
+ background-color: #fbfbf9;
+ }
+ code {
+ font: 13px/1.4em Monaco, monospace;
+ background-color: #f3f3f3;
+ color: #444;
+ padding: 1px 2px;
+
+ border-radius: 2px;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ }
+ pre {
+ border: 1px solid #ddd;
+ border-left: 6px solid #c0c0c0;
+ background-color: #f3f3f3;
+ color: #444;
+ font: 13px/1.4em Monaco, monospace;
+ overflow: auto;
+
+ margin: 1em 0 1.5em 0;
+ padding: 1em;
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+
+ -webkit-border-top-right-radius: 5px;
+ -webkit-border-bottom-right-radius: 5px;
+ -moz-border-radius-topright: 5px;
+ -moz-border-radius-bottomright: 5px;
+ border-top-right-radius: 5px;
+ border-bottom-right-radius: 5px;
+ }
+ pre code {
+ font-family: inherit;
+ font-size: inherit;
+ background-color: inherit;
+ color: inherit;
+ padding: 0;
+
+ border-radius: none;
+ -webkit-border-radius: none;
+ -moz-border-radius: none;
+ }
+ a {
+ color: #326EA1;
+ text-decoration: underline;
+ padding: 1px 2px;
+ -webkit-transition: background-color 0.15s;
+ -webkit-transition: color 0.15s;
+ -moz-transition: background-color 0.15s;
+ -moz-transition: color 0.15s;
+ transition: background-color 0.15s;
+ transition: color 0.15s;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ }
+ a:hover, a.hover {
+ color: #fff;
+ background-color: #333;
+ text-decoration: none;
+ padding: 1px 2px;
+ }
+ a.active {
+ font-weight: bold;
+ }
+ h1, h2, h3, h4, h5, h6 {
+ padding: 0.8em 0 0.2em 0;
+ margin: 0;
+ }
+ h1 {
+ margin-top: 30px;
+ padding: 15px 0 5px 5px;
+ font-size: 2em;
+ line-height: 1.3em;
+ border-bottom: 3px solid #cdcdcc;
+ }
+ h2 {
+ margin-top: 30px;
+ padding: 15px 0 5px 5px;
+ font-size: 1.5em;
+ line-height: 1.3em;
+ border-bottom: 1px solid #cdcdcc;
+ }
+ li {
+ margin: 0;
+ padding: 0;
+ }
+ em, i {
+ font-style: italic;
+ }
+ strong, b {
+ font-weight: bold;
+ color: #000;
+ }
+ p {
+ margin: 0;
+ padding: 0.5em 0;
+ }
+ ul.columns {
+ -moz-column-count: 3;
+ -moz-column-gap: 20px;
+ -webkit-column-count: 3;
+ -webkit-column-gap: 20px;
+ column-count: 3;
+ column-gap: 20px;
+ }
+ dl dt {
+ font: 13px/1.4em Monaco, monospace;
+ font-weight: bold;
+ }
+ dl dd {
+ margin-bottom: 0.5em;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>DynamoDB Session Handler</h1>
+ <p>The <strong>DynamoDB Session Handler</strong> is a custom session handler for PHP that allows Amazon DynamoDB to be used as a session store while still using PHP&rsquo;s native session functions.</p>
+
+ <h2>What issues does this address?</h2>
+ <p>The native PHP session handler stores sessions on the local file system. This is unreliable in distributed web applications, because the user may be routed to servers that do not contain the session data. To solve this problem, PHP developers have implemented custom solutions for storing user session data using databases, shared file systems, Memcache servers, tamper-proof cookies, etc., by taking advantage of the interface provided by PHP via the <code>session_set_save_handler()</code> function. Unfortunately, most of these solutions require a lot of configuration or prior knowledge about the storage mechanism in order to setup. Some of them also require the provisioning or management of additional servers.</p>
+
+ <h2>Proposed solution</h2>
+ <p>The DynamoDB Session Handler uses Amazon DynamoDB as a session store, which alleviates many of the problems with existing solutions. There are no additional servers to manage, and there is very little configuration required. The Amazon DynamoDB is also fundamentally designed for low latency (the data is even stored on <abbr title="Solid State Drive">SSD</abbr>s), so the performance impact is much smaller when compared to other databases. Since the Session Handler is designed to be a drop in replacement for the default PHP session handler, it also implements session locking in a familiar way.</p>
+
+ <h2>How do I use it?</h2>
+ <p>The first step is to instantiate the Amazon DynamoDB client and register the session handler.</p>
+ <pre>require_once 'AWSSDKforPHP/sdk.class.php';
+
+// Instantiate the Amazon DynamoDB client.
+// REMEMBER: You need to set 'default_cache_config' in your config.inc.php.
+$dynamodb = new AmazonDynamoDB();
+
+// Register the DynamoDB Session Handler.
+$handler = $dynamodb->register_session_handler(array(
+ 'table_name' => 'my-sessions-table'
+));</pre>
+ <p>Before you can use the session handler, you need to create a table to store the sessions in. This can be done through the <a href="https://console.aws.amazon.com/dynamodb/home">AWS Console for Amazon DynamoDB</a>, or using the session handler class (which you must configure with the table name like in the example above).</p>
+ <pre>// Create a table for session storage with default settings.
+$handler->create_sessions_table();</pre>
+ <p>If you create the table via the AWS Console, you need to make sure the primary key is a string. By default the DynamoDB Session Handler looks for a key named "id", so if you name the key something else, you will need to specify that when you configure the session handler (see the <a href="#configuration">Configuration section</a> below).</p>
+ <p>Once the session handler is registered with a valid table, you can write to (and read from) the session using the standard <code>$_SESSION</code> superglobal.</p>
+ <pre>// Start the session. This will acquire a lock if session locking is enabled.
+session_start();
+
+// Alter the session data.
+$_SESSION['username'] = 'jeremy';
+$_SESSION['role'] = 'admin';
+
+// Close and write to the session.
+// REMEMBER: You should close the session ASAP to release the session lock.
+session_write_close();</pre>
+
+ <h3>Removing expired sessions</h3>
+ <p>The session handler ties into PHP's native session garbage collection functionality, so expired sessions will be deleted periodically and automatically based on how you configure PHP to do the garbage collection. See the PHP manual for the following PHP INI settings: <a href="http://www.php.net/manual/en/session.configuration.php#ini.session.gc-probability">session.gc_probability</a>, <a href="http://www.php.net/manual/en/session.configuration.php#ini.session.gc-divisor">session.gc_divisor</a>, and <a href="http://www.php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime">session.gc_maxlifetime</a>. You may also manually call the <code>DynamoDBSessionHandler::garbage_collect()</code> to clean up the expired sessions.</p>
+
+ <h2 id="configuration">Configuring the DynamoDB Session Handler</h2>
+ <p>You may configure the behavior of the session handler using a the following settings:</p>
+ <dl>
+ <dt>table_name</dt>
+ <dd>The name of the DynamoDB table in which to store sessions.</dd>
+
+ <dt>hash_key</dt>
+ <dd>The name of the primary hash key in the DynamoDB sessions table.</dd>
+
+ <dt>session_lifetime</dt>
+ <dd>The lifetime of an inactive session before it should be garbage collected. If <code>0</code> is used, then the actual lifetime value that will be used is <code>ini_get('session.gc_maxlifetime')</code>.</dd>
+
+ <dt>consistent_reads</dt>
+ <dd>Whether or not the session handler should do consistent reads from DynamoDB.</dd>
+
+ <dt>session_locking</dt>
+ <dd>Whether or not the session handler should do session locking (see the <a href="#session_locking">Session locking section</a> for more information).</dd>
+
+ <dt>max_lock_wait_time</dt>
+ <dd>Maximum time, in seconds, that the session handler should take to acquire a lock before giving up. Only used if <code>session_locking</code> is <code>true</code>.</dd>
+
+ <dt>min_lock_retry_utime</dt>
+ <dd>Minimum time, in microseconds, that the session handler should wait to retry acquiring a lock. Only used if <code>session_locking</code> is <code>true</code>.</dd>
+
+ <dt>max_lock_retry_utime</dt>
+ <dd>Maximum time, in microseconds, that the session handler should wait to retry acquiring a lock. Only used if <code>session_locking</code> is <code>true</code>.</dd>
+ </dl>
+
+ <p>To configure the Session Handle, you must pass the configuration data into the constructor. (<strong>Note</strong>: The values used below are actually the default settings.)</p>
+ <pre>$dynamodb = new AmazonDynamoDB();
+$handler = $dynamodb->register_session_handler(array(
+ 'table_name' => 'sessions',
+ 'hash_key' => 'id',
+ 'session_lifetime' => 0,
+ 'consistent_reads' => true,
+ 'session_locking' => true,
+ 'max_lock_wait_time' => 15,
+ 'min_lock_retry_utime' => 5000,
+ 'max_lock_retry_utime' => 50000,
+));</pre>
+
+ <h2 id="session_locking">Session locking</h2>
+ <p>The default session handler for PHP locks sessions using a pessimistic locking algorithm. If a request (process) opens a session for reading using the <code>session_start()</code> function, it first acquires a lock. The lock is closed when that request writes back to the session, either when the request is complete, or via the <code>session_write_close()</code> function. Since the DynamoDB Session Handler is meant to be a drop in replacement for the default session handler, it also implements the same locking scheme. However, this can be slow, undesirable, and costly when multiple, simultaneous requests from the same user occur, particularly with ajax requests or HTML iframes. In some cases, you may not want or need the session to be locked. After evaluating whether or not your application actually requires session locking, you may turn off locking when you configure the session handler by setting <code>session_locking</code> to <code>false</code>.</p>
+
+ <h2 id="pricing">Pricing</h2>
+ <p>Aside from nominal data storage and data transfer fees, the costs associated with using Amazon DynamoDB are calculated based on provisioned throughput capacity and item size (see the <a href="http://aws.amazon.com/dynamodb/#pricing">Amazon DynamoDB pricing</a> details). Throughput is measured in units of Read Capacity and Write Capacity. Ultimately, the throughput and costs required for your sessions table is going to be based on your website traffic, but the following is a list of the capacity units required for each session-related operation:</p>
+ <ul>
+ <li><strong>Reading</strong> via <code>session_start()</code>
+ <p>With locking enabled: 1 unit of Write Capacity + 1 unit of Write Capacity for each time it must retry acquiring the lock</p>
+ <p>With locking disabed: 1 unit of Read Capacity (or 0.5 units of Read Capacity if <i>consistent reads</i> are disabled)</p>
+ </li>
+ <li><strong>Writing</strong> via <code>session_write_close()</code>
+ <p>1 unit of Write Capacity</p>
+ </li>
+ <li><strong>Deleting</strong> via <code>session_destroy()</code>
+ <p>1 unit of Write Capacity</p>
+ </li>
+ <li><strong>Garbage Collecting</strong> via <code>DyanamoDBSessionHandler::garbage_collect()</code>
+ <p>0.5 units of Read Capacity per KB of data in the sessions table + 1 unit of Write Capacity per expired item</p>
+ </li>
+ </ul>
+
+ <h2 id="more_information">More information</h2>
+ <p>For more information on the Amazon DynamoDB service please visit the <a href="http://aws.amazon.com/dynamodb">Amazon DynamoDB homepage</a>.</p>
+
+ </body>
+</html>
diff --git a/3rdparty/aws-sdk/_docs/KNOWNISSUES.md b/3rdparty/aws-sdk/_docs/KNOWNISSUES.md
new file mode 100644
index 00000000000..9773c3932b8
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/KNOWNISSUES.md
@@ -0,0 +1,65 @@
+# Known Issues
+
+## 2GB limit for 32-bit stacks; all Windows stacks.
+
+Because PHP's integer type is signed and many platforms use 32-bit integers, the AWS SDK for PHP does not correctly
+handle files larger than 2GB on a 32-bit stack (where "stack" includes CPU, OS, web server, and PHP binary). This is a
+[well-known PHP issue]. In the case of Microsoft® Windows®, there are no official builds of PHP that support 64-bit
+integers.
+
+The recommended solution is to use a 64-bit Linux stack, such as the [64-bit Amazon Linux AMI] with the latest version of
+PHP installed.
+
+For more information, please see: [PHP filesize: Return values]. A workaround is suggested in
+`AmazonS3::create_mpu_object()` [with files bigger than 2GB].
+
+ [well-known PHP issue]: http://www.google.com/search?q=php+2gb+32-bit
+ [64-bit Amazon Linux AMI]: http://aws.amazon.com/amazon-linux-ami/
+ [PHP filesize: Return values]: http://docs.php.net/manual/en/function.filesize.php#refsect1-function.filesize-returnvalues
+ [with files bigger than 2GB]: https://forums.aws.amazon.com/thread.jspa?messageID=215487#215487
+
+
+## Amazon S3 Buckets containing periods
+
+Amazon S3's SSL certificate covers domains that match `*.s3.amazonaws.com`. When buckets (e.g., `my-bucket`) are accessed
+using DNS-style addressing (e.g., `my-bucket.s3.amazonaws.com`), those SSL/HTTPS connections are covered by the certificate.
+
+However, when a bucket name contains one or more periods (e.g., `s3.my-domain.com`) and is accessed using DNS-style
+addressing (e.g., `s3.my-domain.com.s3.amazonaws.com`), that SSL/HTTPS connection will fail because the certificate
+doesn't match.
+
+The most secure workaround is to change the bucket name to one that does not contain periods. Less secure workarounds
+are to use `disable_ssl()` or `disable_ssl_verification()`. Because of the security implications, calling either of
+these methods will throw a warning. You can avoid the warning by adjusting your `error_reporting()` settings.
+
+
+## Expiring request signatures
+
+When leveraging `AmazonS3::create_mpu_object()`, it's possible that later parts of the multipart upload will fail if
+the upload takes more than 15 minutes.
+
+
+## Too many open file connections
+
+When leveraging `AmazonS3::create_mpu_object()`, it's possible that the SDK will attempt to open too many file resources
+at once. Because the file connection limit is not available to the PHP environment, the SDK is unable to automatically
+adjust the number of connections it attempts to open.
+
+A workaround is to increase the part size so that fewer file connections are opened.
+
+
+## Exceptionally large batch requests
+
+When leveraging the batch request feature to execute multiple requests in parallel, it's possible that the SDK will
+throw a fatal exception if a particular batch pool is exceptionally large and a service gets overloaded with requests.
+
+This seems to be most common when attempting to send a large number of emails with the SES service.
+
+
+## Long-running processes using SSL leak memory
+
+When making requests with the SDK over SSL during long-running processes, there will be a gradual memory leak that can
+eventually cause a crash. The leak occurs within the PHP bindings for cURL when attempting to verify the peer during an
+SSL handshake. See <https://bugs.php.net/61030> for details about the bug.
+
+A workaround is to disable SSL for requests executed in long-running processes.
diff --git a/3rdparty/aws-sdk/_docs/LICENSE.md b/3rdparty/aws-sdk/_docs/LICENSE.md
new file mode 100644
index 00000000000..853ab3bae8e
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/LICENSE.md
@@ -0,0 +1,151 @@
+# Apache License
+Version 2.0, January 2004
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+
+## 1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1
+through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the
+License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled
+by, or are under common control with that entity. For the purposes of this definition, "control" means
+(i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract
+or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial
+ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software
+source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form,
+including but not limited to compiled object code, generated documentation, and conversions to other media
+types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License,
+as indicated by a copyright notice that is included in or attached to the work (an example is provided in the
+Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from)
+the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent,
+as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not
+include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work
+and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any
+modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to
+Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to
+submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of
+electronic, verbal, or written communication sent to the Licensor or its representatives, including but not
+limited to communication on electronic mailing lists, source code control systems, and issue tracking systems
+that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but
+excluding communication that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been
+received by Licensor and subsequently incorporated within the Work.
+
+
+## 2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual,
+worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare
+Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+
+## 3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual,
+worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent
+license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such
+license applies only to those patent claims licensable by such Contributor that are necessarily infringed by
+their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such
+Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim
+or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work
+constitutes direct or contributory patent infringement, then any patent licenses granted to You under this
+License for that Work shall terminate as of the date such litigation is filed.
+
+
+## 4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without
+modifications, and in Source or Object form, provided that You meet the following conditions:
+
+ 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+ 2. You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+ 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent,
+ trademark, and attribution notices from the Source form of the Work, excluding those notices that do
+ not pertain to any part of the Derivative Works; and
+
+ 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that
+ You distribute must include a readable copy of the attribution notices contained within such NOTICE
+ file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed as part of the Derivative Works; within
+ the Source form or documentation, if provided along with the Derivative Works; or, within a display
+ generated by the Derivative Works, if and wherever such third-party notices normally appear. The
+ contents of the NOTICE file are for informational purposes only and do not modify the License. You may
+ add Your own attribution notices within Derivative Works that You distribute, alongside or as an
+ addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be
+ construed as modifying the License.
+
+You may add Your own copyright statement to Your modifications and may provide additional or different license
+terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative
+Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the
+conditions stated in this License.
+
+
+## 5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by
+You to the Licensor shall be under the terms and conditions of this License, without any additional terms or
+conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate
+license agreement you may have executed with Licensor regarding such Contributions.
+
+
+## 6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks, service marks, or product names of
+the Licensor, except as required for reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+
+## 7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor
+provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT,
+MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the
+appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+
+## 8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless
+required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any
+Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential
+damages of any character arising as a result of this License or out of the use or inability to use the Work
+(including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has been advised of the possibility
+of such damages.
+
+
+## 9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for,
+acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this
+License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole
+responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold
+each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason
+of your accepting any such warranty or additional liability.
+
+
+END OF TERMS AND CONDITIONS
diff --git a/3rdparty/aws-sdk/_docs/NOTICE.md b/3rdparty/aws-sdk/_docs/NOTICE.md
new file mode 100644
index 00000000000..780c2e4c9d5
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/NOTICE.md
@@ -0,0 +1,444 @@
+# AWS SDK for PHP
+
+Based on [CloudFusion](http://getcloudfusion.com). Includes other third-party software.
+
+See below for complete copyright and licensing notices.
+
+
+## AWS SDK for PHP
+
+<http://aws.amazon.com/php>
+
+Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License").
+You may not use this file except in compliance with the License.
+A copy of the License is located at
+
+<http://aws.amazon.com/apache2.0>
+
+or in the "license" file accompanying this file. This file 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.
+
+
+## CloudFusion
+
+<http://getcloudfusion.com>
+
+* Copyright 2005-2010 [Ryan Parman](http://ryanparman.com)
+* Copyright 2007-2010 [Foleeo Inc.](http://warpshare.com)
+* Copyright 2007-2010 "CONTRIBUTORS" (see [CONTRIBUTORS.md](CONTRIBUTORS.md) for a list)
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the organization nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+<http://opensource.org/licenses/bsd-license.php>
+
+
+## CacheCore
+
+<http://github.com/skyzyx/cachecore>
+
+* Copyright 2007-2010 [Ryan Parman](http://ryanparman.com)
+* Copyright 2007-2010 [Foleeo Inc.](http://warpshare.com)
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the organization nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+<http://opensource.org/licenses/bsd-license.php>
+
+
+## RequestCore
+
+<http://github.com/skyzyx/requestcore>
+
+* Copyright 2007-2010 [Ryan Parman](http://ryanparman.com)
+* Copyright 2007-2010 [Foleeo Inc.](http://warpshare.com)
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the organization nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+<http://opensource.org/licenses/bsd-license.php>
+
+
+## SimplePie
+
+<http://simplepie.org>
+
+* Copyright 2004-2010 [Ryan Parman](http://ryanparman.com)
+* Copyright 2005-2010 [Geoffrey Sneddon](http://gsnedders.com)
+* Copyright 2008-2011 [Ryan McCue](http://ryanmccue.info)
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the organization nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+<http://opensource.org/licenses/bsd-license.php>
+
+
+## Reqwest
+
+<https://github.com/ded/reqwest>
+
+* Copyright 2011 [Dustin Diaz](http://dustindiaz.com)
+
+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.
+
+<http://www.opensource.org/licenses/mit-license.php>
+
+
+## Human readable file sizes
+
+<http://aidanlister.com/2004/04/human-readable-file-sizes/>
+
+* Copyright 2004-2010 [Aidan Lister](http://aidanlister.com)
+* Copyright 2007-2010 [Ryan Parman](http://ryanparman.com)
+
+Redistribution and use in source and binary forms, with or without
+modification, is permitted provided that the following conditions
+are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ 3. The name "PHP" must not be used to endorse or promote products
+ derived from this software without prior written permission. For
+ written permission, please contact group@php.net.
+
+ 4. Products derived from this software may not be called "PHP", nor
+ may "PHP" appear in their name, without prior written permission
+ from group@php.net. You may indicate that your software works in
+ conjunction with PHP by saying "Foo for PHP" instead of calling
+ it "PHP Foo" or "phpfoo"
+
+ 5. The PHP Group may publish revised and/or new versions of the
+ license from time to time. Each version will be given a
+ distinguishing version number.
+ Once covered code has been published under a particular version
+ of the license, you may always continue to use it under the terms
+ of that version. You may also choose to use such covered code
+ under the terms of any subsequent version of the license
+ published by the PHP Group. No one other than the PHP Group has
+ the right to modify the terms applicable to covered code created
+ under this License.
+
+ 6. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes PHP software, freely available from
+ <http://www.php.net/software/>".
+
+THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
+ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
+DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+<http://www.php.net/license/3_01.txt>
+
+
+## Snippets from PHP.net documentation
+
+* `CFUtilities::is_base64()` - Copyright 2008 "debug" <http://us.php.net/manual/en/function.base64-decode.php#81425>
+
+Redistribution and use in source and binary forms, with or without
+modification, is permitted provided that the following conditions
+are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ 3. The name "PHP" must not be used to endorse or promote products
+ derived from this software without prior written permission. For
+ written permission, please contact group@php.net.
+
+ 4. Products derived from this software may not be called "PHP", nor
+ may "PHP" appear in their name, without prior written permission
+ from group@php.net. You may indicate that your software works in
+ conjunction with PHP by saying "Foo for PHP" instead of calling
+ it "PHP Foo" or "phpfoo"
+
+ 5. The PHP Group may publish revised and/or new versions of the
+ license from time to time. Each version will be given a
+ distinguishing version number.
+ Once covered code has been published under a particular version
+ of the license, you may always continue to use it under the terms
+ of that version. You may also choose to use such covered code
+ under the terms of any subsequent version of the license
+ published by the PHP Group. No one other than the PHP Group has
+ the right to modify the terms applicable to covered code created
+ under this License.
+
+ 6. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes PHP software, freely available from
+ <http://www.php.net/software/>".
+
+THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
+ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
+DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+<http://www.php.net/license/3_01.txt>
+
+
+## phunction PHP framework
+
+<http://sourceforge.net/projects/phunction/>
+
+* Copyright 2010 [Alix Axel](mailto:alix-axel@users.sf.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, 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.
+
+<http://www.opensource.org/licenses/mit-license.php>
+
+
+## Symfony YAML Component
+
+<http://components.symfony-project.org/yaml/>
+
+Copyright 2008-2009 [Fabien Potencier](http://fabien.potencier.org)
+
+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.
+
+<http://opensource.org/licenses/mit-license.php>
+
+
+## PEAR Console_ProgressBar
+
+<http://pear.php.net/package/Console_ProgressBar/>
+
+Copyright 2003-2007 [Stefan Walk](http://pear.php.net/user/et)
+
+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.
+
+<http://opensource.org/licenses/mit-license.php>
+
+
+## Mozilla Certificate Authority
+
+* <http://curl.haxx.se/ca/cacert.pem>
+* <https://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1>
+
+The contents of this file are subject to the Mozilla Public License Version
+1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+for the specific language governing rights and limitations under the
+License.
+
+The Original Code is the Netscape security libraries.
+
+The Initial Developer of the Original Code is Netscape Communications
+Corporation. Portions created by the Initial Developer are Copyright
+(C) 1994-2000 the Initial Developer. All Rights Reserved.
+
+<http://www.mozilla.org/MPL/>
+
+
+## array-to-domdocument
+
+<https://code.google.com/p/array-to-domdocument/>
+
+* Copyright 2010-2011 [Omer Hassan](https://code.google.com/u/113495690012051782542/)
+* Portions copyright 2012 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, 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.
+
+<http://opensource.org/licenses/mit-license.php>
diff --git a/3rdparty/aws-sdk/_docs/STREAMWRAPPER_README.html b/3rdparty/aws-sdk/_docs/STREAMWRAPPER_README.html
new file mode 100644
index 00000000000..5d91068aa23
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/STREAMWRAPPER_README.html
@@ -0,0 +1,243 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+ <title>README</title>
+ <style type="text/css" media="screen">
+ body {
+ font: 18px/1.5em 'Book Antiqua', 'Palatino Linotype', Palatino, 'Minion Pro', Cambria, Georgia, serif;
+ padding: 50px 10%;
+ max-width: 1000px;
+ margin: 0 auto;
+ color: #080000;
+ background-color: #fbfbf9;
+ }
+ code {
+ font: 13px/1.4em Monaco, monospace;
+ background-color: #f3f3f3;
+ color: #444;
+ padding: 1px 2px;
+
+ border-radius: 2px;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ }
+ pre {
+ border: 1px solid #ddd;
+ border-left: 6px solid #c0c0c0;
+ background-color: #f3f3f3;
+ color: #444;
+ font: 13px/1.4em Monaco, monospace;
+ overflow: auto;
+
+ margin: 1em 0 1.5em 0;
+ padding: 1em;
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+
+ -webkit-border-top-right-radius: 5px;
+ -webkit-border-bottom-right-radius: 5px;
+ -moz-border-radius-topright: 5px;
+ -moz-border-radius-bottomright: 5px;
+ border-top-right-radius: 5px;
+ border-bottom-right-radius: 5px;
+ }
+ pre code {
+ font-family: inherit;
+ font-size: inherit;
+ background-color: inherit;
+ color: inherit;
+ padding: 0;
+
+ border-radius: none;
+ -webkit-border-radius: none;
+ -moz-border-radius: none;
+ }
+ a {
+ color: #326EA1;
+ text-decoration: underline;
+ padding: 1px 2px;
+ -webkit-transition: background-color 0.15s;
+ -webkit-transition: color 0.15s;
+ -moz-transition: background-color 0.15s;
+ -moz-transition: color 0.15s;
+ transition: background-color 0.15s;
+ transition: color 0.15s;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ }
+ a:hover, a.hover {
+ color: #fff;
+ background-color: #333;
+ text-decoration: none;
+ padding: 1px 2px;
+ }
+ a.active {
+ font-weight: bold;
+ }
+ h1, h2, h3, h4, h5, h6 {
+ padding: 0.8em 0 0.2em 0;
+ margin: 0;
+ }
+ h1 {
+ margin-top: 30px;
+ padding: 15px 0 5px 5px;
+ font-size: 2em;
+ line-height: 1.3em;
+ border-bottom: 3px solid #cdcdcc;
+ }
+ h2 {
+ margin-top: 30px;
+ padding: 15px 0 5px 5px;
+ font-size: 1.5em;
+ line-height: 1.3em;
+ border-bottom: 1px solid #cdcdcc;
+ }
+ li {
+ margin: 0;
+ padding: 0;
+ }
+ em, i {
+ font-style: italic;
+ }
+ strong, b {
+ font-weight: bold;
+ color: #000;
+ }
+ p {
+ margin: 0;
+ padding: 0.5em 0;
+ }
+ ul.columns {
+ -moz-column-count: 3;
+ -moz-column-gap: 20px;
+ -webkit-column-count: 3;
+ -webkit-column-gap: 20px;
+ column-count: 3;
+ column-gap: 20px;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>S3 Stream Wrapper</h1>
+ <p>The <strong>S3 Stream Wrapper</strong> is a stream wrapper interface for PHP that provides access to Amazon S3 using PHP&#8217;s standard File System API functions.</p>
+
+ <h2>What issues does this address?</h2>
+ <p>There are a large number of existing applications, code snippets and other bits of PHP that are designed to read and write from the local file system as part of their normal operations. Many of these apps could benefit from moving into the cloud, but doing so would require rewriting a substantial amount of code.</p>
+ <p>What if we could simplify this process so that the updates required to make an existing application cloud-backed would be very minimal?</p>
+
+ <h2>Proposed solution</h2>
+ <p>PHP provides an interface for solving this exact kind of problem, called the <a href="http://php.net/streamwrapper">Stream Wrapper</a> interface. By writing a class that implements this interface and <a href="http://php.net/manual/en/function.stream-wrapper-register.php">registering it as a handler</a> we can reduce both the amount of rewriting that needs to be done for existing applications, as well as substantially lower the learning curve for reading and writing from Amazon S3.</p>
+
+ <h2>How do I use it?</h2>
+ <p>After including the AWS SDK for PHP in your project, use the <code>AmazonS3::register_stream_wrapper()</code> method to register <code>s3://</code> as a <a href="http://php.net/manual/en/wrappers.php">supported stream wrapper</a> for Amazon S3. <em>It's that simple</em>. Amazon S3 file patterns take the following form: <code>s3://bucket/object</code>.</p>
+
+ <pre><code>require_once 'AWSSDKforPHP/sdk.class.php';
+
+$s3 = new AmazonS3();
+$s3->register_stream_wrapper();
+
+$directory = 's3://my-new-bucket';
+$filename = $directory . '/put.txt';
+$contents = '';
+
+if (mkdir($directory))
+{
+ if (file_put_contents($filename, 'This is some sample data.'))
+ {
+ $handle = fopen($filename, 'rb+');
+ $contents = stream_get_contents($handle);
+ fclose($handle);
+ }
+
+ rmdir($directory);
+}
+
+echo $contents;</code></pre>
+
+ <p>You may also pass a different protocol name as a parameter to <code>AmazonS3::register_stream_wrapper()</code> if you want to use something besides <code>s3://</code>. Using this technique you can create more than one stream wrapper with different configurations (e.g. for different regions). To do that you just need to create separate instances of the <code>AmazonS3</code> class, configure them, and then register a stream wrapper for each of them with different protocol names.</p>
+
+ <pre><code>require_once 'AWSSDKforPHP/sdk.class.php';
+
+$s3east = new AmazonS3();
+$s3east->set_region(AmazonS3::REGION_US_E1);
+$s3east->register_stream_wrapper('s3east');
+mkdir('s3east://my-easterly-bucket');
+
+$s3west = new AmazonS3();
+$s3west->set_region(AmazonS3::REGION_US_W1);
+$s3west->register_stream_wrapper('s3west');
+mkdir('s3west://my-westerly-bucket');</code></pre>
+
+ <h2>Tests and usage examples</h2>
+ <p>We are also including tests written in the <a href="http://qa.php.net/phpt_details.php">PHPT</a> format. Not only do these tests show how the software can be used, but any tests submitted back to us should be in this format. These tests will likely fail for you unless you change the bucket names to be globally unique across S3. You can run the tests with <code>pear</code>.</p>
+ <pre><code>cd S3StreamWrapper/tests;
+pear run-tests;</code></pre>
+ <p>If you have <a href="http://phpunit.de">PHPUnit</a> 3.6+ and <a href="http://xdebug.org">Xdebug</a> installed, you can generate a code coverage report as follows:</p>
+ <pre><code>cd S3StreamWrapper/tests && \
+phpunit --colors --coverage-html ./_coverage_report . && \
+open ./_coverage_report/index.html;</code></pre>
+
+ <h2>Notes and Known Issues</h2>
+ <ul>
+ <li><p><code>stream_lock()</code> and <code>stream_cast()</code> are not currently implemented, and likely won't be.</p></li>
+ <li><p>Strangely <code>touch()</code> doesn&#8217;t seem to work. I think this is because of an issue with my implementation of <code>url_stat()</code>, but I can&#8217;t find any information on the magical combination of parameters that will make this work.</p></li>
+ <li><p>Using <code>fopen()</code> will always open in <code>rb+</code> mode. Amazon S3 as a service doesn&#8217;t support anything else.</p></li>
+ <li><p>Because of the way that PHP interacts with the <a href="http://php.net/manual/en/class.streamwrapper.php">StreamWrapper</a> interface, it&#8217;s difficult to optimize for batch requests under the hood. If you need to push or pull data from several objects, you may find that using <a href="http://docs.amazonwebservices.com/AWSSDKforPHP/latest/#m=CFRuntime/batch">batch requests</a> with the <a href="http://docs.amazonwebservices.com/AWSSDKforPHP/latest/#i=AmazonS3">standard interface</a> has better latency.</p></li>
+ <li><p><code>rmdir()</code> does not do a force-delete, so you will need to iterate over the files to delete them one-by-one.</p></li>
+ <li><p><code>realpath()</code>, <code>glob()</code>, <code>chmod()</code>, <code>chown()</code>, <code>chgrp()</code>, <code>tempnam()</code> and a few other functions don&#8217;t support the StreamWrapper interface at the PHP-level because they're designed to work with the (no/low-latency) local file system.</p></li>
+ <li><p>Support for <code>ftruncate()</code> does not exist in any current release of PHP, but is implemented on the PHP trunk for a future release. <a href="http://bugs.php.net/53888">http://bugs.php.net/53888</a>.</p></li>
+ <li><p>Since <a href="http://docs.amazonwebservices.com/AmazonS3/latest/gsg/WorkingWithS3.html#WriteObject">Amazon S3 doesn&#8217;t support appending data</a>, it is best to avoid functions that expect or rely on that functionality (e.g. <a href="http://php.net/fputcsv">fputcsv()</a>).</p></li>
+ </ul>
+
+ <h2>Successfully tested with</h2>
+ <ul class="columns">
+ <li><a href="http://php.net/close_dir">close_dir()</a></li>
+ <li><a href="http://php.net/file_exists">file_exists()</a></li>
+ <li><a href="http://php.net/file_get_contents">file_get_contents()</a></li>
+ <li><a href="http://php.net/file_put_contents">file_put_contents()</a></li>
+ <li><a href="http://php.net/fclose">fclose()</a></li>
+ <li><a href="http://php.net/feof">feof()</a></li>
+ <li><a href="http://php.net/fflush">fflush()</a></li>
+ <li><a href="http://php.net/fgetc">fgetc()</a></li>
+ <li><a href="http://php.net/fgetcsv">fgetcsv()</a></li>
+ <li><a href="http://php.net/fgets">fgets()</a></li>
+ <li><a href="http://php.net/fgetss">fgetss()</a></li>
+ <li><a href="http://php.net/fopen">fopen()</a></li>
+ <li><a href="http://php.net/fpassthru">fpassthru()</a></li>
+ <li><a href="http://php.net/fputs">fputs()</a></li>
+ <li><a href="http://php.net/fread">fread()</a></li>
+ <li><a href="http://php.net/fseek">fseek()</a></li>
+ <li><a href="http://php.net/fstat">fstat()</a></li>
+ <li><a href="http://php.net/ftell">ftell()</a></li>
+ <li><a href="http://php.net/fwrite">fwrite()</a></li>
+ <li><a href="http://php.net/is_dir">is_dir()</a></li>
+ <li><a href="http://php.net/is_file">is_file()</a></li>
+ <li><a href="http://php.net/is_readable">is_readable()</a></li>
+ <li><a href="http://php.net/is_writable">is_writable()</a></li>
+ <li><a href="http://php.net/mkdir">mkdir()</a></li>
+ <li><a href="http://php.net/open_dir">open_dir()</a></li>
+ <li><a href="http://php.net/read_dir">read_dir()</a></li>
+ <li><a href="http://php.net/rewind">rewind()</a></li>
+ <li><a href="http://php.net/rewinddir">rewinddir()</a></li>
+ <li><a href="http://php.net/rmdir">rmdir()</a></li>
+ <li><a href="http://php.net/scandir">scandir()</a></li>
+ <li><a href="http://php.net/stream_get_contents">stream_get_contents()</a></li>
+ <li><a href="http://php.net/unlink">unlink()</a></li>
+ </ul>
+
+ <h2>Known issues with</h2>
+ <ul>
+ <li><a href="http://php.net/chgrp">chgrp()</a></li>
+ <li><a href="http://php.net/chmod">chmod()</a></li>
+ <li><a href="http://php.net/chown">chown()</a></li>
+ <li><a href="http://php.net/fputcsv">fputcsv()</a></li>
+ <li><a href="http://php.net/glob">glob()</a></li>
+ <li><a href="http://php.net/realpath">realpath()</a></li>
+ <li><a href="http://php.net/tempnam">tempnam()</a></li>
+ <li><a href="http://php.net/touch">touch()</a></li>
+ </ul>
+
+ <p>A future version <em>may</em> provide S3-specific implementations of some of these functions (e.g., <code>s3chmod()</code>, <code>s3glob()</code>, <code>s3touch()</code>).</p>
+ </body>
+</html>
diff --git a/3rdparty/aws-sdk/_docs/WHERE_IS_THE_API_REFERENCE.md b/3rdparty/aws-sdk/_docs/WHERE_IS_THE_API_REFERENCE.md
new file mode 100644
index 00000000000..7ad235576b4
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/WHERE_IS_THE_API_REFERENCE.md
@@ -0,0 +1,2 @@
+You can find the API Reference at:
+http://docs.amazonwebservices.com/AWSSDKforPHP/latest/
diff --git a/3rdparty/aws-sdk/authentication/signable.interface.php b/3rdparty/aws-sdk/authentication/signable.interface.php
new file mode 100644
index 00000000000..5316d16a815
--- /dev/null
+++ b/3rdparty/aws-sdk/authentication/signable.interface.php
@@ -0,0 +1,48 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// INTERFACE
+
+/**
+ * The interface implemented by all signing classes.
+ *
+ * @version 2011.11.22
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+interface Signable
+{
+ /**
+ * Constructs a new instance of the implementing class.
+ *
+ * @param string $endpoint (Required) The endpoint to direct the request to.
+ * @param string $operation (Required) The operation to execute as a result of this request.
+ * @param array $payload (Required) The options to use as part of the payload in the request.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return void
+ */
+ public function __construct($endpoint, $operation, $payload, CFCredential $credentials);
+
+ /**
+ * Generates a cURL handle with all of the required authentication bits set.
+ *
+ * @return resource A cURL handle ready for executing.
+ */
+ public function authenticate();
+}
diff --git a/3rdparty/aws-sdk/authentication/signature_v2query.class.php b/3rdparty/aws-sdk/authentication/signature_v2query.class.php
new file mode 100644
index 00000000000..a91190e1a25
--- /dev/null
+++ b/3rdparty/aws-sdk/authentication/signature_v2query.class.php
@@ -0,0 +1,163 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Implements support for Signature v2 (AWS Query).
+ *
+ * @version 2011.11.22
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class AuthV2Query extends Signer implements Signable
+{
+ /**
+ * Constructs a new instance of the <AuthV2Query> class.
+ *
+ * @param string $endpoint (Required) The endpoint to direct the request to.
+ * @param string $operation (Required) The operation to execute as a result of this request.
+ * @param array $payload (Required) The options to use as part of the payload in the request.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return void
+ */
+ public function __construct($endpoint, $operation, $payload, CFCredential $credentials)
+ {
+ parent::__construct($endpoint, $operation, $payload, $credentials);
+ }
+
+ /**
+ * Generates a cURL handle with all of the required authentication bits set.
+ *
+ * @return resource A cURL handle ready for executing.
+ */
+ public function authenticate()
+ {
+ // Determine signing values
+ $current_time = time();
+ $date = gmdate(CFUtilities::DATE_FORMAT_RFC2616, $current_time);
+ $timestamp = gmdate(CFUtilities::DATE_FORMAT_ISO8601, $current_time);
+ $query = array();
+
+ // Do we have an authentication token?
+ if ($this->auth_token)
+ {
+ $headers['X-Amz-Security-Token'] = $this->auth_token;
+ $query['SecurityToken'] = $this->auth_token;
+ }
+
+ // Only add it if it exists.
+ if ($this->api_version)
+ {
+ $query['Version'] = $this->api_version;
+ }
+
+ $query['Action'] = $this->operation;
+ $query['AWSAccessKeyId'] = $this->key;
+ $query['SignatureMethod'] = 'HmacSHA256';
+ $query['SignatureVersion'] = 2;
+ $query['Timestamp'] = $timestamp;
+
+ // Merge in any options that were passed in
+ if (is_array($this->payload))
+ {
+ $query = array_merge($query, $this->payload);
+ }
+
+ // Do a case-sensitive, natural order sort on the array keys.
+ uksort($query, 'strcmp');
+
+ // Create the string that needs to be hashed.
+ $canonical_query_string = $this->util->to_signable_string($query);
+
+ // Remove the default scheme from the domain.
+ $domain = str_replace(array('http://', 'https://'), '', $this->endpoint);
+
+ // Parse our request.
+ $parsed_url = parse_url('http://' . $domain);
+
+ // Set the proper host header.
+ if (isset($parsed_url['port']) && (integer) $parsed_url['port'] !== 80 && (integer) $parsed_url['port'] !== 443)
+ {
+ $host_header = strtolower($parsed_url['host']) . ':' . $parsed_url['port'];
+ }
+ else
+ {
+ $host_header = strtolower($parsed_url['host']);
+ }
+
+ // Set the proper request URI.
+ $request_uri = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
+
+ // Prepare the string to sign
+ $this->string_to_sign = "POST\n$host_header\n$request_uri\n$canonical_query_string";
+
+ // Hash the AWS secret key and generate a signature for the request.
+ $query['Signature'] = base64_encode(hash_hmac('sha256', $this->string_to_sign, $this->secret_key, true));
+
+ // Generate the querystring from $query
+ $this->querystring = $this->util->to_query_string($query);
+
+ // Gather information to pass along to other classes.
+ $helpers = array(
+ 'utilities' => $this->utilities_class,
+ 'request' => $this->request_class,
+ 'response' => $this->response_class,
+ );
+
+ // Compose the request.
+ $request_url = ($this->use_ssl ? 'https://' : 'http://') . $domain;
+ $request_url .= !isset($parsed_url['path']) ? '/' : '';
+
+ // Instantiate the request class
+ $request = new $this->request_class($request_url, $this->proxy, $helpers, $this->credentials);
+ $request->set_method('POST');
+ $request->set_body($this->querystring);
+ $headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
+
+ // Pass along registered stream callbacks
+ if ($this->registered_streaming_read_callback)
+ {
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
+ }
+
+ if ($this->registered_streaming_write_callback)
+ {
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
+ }
+
+ // Sort headers
+ uksort($headers, 'strnatcasecmp');
+
+ // Add headers to request and compute the string to sign
+ foreach ($headers as $header_key => $header_value)
+ {
+ // Strip linebreaks from header values as they're illegal and can allow for security issues
+ $header_value = str_replace(array("\r", "\n"), '', $header_value);
+
+ // Add the header if it has a value
+ if ($header_value !== '')
+ {
+ $request->add_header($header_key, $header_value);
+ }
+ }
+
+ return $request;
+ }
+}
diff --git a/3rdparty/aws-sdk/authentication/signature_v3json.class.php b/3rdparty/aws-sdk/authentication/signature_v3json.class.php
new file mode 100644
index 00000000000..d07f554d1f7
--- /dev/null
+++ b/3rdparty/aws-sdk/authentication/signature_v3json.class.php
@@ -0,0 +1,235 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Implements support for Signature v3 (JSON).
+ *
+ * @version 2011.12.08
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class AuthV3JSON extends Signer implements Signable
+{
+ /**
+ * Constructs a new instance of the <AuthV3JSON> class.
+ *
+ * @param string $endpoint (Required) The endpoint to direct the request to.
+ * @param string $operation (Required) The operation to execute as a result of this request.
+ * @param array $payload (Required) The options to use as part of the payload in the request.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return void
+ */
+ public function __construct($endpoint, $operation, $payload, CFCredential $credentials)
+ {
+ parent::__construct($endpoint, $operation, $payload, $credentials);
+ }
+
+ /**
+ * Generates a cURL handle with all of the required authentication bits set.
+ *
+ * @return resource A cURL handle ready for executing.
+ */
+ public function authenticate()
+ {
+ // Determine signing values
+ $current_time = time();
+ $date = gmdate(CFUtilities::DATE_FORMAT_RFC2616, $current_time);
+ $timestamp = gmdate(CFUtilities::DATE_FORMAT_ISO8601, $current_time);
+ $nonce = $this->util->generate_guid();
+ $curlopts = array();
+ $signed_headers = array();
+ $return_curl_handle = false;
+ $x_amz_target = null;
+ $query = array('body' => $this->payload);
+
+ // Do we have an authentication token?
+ if ($this->auth_token)
+ {
+ $headers['X-Amz-Security-Token'] = $this->auth_token;
+ $query['SecurityToken'] = $this->auth_token;
+ }
+
+ // Manage the key-value pairs that are used in the query.
+ if (stripos($this->operation, 'x-amz-target') !== false)
+ {
+ $x_amz_target = trim(str_ireplace('x-amz-target:', '', $this->operation));
+ }
+ else
+ {
+ $query['Action'] = $this->operation;
+ }
+
+ // Only add it if it exists.
+ if ($this->api_version)
+ {
+ $query['Version'] = $this->api_version;
+ }
+
+ $curlopts = array();
+
+ // Set custom CURLOPT settings
+ if (is_array($this->payload) && isset($this->payload['curlopts']))
+ {
+ $curlopts = $this->payload['curlopts'];
+ unset($this->payload['curlopts']);
+ }
+
+ // Merge in any options that were passed in
+ if (is_array($this->payload))
+ {
+ $query = array_merge($query, $this->payload);
+ }
+
+ $return_curl_handle = isset($query['returnCurlHandle']) ? $query['returnCurlHandle'] : false;
+ unset($query['returnCurlHandle']);
+
+ // Do a case-sensitive, natural order sort on the array keys.
+ uksort($query, 'strcmp');
+
+ // Normalize JSON input
+ if (isset($query['body']) && $query['body'] === '[]')
+ {
+ $query['body'] = '{}';
+ }
+
+ // Create the string that needs to be hashed.
+ $canonical_query_string = $this->util->encode_signature2($query['body']);
+
+ // Remove the default scheme from the domain.
+ $domain = str_replace(array('http://', 'https://'), '', $this->endpoint);
+
+ // Parse our request.
+ $parsed_url = parse_url('http://' . $domain);
+
+ // Set the proper host header.
+ if (isset($parsed_url['port']) && (integer) $parsed_url['port'] !== 80 && (integer) $parsed_url['port'] !== 443)
+ {
+ $host_header = strtolower($parsed_url['host']) . ':' . $parsed_url['port'];
+ }
+ else
+ {
+ $host_header = strtolower($parsed_url['host']);
+ }
+
+ // Set the proper request URI.
+ $request_uri = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
+
+ // Generate the querystring from $query
+ $this->querystring = $this->util->to_query_string($query);
+
+ // Gather information to pass along to other classes.
+ $helpers = array(
+ 'utilities' => $this->utilities_class,
+ 'request' => $this->request_class,
+ 'response' => $this->response_class,
+ );
+
+ // Compose the request.
+ $request_url = ($this->use_ssl ? 'https://' : 'http://') . $domain;
+ $request_url .= !isset($parsed_url['path']) ? '/' : '';
+
+ // Instantiate the request class
+ $request = new $this->request_class($request_url, $this->proxy, $helpers, $this->credentials);
+ $request->set_method('POST');
+ //$request->set_body($this->querystring);
+ //$headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
+
+ // Signing using X-Amz-Target is handled differently.
+ $headers['X-Amz-Target'] = $x_amz_target;
+ $headers['Content-Type'] = 'application/x-amz-json-1.0';
+ $request->set_body($query['body']);
+ $this->querystring = $query['body'];
+
+ // Pass along registered stream callbacks
+ if ($this->registered_streaming_read_callback)
+ {
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
+ }
+
+ if ($this->registered_streaming_write_callback)
+ {
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
+ }
+
+ // Add authentication headers
+ // $headers['X-Amz-Nonce'] = $nonce;
+ $headers['Date'] = $date;
+ $headers['Content-Length'] = strlen($this->querystring);
+ $headers['Content-MD5'] = $this->util->hex_to_base64(md5($this->querystring));
+ $headers['Host'] = $host_header;
+
+ // Sort headers
+ uksort($headers, 'strnatcasecmp');
+
+ // Prepare the string to sign (HTTP)
+ $this->string_to_sign = "POST\n$request_uri\n\n";
+
+ // Add headers to request and compute the string to sign
+ foreach ($headers as $header_key => $header_value)
+ {
+ // Strip linebreaks from header values as they're illegal and can allow for security issues
+ $header_value = str_replace(array("\r", "\n"), '', $header_value);
+
+ // Add the header if it has a value
+ if ($header_value !== '')
+ {
+ $request->add_header($header_key, $header_value);
+ }
+
+ // Generate the string to sign
+ if (
+ substr(strtolower($header_key), 0, 8) === 'content-' ||
+ strtolower($header_key) === 'date' ||
+ strtolower($header_key) === 'expires' ||
+ strtolower($header_key) === 'host' ||
+ substr(strtolower($header_key), 0, 6) === 'x-amz-'
+ )
+ {
+ $this->string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
+ $signed_headers[] = $header_key;
+ }
+ }
+
+ $this->string_to_sign .= "\n";
+
+ if (isset($query['body']) && $query['body'] !== '')
+ {
+ $this->string_to_sign .= $query['body'];
+ }
+
+ // Convert from string-to-sign to bytes-to-sign
+ $bytes_to_sign = hash('sha256', $this->string_to_sign, true);
+
+ // Hash the AWS secret key and generate a signature for the request.
+ $signature = base64_encode(hash_hmac('sha256', $bytes_to_sign, $this->secret_key, true));
+
+ $headers['X-Amzn-Authorization'] = 'AWS3'
+ . ' AWSAccessKeyId=' . $this->key
+ . ',Algorithm=HmacSHA256'
+ . ',SignedHeaders=' . implode(';', $signed_headers)
+ . ',Signature=' . $signature;
+
+ $request->add_header('X-Amzn-Authorization', $headers['X-Amzn-Authorization']);
+ $request->request_headers = $headers;
+
+ return $request;
+ }
+}
diff --git a/3rdparty/aws-sdk/authentication/signature_v3query.class.php b/3rdparty/aws-sdk/authentication/signature_v3query.class.php
new file mode 100644
index 00000000000..04565f928ed
--- /dev/null
+++ b/3rdparty/aws-sdk/authentication/signature_v3query.class.php
@@ -0,0 +1,192 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Implements support for Signature v3 (AWS Query).
+ *
+ * @version 2011.11.22
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class AuthV3Query extends Signer implements Signable
+{
+ /**
+ * Constructs a new instance of the <AuthV3Query> class.
+ *
+ * @param string $endpoint (Required) The endpoint to direct the request to.
+ * @param string $operation (Required) The operation to execute as a result of this request.
+ * @param array $payload (Required) The options to use as part of the payload in the request.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return void
+ */
+ public function __construct($endpoint, $operation, $payload, CFCredential $credentials)
+ {
+ parent::__construct($endpoint, $operation, $payload, $credentials);
+ }
+
+ /**
+ * Generates a cURL handle with all of the required authentication bits set.
+ *
+ * @return resource A cURL handle ready for executing.
+ */
+ public function authenticate()
+ {
+ // Determine signing values
+ $current_time = time();
+ $date = gmdate(CFUtilities::DATE_FORMAT_RFC2616, $current_time);
+ $timestamp = gmdate(CFUtilities::DATE_FORMAT_ISO8601, $current_time);
+ $nonce = $this->util->generate_guid();
+ $curlopts = array();
+ $signed_headers = array();
+
+ // Do we have an authentication token?
+ if ($this->auth_token)
+ {
+ $headers['X-Amz-Security-Token'] = $this->auth_token;
+ $query['SecurityToken'] = $this->auth_token;
+ }
+
+ $query['Action'] = $this->operation;
+ $query['Version'] = $this->api_version;
+
+ // Set custom CURLOPT settings
+ if (is_array($this->payload) && isset($this->payload['curlopts']))
+ {
+ $curlopts = $this->payload['curlopts'];
+ unset($this->payload['curlopts']);
+ }
+
+ // Merge in any options that were passed in
+ if (is_array($this->payload))
+ {
+ $query = array_merge($query, $this->payload);
+ }
+
+ $return_curl_handle = isset($query['returnCurlHandle']) ? $query['returnCurlHandle'] : false;
+ unset($query['returnCurlHandle']);
+
+ // Do a case-sensitive, natural order sort on the array keys.
+ uksort($query, 'strcmp');
+ $canonical_query_string = $this->util->to_signable_string($query);
+
+ // Remove the default scheme from the domain.
+ $domain = str_replace(array('http://', 'https://'), '', $this->endpoint);
+
+ // Parse our request.
+ $parsed_url = parse_url('http://' . $domain);
+
+ // Set the proper host header.
+ if (isset($parsed_url['port']) && (integer) $parsed_url['port'] !== 80 && (integer) $parsed_url['port'] !== 443)
+ {
+ $host_header = strtolower($parsed_url['host']) . ':' . $parsed_url['port'];
+ }
+ else
+ {
+ $host_header = strtolower($parsed_url['host']);
+ }
+
+ // Set the proper request URI.
+ $request_uri = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
+
+ // Generate the querystring from $query
+ $this->querystring = $this->util->to_query_string($query);
+
+ // Gather information to pass along to other classes.
+ $helpers = array(
+ 'utilities' => $this->utilities_class,
+ 'request' => $this->request_class,
+ 'response' => $this->response_class,
+ );
+
+ // Compose the request.
+ $request_url = ($this->use_ssl ? 'https://' : 'http://') . $domain;
+ $request_url .= !isset($parsed_url['path']) ? '/' : '';
+
+ // Instantiate the request class
+ $request = new $this->request_class($request_url, $this->proxy, $helpers, $this->credentials);
+ $request->set_method('POST');
+ $request->set_body($this->querystring);
+ $headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
+
+ // Pass along registered stream callbacks
+ if ($this->registered_streaming_read_callback)
+ {
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
+ }
+
+ if ($this->registered_streaming_write_callback)
+ {
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
+ }
+
+ // Add authentication headers
+ $headers['X-Amz-Nonce'] = $nonce;
+ $headers['Date'] = $date;
+ $headers['Content-Length'] = strlen($this->querystring);
+ $headers['Content-MD5'] = $this->util->hex_to_base64(md5($this->querystring));
+ $headers['Host'] = $host_header;
+
+ // Sort headers
+ uksort($headers, 'strnatcasecmp');
+
+ // Prepare the string to sign (HTTPS)
+ $this->string_to_sign = $date . $nonce;
+
+ // Add headers to request and compute the string to sign
+ foreach ($headers as $header_key => $header_value)
+ {
+ // Strip linebreaks from header values as they're illegal and can allow for security issues
+ $header_value = str_replace(array("\r", "\n"), '', $header_value);
+
+ // Add the header if it has a value
+ if ($header_value !== '')
+ {
+ $request->add_header($header_key, $header_value);
+ }
+
+ // Generate the string to sign
+ if (
+ substr(strtolower($header_key), 0, 8) === 'content-' ||
+ strtolower($header_key) === 'date' ||
+ strtolower($header_key) === 'expires' ||
+ strtolower($header_key) === 'host' ||
+ substr(strtolower($header_key), 0, 6) === 'x-amz-'
+ )
+ {
+ $signed_headers[] = $header_key;
+ }
+ }
+
+ // Hash the AWS secret key and generate a signature for the request.
+ $signature = base64_encode(hash_hmac('sha256', $this->string_to_sign, $this->secret_key, true));
+
+ $headers['X-Amzn-Authorization'] = 'AWS3-HTTPS'
+ . ' AWSAccessKeyId=' . $this->key
+ . ',Algorithm=HmacSHA256'
+ . ',SignedHeaders=' . implode(';', $signed_headers)
+ . ',Signature=' . $signature;
+
+ $request->add_header('X-Amzn-Authorization', $headers['X-Amzn-Authorization']);
+ $request->request_headers = $headers;
+
+ return $request;
+ }
+}
diff --git a/3rdparty/aws-sdk/authentication/signature_v4json.class.php b/3rdparty/aws-sdk/authentication/signature_v4json.class.php
new file mode 100644
index 00000000000..d3ab07ad8bf
--- /dev/null
+++ b/3rdparty/aws-sdk/authentication/signature_v4json.class.php
@@ -0,0 +1,353 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Implements support for Signature v4 (Query).
+ *
+ * @version 2011.01.03
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class AuthV4JSON extends Signer implements Signable
+{
+ /**
+ * Constructs a new instance of the <AuthV4Query> class.
+ *
+ * @param string $endpoint (Required) The endpoint to direct the request to.
+ * @param string $operation (Required) The operation to execute as a result of this request.
+ * @param array $payload (Required) The options to use as part of the payload in the request.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return void
+ */
+ public function __construct($endpoint, $operation, $payload, CFCredential $credentials)
+ {
+ parent::__construct($endpoint, $operation, $payload, $credentials);
+ }
+
+ /**
+ * Generates a cURL handle with all of the required authentication bits set.
+ *
+ * @return resource A cURL handle ready for executing.
+ */
+ public function authenticate()
+ {
+ // Determine signing values
+ $current_time = time();
+ $timestamp = gmdate(CFUtilities::DATE_FORMAT_SIGV4, $current_time);
+
+ // Initialize
+ $x_amz_target = null;
+
+ $this->headers = array();
+ $this->signed_headers = array();
+ $this->canonical_headers = array();
+ $this->query = array();
+
+ // Prepare JSON structure
+ $decoded = json_decode($this->payload, true);
+ $data = (array) (is_array($decoded) ? $decoded : $this->payload);
+ unset($data['curlopts']);
+ unset($data['returnCurlHandle']);
+ $this->body = json_encode($data);
+ if ($this->body === '' || $this->body === '[]')
+ {
+ $this->body = '{}';
+ }
+
+ // Do we have an authentication token?
+ if ($this->auth_token)
+ {
+ $this->headers['X-Amz-Security-Token'] = $this->auth_token;
+ $this->query['SecurityToken'] = $this->auth_token;
+ }
+
+ // Manage the key-value pairs that are used in the query.
+ if (stripos($this->operation, 'x-amz-target') !== false)
+ {
+ $x_amz_target = trim(str_ireplace('x-amz-target:', '', $this->operation));
+ }
+ else
+ {
+ $this->query['Action'] = $this->operation;
+ }
+
+ // Only add it if it exists.
+ if ($this->api_version)
+ {
+ $this->query['Version'] = $this->api_version;
+ }
+
+ // Do a case-sensitive, natural order sort on the array keys.
+ uksort($this->query, 'strcmp');
+
+ // Remove the default scheme from the domain.
+ $domain = str_replace(array('http://', 'https://'), '', $this->endpoint);
+
+ // Parse our request.
+ $parsed_url = parse_url('http://' . $domain);
+
+ // Set the proper host header.
+ if (isset($parsed_url['port']) && (integer) $parsed_url['port'] !== 80 && (integer) $parsed_url['port'] !== 443)
+ {
+ $host_header = strtolower($parsed_url['host']) . ':' . $parsed_url['port'];
+ }
+ else
+ {
+ $host_header = strtolower($parsed_url['host']);
+ }
+
+ // Generate the querystring from $this->query
+ $this->querystring = $this->util->to_query_string($this->query);
+
+ // Gather information to pass along to other classes.
+ $helpers = array(
+ 'utilities' => $this->utilities_class,
+ 'request' => $this->request_class,
+ 'response' => $this->response_class,
+ );
+
+ // Compose the request.
+ $request_url = ($this->use_ssl ? 'https://' : 'http://') . $domain;
+ $request_url .= !isset($parsed_url['path']) ? '/' : '';
+
+ // Instantiate the request class
+ $request = new $this->request_class($request_url, $this->proxy, $helpers, $this->credentials);
+ $request->set_method('POST');
+ $request->set_body($this->body);
+ $this->querystring = $this->body;
+ $this->headers['Content-Type'] = 'application/x-amz-json-1.1';
+ $this->headers['X-Amz-Target'] = $x_amz_target;
+
+ // Pass along registered stream callbacks
+ if ($this->registered_streaming_read_callback)
+ {
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
+ }
+
+ if ($this->registered_streaming_write_callback)
+ {
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
+ }
+
+ // Add authentication headers
+ $this->headers['X-Amz-Date'] = $timestamp;
+ $this->headers['Content-Length'] = strlen($this->querystring);
+ $this->headers['Host'] = $host_header;
+
+ // Sort headers
+ uksort($this->headers, 'strnatcasecmp');
+
+ // Add headers to request and compute the string to sign
+ foreach ($this->headers as $header_key => $header_value)
+ {
+ // Strip linebreaks from header values as they're illegal and can allow for security issues
+ $header_value = str_replace(array("\r", "\n"), '', $header_value);
+
+ $request->add_header($header_key, $header_value);
+ $this->canonical_headers[] = strtolower($header_key) . ':' . $header_value;
+
+ $this->signed_headers[] = strtolower($header_key);
+ }
+
+ $this->headers['Authorization'] = $this->authorization($timestamp);
+ $request->add_header('Authorization', $this->headers['Authorization']);
+ $request->request_headers = $this->headers;
+
+ return $request;
+ }
+
+ /**
+ * Generates the authorization string to use for the request.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The authorization string.
+ */
+ protected function authorization($datetime)
+ {
+ $access_key_id = $this->key;
+
+ $parts = array();
+ $parts[] = "AWS4-HMAC-SHA256 Credential=${access_key_id}/" . $this->credential_string($datetime);
+ $parts[] = 'SignedHeaders=' . implode(';', $this->signed_headers);
+ $parts[] = 'Signature=' . $this->hex16($this->signature($datetime));
+
+ return implode(',', $parts);
+ }
+
+ /**
+ * Calculate the signature.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The signature.
+ */
+ protected function signature($datetime)
+ {
+ $k_date = $this->hmac('AWS4' . $this->secret_key, substr($datetime, 0, 8));
+ $k_region = $this->hmac($k_date, $this->region());
+ $k_service = $this->hmac($k_region, $this->service());
+ $k_credentials = $this->hmac($k_service, 'aws4_request');
+ $signature = $this->hmac($k_credentials, $this->string_to_sign($datetime));
+
+ return $signature;
+ }
+
+ /**
+ * Calculate the string to sign.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The string to sign.
+ */
+ protected function string_to_sign($datetime)
+ {
+ $parts = array();
+ $parts[] = 'AWS4-HMAC-SHA256';
+ $parts[] = $datetime;
+ $parts[] = $this->credential_string($datetime);
+ $parts[] = $this->hex16($this->hash($this->canonical_request()));
+
+ $this->string_to_sign = implode("\n", $parts);
+
+ return $this->string_to_sign;
+ }
+
+ /**
+ * Generates the credential string to use for signing.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The credential string.
+ */
+ protected function credential_string($datetime)
+ {
+ $parts = array();
+ $parts[] = substr($datetime, 0, 8);
+ $parts[] = $this->region();
+ $parts[] = $this->service();
+ $parts[] = 'aws4_request';
+
+ return implode('/', $parts);
+ }
+
+ /**
+ * Calculate the canonical request.
+ *
+ * @return string The canonical request.
+ */
+ protected function canonical_request()
+ {
+ $parts = array();
+ $parts[] = 'POST';
+ $parts[] = $this->canonical_uri();
+ $parts[] = ''; // $parts[] = $this->canonical_querystring();
+ $parts[] = implode("\n", $this->canonical_headers) . "\n";
+ $parts[] = implode(';', $this->signed_headers);
+ $parts[] = $this->hex16($this->hash($this->body));
+
+ $this->canonical_request = implode("\n", $parts);
+
+ return $this->canonical_request;
+ }
+
+ /**
+ * The region ID to use in the signature.
+ *
+ * @return return The region ID.
+ */
+ protected function region()
+ {
+ $pieces = explode('.', $this->endpoint);
+
+ // Handle cases with single/no region (i.e. service.region.amazonaws.com vs. service.amazonaws.com)
+ if (count($pieces < 4))
+ {
+ return 'us-east-1';
+ }
+
+ return $pieces[1];
+ }
+
+ /**
+ * The service ID to use in the signature.
+ *
+ * @return return The service ID.
+ */
+ protected function service()
+ {
+ $pieces = explode('.', $this->endpoint);
+ return $pieces[0];
+ }
+
+ /**
+ * The request URI path.
+ *
+ * @return string The request URI path.
+ */
+ protected function canonical_uri()
+ {
+ return '/';
+ }
+
+ /**
+ * The canonical query string.
+ *
+ * @return string The canonical query string.
+ */
+ protected function canonical_querystring()
+ {
+ if (!isset($this->canonical_querystring))
+ {
+ $this->canonical_querystring = $this->util->to_signable_string($this->query);
+ }
+
+ return $this->canonical_querystring;
+ }
+
+ /**
+ * Hex16-pack the data.
+ *
+ * @param string $value (Required) The data to hex16 pack.
+ * @return string The hex16-packed data.
+ */
+ protected function hex16($value)
+ {
+ $result = unpack('H*', $value);
+ return reset($result);
+ }
+
+ /**
+ * Applies HMAC SHA-256 encryption to the string, salted by the key.
+ *
+ * @return string Raw HMAC SHA-256 hashed string.
+ */
+ protected function hmac($key, $string)
+ {
+ return hash_hmac('sha256', $string, $key, true);
+ }
+
+ /**
+ * SHA-256 hashes the string.
+ *
+ * @return string Raw SHA-256 hashed string.
+ */
+ protected function hash($string)
+ {
+ return hash('sha256', $string, true);
+ }
+}
diff --git a/3rdparty/aws-sdk/authentication/signature_v4query.class.php b/3rdparty/aws-sdk/authentication/signature_v4query.class.php
new file mode 100644
index 00000000000..bd5a3fbf5b5
--- /dev/null
+++ b/3rdparty/aws-sdk/authentication/signature_v4query.class.php
@@ -0,0 +1,345 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Implements support for Signature v4 (Query).
+ *
+ * @version 2011.01.03
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class AuthV4Query extends Signer implements Signable
+{
+ /**
+ * Constructs a new instance of the <AuthV4Query> class.
+ *
+ * @param string $endpoint (Required) The endpoint to direct the request to.
+ * @param string $operation (Required) The operation to execute as a result of this request.
+ * @param array $payload (Required) The options to use as part of the payload in the request.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return void
+ */
+ public function __construct($endpoint, $operation, $payload, CFCredential $credentials)
+ {
+ parent::__construct($endpoint, $operation, $payload, $credentials);
+ }
+
+ /**
+ * Generates a cURL handle with all of the required authentication bits set.
+ *
+ * @return resource A cURL handle ready for executing.
+ */
+ public function authenticate()
+ {
+ // Determine signing values
+ $current_time = time();
+ $timestamp = gmdate(CFUtilities::DATE_FORMAT_SIGV4, $current_time);
+
+ // Initialize
+ $x_amz_target = null;
+
+ $this->headers = array();
+ $this->signed_headers = array();
+ $this->canonical_headers = array();
+ $this->query = array('body' => is_array($this->payload) ? $this->payload : array());
+
+ // Do we have an authentication token?
+ if ($this->auth_token)
+ {
+ $this->headers['X-Amz-Security-Token'] = $this->auth_token;
+ $this->query['body']['SecurityToken'] = $this->auth_token;
+ }
+
+ // Manage the key-value pairs that are used in the query.
+ if (stripos($this->operation, 'x-amz-target') !== false)
+ {
+ $x_amz_target = trim(str_ireplace('x-amz-target:', '', $this->operation));
+ }
+ else
+ {
+ $this->query['body']['Action'] = $this->operation;
+ }
+
+ // Only add it if it exists.
+ if ($this->api_version)
+ {
+ $this->query['body']['Version'] = $this->api_version;
+ }
+
+ // Do a case-sensitive, natural order sort on the array keys.
+ uksort($this->query['body'], 'strcmp');
+
+ // Remove the default scheme from the domain.
+ $domain = str_replace(array('http://', 'https://'), '', $this->endpoint);
+
+ // Parse our request.
+ $parsed_url = parse_url('http://' . $domain);
+
+ // Set the proper host header.
+ if (isset($parsed_url['port']) && (integer) $parsed_url['port'] !== 80 && (integer) $parsed_url['port'] !== 443)
+ {
+ $host_header = strtolower($parsed_url['host']) . ':' . $parsed_url['port'];
+ }
+ else
+ {
+ $host_header = strtolower($parsed_url['host']);
+ }
+
+ // Generate the querystring from $this->query
+ $this->querystring = $this->util->to_query_string($this->query);
+
+ // Gather information to pass along to other classes.
+ $helpers = array(
+ 'utilities' => $this->utilities_class,
+ 'request' => $this->request_class,
+ 'response' => $this->response_class,
+ );
+
+ // Compose the request.
+ $request_url = ($this->use_ssl ? 'https://' : 'http://') . $domain;
+ $request_url .= !isset($parsed_url['path']) ? '/' : '';
+
+ // Instantiate the request class
+ $request = new $this->request_class($request_url, $this->proxy, $helpers, $this->credentials);
+ $request->set_method('POST');
+ $request->set_body($this->canonical_querystring());
+ $this->querystring = $this->canonical_querystring();
+
+ $this->headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
+ $this->headers['X-Amz-Target'] = $x_amz_target;
+
+ // Pass along registered stream callbacks
+ if ($this->registered_streaming_read_callback)
+ {
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
+ }
+
+ if ($this->registered_streaming_write_callback)
+ {
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
+ }
+
+ // Add authentication headers
+ $this->headers['X-Amz-Date'] = $timestamp;
+ $this->headers['Content-Length'] = strlen($this->querystring);
+ $this->headers['Content-MD5'] = $this->util->hex_to_base64(md5($this->querystring));
+ $this->headers['Host'] = $host_header;
+
+ // Sort headers
+ uksort($this->headers, 'strnatcasecmp');
+
+ // Add headers to request and compute the string to sign
+ foreach ($this->headers as $header_key => $header_value)
+ {
+ // Strip linebreaks from header values as they're illegal and can allow for security issues
+ $header_value = str_replace(array("\r", "\n"), '', $header_value);
+
+ $request->add_header($header_key, $header_value);
+ $this->canonical_headers[] = strtolower($header_key) . ':' . $header_value;
+
+ $this->signed_headers[] = strtolower($header_key);
+ }
+
+ $this->headers['Authorization'] = $this->authorization($timestamp);
+
+ $request->add_header('Authorization', $this->headers['Authorization']);
+ $request->request_headers = $this->headers;
+
+ return $request;
+ }
+
+ /**
+ * Generates the authorization string to use for the request.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The authorization string.
+ */
+ protected function authorization($datetime)
+ {
+ $access_key_id = $this->key;
+
+ $parts = array();
+ $parts[] = "AWS4-HMAC-SHA256 Credential=${access_key_id}/" . $this->credential_string($datetime);
+ $parts[] = 'SignedHeaders=' . implode(';', $this->signed_headers);
+ $parts[] = 'Signature=' . $this->hex16($this->signature($datetime));
+
+ return implode(',', $parts);
+ }
+
+ /**
+ * Calculate the signature.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The signature.
+ */
+ protected function signature($datetime)
+ {
+ $k_date = $this->hmac('AWS4' . $this->secret_key, substr($datetime, 0, 8));
+ $k_region = $this->hmac($k_date, $this->region());
+ $k_service = $this->hmac($k_region, $this->service());
+ $k_credentials = $this->hmac($k_service, 'aws4_request');
+ $signature = $this->hmac($k_credentials, $this->string_to_sign($datetime));
+
+ return $signature;
+ }
+
+ /**
+ * Calculate the string to sign.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The string to sign.
+ */
+ protected function string_to_sign($datetime)
+ {
+ $parts = array();
+ $parts[] = 'AWS4-HMAC-SHA256';
+ $parts[] = $datetime;
+ $parts[] = $this->credential_string($datetime);
+ $parts[] = $this->hex16($this->hash($this->canonical_request()));
+
+ $this->string_to_sign = implode("\n", $parts);
+
+ return $this->string_to_sign;
+ }
+
+ /**
+ * Generates the credential string to use for signing.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The credential string.
+ */
+ protected function credential_string($datetime)
+ {
+ $parts = array();
+ $parts[] = substr($datetime, 0, 8);
+ $parts[] = $this->region();
+ $parts[] = $this->service();
+ $parts[] = 'aws4_request';
+
+ return implode('/', $parts);
+ }
+
+ /**
+ * Calculate the canonical request.
+ *
+ * @return string The canonical request.
+ */
+ protected function canonical_request()
+ {
+ $parts = array();
+ $parts[] = 'POST';
+ $parts[] = $this->canonical_uri();
+ $parts[] = ''; // $parts[] = $this->canonical_querystring();
+ $parts[] = implode("\n", $this->canonical_headers) . "\n";
+ $parts[] = implode(';', $this->signed_headers);
+ $parts[] = $this->hex16($this->hash($this->canonical_querystring()));
+
+ $this->canonical_request = implode("\n", $parts);
+
+ return $this->canonical_request;
+ }
+
+ /**
+ * The region ID to use in the signature.
+ *
+ * @return return The region ID.
+ */
+ protected function region()
+ {
+ $pieces = explode('.', $this->endpoint);
+
+ // Handle cases with single/no region (i.e. service.region.amazonaws.com vs. service.amazonaws.com)
+ if (count($pieces < 4))
+ {
+ return 'us-east-1';
+ }
+
+ return $pieces[1];
+ }
+
+ /**
+ * The service ID to use in the signature.
+ *
+ * @return return The service ID.
+ */
+ protected function service()
+ {
+ $pieces = explode('.', $this->endpoint);
+ return ($pieces[0] === 'email') ? 'ses' : $pieces[0];
+ }
+
+ /**
+ * The request URI path.
+ *
+ * @return string The request URI path.
+ */
+ protected function canonical_uri()
+ {
+ return '/';
+ }
+
+ /**
+ * The canonical query string.
+ *
+ * @return string The canonical query string.
+ */
+ protected function canonical_querystring()
+ {
+ if (!isset($this->canonical_querystring))
+ {
+ $this->canonical_querystring = $this->util->to_signable_string($this->query['body']);
+ }
+
+ return $this->canonical_querystring;
+ }
+
+ /**
+ * Hex16-pack the data.
+ *
+ * @param string $value (Required) The data to hex16 pack.
+ * @return string The hex16-packed data.
+ */
+ protected function hex16($value)
+ {
+ $result = unpack('H*', $value);
+ return reset($result);
+ }
+
+ /**
+ * Applies HMAC SHA-256 encryption to the string, salted by the key.
+ *
+ * @return string Raw HMAC SHA-256 hashed string.
+ */
+ protected function hmac($key, $string)
+ {
+ return hash_hmac('sha256', $string, $key, true);
+ }
+
+ /**
+ * SHA-256 hashes the string.
+ *
+ * @return string Raw SHA-256 hashed string.
+ */
+ protected function hash($string)
+ {
+ return hash('sha256', $string, true);
+ }
+}
diff --git a/3rdparty/aws-sdk/authentication/signer.abstract.php b/3rdparty/aws-sdk/authentication/signer.abstract.php
new file mode 100644
index 00000000000..f6bf7912f7b
--- /dev/null
+++ b/3rdparty/aws-sdk/authentication/signer.abstract.php
@@ -0,0 +1,68 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * The abstract class that serves as the base class that signer classes extend.
+ *
+ * @version 2011.11.22
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+abstract class Signer
+{
+ /**
+ * The endpoint to direct the request to.
+ */
+ public $endpoint;
+
+ /**
+ * The operation to execute as a result of this request.
+ */
+ public $operation;
+
+ /**
+ * The options to use as part of the payload in the request.
+ */
+ public $payload;
+
+ /**
+ * The credentials to use for signing and making requests.
+ */
+ public $credentials;
+
+
+ /**
+ * Constructs a new instance of the implementing class.
+ *
+ * @param string $endpoint (Required) The endpoint to direct the request to.
+ * @param string $operation (Required) The operation to execute as a result of this request.
+ * @param array $payload (Required) The options to use as part of the payload in the request.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return void
+ */
+ public function __construct($endpoint, $operation, $payload, CFCredential $credentials)
+ {
+ $this->endpoint = $endpoint;
+ $this->operation = $operation;
+ $this->payload = $payload;
+ $this->credentials = $credentials;
+ }
+}
diff --git a/3rdparty/aws-sdk/lib/cachecore/LICENSE b/3rdparty/aws-sdk/lib/cachecore/LICENSE
new file mode 100755
index 00000000000..49b38bd620a
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2006-2010 Ryan Parman, Foleeo Inc., and contributors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are
+permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of
+ conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice, this list
+ of conditions and the following disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ * Neither the name of Ryan Parman, Foleeo Inc. nor the names of its contributors may be used to
+ endorse or promote products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
+AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/3rdparty/aws-sdk/lib/cachecore/README b/3rdparty/aws-sdk/lib/cachecore/README
new file mode 100755
index 00000000000..07e00267cbb
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/README
@@ -0,0 +1 @@
+A simple caching system for PHP5 that provides a single interface for a variety of storage types.
diff --git a/3rdparty/aws-sdk/lib/cachecore/_sql/README b/3rdparty/aws-sdk/lib/cachecore/_sql/README
new file mode 100755
index 00000000000..e25d53d1208
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/_sql/README
@@ -0,0 +1,5 @@
+The .sql files in this directory contain the code to create the tables for database caching.
+
+If you're not using database caching, you can safely ignore these.
+
+If you ARE using database caching, simply load the correct *.sql file into your database to set up the required tables.
diff --git a/3rdparty/aws-sdk/lib/cachecore/_sql/mysql.sql b/3rdparty/aws-sdk/lib/cachecore/_sql/mysql.sql
new file mode 100755
index 00000000000..2efee3a732f
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/_sql/mysql.sql
@@ -0,0 +1,7 @@
+CREATE TABLE `cache` (
+ `id` char(40) NOT NULL default '',
+ `expires` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
+ `data` longtext,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `id` (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 \ No newline at end of file
diff --git a/3rdparty/aws-sdk/lib/cachecore/_sql/pgsql.sql b/3rdparty/aws-sdk/lib/cachecore/_sql/pgsql.sql
new file mode 100755
index 00000000000..f2bdd86a528
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/_sql/pgsql.sql
@@ -0,0 +1,6 @@
+CREATE TABLE "cache" (
+ expires timestamp without time zone NOT NULL,
+ id character(40) NOT NULL,
+ data text NOT NULL
+)
+WITH (OIDS=TRUE); \ No newline at end of file
diff --git a/3rdparty/aws-sdk/lib/cachecore/_sql/sqlite3.sql b/3rdparty/aws-sdk/lib/cachecore/_sql/sqlite3.sql
new file mode 100755
index 00000000000..590f45e4ff1
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/_sql/sqlite3.sql
@@ -0,0 +1,2 @@
+CREATE TABLE cache (id TEXT, expires NUMERIC, data BLOB);
+CREATE UNIQUE INDEX idx ON cache(id ASC); \ No newline at end of file
diff --git a/3rdparty/aws-sdk/lib/cachecore/cacheapc.class.php b/3rdparty/aws-sdk/lib/cachecore/cacheapc.class.php
new file mode 100755
index 00000000000..59f5e88f397
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/cacheapc.class.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Container for all APC-based cache methods. Inherits additional methods from <CacheCore>. Adheres
+ * to the ICacheCore interface.
+ *
+ * @version 2012.04.17
+ * @copyright 2006-2012 Ryan Parman
+ * @copyright 2006-2010 Foleeo, Inc.
+ * @copyright 2012 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2010 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ * @link http://github.com/skyzyx/cachecore CacheCore
+ * @link http://getcloudfusion.com CloudFusion
+ * @link http://php.net/apc APC
+ */
+class CacheAPC extends CacheCore implements ICacheCore
+{
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $name (Required) A name to uniquely identify the cache object.
+ * @param string $location (Optional) The location to store the cache object in. This may vary by cache method. The default value is NULL.
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. The default value is true.
+ * @return object Reference to the cache object.
+ */
+ public function __construct($name, $location = null, $expires = 0, $gzip = true)
+ {
+ parent::__construct($name, null, $expires, $gzip);
+ $this->id = $this->name;
+ }
+
+ /**
+ * Creates a new cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function create($data)
+ {
+ $data = serialize($data);
+ $data = $this->gzip ? gzcompress($data) : $data;
+
+ return apc_add($this->id, $data, $this->expires);
+ }
+
+ /**
+ * Reads a cache.
+ *
+ * @return mixed Either the content of the cache object, or boolean `false`.
+ */
+ public function read()
+ {
+ if ($data = apc_fetch($this->id))
+ {
+ $data = $this->gzip ? gzuncompress($data) : $data;
+ return unserialize($data);
+ }
+
+ return false;
+ }
+
+ /**
+ * Updates an existing cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function update($data)
+ {
+ $data = serialize($data);
+ $data = $this->gzip ? gzcompress($data) : $data;
+
+ return apc_store($this->id, $data, $this->expires);
+ }
+
+ /**
+ * Deletes a cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function delete()
+ {
+ return apc_delete($this->id);
+ }
+
+ /**
+ * Implemented here, but always returns `false`. APC manages its own expirations.
+ *
+ * @return boolean Whether the cache is expired or not.
+ */
+ public function is_expired()
+ {
+ return false;
+ }
+
+ /**
+ * Implemented here, but always returns `false`. APC manages its own expirations.
+ *
+ * @return mixed Either the Unix time stamp of the cache creation, or boolean `false`.
+ */
+ public function timestamp()
+ {
+ return false;
+ }
+
+ /**
+ * Implemented here, but always returns `false`. APC manages its own expirations.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function reset()
+ {
+ return false;
+ }
+}
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+class CacheAPC_Exception extends CacheCore_Exception {}
diff --git a/3rdparty/aws-sdk/lib/cachecore/cachecore.class.php b/3rdparty/aws-sdk/lib/cachecore/cachecore.class.php
new file mode 100755
index 00000000000..1670d316408
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/cachecore.class.php
@@ -0,0 +1,160 @@
+<?php
+/**
+ * Container for all shared caching methods. This is not intended to be instantiated directly, but is
+ * extended by the cache-specific classes.
+ *
+ * @version 2012.04.17
+ * @copyright 2006-2012 Ryan Parman
+ * @copyright 2006-2010 Foleeo, Inc.
+ * @copyright 2012 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2010 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ * @link http://github.com/skyzyx/cachecore CacheCore
+ * @link http://getcloudfusion.com CloudFusion
+ */
+class CacheCore
+{
+ /**
+ * A name to uniquely identify the cache object by.
+ */
+ var $name;
+
+ /**
+ * Where to store the cache.
+ */
+ var $location;
+
+ /**
+ * The number of seconds before a cache object is considered stale.
+ */
+ var $expires;
+
+ /**
+ * Used internally to uniquely identify the location + name of the cache object.
+ */
+ var $id;
+
+ /**
+ * Stores the time when the cache object was created.
+ */
+ var $timestamp;
+
+ /**
+ * Stores whether or not the content should be gzipped when stored
+ */
+ var $gzip;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $name (Required) A name to uniquely identify the cache object.
+ * @param string $location (Optional) The location to store the cache object in. This may vary by cache method. The default value is NULL.
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. The default value is true.
+ * @return object Reference to the cache object.
+ */
+ public function __construct($name, $location = null, $expires = 0, $gzip = true)
+ {
+ if (!extension_loaded('zlib'))
+ {
+ $gzip = false;
+ }
+
+ $this->name = $name;
+ $this->location = $location;
+ $this->expires = $expires;
+ $this->gzip = $gzip;
+
+ return $this;
+ }
+
+ /**
+ * Allows for chaining from the constructor. Requires PHP 5.3 or newer.
+ *
+ * @param string $name (Required) A name to uniquely identify the cache object.
+ * @param string $location (Optional) The location to store the cache object in. This may vary by cache method. The default value is NULL.
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. The default value is true.
+ * @return object Reference to the cache object.
+ */
+ public static function init($name, $location = null, $expires = 0, $gzip = true)
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '<'))
+ {
+ throw new Exception('PHP 5.3 or newer is required to use CacheCore::init().');
+ }
+
+ $self = get_called_class();
+ return new $self($name, $location, $expires, $gzip);
+ }
+
+ /**
+ * Set the number of seconds until a cache expires.
+ *
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @return $this
+ */
+ public function expire_in($seconds)
+ {
+ $this->expires = $seconds;
+ return $this;
+ }
+
+ /**
+ * Provides a simple, straightforward cache-logic mechanism. Useful for non-complex response caches.
+ *
+ * @param string|function $callback (Required) The name of the function to fire when we need to fetch new data to cache.
+ * @param array params (Optional) Parameters to pass into the callback function, as an array.
+ * @return array The cached data being requested.
+ */
+ public function response_manager($callback, $params = null)
+ {
+ // Automatically handle $params values.
+ $params = is_array($params) ? $params : array($params);
+
+ if ($data = $this->read())
+ {
+ if ($this->is_expired())
+ {
+ if ($data = call_user_func_array($callback, $params))
+ {
+ $this->update($data);
+ }
+ else
+ {
+ $this->reset();
+ $data = $this->read();
+ }
+ }
+ }
+ else
+ {
+ if ($data = call_user_func_array($callback, $params))
+ {
+ $this->create($data);
+ }
+ }
+
+ return $data;
+ }
+}
+
+
+/*%******************************************************************************************%*/
+// CORE DEPENDENCIES
+
+// Include the ICacheCore interface.
+if (file_exists(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'icachecore.interface.php'))
+{
+ include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'icachecore.interface.php';
+}
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+class CacheCore_Exception extends Exception {}
diff --git a/3rdparty/aws-sdk/lib/cachecore/cachefile.class.php b/3rdparty/aws-sdk/lib/cachecore/cachefile.class.php
new file mode 100755
index 00000000000..3df240151fb
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/cachefile.class.php
@@ -0,0 +1,189 @@
+<?php
+/**
+ * Container for all file-based cache methods. Inherits additional methods from <CacheCore>. Adheres
+ * to the ICacheCore interface.
+ *
+ * @version 2012.04.17
+ * @copyright 2006-2012 Ryan Parman
+ * @copyright 2006-2010 Foleeo, Inc.
+ * @copyright 2012 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2010 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ * @link http://github.com/skyzyx/cachecore CacheCore
+ * @link http://getcloudfusion.com CloudFusion
+ */
+class CacheFile extends CacheCore implements ICacheCore
+{
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $name (Required) A name to uniquely identify the cache object.
+ * @param string $location (Optional) The location to store the cache object in. This may vary by cache method. The default value is NULL.
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. The default value is true.
+ * @return object Reference to the cache object.
+ */
+ public function __construct($name, $location = null, $expires = 0, $gzip = true)
+ {
+ parent::__construct($name, $location, $expires, $gzip);
+ $this->id = $this->location . '/' . $this->name . '.cache';
+ }
+
+ /**
+ * Creates a new cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function create($data)
+ {
+ if (file_exists($this->id))
+ {
+ return false;
+ }
+ elseif (realpath($this->location) && file_exists($this->location) && is_writeable($this->location))
+ {
+ $data = serialize($data);
+ $data = $this->gzip ? gzcompress($data) : $data;
+
+ return (bool) file_put_contents($this->id, $data);
+ }
+ elseif (realpath($this->location) && file_exists($this->location))
+ {
+ throw new CacheFile_Exception('The file system location "' . $this->location . '" is not writable. Check the file system permissions for this directory.');
+ }
+ else
+ {
+ throw new CacheFile_Exception('The file system location "' . $this->location . '" does not exist. Create the directory, or double-check any relative paths that may have been set.');
+ }
+
+ return false;
+ }
+
+ /**
+ * Reads a cache.
+ *
+ * @return mixed Either the content of the cache object, or boolean `false`.
+ */
+ public function read()
+ {
+ if (file_exists($this->id) && is_readable($this->id))
+ {
+ $data = file_get_contents($this->id);
+ $data = $this->gzip ? gzuncompress($data) : $data;
+ $data = unserialize($data);
+
+ if ($data === false)
+ {
+ /*
+ This should only happen when someone changes the gzip settings and there is
+ existing data or someone has been mucking about in the cache folder manually.
+ Delete the bad entry since the file cache doesn't clean up after itself and
+ then return false so fresh data will be retrieved.
+ */
+ $this->delete();
+ return false;
+ }
+
+ return $data;
+ }
+
+ return false;
+ }
+
+ /**
+ * Updates an existing cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function update($data)
+ {
+ if (file_exists($this->id) && is_writeable($this->id))
+ {
+ $data = serialize($data);
+ $data = $this->gzip ? gzcompress($data) : $data;
+
+ return (bool) file_put_contents($this->id, $data);
+ }
+ else
+ {
+ throw new CacheFile_Exception('The file system location is not writeable. Check your file system permissions and ensure that the cache directory exists.');
+ }
+
+ return false;
+ }
+
+ /**
+ * Deletes a cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function delete()
+ {
+ if (file_exists($this->id))
+ {
+ return unlink($this->id);
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks whether the cache object is expired or not.
+ *
+ * @return boolean Whether the cache is expired or not.
+ */
+ public function is_expired()
+ {
+ if ($this->timestamp() + $this->expires < time())
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Retrieves the timestamp of the cache.
+ *
+ * @return mixed Either the Unix time stamp of the cache creation, or boolean `false`.
+ */
+ public function timestamp()
+ {
+ clearstatcache();
+
+ if (file_exists($this->id))
+ {
+ $this->timestamp = filemtime($this->id);
+ return $this->timestamp;
+ }
+
+ return false;
+ }
+
+ /**
+ * Resets the freshness of the cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function reset()
+ {
+ if (file_exists($this->id))
+ {
+ return touch($this->id);
+ }
+
+ return false;
+ }
+}
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+class CacheFile_Exception extends CacheCore_Exception {}
diff --git a/3rdparty/aws-sdk/lib/cachecore/cachemc.class.php b/3rdparty/aws-sdk/lib/cachecore/cachemc.class.php
new file mode 100755
index 00000000000..5b0f8a93061
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/cachemc.class.php
@@ -0,0 +1,183 @@
+<?php
+/**
+ * Container for all Memcache-based cache methods. Inherits additional methods from <CacheCore>. Adheres
+ * to the ICacheCore interface.
+ *
+ * @version 2012.04.17
+ * @copyright 2006-2012 Ryan Parman
+ * @copyright 2006-2010 Foleeo, Inc.
+ * @copyright 2012 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2010 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ * @link http://github.com/skyzyx/cachecore CacheCore
+ * @link http://getcloudfusion.com CloudFusion
+ * @link http://php.net/memcache Memcache
+ * @link http://php.net/memcached Memcached
+ */
+class CacheMC extends CacheCore implements ICacheCore
+{
+ /**
+ * Holds the Memcache object.
+ */
+ var $memcache = null;
+
+ /**
+ * Whether the Memcached extension is being used (as opposed to Memcache).
+ */
+ var $is_memcached = false;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $name (Required) A name to uniquely identify the cache object.
+ * @param string $location (Optional) The location to store the cache object in. This may vary by cache method. The default value is NULL.
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. The default value is true.
+ * @return object Reference to the cache object.
+ */
+ public function __construct($name, $location = null, $expires = 0, $gzip = true)
+ {
+ parent::__construct($name, null, $expires, $gzip);
+ $this->id = $this->name;
+
+ // Prefer Memcached over Memcache.
+ if (class_exists('Memcached'))
+ {
+ $this->memcache = new Memcached();
+ $this->is_memcached = true;
+ }
+ elseif (class_exists('Memcache'))
+ {
+ $this->memcache = new Memcache();
+ }
+ else
+ {
+ return false;
+ }
+
+ // Enable compression, if available
+ if ($this->gzip)
+ {
+ if ($this->is_memcached)
+ {
+ $this->memcache->setOption(Memcached::OPT_COMPRESSION, true);
+ }
+ else
+ {
+ $this->gzip = MEMCACHE_COMPRESSED;
+ }
+ }
+
+ // Process Memcached servers.
+ if (isset($location) && sizeof($location) > 0)
+ {
+ foreach ($location as $loc)
+ {
+ if (isset($loc['port']) && !empty($loc['port']))
+ {
+ $this->memcache->addServer($loc['host'], $loc['port']);
+ }
+ else
+ {
+ $this->memcache->addServer($loc['host'], 11211);
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Creates a new cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function create($data)
+ {
+ if ($this->is_memcached)
+ {
+ return $this->memcache->set($this->id, $data, $this->expires);
+ }
+ return $this->memcache->set($this->id, $data, $this->gzip, $this->expires);
+ }
+
+ /**
+ * Reads a cache.
+ *
+ * @return mixed Either the content of the cache object, or boolean `false`.
+ */
+ public function read()
+ {
+ if ($this->is_memcached)
+ {
+ return $this->memcache->get($this->id);
+ }
+ return $this->memcache->get($this->id, $this->gzip);
+ }
+
+ /**
+ * Updates an existing cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function update($data)
+ {
+ if ($this->is_memcached)
+ {
+ return $this->memcache->replace($this->id, $data, $this->expires);
+ }
+ return $this->memcache->replace($this->id, $data, $this->gzip, $this->expires);
+ }
+
+ /**
+ * Deletes a cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function delete()
+ {
+ return $this->memcache->delete($this->id);
+ }
+
+ /**
+ * Implemented here, but always returns `false`. Memcache manages its own expirations.
+ *
+ * @return boolean Whether the cache is expired or not.
+ */
+ public function is_expired()
+ {
+ return false;
+ }
+
+ /**
+ * Implemented here, but always returns `false`. Memcache manages its own expirations.
+ *
+ * @return mixed Either the Unix time stamp of the cache creation, or boolean `false`.
+ */
+ public function timestamp()
+ {
+ return false;
+ }
+
+ /**
+ * Implemented here, but always returns `false`. Memcache manages its own expirations.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function reset()
+ {
+ return false;
+ }
+}
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+class CacheMC_Exception extends CacheCore_Exception {}
diff --git a/3rdparty/aws-sdk/lib/cachecore/cachepdo.class.php b/3rdparty/aws-sdk/lib/cachecore/cachepdo.class.php
new file mode 100755
index 00000000000..5716021d8fc
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/cachepdo.class.php
@@ -0,0 +1,297 @@
+<?php
+/**
+ * Container for all PDO-based cache methods. Inherits additional methods from <CacheCore>. Adheres
+ * to the ICacheCore interface.
+ *
+ * @version 2012.04.17
+ * @copyright 2006-2012 Ryan Parman
+ * @copyright 2006-2010 Foleeo, Inc.
+ * @copyright 2012 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2010 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ * @link http://github.com/skyzyx/cachecore CacheCore
+ * @link http://getcloudfusion.com CloudFusion
+ * @link http://php.net/pdo PDO
+ */
+class CachePDO extends CacheCore implements ICacheCore
+{
+ /**
+ * Reference to the PDO connection object.
+ */
+ var $pdo = null;
+
+ /**
+ * Holds the parsed URL components.
+ */
+ var $dsn = null;
+
+ /**
+ * Holds the PDO-friendly version of the connection string.
+ */
+ var $dsn_string = null;
+
+ /**
+ * Holds the prepared statement for creating an entry.
+ */
+ var $create = null;
+
+ /**
+ * Holds the prepared statement for reading an entry.
+ */
+ var $read = null;
+
+ /**
+ * Holds the prepared statement for updating an entry.
+ */
+ var $update = null;
+
+ /**
+ * Holds the prepared statement for resetting the expiry of an entry.
+ */
+ var $reset = null;
+
+ /**
+ * Holds the prepared statement for deleting an entry.
+ */
+ var $delete = null;
+
+ /**
+ * Holds the response of the read so we only need to fetch it once instead of doing
+ * multiple queries.
+ */
+ var $store_read = null;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * Tested with [MySQL 5.0.x](http://mysql.com), [PostgreSQL](http://postgresql.com), and
+ * [SQLite 3.x](http://sqlite.org). SQLite 2.x is assumed to work. No other PDO-supported databases have
+ * been tested (e.g. Oracle, Microsoft SQL Server, IBM DB2, ODBC, Sybase, Firebird). Feel free to send
+ * patches for additional database support.
+ *
+ * See <http://php.net/pdo> for more information.
+ *
+ * @param string $name (Required) A name to uniquely identify the cache object.
+ * @param string $location (Optional) The location to store the cache object in. This may vary by cache method. The default value is NULL.
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. The default value is true.
+ * @return object Reference to the cache object.
+ */
+ public function __construct($name, $location = null, $expires = 0, $gzip = true)
+ {
+ // Make sure the name is no longer than 40 characters.
+ $name = sha1($name);
+
+ // Call parent constructor and set id.
+ parent::__construct($name, $location, $expires, $gzip);
+ $this->id = $this->name;
+ $options = array();
+
+ // Check if the location contains :// (e.g. mysql://user:pass@hostname:port/table)
+ if (stripos($location, '://') === false)
+ {
+ // No? Just pass it through.
+ $this->dsn = parse_url($location);
+ $this->dsn_string = $location;
+ }
+ else
+ {
+ // Yes? Parse and set the DSN
+ $this->dsn = parse_url($location);
+ $this->dsn_string = $this->dsn['scheme'] . ':host=' . $this->dsn['host'] . ((isset($this->dsn['port'])) ? ';port=' . $this->dsn['port'] : '') . ';dbname=' . substr($this->dsn['path'], 1);
+ }
+
+ // Make sure that user/pass are defined.
+ $user = isset($this->dsn['user']) ? $this->dsn['user'] : null;
+ $pass = isset($this->dsn['pass']) ? $this->dsn['pass'] : null;
+
+ // Set persistence for databases that support it.
+ switch ($this->dsn['scheme'])
+ {
+ case 'mysql': // MySQL
+ case 'pgsql': // PostgreSQL
+ $options[PDO::ATTR_PERSISTENT] = true;
+ break;
+ }
+
+ // Instantiate a new PDO object with a persistent connection.
+ $this->pdo = new PDO($this->dsn_string, $user, $pass, $options);
+
+ // Define prepared statements for improved performance.
+ $this->create = $this->pdo->prepare("INSERT INTO cache (id, expires, data) VALUES (:id, :expires, :data)");
+ $this->read = $this->pdo->prepare("SELECT id, expires, data FROM cache WHERE id = :id");
+ $this->reset = $this->pdo->prepare("UPDATE cache SET expires = :expires WHERE id = :id");
+ $this->delete = $this->pdo->prepare("DELETE FROM cache WHERE id = :id");
+ }
+
+ /**
+ * Creates a new cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function create($data)
+ {
+ $data = serialize($data);
+ $data = $this->gzip ? gzcompress($data) : $data;
+
+ $this->create->bindParam(':id', $this->id);
+ $this->create->bindParam(':data', $data);
+ $this->create->bindParam(':expires', $this->generate_timestamp());
+
+ return (bool) $this->create->execute();
+ }
+
+ /**
+ * Reads a cache.
+ *
+ * @return mixed Either the content of the cache object, or boolean `false`.
+ */
+ public function read()
+ {
+ if (!$this->store_read)
+ {
+ $this->read->bindParam(':id', $this->id);
+ $this->read->execute();
+ $this->store_read = $this->read->fetch(PDO::FETCH_ASSOC);
+ }
+
+ if ($this->store_read)
+ {
+ $data = $this->store_read['data'];
+ $data = $this->gzip ? gzuncompress($data) : $data;
+
+ return unserialize($data);
+ }
+
+ return false;
+ }
+
+ /**
+ * Updates an existing cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function update($data)
+ {
+ $this->delete();
+ return $this->create($data);
+ }
+
+ /**
+ * Deletes a cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function delete()
+ {
+ $this->delete->bindParam(':id', $this->id);
+ return $this->delete->execute();
+ }
+
+ /**
+ * Checks whether the cache object is expired or not.
+ *
+ * @return boolean Whether the cache is expired or not.
+ */
+ public function is_expired()
+ {
+ if ($this->timestamp() + $this->expires < time())
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Retrieves the timestamp of the cache.
+ *
+ * @return mixed Either the Unix time stamp of the cache creation, or boolean `false`.
+ */
+ public function timestamp()
+ {
+ if (!$this->store_read)
+ {
+ $this->read->bindParam(':id', $this->id);
+ $this->read->execute();
+ $this->store_read = $this->read->fetch(PDO::FETCH_ASSOC);
+ }
+
+ if ($this->store_read)
+ {
+ $value = $this->store_read['expires'];
+
+ // If 'expires' isn't yet an integer, convert it into one.
+ if (!is_numeric($value))
+ {
+ $value = strtotime($value);
+ }
+
+ $this->timestamp = date('U', $value);
+ return $this->timestamp;
+ }
+
+ return false;
+ }
+
+ /**
+ * Resets the freshness of the cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function reset()
+ {
+ $this->reset->bindParam(':id', $this->id);
+ $this->reset->bindParam(':expires', $this->generate_timestamp());
+ return (bool) $this->reset->execute();
+ }
+
+ /**
+ * Returns a list of supported PDO database drivers. Identical to <PDO::getAvailableDrivers()>.
+ *
+ * @return array The list of supported database drivers.
+ * @link http://php.net/pdo.getavailabledrivers PHP Method
+ */
+ public function get_drivers()
+ {
+ return PDO::getAvailableDrivers();
+ }
+
+ /**
+ * Returns a timestamp value apropriate to the current database type.
+ *
+ * @return mixed Timestamp for MySQL and PostgreSQL, integer value for SQLite.
+ */
+ protected function generate_timestamp()
+ {
+ // Define 'expires' settings differently.
+ switch ($this->dsn['scheme'])
+ {
+ // These support timestamps.
+ case 'mysql': // MySQL
+ case 'pgsql': // PostgreSQL
+ $expires = date(DATE_FORMAT_MYSQL, time());
+ break;
+
+ // These support integers.
+ case 'sqlite': // SQLite 3
+ case 'sqlite2': // SQLite 2
+ $expires = time();
+ break;
+ }
+
+ return $expires;
+ }
+}
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+class CachePDO_Exception extends CacheCore_Exception {}
diff --git a/3rdparty/aws-sdk/lib/cachecore/cachexcache.class.php b/3rdparty/aws-sdk/lib/cachecore/cachexcache.class.php
new file mode 100755
index 00000000000..a0f279aaea3
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/cachexcache.class.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * Container for all XCache-based cache methods. Inherits additional methods from <CacheCore>. Adheres
+ * to the ICacheCore interface.
+ *
+ * @version 2012.04.17
+ * @copyright 2006-2012 Ryan Parman
+ * @copyright 2006-2010 Foleeo, Inc.
+ * @copyright 2012 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2010 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ * @link http://github.com/skyzyx/cachecore CacheCore
+ * @link http://getcloudfusion.com CloudFusion
+ * @link http://xcache.lighttpd.net XCache
+ */
+class CacheXCache extends CacheCore implements ICacheCore
+{
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $name (Required) A name to uniquely identify the cache object.
+ * @param string $location (Optional) The location to store the cache object in. This may vary by cache method. The default value is NULL.
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. The default value is true.
+ * @return object Reference to the cache object.
+ */
+ public function __construct($name, $location = null, $expires = 0, $gzip = true)
+ {
+ parent::__construct($name, null, $expires, $gzip);
+ $this->id = $this->name;
+ }
+
+ /**
+ * Creates a new cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function create($data)
+ {
+ $data = serialize($data);
+ $data = $this->gzip ? gzcompress($data) : $data;
+
+ return xcache_set($this->id, $data, $this->expires);
+ }
+
+ /**
+ * Reads a cache.
+ *
+ * @return mixed Either the content of the cache object, or boolean `false`.
+ */
+ public function read()
+ {
+ if ($data = xcache_get($this->id))
+ {
+ $data = $this->gzip ? gzuncompress($data) : $data;
+ return unserialize($data);
+ }
+
+ return false;
+ }
+
+ /**
+ * Updates an existing cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function update($data)
+ {
+ $data = serialize($data);
+ $data = $this->gzip ? gzcompress($data) : $data;
+
+ return xcache_set($this->id, $data, $this->expires);
+ }
+
+ /**
+ * Deletes a cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function delete()
+ {
+ return xcache_unset($this->id);
+ }
+
+ /**
+ * Defined here, but always returns false. XCache manages it's own expirations. It's worth
+ * mentioning that if the server is configured for a long xcache.var_gc_interval then it IS
+ * possible for expired data to remain in the var cache, though it is not possible to access
+ * it.
+ *
+ * @return boolean Whether the cache is expired or not.
+ */
+ public function is_expired()
+ {
+ return false;
+ }
+
+ /**
+ * Implemented here, but always returns `false`. XCache manages its own expirations.
+ *
+ * @return mixed Either the Unix time stamp of the cache creation, or boolean `false`.
+ */
+ public function timestamp()
+ {
+ return false;
+ }
+
+ /**
+ * Implemented here, but always returns `false`. XCache manages its own expirations.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function reset()
+ {
+ return false;
+ }
+}
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+class CacheXCache_Exception extends CacheCore_Exception {}
diff --git a/3rdparty/aws-sdk/lib/cachecore/icachecore.interface.php b/3rdparty/aws-sdk/lib/cachecore/icachecore.interface.php
new file mode 100755
index 00000000000..8d49f5bf492
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/icachecore.interface.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Defines the methods that all implementing classes MUST have. Covers CRUD (create, read, update,
+ * delete) methods, as well as others that are used in the base <CacheCore> class.
+ *
+ * @version 2009.03.22
+ * @copyright 2006-2010 Ryan Parman
+ * @copyright 2006-2010 Foleeo, Inc.
+ * @copyright 2008-2010 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ * @link http://github.com/skyzyx/cachecore CacheCore
+ * @link http://getcloudfusion.com CloudFusion
+ */
+interface ICacheCore
+{
+ /**
+ * Creates a new cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function create($data);
+
+ /**
+ * Reads a cache.
+ *
+ * @return mixed Either the content of the cache object, or boolean `false`.
+ */
+ public function read();
+
+ /**
+ * Updates an existing cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function update($data);
+
+ /**
+ * Deletes a cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function delete();
+
+ /**
+ * Checks whether the cache object is expired or not.
+ *
+ * @return boolean Whether the cache is expired or not.
+ */
+ public function is_expired();
+
+ /**
+ * Retrieves the timestamp of the cache.
+ *
+ * @return mixed Either the Unix time stamp of the cache creation, or boolean `false`.
+ */
+ public function timestamp();
+
+ /**
+ * Resets the freshness of the cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function reset();
+}
diff --git a/3rdparty/aws-sdk/lib/dom/ArrayToDOMDocument.php b/3rdparty/aws-sdk/lib/dom/ArrayToDOMDocument.php
new file mode 100644
index 00000000000..06ad502eebb
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/dom/ArrayToDOMDocument.php
@@ -0,0 +1,181 @@
+<?php
+/**
+ * @author Omer Hassan
+ * @author Ryan Parman
+ * @license MIT
+ */
+class Array2DOM
+{
+ const ATTRIBUTES = '__attributes__';
+ const CONTENT = '__content__';
+
+ /**
+ * @param array $source
+ * @param string $rootTagName
+ * @return DOMDocument
+ */
+ public static function arrayToDOMDocument(array $source, $rootTagName = 'root')
+ {
+ $document = new DOMDocument();
+ $document->appendChild(self::createDOMElement($source, $rootTagName, $document));
+
+ return $document;
+ }
+
+ /**
+ * @param array $source
+ * @param string $rootTagName
+ * @param bool $formatOutput
+ * @return string
+ */
+ public static function arrayToXMLString(array $source, $rootTagName = 'root', $formatOutput = true)
+ {
+ $document = self::arrayToDOMDocument($source, $rootTagName);
+ $document->formatOutput = $formatOutput;
+
+ return $document->saveXML();
+ }
+
+ /**
+ * @param DOMDocument $document
+ * @return array
+ */
+ public static function domDocumentToArray(DOMDocument $document)
+ {
+ return self::createArray($document->documentElement);
+ }
+
+ /**
+ * @param string $xmlString
+ * @return array
+ */
+ public static function xmlStringToArray($xmlString)
+ {
+ $document = new DOMDocument();
+
+ return $document->loadXML($xmlString) ? self::domDocumentToArray($document) : array();
+ }
+
+ /**
+ * @param mixed $source
+ * @param string $tagName
+ * @param DOMDocument $document
+ * @return DOMNode
+ */
+ private static function createDOMElement($source, $tagName, DOMDocument $document)
+ {
+ if (!is_array($source))
+ {
+ $element = $document->createElement($tagName);
+ $element->appendChild($document->createCDATASection($source));
+
+ return $element;
+ }
+
+ $element = $document->createElement($tagName);
+
+ foreach ($source as $key => $value)
+ {
+ if (is_string($key) && !is_numeric($key))
+ {
+ if ($key === self::ATTRIBUTES)
+ {
+ foreach ($value as $attributeName => $attributeValue)
+ {
+ $element->setAttribute($attributeName, $attributeValue);
+ }
+ }
+ elseif ($key === self::CONTENT)
+ {
+ $element->appendChild($document->createCDATASection($value));
+ }
+ elseif (is_string($value) && !is_numeric($value))
+ {
+ $element->appendChild(self::createDOMElement($value, $key, $document));
+ }
+ elseif (is_array($value) && count($value))
+ {
+ $keyNode = $document->createElement($key);
+
+ foreach ($value as $elementKey => $elementValue)
+ {
+ if (is_string($elementKey) && !is_numeric($elementKey))
+ {
+ $keyNode->appendChild(self::createDOMElement($elementValue, $elementKey, $document));
+ }
+ else
+ {
+ $element->appendChild(self::createDOMElement($elementValue, $key, $document));
+ }
+ }
+
+ if ($keyNode->hasChildNodes())
+ {
+ $element->appendChild($keyNode);
+ }
+ }
+ else
+ {
+ if (is_bool($value))
+ {
+ $value = $value ? 'true' : 'false';
+ }
+
+ $element->appendChild(self::createDOMElement($value, $key, $document));
+ }
+ }
+ else
+ {
+ $element->appendChild(self::createDOMElement($value, $tagName, $document));
+ }
+ }
+
+ return $element;
+ }
+
+ /**
+ * @param DOMNode $domNode
+ * @return array
+ */
+ private static function createArray(DOMNode $domNode)
+ {
+ $array = array();
+
+ for ($i = 0; $i < $domNode->childNodes->length; $i++)
+ {
+ $item = $domNode->childNodes->item($i);
+
+ if ($item->nodeType === XML_ELEMENT_NODE)
+ {
+ $arrayElement = array();
+
+ for ($attributeIndex = 0; !is_null($attribute = $item->attributes->item($attributeIndex)); $attributeIndex++)
+ {
+ if ($attribute->nodeType === XML_ATTRIBUTE_NODE)
+ {
+ $arrayElement[self::ATTRIBUTES][$attribute->nodeName] = $attribute->nodeValue;
+ }
+ }
+
+ $children = self::createArray($item);
+
+ if (is_array($children))
+ {
+ $arrayElement = array_merge($arrayElement, $children);
+ }
+ else
+ {
+ $arrayElement[self::CONTENT] = $children;
+ }
+
+ $array[$item->nodeName][] = $arrayElement;
+ }
+ elseif ($item->nodeType === XML_CDATA_SECTION_NODE || ($item->nodeType === XML_TEXT_NODE && trim($item->nodeValue) !== ''))
+ {
+ return $item->nodeValue;
+ }
+ }
+
+ return $array;
+ }
+}
diff --git a/3rdparty/aws-sdk/lib/requestcore/LICENSE b/3rdparty/aws-sdk/lib/requestcore/LICENSE
new file mode 100755
index 00000000000..49b38bd620a
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/requestcore/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2006-2010 Ryan Parman, Foleeo Inc., and contributors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are
+permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of
+ conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice, this list
+ of conditions and the following disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ * Neither the name of Ryan Parman, Foleeo Inc. nor the names of its contributors may be used to
+ endorse or promote products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
+AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/3rdparty/aws-sdk/lib/requestcore/README.md b/3rdparty/aws-sdk/lib/requestcore/README.md
new file mode 100755
index 00000000000..373ea4dccad
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/requestcore/README.md
@@ -0,0 +1,15 @@
+# RequestCore
+
+RequestCore is a lightweight cURL-based HTTP request/response class that leverages MultiCurl for parallel requests.
+
+### PEAR HTTP_Request?
+
+RequestCore was written as a replacement for [PEAR HTTP_Request](http://pear.php.net/http_request/). While PEAR HTTP_Request is full-featured and heavy, RequestCore features only the essentials and is very lightweight. It also leverages the batch request support in cURL's `curl_multi_exec()` to enable multi-threaded requests that fire in parallel.
+
+### Reference and Download
+
+You can find the class reference at <http://skyzyx.github.com/requestcore/>. You can get the code from <http://github.com/skyzyx/requestcore>.
+
+### License and Copyright
+
+This code is Copyright (c) 2008-2010, Ryan Parman. However, I'm licensing this code for others to use under the [Simplified BSD license](http://www.opensource.org/licenses/bsd-license.php).
diff --git a/3rdparty/aws-sdk/lib/requestcore/cacert.pem b/3rdparty/aws-sdk/lib/requestcore/cacert.pem
new file mode 100755
index 00000000000..80bff62fd27
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/requestcore/cacert.pem
@@ -0,0 +1,3390 @@
+##
+## ca-bundle.crt -- Bundle of CA Root Certificates
+##
+## Certificate data from Mozilla as of: Wed Jan 18 00:04:16 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.
+##
+
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+# @(#) $RCSfile: certdata.txt,v $ $Revision: 1.81 $ $Date: 2012/01/17 22:02:37 $
+
+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 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 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-----
+
+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-----
+MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
+EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
+ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
+XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
+lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
+lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
+lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
+66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
+wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
+D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
+BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
+J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
+DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
+a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
+ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
+Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
+UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
+VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
++JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
+IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
+WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
+f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
+4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
+VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 3
+==================
+-----BEGIN CERTIFICATE-----
+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
+EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
+OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
+DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
+KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
+DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
+BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
+p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
+nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
+MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
+Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
+uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
+BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
+YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
+BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
+VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
+ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
+AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
+qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
+hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
+POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
+Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
+8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
+bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
+g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
+vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
+qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
+-----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 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 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-----
+
+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 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-----
+MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQG
+EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy
+dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4
+MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln
+aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIIC
+IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9m2BtRsiM
+MW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdihFvkcxC7mlSpnzNApbjyF
+NDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/TilftKaNXXsLmREDA/7n29uj/x2lzZAe
+AR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkC
+b6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn
+7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbN
+cA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUp
+WyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5
+haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNY
+MUJDLXT5xp6mig/p/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw
+HQYDVR0hBBYwFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j
+BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9
+MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn
+jgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQ
+MbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4H
+VtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtl
+vrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ipmXeascCl
+OS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HHb6D0jqTsNFFbjCYDcKF3
+1QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBaZmBwXarNeNQk7shBoJMBkpxq
+nvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCy
+x/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMW
+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 Gold CA - G2
+======================
+-----BEGIN CERTIFICATE-----
+MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
+EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
+MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
+c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
+t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
+jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
+vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
+ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
+AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
+jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
+peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
+7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
+GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
+OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
+L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
+5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
+44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
+Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
+Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
+mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
+vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
+KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
+NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
+viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
+-----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-----
+
+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 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-----
+MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
+CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
+Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
+TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
+ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
+5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
+vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
+CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
+e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
+OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
+CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
+48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
+trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
+qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
+AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
+ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
+A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
++51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
+f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
+kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
+CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
+URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
+CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
+oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
+IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
+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-----
+MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD
+T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4
+MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG
+A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk
+WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD
+YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew
+MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb
+m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk
+HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT
+xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2
+3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9
+2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq
+TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz
+4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU
+9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv
+bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg
+aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP
+eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk
+zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1
+ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI
+KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq
+nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE
+I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp
+MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o
+tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA==
+-----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-----
+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
+EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
+MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
+QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
+03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
+ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
++zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
+PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
+OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
+F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
+0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
+leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
+AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
+SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
+NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
+BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
+Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
+kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
+hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
+g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
+aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
+nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
+ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
+Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
+WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
+-----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-----
diff --git a/3rdparty/aws-sdk/lib/requestcore/requestcore.class.php b/3rdparty/aws-sdk/lib/requestcore/requestcore.class.php
new file mode 100755
index 00000000000..087694f08cd
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/requestcore/requestcore.class.php
@@ -0,0 +1,1028 @@
+<?php
+/**
+ * Handles all HTTP requests using cURL and manages the responses.
+ *
+ * @version 2012.01.17
+ * @copyright 2006-2011 Ryan Parman
+ * @copyright 2006-2010 Foleeo Inc.
+ * @copyright 2010-2011 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2011 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ */
+class RequestCore
+{
+ /**
+ * The URL being requested.
+ */
+ public $request_url;
+
+ /**
+ * The headers being sent in the request.
+ */
+ public $request_headers;
+
+ /**
+ * The body being sent in the request.
+ */
+ public $request_body;
+
+ /**
+ * The response returned by the request.
+ */
+ public $response;
+
+ /**
+ * The headers returned by the request.
+ */
+ public $response_headers;
+
+ /**
+ * The body returned by the request.
+ */
+ public $response_body;
+
+ /**
+ * The HTTP status code returned by the request.
+ */
+ public $response_code;
+
+ /**
+ * Additional response data.
+ */
+ public $response_info;
+
+ /**
+ * The handle for the cURL object.
+ */
+ public $curl_handle;
+
+ /**
+ * The method by which the request is being made.
+ */
+ public $method;
+
+ /**
+ * Stores the proxy settings to use for the request.
+ */
+ public $proxy = null;
+
+ /**
+ * The username to use for the request.
+ */
+ public $username = null;
+
+ /**
+ * The password to use for the request.
+ */
+ public $password = null;
+
+ /**
+ * Custom CURLOPT settings.
+ */
+ public $curlopts = null;
+
+ /**
+ * The state of debug mode.
+ */
+ public $debug_mode = false;
+
+ /**
+ * The default class to use for HTTP Requests (defaults to <RequestCore>).
+ */
+ public $request_class = 'RequestCore';
+
+ /**
+ * The default class to use for HTTP Responses (defaults to <ResponseCore>).
+ */
+ public $response_class = 'ResponseCore';
+
+ /**
+ * Default useragent string to use.
+ */
+ public $useragent = 'RequestCore/1.4.4';
+
+ /**
+ * File to read from while streaming up.
+ */
+ public $read_file = null;
+
+ /**
+ * The resource to read from while streaming up.
+ */
+ public $read_stream = null;
+
+ /**
+ * The size of the stream to read from.
+ */
+ public $read_stream_size = null;
+
+ /**
+ * The length already read from the stream.
+ */
+ public $read_stream_read = 0;
+
+ /**
+ * File to write to while streaming down.
+ */
+ public $write_file = null;
+
+ /**
+ * The resource to write to while streaming down.
+ */
+ public $write_stream = null;
+
+ /**
+ * Stores the intended starting seek position.
+ */
+ public $seek_position = null;
+
+ /**
+ * The location of the cacert.pem file to use.
+ */
+ public $cacert_location = false;
+
+ /**
+ * The state of SSL certificate verification.
+ */
+ public $ssl_verification = true;
+
+ /**
+ * The user-defined callback function to call when a stream is read from.
+ */
+ public $registered_streaming_read_callback = null;
+
+ /**
+ * The user-defined callback function to call when a stream is written to.
+ */
+ public $registered_streaming_write_callback = null;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTANTS
+
+ /**
+ * GET HTTP Method
+ */
+ const HTTP_GET = 'GET';
+
+ /**
+ * POST HTTP Method
+ */
+ const HTTP_POST = 'POST';
+
+ /**
+ * PUT HTTP Method
+ */
+ const HTTP_PUT = 'PUT';
+
+ /**
+ * DELETE HTTP Method
+ */
+ const HTTP_DELETE = 'DELETE';
+
+ /**
+ * HEAD HTTP Method
+ */
+ const HTTP_HEAD = 'HEAD';
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR/DESTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $url (Optional) The URL to request or service endpoint to query.
+ * @param string $proxy (Optional) The faux-url to use for proxy settings. Takes the following format: `proxy://user:pass@hostname:port`
+ * @param array $helpers (Optional) An associative array of classnames to use for request, and response functionality. Gets passed in automatically by the calling class.
+ * @return $this A reference to the current instance.
+ */
+ public function __construct($url = null, $proxy = null, $helpers = null)
+ {
+ // Set some default values.
+ $this->request_url = $url;
+ $this->method = self::HTTP_GET;
+ $this->request_headers = array();
+ $this->request_body = '';
+
+ // Set a new Request class if one was set.
+ if (isset($helpers['request']) && !empty($helpers['request']))
+ {
+ $this->request_class = $helpers['request'];
+ }
+
+ // Set a new Request class if one was set.
+ if (isset($helpers['response']) && !empty($helpers['response']))
+ {
+ $this->response_class = $helpers['response'];
+ }
+
+ if ($proxy)
+ {
+ $this->set_proxy($proxy);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Destructs the instance. Closes opened file handles.
+ *
+ * @return $this A reference to the current instance.
+ */
+ public function __destruct()
+ {
+ if (isset($this->read_file) && isset($this->read_stream))
+ {
+ fclose($this->read_stream);
+ }
+
+ if (isset($this->write_file) && isset($this->write_stream))
+ {
+ fclose($this->write_stream);
+ }
+
+ return $this;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // REQUEST METHODS
+
+ /**
+ * Sets the credentials to use for authentication.
+ *
+ * @param string $user (Required) The username to authenticate with.
+ * @param string $pass (Required) The password to authenticate with.
+ * @return $this A reference to the current instance.
+ */
+ public function set_credentials($user, $pass)
+ {
+ $this->username = $user;
+ $this->password = $pass;
+ return $this;
+ }
+
+ /**
+ * Adds a custom HTTP header to the cURL request.
+ *
+ * @param string $key (Required) The custom HTTP header to set.
+ * @param mixed $value (Required) The value to assign to the custom HTTP header.
+ * @return $this A reference to the current instance.
+ */
+ public function add_header($key, $value)
+ {
+ $this->request_headers[$key] = $value;
+ return $this;
+ }
+
+ /**
+ * Removes an HTTP header from the cURL request.
+ *
+ * @param string $key (Required) The custom HTTP header to set.
+ * @return $this A reference to the current instance.
+ */
+ public function remove_header($key)
+ {
+ if (isset($this->request_headers[$key]))
+ {
+ unset($this->request_headers[$key]);
+ }
+ return $this;
+ }
+
+ /**
+ * Set the method type for the request.
+ *
+ * @param string $method (Required) One of the following constants: <HTTP_GET>, <HTTP_POST>, <HTTP_PUT>, <HTTP_HEAD>, <HTTP_DELETE>.
+ * @return $this A reference to the current instance.
+ */
+ public function set_method($method)
+ {
+ $this->method = strtoupper($method);
+ return $this;
+ }
+
+ /**
+ * Sets a custom useragent string for the class.
+ *
+ * @param string $ua (Required) The useragent string to use.
+ * @return $this A reference to the current instance.
+ */
+ public function set_useragent($ua)
+ {
+ $this->useragent = $ua;
+ return $this;
+ }
+
+ /**
+ * Set the body to send in the request.
+ *
+ * @param string $body (Required) The textual content to send along in the body of the request.
+ * @return $this A reference to the current instance.
+ */
+ public function set_body($body)
+ {
+ $this->request_body = $body;
+ return $this;
+ }
+
+ /**
+ * Set the URL to make the request to.
+ *
+ * @param string $url (Required) The URL to make the request to.
+ * @return $this A reference to the current instance.
+ */
+ public function set_request_url($url)
+ {
+ $this->request_url = $url;
+ return $this;
+ }
+
+ /**
+ * Set additional CURLOPT settings. These will merge with the default settings, and override if
+ * there is a duplicate.
+ *
+ * @param array $curlopts (Optional) A set of key-value pairs that set `CURLOPT` options. These will merge with the existing CURLOPTs, and ones passed here will override the defaults. Keys should be the `CURLOPT_*` constants, not strings.
+ * @return $this A reference to the current instance.
+ */
+ public function set_curlopts($curlopts)
+ {
+ $this->curlopts = $curlopts;
+ return $this;
+ }
+
+ /**
+ * Sets the length in bytes to read from the stream while streaming up.
+ *
+ * @param integer $size (Required) The length in bytes to read from the stream.
+ * @return $this A reference to the current instance.
+ */
+ public function set_read_stream_size($size)
+ {
+ $this->read_stream_size = $size;
+
+ return $this;
+ }
+
+ /**
+ * Sets the resource to read from while streaming up. Reads the stream from its current position until
+ * EOF or `$size` bytes have been read. If `$size` is not given it will be determined by <php:fstat()> and
+ * <php:ftell()>.
+ *
+ * @param resource $resource (Required) The readable resource to read from.
+ * @param integer $size (Optional) The size of the stream to read.
+ * @return $this A reference to the current instance.
+ */
+ public function set_read_stream($resource, $size = null)
+ {
+ if (!isset($size) || $size < 0)
+ {
+ $stats = fstat($resource);
+
+ if ($stats && $stats['size'] >= 0)
+ {
+ $position = ftell($resource);
+
+ if ($position !== false && $position >= 0)
+ {
+ $size = $stats['size'] - $position;
+ }
+ }
+ }
+
+ $this->read_stream = $resource;
+
+ return $this->set_read_stream_size($size);
+ }
+
+ /**
+ * Sets the file to read from while streaming up.
+ *
+ * @param string $location (Required) The readable location to read from.
+ * @return $this A reference to the current instance.
+ */
+ public function set_read_file($location)
+ {
+ $this->read_file = $location;
+ $read_file_handle = fopen($location, 'r');
+
+ return $this->set_read_stream($read_file_handle);
+ }
+
+ /**
+ * Sets the resource to write to while streaming down.
+ *
+ * @param resource $resource (Required) The writeable resource to write to.
+ * @return $this A reference to the current instance.
+ */
+ public function set_write_stream($resource)
+ {
+ $this->write_stream = $resource;
+
+ return $this;
+ }
+
+ /**
+ * Sets the file to write to while streaming down.
+ *
+ * @param string $location (Required) The writeable location to write to.
+ * @return $this A reference to the current instance.
+ */
+ public function set_write_file($location)
+ {
+ $this->write_file = $location;
+ $write_file_handle = fopen($location, 'w');
+
+ return $this->set_write_stream($write_file_handle);
+ }
+
+ /**
+ * Set the proxy to use for making requests.
+ *
+ * @param string $proxy (Required) The faux-url to use for proxy settings. Takes the following format: `proxy://user:pass@hostname:port`
+ * @return $this A reference to the current instance.
+ */
+ public function set_proxy($proxy)
+ {
+ $proxy = parse_url($proxy);
+ $proxy['user'] = isset($proxy['user']) ? $proxy['user'] : null;
+ $proxy['pass'] = isset($proxy['pass']) ? $proxy['pass'] : null;
+ $proxy['port'] = isset($proxy['port']) ? $proxy['port'] : null;
+ $this->proxy = $proxy;
+ return $this;
+ }
+
+ /**
+ * Set the intended starting seek position.
+ *
+ * @param integer $position (Required) The byte-position of the stream to begin reading from.
+ * @return $this A reference to the current instance.
+ */
+ public function set_seek_position($position)
+ {
+ $this->seek_position = isset($position) ? (integer) $position : null;
+
+ return $this;
+ }
+
+ /**
+ * Register a callback function to execute whenever a data stream is read from using
+ * <CFRequest::streaming_read_callback()>.
+ *
+ * The user-defined callback function should accept three arguments:
+ *
+ * <ul>
+ * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
+ * <li><code>$file_handle</code> - <code>resource</code> - Required - The file handle resource that represents the file on the local file system.</li>
+ * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
+ * </ul>
+ *
+ * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
+ * <li>The name of a global function to execute, passed as a string.</li>
+ * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
+ * <li>An anonymous function (PHP 5.3+).</li></ul>
+ * @return $this A reference to the current instance.
+ */
+ public function register_streaming_read_callback($callback)
+ {
+ $this->registered_streaming_read_callback = $callback;
+
+ return $this;
+ }
+
+ /**
+ * Register a callback function to execute whenever a data stream is written to using
+ * <CFRequest::streaming_write_callback()>.
+ *
+ * The user-defined callback function should accept two arguments:
+ *
+ * <ul>
+ * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
+ * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
+ * </ul>
+ *
+ * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
+ * <li>The name of a global function to execute, passed as a string.</li>
+ * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
+ * <li>An anonymous function (PHP 5.3+).</li></ul>
+ * @return $this A reference to the current instance.
+ */
+ public function register_streaming_write_callback($callback)
+ {
+ $this->registered_streaming_write_callback = $callback;
+
+ return $this;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // PREPARE, SEND, AND PROCESS REQUEST
+
+ /**
+ * A callback function that is invoked by cURL for streaming up.
+ *
+ * @param resource $curl_handle (Required) The cURL handle for the request.
+ * @param resource $file_handle (Required) The open file handle resource.
+ * @param integer $length (Required) The maximum number of bytes to read.
+ * @return binary Binary data from a stream.
+ */
+ public function streaming_read_callback($curl_handle, $file_handle, $length)
+ {
+ // Once we've sent as much as we're supposed to send...
+ if ($this->read_stream_read >= $this->read_stream_size)
+ {
+ // Send EOF
+ return '';
+ }
+
+ // If we're at the beginning of an upload and need to seek...
+ if ($this->read_stream_read == 0 && isset($this->seek_position) && $this->seek_position !== ftell($this->read_stream))
+ {
+ if (fseek($this->read_stream, $this->seek_position) !== 0)
+ {
+ throw new RequestCore_Exception('The stream does not support seeking and is either not at the requested position or the position is unknown.');
+ }
+ }
+
+ $read = fread($this->read_stream, min($this->read_stream_size - $this->read_stream_read, $length)); // Remaining upload data or cURL's requested chunk size
+ $this->read_stream_read += strlen($read);
+
+ $out = $read === false ? '' : $read;
+
+ // Execute callback function
+ if ($this->registered_streaming_read_callback)
+ {
+ call_user_func($this->registered_streaming_read_callback, $curl_handle, $file_handle, $out);
+ }
+
+ return $out;
+ }
+
+ /**
+ * A callback function that is invoked by cURL for streaming down.
+ *
+ * @param resource $curl_handle (Required) The cURL handle for the request.
+ * @param binary $data (Required) The data to write.
+ * @return integer The number of bytes written.
+ */
+ public function streaming_write_callback($curl_handle, $data)
+ {
+ $length = strlen($data);
+ $written_total = 0;
+ $written_last = 0;
+
+ while ($written_total < $length)
+ {
+ $written_last = fwrite($this->write_stream, substr($data, $written_total));
+
+ if ($written_last === false)
+ {
+ return $written_total;
+ }
+
+ $written_total += $written_last;
+ }
+
+ // Execute callback function
+ if ($this->registered_streaming_write_callback)
+ {
+ call_user_func($this->registered_streaming_write_callback, $curl_handle, $written_total);
+ }
+
+ return $written_total;
+ }
+
+ /**
+ * Prepares and adds the details of the cURL request. This can be passed along to a <php:curl_multi_exec()>
+ * function.
+ *
+ * @return resource The handle for the cURL object.
+ */
+ public function prep_request()
+ {
+ $curl_handle = curl_init();
+
+ // Set default options.
+ curl_setopt($curl_handle, CURLOPT_URL, $this->request_url);
+ curl_setopt($curl_handle, CURLOPT_FILETIME, true);
+ curl_setopt($curl_handle, CURLOPT_FRESH_CONNECT, false);
+ curl_setopt($curl_handle, CURLOPT_CLOSEPOLICY, CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
+ curl_setopt($curl_handle, CURLOPT_MAXREDIRS, 5);
+ curl_setopt($curl_handle, CURLOPT_HEADER, true);
+ curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl_handle, CURLOPT_TIMEOUT, 5184000);
+ curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 120);
+ curl_setopt($curl_handle, CURLOPT_NOSIGNAL, true);
+ curl_setopt($curl_handle, CURLOPT_REFERER, $this->request_url);
+ curl_setopt($curl_handle, CURLOPT_USERAGENT, $this->useragent);
+ curl_setopt($curl_handle, CURLOPT_READFUNCTION, array($this, 'streaming_read_callback'));
+
+ // Verification of the SSL cert
+ if ($this->ssl_verification)
+ {
+ curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
+ }
+ else
+ {
+ curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, false);
+ }
+
+ // chmod the file as 0755
+ if ($this->cacert_location === true)
+ {
+ curl_setopt($curl_handle, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
+ }
+ elseif (is_string($this->cacert_location))
+ {
+ curl_setopt($curl_handle, CURLOPT_CAINFO, $this->cacert_location);
+ }
+
+ // Debug mode
+ if ($this->debug_mode)
+ {
+ curl_setopt($curl_handle, CURLOPT_VERBOSE, true);
+ }
+
+ // Handle open_basedir & safe mode
+ if (!ini_get('safe_mode') && !ini_get('open_basedir'))
+ {
+ curl_setopt($curl_handle, CURLOPT_FOLLOWLOCATION, true);
+ }
+
+ // Enable a proxy connection if requested.
+ if ($this->proxy)
+ {
+ curl_setopt($curl_handle, CURLOPT_HTTPPROXYTUNNEL, true);
+
+ $host = $this->proxy['host'];
+ $host .= ($this->proxy['port']) ? ':' . $this->proxy['port'] : '';
+ curl_setopt($curl_handle, CURLOPT_PROXY, $host);
+
+ if (isset($this->proxy['user']) && isset($this->proxy['pass']))
+ {
+ curl_setopt($curl_handle, CURLOPT_PROXYUSERPWD, $this->proxy['user'] . ':' . $this->proxy['pass']);
+ }
+ }
+
+ // Set credentials for HTTP Basic/Digest Authentication.
+ if ($this->username && $this->password)
+ {
+ curl_setopt($curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+ curl_setopt($curl_handle, CURLOPT_USERPWD, $this->username . ':' . $this->password);
+ }
+
+ // Handle the encoding if we can.
+ if (extension_loaded('zlib'))
+ {
+ curl_setopt($curl_handle, CURLOPT_ENCODING, 'gzip, deflate');
+ }
+
+ // Process custom headers
+ if (isset($this->request_headers) && count($this->request_headers))
+ {
+ $temp_headers = array();
+
+ foreach ($this->request_headers as $k => $v)
+ {
+ $temp_headers[] = $k . ': ' . $v;
+ }
+
+ curl_setopt($curl_handle, CURLOPT_HTTPHEADER, $temp_headers);
+ }
+
+ switch ($this->method)
+ {
+ case self::HTTP_PUT:
+ curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, 'PUT');
+ if (isset($this->read_stream))
+ {
+ if (!isset($this->read_stream_size) || $this->read_stream_size < 0)
+ {
+ throw new RequestCore_Exception('The stream size for the streaming upload cannot be determined.');
+ }
+
+ curl_setopt($curl_handle, CURLOPT_INFILESIZE, $this->read_stream_size);
+ curl_setopt($curl_handle, CURLOPT_UPLOAD, true);
+ }
+ else
+ {
+ curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
+ }
+ break;
+
+ case self::HTTP_POST:
+ curl_setopt($curl_handle, CURLOPT_POST, true);
+ curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
+ break;
+
+ case self::HTTP_HEAD:
+ curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, self::HTTP_HEAD);
+ curl_setopt($curl_handle, CURLOPT_NOBODY, 1);
+ break;
+
+ default: // Assumed GET
+ curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, $this->method);
+ if (isset($this->write_stream))
+ {
+ curl_setopt($curl_handle, CURLOPT_WRITEFUNCTION, array($this, 'streaming_write_callback'));
+ curl_setopt($curl_handle, CURLOPT_HEADER, false);
+ }
+ else
+ {
+ curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
+ }
+ break;
+ }
+
+ // Merge in the CURLOPTs
+ if (isset($this->curlopts) && sizeof($this->curlopts) > 0)
+ {
+ foreach ($this->curlopts as $k => $v)
+ {
+ curl_setopt($curl_handle, $k, $v);
+ }
+ }
+
+ return $curl_handle;
+ }
+
+ /**
+ * Take the post-processed cURL data and break it down into useful header/body/info chunks. Uses the
+ * data stored in the `curl_handle` and `response` properties unless replacement data is passed in via
+ * parameters.
+ *
+ * @param resource $curl_handle (Optional) The reference to the already executed cURL request.
+ * @param string $response (Optional) The actual response content itself that needs to be parsed.
+ * @return ResponseCore A <ResponseCore> object containing a parsed HTTP response.
+ */
+ public function process_response($curl_handle = null, $response = null)
+ {
+ // Accept a custom one if it's passed.
+ if ($curl_handle && $response)
+ {
+ $this->curl_handle = $curl_handle;
+ $this->response = $response;
+ }
+
+ // As long as this came back as a valid resource...
+ if (is_resource($this->curl_handle))
+ {
+ // Determine what's what.
+ $header_size = curl_getinfo($this->curl_handle, CURLINFO_HEADER_SIZE);
+ $this->response_headers = substr($this->response, 0, $header_size);
+ $this->response_body = substr($this->response, $header_size);
+ $this->response_code = curl_getinfo($this->curl_handle, CURLINFO_HTTP_CODE);
+ $this->response_info = curl_getinfo($this->curl_handle);
+
+ // Parse out the headers
+ $this->response_headers = explode("\r\n\r\n", trim($this->response_headers));
+ $this->response_headers = array_pop($this->response_headers);
+ $this->response_headers = explode("\r\n", $this->response_headers);
+ array_shift($this->response_headers);
+
+ // Loop through and split up the headers.
+ $header_assoc = array();
+ foreach ($this->response_headers as $header)
+ {
+ $kv = explode(': ', $header);
+ $header_assoc[strtolower($kv[0])] = $kv[1];
+ }
+
+ // Reset the headers to the appropriate property.
+ $this->response_headers = $header_assoc;
+ $this->response_headers['_info'] = $this->response_info;
+ $this->response_headers['_info']['method'] = $this->method;
+
+ if ($curl_handle && $response)
+ {
+ return new $this->response_class($this->response_headers, $this->response_body, $this->response_code, $this->curl_handle);
+ }
+ }
+
+ // Return false
+ return false;
+ }
+
+ /**
+ * Sends the request, calling necessary utility functions to update built-in properties.
+ *
+ * @param boolean $parse (Optional) Whether to parse the response with ResponseCore or not.
+ * @return string The resulting unparsed data from the request.
+ */
+ public function send_request($parse = false)
+ {
+ set_time_limit(0);
+
+ $curl_handle = $this->prep_request();
+ $this->response = curl_exec($curl_handle);
+
+ if ($this->response === false)
+ {
+ throw new cURL_Exception('cURL resource: ' . (string) $curl_handle . '; cURL error: ' . curl_error($curl_handle) . ' (cURL error code ' . curl_errno($curl_handle) . '). See http://curl.haxx.se/libcurl/c/libcurl-errors.html for an explanation of error codes.');
+ }
+
+ $parsed_response = $this->process_response($curl_handle, $this->response);
+
+ curl_close($curl_handle);
+
+ if ($parse)
+ {
+ return $parsed_response;
+ }
+
+ return $this->response;
+ }
+
+ /**
+ * Sends the request using <php:curl_multi_exec()>, enabling parallel requests. Uses the "rolling" method.
+ *
+ * @param array $handles (Required) An indexed array of cURL handles to process simultaneously.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>callback</code> - <code>string|array</code> - Optional - The string name of a function to pass the response data to. If this is a method, pass an array where the <code>[0]</code> index is the class and the <code>[1]</code> index is the method name.</li>
+ * <li><code>limit</code> - <code>integer</code> - Optional - The number of simultaneous requests to make. This can be useful for scaling around slow server responses. Defaults to trusting cURLs judgement as to how many to use.</li></ul>
+ * @return array Post-processed cURL responses.
+ */
+ public function send_multi_request($handles, $opt = null)
+ {
+ set_time_limit(0);
+
+ // Skip everything if there are no handles to process.
+ if (count($handles) === 0) return array();
+
+ if (!$opt) $opt = array();
+
+ // Initialize any missing options
+ $limit = isset($opt['limit']) ? $opt['limit'] : -1;
+
+ // Initialize
+ $handle_list = $handles;
+ $http = new $this->request_class();
+ $multi_handle = curl_multi_init();
+ $handles_post = array();
+ $added = count($handles);
+ $last_handle = null;
+ $count = 0;
+ $i = 0;
+
+ // Loop through the cURL handles and add as many as it set by the limit parameter.
+ while ($i < $added)
+ {
+ if ($limit > 0 && $i >= $limit) break;
+ curl_multi_add_handle($multi_handle, array_shift($handles));
+ $i++;
+ }
+
+ do
+ {
+ $active = false;
+
+ // Start executing and wait for a response.
+ while (($status = curl_multi_exec($multi_handle, $active)) === CURLM_CALL_MULTI_PERFORM)
+ {
+ // Start looking for possible responses immediately when we have to add more handles
+ if (count($handles) > 0) break;
+ }
+
+ // Figure out which requests finished.
+ $to_process = array();
+
+ while ($done = curl_multi_info_read($multi_handle))
+ {
+ // Since curl_errno() isn't reliable for handles that were in multirequests, we check the 'result' of the info read, which contains the curl error number, (listed here http://curl.haxx.se/libcurl/c/libcurl-errors.html )
+ if ($done['result'] > 0)
+ {
+ throw new cURL_Multi_Exception('cURL resource: ' . (string) $done['handle'] . '; cURL error: ' . curl_error($done['handle']) . ' (cURL error code ' . $done['result'] . '). See http://curl.haxx.se/libcurl/c/libcurl-errors.html for an explanation of error codes.');
+ }
+
+ // Because curl_multi_info_read() might return more than one message about a request, we check to see if this request is already in our array of completed requests
+ elseif (!isset($to_process[(int) $done['handle']]))
+ {
+ $to_process[(int) $done['handle']] = $done;
+ }
+ }
+
+ // Actually deal with the request
+ foreach ($to_process as $pkey => $done)
+ {
+ $response = $http->process_response($done['handle'], curl_multi_getcontent($done['handle']));
+ $key = array_search($done['handle'], $handle_list, true);
+ $handles_post[$key] = $response;
+
+ if (count($handles) > 0)
+ {
+ curl_multi_add_handle($multi_handle, array_shift($handles));
+ }
+
+ curl_multi_remove_handle($multi_handle, $done['handle']);
+ curl_close($done['handle']);
+ }
+ }
+ while ($active || count($handles_post) < $added);
+
+ curl_multi_close($multi_handle);
+
+ ksort($handles_post, SORT_NUMERIC);
+ return $handles_post;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // RESPONSE METHODS
+
+ /**
+ * Get the HTTP response headers from the request.
+ *
+ * @param string $header (Optional) A specific header value to return. Defaults to all headers.
+ * @return string|array All or selected header values.
+ */
+ public function get_response_header($header = null)
+ {
+ if ($header)
+ {
+ return $this->response_headers[strtolower($header)];
+ }
+ return $this->response_headers;
+ }
+
+ /**
+ * Get the HTTP response body from the request.
+ *
+ * @return string The response body.
+ */
+ public function get_response_body()
+ {
+ return $this->response_body;
+ }
+
+ /**
+ * Get the HTTP response code from the request.
+ *
+ * @return string The HTTP response code.
+ */
+ public function get_response_code()
+ {
+ return $this->response_code;
+ }
+}
+
+
+/**
+ * Container for all response-related methods.
+ */
+class ResponseCore
+{
+ /**
+ * Stores the HTTP header information.
+ */
+ public $header;
+
+ /**
+ * Stores the SimpleXML response.
+ */
+ public $body;
+
+ /**
+ * Stores the HTTP response code.
+ */
+ public $status;
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param array $header (Required) Associative array of HTTP headers (typically returned by <RequestCore::get_response_header()>).
+ * @param string $body (Required) XML-formatted response from AWS.
+ * @param integer $status (Optional) HTTP response status code from the request.
+ * @return object Contains an <php:array> `header` property (HTTP headers as an associative array), a <php:SimpleXMLElement> or <php:string> `body` property, and an <php:integer> `status` code.
+ */
+ public function __construct($header, $body, $status = null)
+ {
+ $this->header = $header;
+ $this->body = $body;
+ $this->status = $status;
+
+ return $this;
+ }
+
+ /**
+ * Did we receive the status code we expected?
+ *
+ * @param integer|array $codes (Optional) The status code(s) to expect. Pass an <php:integer> for a single acceptable value, or an <php:array> of integers for multiple acceptable values.
+ * @return boolean Whether we received the expected status code or not.
+ */
+ public function isOK($codes = array(200, 201, 204, 206))
+ {
+ if (is_array($codes))
+ {
+ return in_array($this->status, $codes);
+ }
+
+ return $this->status === $codes;
+ }
+}
+
+class cURL_Exception extends Exception {}
+class cURL_Multi_Exception extends cURL_Exception {}
+class RequestCore_Exception extends Exception {}
diff --git a/3rdparty/aws-sdk/lib/yaml/LICENSE b/3rdparty/aws-sdk/lib/yaml/LICENSE
new file mode 100644
index 00000000000..3cef853170e
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/yaml/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2008-2009 Fabien Potencier
+
+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.
diff --git a/3rdparty/aws-sdk/lib/yaml/README.markdown b/3rdparty/aws-sdk/lib/yaml/README.markdown
new file mode 100644
index 00000000000..e4f80cfbac4
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/yaml/README.markdown
@@ -0,0 +1,15 @@
+Symfony YAML: A PHP library that speaks YAML
+============================================
+
+Symfony YAML is a PHP library that parses YAML strings and converts them to
+PHP arrays. It can also converts PHP arrays to YAML strings. Its official
+website is at http://components.symfony-project.org/yaml/.
+
+The documentation is to be found in the `doc/` directory.
+
+Symfony YAML is licensed under the MIT license (see LICENSE file).
+
+The Symfony YAML library is developed and maintained by the
+[symfony](http://www.symfony-project.org/) project team. It has been extracted
+from symfony to be used as a standalone library. Symfony YAML is part of the
+[symfony components project](http://components.symfony-project.org/).
diff --git a/3rdparty/aws-sdk/lib/yaml/lib/sfYaml.php b/3rdparty/aws-sdk/lib/yaml/lib/sfYaml.php
new file mode 100644
index 00000000000..1d89ccc9736
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/yaml/lib/sfYaml.php
@@ -0,0 +1,135 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfYaml offers convenience methods to load and dump YAML.
+ *
+ * @package symfony
+ * @subpackage yaml
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version SVN: $Id: sfYaml.class.php 8988 2008-05-15 20:24:26Z fabien $
+ */
+class sfYaml
+{
+ static protected
+ $spec = '1.2';
+
+ /**
+ * Sets the YAML specification version to use.
+ *
+ * @param string $version The YAML specification version
+ */
+ static public function setSpecVersion($version)
+ {
+ if (!in_array($version, array('1.1', '1.2')))
+ {
+ throw new InvalidArgumentException(sprintf('Version %s of the YAML specifications is not supported', $version));
+ }
+
+ self::$spec = $version;
+ }
+
+ /**
+ * Gets the YAML specification version to use.
+ *
+ * @return string The YAML specification version
+ */
+ static public function getSpecVersion()
+ {
+ return self::$spec;
+ }
+
+ /**
+ * Loads YAML into a PHP array.
+ *
+ * The load method, when supplied with a YAML stream (string or file),
+ * will do its best to convert YAML in a file into a PHP array.
+ *
+ * Usage:
+ * <code>
+ * $array = sfYaml::load('config.yml');
+ * print_r($array);
+ * </code>
+ *
+ * @param string $input Path of YAML file or string containing YAML
+ *
+ * @return array The YAML converted to a PHP array
+ *
+ * @throws InvalidArgumentException If the YAML is not valid
+ */
+ public static function load($input)
+ {
+ $file = '';
+
+ // if input is a file, process it
+ if (strpos($input, "\n") === false && is_file($input))
+ {
+ $file = $input;
+
+ ob_start();
+ $retval = include($input);
+ $content = ob_get_clean();
+
+ // if an array is returned by the config file assume it's in plain php form else in YAML
+ $input = is_array($retval) ? $retval : $content;
+ }
+
+ // if an array is returned by the config file assume it's in plain php form else in YAML
+ if (is_array($input))
+ {
+ return $input;
+ }
+
+ require_once dirname(__FILE__).'/sfYamlParser.php';
+
+ $yaml = new sfYamlParser();
+
+ try
+ {
+ $ret = $yaml->parse($input);
+ }
+ catch (Exception $e)
+ {
+ throw new InvalidArgumentException(sprintf('Unable to parse %s: %s', $file ? sprintf('file "%s"', $file) : 'string', $e->getMessage()));
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Dumps a PHP array to a YAML string.
+ *
+ * The dump method, when supplied with an array, will do its best
+ * to convert the array into friendly YAML.
+ *
+ * @param array $array PHP array
+ * @param integer $inline The level where you switch to inline YAML
+ *
+ * @return string A YAML string representing the original PHP array
+ */
+ public static function dump($array, $inline = 2)
+ {
+ require_once dirname(__FILE__).'/sfYamlDumper.php';
+
+ $yaml = new sfYamlDumper();
+
+ return $yaml->dump($array, $inline);
+ }
+}
+
+/**
+ * Wraps echo to automatically provide a newline.
+ *
+ * @param string $string The string to echo with new line
+ */
+function echoln($string)
+{
+ echo $string."\n";
+}
diff --git a/3rdparty/aws-sdk/lib/yaml/lib/sfYamlDumper.php b/3rdparty/aws-sdk/lib/yaml/lib/sfYamlDumper.php
new file mode 100644
index 00000000000..0ada2b37d21
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/yaml/lib/sfYamlDumper.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfYamlInline.php');
+
+/**
+ * sfYamlDumper dumps PHP variables to YAML strings.
+ *
+ * @package symfony
+ * @subpackage yaml
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version SVN: $Id: sfYamlDumper.class.php 10575 2008-08-01 13:08:42Z nicolas $
+ */
+class sfYamlDumper
+{
+ /**
+ * Dumps a PHP value to YAML.
+ *
+ * @param mixed $input The PHP value
+ * @param integer $inline The level where you switch to inline YAML
+ * @param integer $indent The level o indentation indentation (used internally)
+ *
+ * @return string The YAML representation of the PHP value
+ */
+ public function dump($input, $inline = 0, $indent = 0)
+ {
+ $output = '';
+ $prefix = $indent ? str_repeat(' ', $indent) : '';
+
+ if ($inline <= 0 || !is_array($input) || empty($input))
+ {
+ $output .= $prefix.sfYamlInline::dump($input);
+ }
+ else
+ {
+ $isAHash = array_keys($input) !== range(0, count($input) - 1);
+
+ foreach ($input as $key => $value)
+ {
+ $willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value);
+
+ $output .= sprintf('%s%s%s%s',
+ $prefix,
+ $isAHash ? sfYamlInline::dump($key).':' : '-',
+ $willBeInlined ? ' ' : "\n",
+ $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + 2)
+ ).($willBeInlined ? "\n" : '');
+ }
+ }
+
+ return $output;
+ }
+}
diff --git a/3rdparty/aws-sdk/lib/yaml/lib/sfYamlInline.php b/3rdparty/aws-sdk/lib/yaml/lib/sfYamlInline.php
new file mode 100644
index 00000000000..66edb4f07ab
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/yaml/lib/sfYamlInline.php
@@ -0,0 +1,442 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once dirname(__FILE__).'/sfYaml.php';
+
+/**
+ * sfYamlInline implements a YAML parser/dumper for the YAML inline syntax.
+ *
+ * @package symfony
+ * @subpackage yaml
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version SVN: $Id: sfYamlInline.class.php 16177 2009-03-11 08:32:48Z fabien $
+ */
+class sfYamlInline
+{
+ const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')';
+
+ /**
+ * Convert a YAML string to a PHP array.
+ *
+ * @param string $value A YAML string
+ *
+ * @return array A PHP array representing the YAML string
+ */
+ static public function load($value)
+ {
+ $value = trim($value);
+
+ if (0 == strlen($value))
+ {
+ return '';
+ }
+
+ if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2)
+ {
+ $mbEncoding = mb_internal_encoding();
+ mb_internal_encoding('ASCII');
+ }
+
+ switch ($value[0])
+ {
+ case '[':
+ $result = self::parseSequence($value);
+ break;
+ case '{':
+ $result = self::parseMapping($value);
+ break;
+ default:
+ $result = self::parseScalar($value);
+ }
+
+ if (isset($mbEncoding))
+ {
+ mb_internal_encoding($mbEncoding);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Dumps a given PHP variable to a YAML string.
+ *
+ * @param mixed $value The PHP variable to convert
+ *
+ * @return string The YAML string representing the PHP array
+ */
+ static public function dump($value)
+ {
+ if ('1.1' === sfYaml::getSpecVersion())
+ {
+ $trueValues = array('true', 'on', '+', 'yes', 'y');
+ $falseValues = array('false', 'off', '-', 'no', 'n');
+ }
+ else
+ {
+ $trueValues = array('true');
+ $falseValues = array('false');
+ }
+
+ switch (true)
+ {
+ case is_resource($value):
+ throw new InvalidArgumentException('Unable to dump PHP resources in a YAML file.');
+ case is_object($value):
+ return '!!php/object:'.serialize($value);
+ case is_array($value):
+ return self::dumpArray($value);
+ case null === $value:
+ return 'null';
+ case true === $value:
+ return 'true';
+ case false === $value:
+ return 'false';
+ case ctype_digit($value):
+ return is_string($value) ? "'$value'" : (int) $value;
+ case is_numeric($value):
+ return is_infinite($value) ? str_ireplace('INF', '.Inf', strval($value)) : (is_string($value) ? "'$value'" : $value);
+ case false !== strpos($value, "\n") || false !== strpos($value, "\r"):
+ return sprintf('"%s"', str_replace(array('"', "\n", "\r"), array('\\"', '\n', '\r'), $value));
+ case preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ - ? | < > = ! % @ ` ]/x', $value):
+ return sprintf("'%s'", str_replace('\'', '\'\'', $value));
+ case '' == $value:
+ return "''";
+ case preg_match(self::getTimestampRegex(), $value):
+ return "'$value'";
+ case in_array(strtolower($value), $trueValues):
+ return "'$value'";
+ case in_array(strtolower($value), $falseValues):
+ return "'$value'";
+ case in_array(strtolower($value), array('null', '~')):
+ return "'$value'";
+ default:
+ return $value;
+ }
+ }
+
+ /**
+ * Dumps a PHP array to a YAML string.
+ *
+ * @param array $value The PHP array to dump
+ *
+ * @return string The YAML string representing the PHP array
+ */
+ static protected function dumpArray($value)
+ {
+ // array
+ $keys = array_keys($value);
+ if (
+ (1 == count($keys) && '0' == $keys[0])
+ ||
+ (count($keys) > 1 && array_reduce($keys, create_function('$v,$w', 'return (integer) $v + $w;'), 0) == count($keys) * (count($keys) - 1) / 2))
+ {
+ $output = array();
+ foreach ($value as $val)
+ {
+ $output[] = self::dump($val);
+ }
+
+ return sprintf('[%s]', implode(', ', $output));
+ }
+
+ // mapping
+ $output = array();
+ foreach ($value as $key => $val)
+ {
+ $output[] = sprintf('%s: %s', self::dump($key), self::dump($val));
+ }
+
+ return sprintf('{ %s }', implode(', ', $output));
+ }
+
+ /**
+ * Parses a scalar to a YAML string.
+ *
+ * @param scalar $scalar
+ * @param string $delimiters
+ * @param array $stringDelimiter
+ * @param integer $i
+ * @param boolean $evaluate
+ *
+ * @return string A YAML string
+ */
+ static public function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true)
+ {
+ if (in_array($scalar[$i], $stringDelimiters))
+ {
+ // quoted scalar
+ $output = self::parseQuotedScalar($scalar, $i);
+ }
+ else
+ {
+ // "normal" string
+ if (!$delimiters)
+ {
+ $output = substr($scalar, $i);
+ $i += strlen($output);
+
+ // remove comments
+ if (false !== $strpos = strpos($output, ' #'))
+ {
+ $output = rtrim(substr($output, 0, $strpos));
+ }
+ }
+ else if (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match))
+ {
+ $output = $match[1];
+ $i += strlen($output);
+ }
+ else
+ {
+ throw new InvalidArgumentException(sprintf('Malformed inline YAML string (%s).', $scalar));
+ }
+
+ $output = $evaluate ? self::evaluateScalar($output) : $output;
+ }
+
+ return $output;
+ }
+
+ /**
+ * Parses a quoted scalar to YAML.
+ *
+ * @param string $scalar
+ * @param integer $i
+ *
+ * @return string A YAML string
+ */
+ static protected function parseQuotedScalar($scalar, &$i)
+ {
+ if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/A', substr($scalar, $i), $match))
+ {
+ throw new InvalidArgumentException(sprintf('Malformed inline YAML string (%s).', substr($scalar, $i)));
+ }
+
+ $output = substr($match[0], 1, strlen($match[0]) - 2);
+
+ if ('"' == $scalar[$i])
+ {
+ // evaluate the string
+ $output = str_replace(array('\\"', '\\n', '\\r'), array('"', "\n", "\r"), $output);
+ }
+ else
+ {
+ // unescape '
+ $output = str_replace('\'\'', '\'', $output);
+ }
+
+ $i += strlen($match[0]);
+
+ return $output;
+ }
+
+ /**
+ * Parses a sequence to a YAML string.
+ *
+ * @param string $sequence
+ * @param integer $i
+ *
+ * @return string A YAML string
+ */
+ static protected function parseSequence($sequence, &$i = 0)
+ {
+ $output = array();
+ $len = strlen($sequence);
+ $i += 1;
+
+ // [foo, bar, ...]
+ while ($i < $len)
+ {
+ switch ($sequence[$i])
+ {
+ case '[':
+ // nested sequence
+ $output[] = self::parseSequence($sequence, $i);
+ break;
+ case '{':
+ // nested mapping
+ $output[] = self::parseMapping($sequence, $i);
+ break;
+ case ']':
+ return $output;
+ case ',':
+ case ' ':
+ break;
+ default:
+ $isQuoted = in_array($sequence[$i], array('"', "'"));
+ $value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i);
+
+ if (!$isQuoted && false !== strpos($value, ': '))
+ {
+ // embedded mapping?
+ try
+ {
+ $value = self::parseMapping('{'.$value.'}');
+ }
+ catch (InvalidArgumentException $e)
+ {
+ // no, it's not
+ }
+ }
+
+ $output[] = $value;
+
+ --$i;
+ }
+
+ ++$i;
+ }
+
+ throw new InvalidArgumentException(sprintf('Malformed inline YAML string %s', $sequence));
+ }
+
+ /**
+ * Parses a mapping to a YAML string.
+ *
+ * @param string $mapping
+ * @param integer $i
+ *
+ * @return string A YAML string
+ */
+ static protected function parseMapping($mapping, &$i = 0)
+ {
+ $output = array();
+ $len = strlen($mapping);
+ $i += 1;
+
+ // {foo: bar, bar:foo, ...}
+ while ($i < $len)
+ {
+ switch ($mapping[$i])
+ {
+ case ' ':
+ case ',':
+ ++$i;
+ continue 2;
+ case '}':
+ return $output;
+ }
+
+ // key
+ $key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false);
+
+ // value
+ $done = false;
+ while ($i < $len)
+ {
+ switch ($mapping[$i])
+ {
+ case '[':
+ // nested sequence
+ $output[$key] = self::parseSequence($mapping, $i);
+ $done = true;
+ break;
+ case '{':
+ // nested mapping
+ $output[$key] = self::parseMapping($mapping, $i);
+ $done = true;
+ break;
+ case ':':
+ case ' ':
+ break;
+ default:
+ $output[$key] = self::parseScalar($mapping, array(',', '}'), array('"', "'"), $i);
+ $done = true;
+ --$i;
+ }
+
+ ++$i;
+
+ if ($done)
+ {
+ continue 2;
+ }
+ }
+ }
+
+ throw new InvalidArgumentException(sprintf('Malformed inline YAML string %s', $mapping));
+ }
+
+ /**
+ * Evaluates scalars and replaces magic values.
+ *
+ * @param string $scalar
+ *
+ * @return string A YAML string
+ */
+ static protected function evaluateScalar($scalar)
+ {
+ $scalar = trim($scalar);
+
+ if ('1.1' === sfYaml::getSpecVersion())
+ {
+ $trueValues = array('true', 'on', '+', 'yes', 'y');
+ $falseValues = array('false', 'off', '-', 'no', 'n');
+ }
+ else
+ {
+ $trueValues = array('true');
+ $falseValues = array('false');
+ }
+
+ switch (true)
+ {
+ case 'null' == strtolower($scalar):
+ case '' == $scalar:
+ case '~' == $scalar:
+ return null;
+ case 0 === strpos($scalar, '!str'):
+ return (string) substr($scalar, 5);
+ case 0 === strpos($scalar, '! '):
+ return intval(self::parseScalar(substr($scalar, 2)));
+ case 0 === strpos($scalar, '!!php/object:'):
+ return unserialize(substr($scalar, 13));
+ case ctype_digit($scalar):
+ $raw = $scalar;
+ $cast = intval($scalar);
+ return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
+ case in_array(strtolower($scalar), $trueValues):
+ return true;
+ case in_array(strtolower($scalar), $falseValues):
+ return false;
+ case is_numeric($scalar):
+ return '0x' == $scalar[0].$scalar[1] ? hexdec($scalar) : floatval($scalar);
+ case 0 == strcasecmp($scalar, '.inf'):
+ case 0 == strcasecmp($scalar, '.NaN'):
+ return -log(0);
+ case 0 == strcasecmp($scalar, '-.inf'):
+ return log(0);
+ case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar):
+ return floatval(str_replace(',', '', $scalar));
+ case preg_match(self::getTimestampRegex(), $scalar):
+ return strtotime($scalar);
+ default:
+ return (string) $scalar;
+ }
+ }
+
+ static protected function getTimestampRegex()
+ {
+ return <<<EOF
+ ~^
+ (?P<year>[0-9][0-9][0-9][0-9])
+ -(?P<month>[0-9][0-9]?)
+ -(?P<day>[0-9][0-9]?)
+ (?:(?:[Tt]|[ \t]+)
+ (?P<hour>[0-9][0-9]?)
+ :(?P<minute>[0-9][0-9])
+ :(?P<second>[0-9][0-9])
+ (?:\.(?P<fraction>[0-9]*))?
+ (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
+ (?::(?P<tz_minute>[0-9][0-9]))?))?)?
+ $~x
+EOF;
+ }
+}
diff --git a/3rdparty/aws-sdk/lib/yaml/lib/sfYamlParser.php b/3rdparty/aws-sdk/lib/yaml/lib/sfYamlParser.php
new file mode 100644
index 00000000000..4c56a56db07
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/yaml/lib/sfYamlParser.php
@@ -0,0 +1,612 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfYamlInline.php');
+
+if (!defined('PREG_BAD_UTF8_OFFSET_ERROR'))
+{
+ define('PREG_BAD_UTF8_OFFSET_ERROR', 5);
+}
+
+/**
+ * sfYamlParser parses YAML strings to convert them to PHP arrays.
+ *
+ * @package symfony
+ * @subpackage yaml
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version SVN: $Id: sfYamlParser.class.php 10832 2008-08-13 07:46:08Z fabien $
+ */
+class sfYamlParser
+{
+ protected
+ $offset = 0,
+ $lines = array(),
+ $currentLineNb = -1,
+ $currentLine = '',
+ $refs = array();
+
+ /**
+ * Constructor
+ *
+ * @param integer $offset The offset of YAML document (used for line numbers in error messages)
+ */
+ public function __construct($offset = 0)
+ {
+ $this->offset = $offset;
+ }
+
+ /**
+ * Parses a YAML string to a PHP value.
+ *
+ * @param string $value A YAML string
+ *
+ * @return mixed A PHP value
+ *
+ * @throws InvalidArgumentException If the YAML is not valid
+ */
+ public function parse($value)
+ {
+ $value = str_replace("\t", ' ', $value); // Convert tabs to spaces.
+
+ $this->currentLineNb = -1;
+ $this->currentLine = '';
+ $this->lines = explode("\n", $this->cleanup($value));
+
+ if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2)
+ {
+ $mbEncoding = mb_internal_encoding();
+ mb_internal_encoding('ASCII');
+ }
+
+ $data = array();
+ while ($this->moveToNextLine())
+ {
+ if ($this->isCurrentLineEmpty())
+ {
+ continue;
+ }
+
+ // tab?
+ if (preg_match('#^\t+#', $this->currentLine))
+ {
+ throw new InvalidArgumentException(sprintf('A YAML file cannot contain tabs as indentation at line %d (%s).', $this->getRealCurrentLineNb() + 1, $this->currentLine));
+ }
+
+ $isRef = $isInPlace = $isProcessed = false;
+ if (preg_match('#^\-((?P<leadspaces>\s+)(?P<value>.+?))?\s*$#', $this->currentLine, $values))
+ {
+ if (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#', $values['value'], $matches))
+ {
+ $isRef = $matches['ref'];
+ $values['value'] = $matches['value'];
+ }
+
+ // array
+ if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#'))
+ {
+ $c = $this->getRealCurrentLineNb() + 1;
+ $parser = new sfYamlParser($c);
+ $parser->refs =& $this->refs;
+ $data[] = $parser->parse($this->getNextEmbedBlock());
+ }
+ else
+ {
+ if (isset($values['leadspaces'])
+ && ' ' == $values['leadspaces']
+ && preg_match('#^(?P<key>'.sfYamlInline::REGEX_QUOTED_STRING.'|[^ \'"\{].*?) *\:(\s+(?P<value>.+?))?\s*$#', $values['value'], $matches))
+ {
+ // this is a compact notation element, add to next block and parse
+ $c = $this->getRealCurrentLineNb();
+ $parser = new sfYamlParser($c);
+ $parser->refs =& $this->refs;
+
+ $block = $values['value'];
+ if (!$this->isNextLineIndented())
+ {
+ $block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + 2);
+ }
+
+ $data[] = $parser->parse($block);
+ }
+ else
+ {
+ $data[] = $this->parseValue($values['value']);
+ }
+ }
+ }
+ else if (preg_match('#^(?P<key>'.sfYamlInline::REGEX_QUOTED_STRING.'|[^ \'"].*?) *\:(\s+(?P<value>.+?))?\s*$#', $this->currentLine, $values))
+ {
+ $key = sfYamlInline::parseScalar($values['key']);
+
+ if ('<<' === $key)
+ {
+ if (isset($values['value']) && '*' === substr($values['value'], 0, 1))
+ {
+ $isInPlace = substr($values['value'], 1);
+ if (!array_key_exists($isInPlace, $this->refs))
+ {
+ throw new InvalidArgumentException(sprintf('Reference "%s" does not exist at line %s (%s).', $isInPlace, $this->getRealCurrentLineNb() + 1, $this->currentLine));
+ }
+ }
+ else
+ {
+ if (isset($values['value']) && $values['value'] !== '')
+ {
+ $value = $values['value'];
+ }
+ else
+ {
+ $value = $this->getNextEmbedBlock();
+ }
+ $c = $this->getRealCurrentLineNb() + 1;
+ $parser = new sfYamlParser($c);
+ $parser->refs =& $this->refs;
+ $parsed = $parser->parse($value);
+
+ $merged = array();
+ if (!is_array($parsed))
+ {
+ throw new InvalidArgumentException(sprintf("YAML merge keys used with a scalar value instead of an array at line %s (%s)", $this->getRealCurrentLineNb() + 1, $this->currentLine));
+ }
+ else if (isset($parsed[0]))
+ {
+ // Numeric array, merge individual elements
+ foreach (array_reverse($parsed) as $parsedItem)
+ {
+ if (!is_array($parsedItem))
+ {
+ throw new InvalidArgumentException(sprintf("Merge items must be arrays at line %s (%s).", $this->getRealCurrentLineNb() + 1, $parsedItem));
+ }
+ $merged = array_merge($parsedItem, $merged);
+ }
+ }
+ else
+ {
+ // Associative array, merge
+ $merged = array_merge($merge, $parsed);
+ }
+
+ $isProcessed = $merged;
+ }
+ }
+ else if (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#', $values['value'], $matches))
+ {
+ $isRef = $matches['ref'];
+ $values['value'] = $matches['value'];
+ }
+
+ if ($isProcessed)
+ {
+ // Merge keys
+ $data = $isProcessed;
+ }
+ // hash
+ else if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#'))
+ {
+ // if next line is less indented or equal, then it means that the current value is null
+ if ($this->isNextLineIndented())
+ {
+ $data[$key] = null;
+ }
+ else
+ {
+ $c = $this->getRealCurrentLineNb() + 1;
+ $parser = new sfYamlParser($c);
+ $parser->refs =& $this->refs;
+ $data[$key] = $parser->parse($this->getNextEmbedBlock());
+ }
+ }
+ else
+ {
+ if ($isInPlace)
+ {
+ $data = $this->refs[$isInPlace];
+ }
+ else
+ {
+ $data[$key] = $this->parseValue($values['value']);
+ }
+ }
+ }
+ else
+ {
+ // 1-liner followed by newline
+ if (2 == count($this->lines) && empty($this->lines[1]))
+ {
+ $value = sfYamlInline::load($this->lines[0]);
+ if (is_array($value))
+ {
+ $first = reset($value);
+ if ('*' === substr($first, 0, 1))
+ {
+ $data = array();
+ foreach ($value as $alias)
+ {
+ $data[] = $this->refs[substr($alias, 1)];
+ }
+ $value = $data;
+ }
+ }
+
+ if (isset($mbEncoding))
+ {
+ mb_internal_encoding($mbEncoding);
+ }
+
+ return $value;
+ }
+
+ switch (preg_last_error())
+ {
+ case PREG_INTERNAL_ERROR:
+ $error = 'Internal PCRE error on line';
+ break;
+ case PREG_BACKTRACK_LIMIT_ERROR:
+ $error = 'pcre.backtrack_limit reached on line';
+ break;
+ case PREG_RECURSION_LIMIT_ERROR:
+ $error = 'pcre.recursion_limit reached on line';
+ break;
+ case PREG_BAD_UTF8_ERROR:
+ $error = 'Malformed UTF-8 data on line';
+ break;
+ case PREG_BAD_UTF8_OFFSET_ERROR:
+ $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point on line';
+ break;
+ default:
+ $error = 'Unable to parse line';
+ }
+
+ throw new InvalidArgumentException(sprintf('%s %d (%s).', $error, $this->getRealCurrentLineNb() + 1, $this->currentLine));
+ }
+
+ if ($isRef)
+ {
+ $this->refs[$isRef] = end($data);
+ }
+ }
+
+ if (isset($mbEncoding))
+ {
+ mb_internal_encoding($mbEncoding);
+ }
+
+ return empty($data) ? null : $data;
+ }
+
+ /**
+ * Returns the current line number (takes the offset into account).
+ *
+ * @return integer The current line number
+ */
+ protected function getRealCurrentLineNb()
+ {
+ return $this->currentLineNb + $this->offset;
+ }
+
+ /**
+ * Returns the current line indentation.
+ *
+ * @return integer The current line indentation
+ */
+ protected function getCurrentLineIndentation()
+ {
+ return strlen($this->currentLine) - strlen(ltrim($this->currentLine, ' '));
+ }
+
+ /**
+ * Returns the next embed block of YAML.
+ *
+ * @param integer $indentation The indent level at which the block is to be read, or null for default
+ *
+ * @return string A YAML string
+ */
+ protected function getNextEmbedBlock($indentation = null)
+ {
+ $this->moveToNextLine();
+
+ if (null === $indentation)
+ {
+ $newIndent = $this->getCurrentLineIndentation();
+
+ if (!$this->isCurrentLineEmpty() && 0 == $newIndent)
+ {
+ throw new InvalidArgumentException(sprintf('Indentation problem at line %d (%s)', $this->getRealCurrentLineNb() + 1, $this->currentLine));
+ }
+ }
+ else
+ {
+ $newIndent = $indentation;
+ }
+
+ $data = array(substr($this->currentLine, $newIndent));
+
+ while ($this->moveToNextLine())
+ {
+ if ($this->isCurrentLineEmpty())
+ {
+ if ($this->isCurrentLineBlank())
+ {
+ $data[] = substr($this->currentLine, $newIndent);
+ }
+
+ continue;
+ }
+
+ $indent = $this->getCurrentLineIndentation();
+
+ if (preg_match('#^(?P<text> *)$#', $this->currentLine, $match))
+ {
+ // empty line
+ $data[] = $match['text'];
+ }
+ else if ($indent >= $newIndent)
+ {
+ $data[] = substr($this->currentLine, $newIndent);
+ }
+ else if (0 == $indent)
+ {
+ $this->moveToPreviousLine();
+
+ break;
+ }
+ else
+ {
+ throw new InvalidArgumentException(sprintf('Indentation problem at line %d (%s)', $this->getRealCurrentLineNb() + 1, $this->currentLine));
+ }
+ }
+
+ return implode("\n", $data);
+ }
+
+ /**
+ * Moves the parser to the next line.
+ */
+ protected function moveToNextLine()
+ {
+ if ($this->currentLineNb >= count($this->lines) - 1)
+ {
+ return false;
+ }
+
+ $this->currentLine = $this->lines[++$this->currentLineNb];
+
+ return true;
+ }
+
+ /**
+ * Moves the parser to the previous line.
+ */
+ protected function moveToPreviousLine()
+ {
+ $this->currentLine = $this->lines[--$this->currentLineNb];
+ }
+
+ /**
+ * Parses a YAML value.
+ *
+ * @param string $value A YAML value
+ *
+ * @return mixed A PHP value
+ */
+ protected function parseValue($value)
+ {
+ if ('*' === substr($value, 0, 1))
+ {
+ if (false !== $pos = strpos($value, '#'))
+ {
+ $value = substr($value, 1, $pos - 2);
+ }
+ else
+ {
+ $value = substr($value, 1);
+ }
+
+ if (!array_key_exists($value, $this->refs))
+ {
+ throw new InvalidArgumentException(sprintf('Reference "%s" does not exist (%s).', $value, $this->currentLine));
+ }
+ return $this->refs[$value];
+ }
+
+ if (preg_match('/^(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?$/', $value, $matches))
+ {
+ $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : '';
+
+ return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), intval(abs($modifiers)));
+ }
+ else
+ {
+ return sfYamlInline::load($value);
+ }
+ }
+
+ /**
+ * Parses a folded scalar.
+ *
+ * @param string $separator The separator that was used to begin this folded scalar (| or >)
+ * @param string $indicator The indicator that was used to begin this folded scalar (+ or -)
+ * @param integer $indentation The indentation that was used to begin this folded scalar
+ *
+ * @return string The text value
+ */
+ protected function parseFoldedScalar($separator, $indicator = '', $indentation = 0)
+ {
+ $separator = '|' == $separator ? "\n" : ' ';
+ $text = '';
+
+ $notEOF = $this->moveToNextLine();
+
+ while ($notEOF && $this->isCurrentLineBlank())
+ {
+ $text .= "\n";
+
+ $notEOF = $this->moveToNextLine();
+ }
+
+ if (!$notEOF)
+ {
+ return '';
+ }
+
+ if (!preg_match('#^(?P<indent>'.($indentation ? str_repeat(' ', $indentation) : ' +').')(?P<text>.*)$#', $this->currentLine, $matches))
+ {
+ $this->moveToPreviousLine();
+
+ return '';
+ }
+
+ $textIndent = $matches['indent'];
+ $previousIndent = 0;
+
+ $text .= $matches['text'].$separator;
+ while ($this->currentLineNb + 1 < count($this->lines))
+ {
+ $this->moveToNextLine();
+
+ if (preg_match('#^(?P<indent> {'.strlen($textIndent).',})(?P<text>.+)$#', $this->currentLine, $matches))
+ {
+ if (' ' == $separator && $previousIndent != $matches['indent'])
+ {
+ $text = substr($text, 0, -1)."\n";
+ }
+ $previousIndent = $matches['indent'];
+
+ $text .= str_repeat(' ', $diff = strlen($matches['indent']) - strlen($textIndent)).$matches['text'].($diff ? "\n" : $separator);
+ }
+ else if (preg_match('#^(?P<text> *)$#', $this->currentLine, $matches))
+ {
+ $text .= preg_replace('#^ {1,'.strlen($textIndent).'}#', '', $matches['text'])."\n";
+ }
+ else
+ {
+ $this->moveToPreviousLine();
+
+ break;
+ }
+ }
+
+ if (' ' == $separator)
+ {
+ // replace last separator by a newline
+ $text = preg_replace('/ (\n*)$/', "\n$1", $text);
+ }
+
+ switch ($indicator)
+ {
+ case '':
+ $text = preg_replace('#\n+$#s', "\n", $text);
+ break;
+ case '+':
+ break;
+ case '-':
+ $text = preg_replace('#\n+$#s', '', $text);
+ break;
+ }
+
+ return $text;
+ }
+
+ /**
+ * Returns true if the next line is indented.
+ *
+ * @return Boolean Returns true if the next line is indented, false otherwise
+ */
+ protected function isNextLineIndented()
+ {
+ $currentIndentation = $this->getCurrentLineIndentation();
+ $notEOF = $this->moveToNextLine();
+
+ while ($notEOF && $this->isCurrentLineEmpty())
+ {
+ $notEOF = $this->moveToNextLine();
+ }
+
+ if (false === $notEOF)
+ {
+ return false;
+ }
+
+ $ret = false;
+ if ($this->getCurrentLineIndentation() <= $currentIndentation)
+ {
+ $ret = true;
+ }
+
+ $this->moveToPreviousLine();
+
+ return $ret;
+ }
+
+ /**
+ * Returns true if the current line is blank or if it is a comment line.
+ *
+ * @return Boolean Returns true if the current line is empty or if it is a comment line, false otherwise
+ */
+ protected function isCurrentLineEmpty()
+ {
+ return $this->isCurrentLineBlank() || $this->isCurrentLineComment();
+ }
+
+ /**
+ * Returns true if the current line is blank.
+ *
+ * @return Boolean Returns true if the current line is blank, false otherwise
+ */
+ protected function isCurrentLineBlank()
+ {
+ return '' == trim($this->currentLine, ' ');
+ }
+
+ /**
+ * Returns true if the current line is a comment line.
+ *
+ * @return Boolean Returns true if the current line is a comment line, false otherwise
+ */
+ protected function isCurrentLineComment()
+ {
+ //checking explicitly the first char of the trim is faster than loops or strpos
+ $ltrimmedLine = ltrim($this->currentLine, ' ');
+ return $ltrimmedLine[0] === '#';
+ }
+
+ /**
+ * Cleanups a YAML string to be parsed.
+ *
+ * @param string $value The input YAML string
+ *
+ * @return string A cleaned up YAML string
+ */
+ protected function cleanup($value)
+ {
+ $value = str_replace(array("\r\n", "\r"), "\n", $value);
+
+ if (!preg_match("#\n$#", $value))
+ {
+ $value .= "\n";
+ }
+
+ // strip YAML header
+ $count = 0;
+ $value = preg_replace('#^\%YAML[: ][\d\.]+.*\n#s', '', $value, -1, $count);
+ $this->offset += $count;
+
+ // remove leading comments and/or ---
+ $trimmedValue = preg_replace('#^((\#.*?\n)|(\-\-\-.*?\n))*#s', '', $value, -1, $count);
+ if ($count == 1)
+ {
+ // items have been removed, update the offset
+ $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
+ $value = $trimmedValue;
+ }
+
+ return $value;
+ }
+}
diff --git a/3rdparty/aws-sdk/sdk.class.php b/3rdparty/aws-sdk/sdk.class.php
new file mode 100755
index 00000000000..8dcb7bf252f
--- /dev/null
+++ b/3rdparty/aws-sdk/sdk.class.php
@@ -0,0 +1,1435 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+/**
+ * Default CFRuntime Exception.
+ */
+class CFRuntime_Exception extends Exception {}
+
+/**
+ * Parsing Exception.
+ */
+class Parser_Exception extends Exception {}
+
+
+/*%******************************************************************************************%*/
+// DETERMINE WHAT ENVIRONMENT DATA TO ADD TO THE USERAGENT FOR METRIC TRACKING
+
+/*
+ Define a temporary callback function for this calculation. Get the PHP version and any
+ required/optional extensions that are leveraged.
+
+ Tracking this data gives Amazon better metrics about what configurations are being used
+ so that forward-looking plans for the code can be made with more certainty (e.g. What
+ version of PHP are most people running? Do they tend to have the latest PCRE?).
+*/
+function __aws_sdk_ua_callback()
+{
+ $ua_append = '';
+ $extensions = get_loaded_extensions();
+ $sorted_extensions = array();
+
+ if ($extensions)
+ {
+ foreach ($extensions as $extension)
+ {
+ if ($extension === 'curl' && function_exists('curl_version'))
+ {
+ $curl_version = curl_version();
+ $sorted_extensions[strtolower($extension)] = $curl_version['version'];
+ }
+ elseif ($extension === 'pcre' && defined('PCRE_VERSION'))
+ {
+ $pcre_version = explode(' ', PCRE_VERSION);
+ $sorted_extensions[strtolower($extension)] = $pcre_version[0];
+ }
+ elseif ($extension === 'openssl' && defined('OPENSSL_VERSION_TEXT'))
+ {
+ $openssl_version = explode(' ', OPENSSL_VERSION_TEXT);
+ $sorted_extensions[strtolower($extension)] = $openssl_version[1];
+ }
+ else
+ {
+ $sorted_extensions[strtolower($extension)] = phpversion($extension);
+ }
+ }
+ }
+
+ foreach (array('simplexml', 'json', 'pcre', 'spl', 'curl', 'openssl', 'apc', 'xcache', 'memcache', 'memcached', 'pdo', 'pdo_sqlite', 'sqlite', 'sqlite3', 'zlib', 'xdebug') as $ua_ext)
+ {
+ if (isset($sorted_extensions[$ua_ext]) && $sorted_extensions[$ua_ext])
+ {
+ $ua_append .= ' ' . $ua_ext . '/' . $sorted_extensions[$ua_ext];
+ }
+ elseif (isset($sorted_extensions[$ua_ext]))
+ {
+ $ua_append .= ' ' . $ua_ext . '/0';
+ }
+ }
+
+ foreach (array('memory_limit', 'date.timezone', 'open_basedir', 'safe_mode', 'zend.enable_gc') as $cfg)
+ {
+ $cfg_value = ini_get($cfg);
+
+ if (in_array($cfg, array('memory_limit', 'date.timezone'), true))
+ {
+ $ua_append .= ' ' . $cfg . '/' . str_replace('/', '.', $cfg_value);
+ }
+ elseif (in_array($cfg, array('open_basedir', 'safe_mode', 'zend.enable_gc'), true))
+ {
+ if ($cfg_value === false || $cfg_value === '' || $cfg_value === 0)
+ {
+ $cfg_value = 'off';
+ }
+ elseif ($cfg_value === true || $cfg_value === '1' || $cfg_value === 1)
+ {
+ $cfg_value = 'on';
+ }
+
+ $ua_append .= ' ' . $cfg . '/' . $cfg_value;
+ }
+ }
+
+ return $ua_append;
+}
+
+
+/*%******************************************************************************************%*/
+// INTERMEDIARY CONSTANTS
+
+define('CFRUNTIME_NAME', 'aws-sdk-php');
+define('CFRUNTIME_VERSION', '1.5.6.2');
+define('CFRUNTIME_BUILD', '20120529180000');
+define('CFRUNTIME_USERAGENT', CFRUNTIME_NAME . '/' . CFRUNTIME_VERSION . ' PHP/' . PHP_VERSION . ' ' . str_replace(' ', '_', php_uname('s')) . '/' . str_replace(' ', '_', php_uname('r')) . ' Arch/' . php_uname('m') . ' SAPI/' . php_sapi_name() . ' Integer/' . PHP_INT_MAX . ' Build/' . CFRUNTIME_BUILD . __aws_sdk_ua_callback());
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Core functionality and default settings shared across all SDK classes. All methods and properties in this
+ * class are inherited by the service-specific classes.
+ *
+ * @version 2012.05.29
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFRuntime
+{
+ /*%******************************************************************************************%*/
+ // CONSTANTS
+
+ /**
+ * Name of the software.
+ */
+ const NAME = CFRUNTIME_NAME;
+
+ /**
+ * Version of the software.
+ */
+ const VERSION = CFRUNTIME_VERSION;
+
+ /**
+ * Build ID of the software.
+ */
+ const BUILD = CFRUNTIME_BUILD;
+
+ /**
+ * User agent string used to identify the software.
+ */
+ const USERAGENT = CFRUNTIME_USERAGENT;
+
+
+ /*%******************************************************************************************%*/
+ // PROPERTIES
+
+ /**
+ * The Amazon API Key.
+ */
+ public $key;
+
+ /**
+ * The Amazon API Secret Key.
+ */
+ public $secret_key;
+
+ /**
+ * The Amazon Authentication Token.
+ */
+ public $auth_token;
+
+ /**
+ * Handle for the utility functions.
+ */
+ public $util;
+
+ /**
+ * An identifier for the current AWS service.
+ */
+ public $service = null;
+
+ /**
+ * The supported API version.
+ */
+ public $api_version = null;
+
+ /**
+ * The state of whether auth should be handled as AWS Query.
+ */
+ public $use_aws_query = true;
+
+ /**
+ * The default class to use for utilities (defaults to <CFUtilities>).
+ */
+ public $utilities_class = 'CFUtilities';
+
+ /**
+ * The default class to use for HTTP requests (defaults to <CFRequest>).
+ */
+ public $request_class = 'CFRequest';
+
+ /**
+ * The default class to use for HTTP responses (defaults to <CFResponse>).
+ */
+ public $response_class = 'CFResponse';
+
+ /**
+ * The default class to use for parsing XML (defaults to <CFSimpleXML>).
+ */
+ public $parser_class = 'CFSimpleXML';
+
+ /**
+ * The default class to use for handling batch requests (defaults to <CFBatchRequest>).
+ */
+ public $batch_class = 'CFBatchRequest';
+
+ /**
+ * The state of SSL/HTTPS use.
+ */
+ public $use_ssl = true;
+
+ /**
+ * The state of SSL certificate verification.
+ */
+ public $ssl_verification = true;
+
+ /**
+ * The proxy to use for connecting.
+ */
+ public $proxy = null;
+
+ /**
+ * The alternate hostname to use, if any.
+ */
+ public $hostname = null;
+
+ /**
+ * The state of the capability to override the hostname with <set_hostname()>.
+ */
+ public $override_hostname = true;
+
+ /**
+ * The alternate port number to use, if any.
+ */
+ public $port_number = null;
+
+ /**
+ * The alternate resource prefix to use, if any.
+ */
+ public $resource_prefix = null;
+
+ /**
+ * The state of cache flow usage.
+ */
+ public $use_cache_flow = false;
+
+ /**
+ * The caching class to use.
+ */
+ public $cache_class = null;
+
+ /**
+ * The caching location to use.
+ */
+ public $cache_location = null;
+
+ /**
+ * When the cache should be considered stale.
+ */
+ public $cache_expires = null;
+
+ /**
+ * The state of cache compression.
+ */
+ public $cache_compress = null;
+
+ /**
+ * The current instantiated cache object.
+ */
+ public $cache_object = null;
+
+ /**
+ * The current instantiated batch request object.
+ */
+ public $batch_object = null;
+
+ /**
+ * The internally instantiated batch request object.
+ */
+ public $internal_batch_object = null;
+
+ /**
+ * The state of batch flow usage.
+ */
+ public $use_batch_flow = false;
+
+ /**
+ * The state of the cache deletion setting.
+ */
+ public $delete_cache = false;
+
+ /**
+ * The state of the debug mode setting.
+ */
+ public $debug_mode = false;
+
+ /**
+ * The number of times to retry failed requests.
+ */
+ public $max_retries = 3;
+
+ /**
+ * The user-defined callback function to call when a stream is read from.
+ */
+ public $registered_streaming_read_callback = null;
+
+ /**
+ * The user-defined callback function to call when a stream is written to.
+ */
+ public $registered_streaming_write_callback = null;
+
+ /**
+ * The credentials to use for authentication.
+ */
+ public $credentials = array();
+
+ /**
+ * The authentication class to use.
+ */
+ public $auth_class = null;
+
+ /**
+ * The operation to execute.
+ */
+ public $operation = null;
+
+ /**
+ * The payload to send.
+ */
+ public $payload = array();
+
+ /**
+ * The string prefix to prepend to the operation name.
+ */
+ public $operation_prefix = '';
+
+ /**
+ * The number of times a request has been retried.
+ */
+ public $redirects = 0;
+
+ /**
+ * The state of whether the response should be parsed or not.
+ */
+ public $parse_the_response = true;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * The constructor. This class should not be instantiated directly. Rather, a service-specific class
+ * should be instantiated.
+ *
+ * @param array $options (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>certificate_authority</code> - <code>boolean</code> - Optional - Determines which Cerificate Authority file to use. A value of boolean <code>false</code> will use the Certificate Authority file available on the system. A value of boolean <code>true</code> will use the Certificate Authority provided by the SDK. Passing a file system path to a Certificate Authority file (chmodded to <code>0755</code>) will use that. Leave this set to <code>false</code> if you're not sure.</li>
+ * <li><code>credentials</code> - <code>string</code> - Optional - The name of the credential set to use for authentication.</li>
+ * <li><code>default_cache_config</code> - <code>string</code> - Optional - This option allows a preferred storage type to be configured for long-term caching. This can be changed later using the <set_cache_config()> method. Valid values are: <code>apc</code>, <code>xcache</code>, or a file system path such as <code>./cache</code> or <code>/tmp/cache/</code>.</li>
+ * <li><code>key</code> - <code>string</code> - Optional - Your AWS key, or a session key. If blank, the default credential set will be used.</li>
+ * <li><code>secret</code> - <code>string</code> - Optional - Your AWS secret key, or a session secret key. If blank, the default credential set will be used.</li>
+ * <li><code>token</code> - <code>string</code> - Optional - An AWS session token.</li></ul>
+ * @return void
+ */
+ public function __construct(array $options = array())
+ {
+ // Instantiate the utilities class.
+ $this->util = new $this->utilities_class();
+
+ // Determine the current service.
+ $this->service = get_class($this);
+
+ // Create credentials based on the options
+ $instance_credentials = new CFCredential($options);
+
+ // Retreive a credential set from config.inc.php if it exists
+ if (isset($options['credentials']))
+ {
+ // Use a specific credential set and merge with the instance credentials
+ $this->credentials = CFCredentials::get($options['credentials'])
+ ->merge($instance_credentials);
+ }
+ else
+ {
+ try
+ {
+ // Use the default credential set and merge with the instance credentials
+ $this->credentials = CFCredentials::get(CFCredentials::DEFAULT_KEY)
+ ->merge($instance_credentials);
+ }
+ catch (CFCredentials_Exception $e)
+ {
+ if (isset($options['key']) && isset($options['secret']))
+ {
+ // Only the instance credentials were provided
+ $this->credentials = $instance_credentials;
+ }
+ else
+ {
+ // No credentials provided in the config file or constructor
+ throw new CFCredentials_Exception('No credentials were provided to ' . $this->service . '.');
+ }
+ }
+ }
+
+ // Set internal credentials after they are resolved
+ $this->key = $this->credentials->key;
+ $this->secret_key = $this->credentials->secret;
+ $this->auth_token = $this->credentials->token;
+
+ // Automatically enable whichever caching mechanism is set to default.
+ $this->set_cache_config($this->credentials->default_cache_config);
+ }
+
+ /**
+ * Alternate approach to constructing a new instance. Supports chaining.
+ *
+ * @param array $options (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>certificate_authority</code> - <code>boolean</code> - Optional - Determines which Cerificate Authority file to use. A value of boolean <code>false</code> will use the Certificate Authority file available on the system. A value of boolean <code>true</code> will use the Certificate Authority provided by the SDK. Passing a file system path to a Certificate Authority file (chmodded to <code>0755</code>) will use that. Leave this set to <code>false</code> if you're not sure.</li>
+ * <li><code>credentials</code> - <code>string</code> - Optional - The name of the credential set to use for authentication.</li>
+ * <li><code>default_cache_config</code> - <code>string</code> - Optional - This option allows a preferred storage type to be configured for long-term caching. This can be changed later using the <set_cache_config()> method. Valid values are: <code>apc</code>, <code>xcache</code>, or a file system path such as <code>./cache</code> or <code>/tmp/cache/</code>.</li>
+ * <li><code>key</code> - <code>string</code> - Optional - Your AWS key, or a session key. If blank, the default credential set will be used.</li>
+ * <li><code>secret</code> - <code>string</code> - Optional - Your AWS secret key, or a session secret key. If blank, the default credential set will be used.</li>
+ * <li><code>token</code> - <code>string</code> - Optional - An AWS session token.</li></ul>
+ * @return void
+ */
+ public static function factory(array $options = array())
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '<'))
+ {
+ throw new Exception('PHP 5.3 or newer is required to instantiate a new class with CLASS::factory().');
+ }
+
+ $self = get_called_class();
+ return new $self($options);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // MAGIC METHODS
+
+ /**
+ * A magic method that allows `camelCase` method names to be translated into `snake_case` names.
+ *
+ * @param string $name (Required) The name of the method.
+ * @param array $arguments (Required) The arguments passed to the method.
+ * @return mixed The results of the intended method.
+ */
+ public function __call($name, $arguments)
+ {
+ // Convert camelCase method calls to snake_case.
+ $method_name = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $name));
+
+ if (method_exists($this, $method_name))
+ {
+ return call_user_func_array(array($this, $method_name), $arguments);
+ }
+
+ throw new CFRuntime_Exception('The method ' . $name . '() is undefined. Attempted to map to ' . $method_name . '() which is also undefined. Error occurred');
+ }
+
+
+ /*%******************************************************************************************%*/
+ // SET CUSTOM SETTINGS
+
+ /**
+ * Set the proxy settings to use.
+ *
+ * @param string $proxy (Required) Accepts proxy credentials in the following format: `proxy://user:pass@hostname:port`
+ * @return $this A reference to the current instance.
+ */
+ public function set_proxy($proxy)
+ {
+ $this->proxy = $proxy;
+ return $this;
+ }
+
+ /**
+ * Set the hostname to connect to. This is useful for alternate services that are API-compatible with
+ * AWS, but run from a different hostname.
+ *
+ * @param string $hostname (Required) The alternate hostname to use in place of the default one. Useful for mock or test applications living on different hostnames.
+ * @param integer $port_number (Optional) The alternate port number to use in place of the default one. Useful for mock or test applications living on different port numbers.
+ * @return $this A reference to the current instance.
+ */
+ public function set_hostname($hostname, $port_number = null)
+ {
+ if ($this->override_hostname)
+ {
+ $this->hostname = $hostname;
+
+ if ($port_number)
+ {
+ $this->port_number = $port_number;
+ $this->hostname .= ':' . (string) $this->port_number;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the resource prefix to use. This method is useful for alternate services that are API-compatible
+ * with AWS.
+ *
+ * @param string $prefix (Required) An alternate prefix to prepend to the resource path. Useful for mock or test applications.
+ * @return $this A reference to the current instance.
+ */
+ public function set_resource_prefix($prefix)
+ {
+ $this->resource_prefix = $prefix;
+ return $this;
+ }
+
+ /**
+ * Disables any subsequent use of the <set_hostname()> method.
+ *
+ * @param boolean $override (Optional) Whether or not subsequent calls to <set_hostname()> should be obeyed. A `false` value disables the further effectiveness of <set_hostname()>. Defaults to `true`.
+ * @return $this A reference to the current instance.
+ */
+ public function allow_hostname_override($override = true)
+ {
+ $this->override_hostname = $override;
+ return $this;
+ }
+
+ /**
+ * Disables SSL/HTTPS connections for hosts that don't support them. Some services, however, still
+ * require SSL support.
+ *
+ * This method will throw a user warning when invoked, which can be hidden by changing your
+ * <php:error_reporting()> settings.
+ *
+ * @return $this A reference to the current instance.
+ */
+ public function disable_ssl()
+ {
+ trigger_error('Disabling SSL connections is potentially unsafe and highly discouraged.', E_USER_WARNING);
+ $this->use_ssl = false;
+ return $this;
+ }
+
+ /**
+ * Disables the verification of the SSL Certificate Authority. Doing so can enable an attacker to carry
+ * out a man-in-the-middle attack.
+ *
+ * https://secure.wikimedia.org/wikipedia/en/wiki/Man-in-the-middle_attack
+ *
+ * This method will throw a user warning when invoked, which can be hidden by changing your
+ * <php:error_reporting()> settings.
+ *
+ * @return $this A reference to the current instance.
+ */
+ public function disable_ssl_verification($ssl_verification = false)
+ {
+ trigger_error('Disabling the verification of SSL certificates can lead to man-in-the-middle attacks. It is potentially unsafe and highly discouraged.', E_USER_WARNING);
+ $this->ssl_verification = $ssl_verification;
+ return $this;
+ }
+
+ /**
+ * Enables HTTP request/response header logging to `STDERR`.
+ *
+ * @param boolean $enabled (Optional) Whether or not to enable debug mode. Defaults to `true`.
+ * @return $this A reference to the current instance.
+ */
+ public function enable_debug_mode($enabled = true)
+ {
+ $this->debug_mode = $enabled;
+ return $this;
+ }
+
+ /**
+ * Sets the maximum number of times to retry failed requests.
+ *
+ * @param integer $retries (Optional) The maximum number of times to retry failed requests. Defaults to `3`.
+ * @return $this A reference to the current instance.
+ */
+ public function set_max_retries($retries = 3)
+ {
+ $this->max_retries = $retries;
+ return $this;
+ }
+
+ /**
+ * Set the caching configuration to use for response caching.
+ *
+ * @param string $location (Required) <p>The location to store the cache object in. This may vary by cache method.</p><ul><li>File - The local file system paths such as <code>./cache</code> (relative) or <code>/tmp/cache/</code> (absolute). The location must be server-writable.</li><li>APC - Pass in <code>apc</code> to use this lightweight cache. You must have the <a href="http://php.net/apc">APC extension</a> installed.</li><li>XCache - Pass in <code>xcache</code> to use this lightweight cache. You must have the <a href="http://xcache.lighttpd.net">XCache</a> extension installed.</li><li>Memcached - Pass in an indexed array of associative arrays. Each associative array should have a <code>host</code> and a <code>port</code> value representing a <a href="http://php.net/memcached">Memcached</a> server to connect to.</li><li>PDO - A URL-style string (e.g. <code>pdo.mysql://user:pass@localhost/cache</code>) or a standard DSN-style string (e.g. <code>pdo.sqlite:/sqlite/cache.db</code>). MUST be prefixed with <code>pdo.</code>. See <code>CachePDO</code> and <a href="http://php.net/pdo">PDO</a> for more details.</li></ul>
+ * @param boolean $gzip (Optional) Whether or not data should be gzipped before being stored. A value of `true` will compress the contents before caching them. A value of `false` will leave the contents uncompressed. Defaults to `true`.
+ * @return $this A reference to the current instance.
+ */
+ public function set_cache_config($location, $gzip = true)
+ {
+ // If we have an array, we're probably passing in Memcached servers and ports.
+ if (is_array($location))
+ {
+ $this->cache_class = 'CacheMC';
+ }
+ else
+ {
+ // I would expect locations like `/tmp/cache`, `pdo.mysql://user:pass@hostname:port`, `pdo.sqlite:memory:`, and `apc`.
+ $type = strtolower(substr($location, 0, 3));
+ switch ($type)
+ {
+ case 'apc':
+ $this->cache_class = 'CacheAPC';
+ break;
+
+ case 'xca': // First three letters of `xcache`
+ $this->cache_class = 'CacheXCache';
+ break;
+
+ case 'pdo':
+ $this->cache_class = 'CachePDO';
+ $location = substr($location, 4);
+ break;
+
+ default:
+ $this->cache_class = 'CacheFile';
+ break;
+ }
+ }
+
+ // Set the remaining cache information.
+ $this->cache_location = $location;
+ $this->cache_compress = $gzip;
+
+ return $this;
+ }
+
+ /**
+ * Register a callback function to execute whenever a data stream is read from using
+ * <CFRequest::streaming_read_callback()>.
+ *
+ * The user-defined callback function should accept three arguments:
+ *
+ * <ul>
+ * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
+ * <li><code>$file_handle</code> - <code>resource</code> - Required - The file handle resource that represents the file on the local file system.</li>
+ * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
+ * </ul>
+ *
+ * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
+ * <li>The name of a global function to execute, passed as a string.</li>
+ * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
+ * <li>An anonymous function (PHP 5.3+).</li></ul>
+ * @return $this A reference to the current instance.
+ */
+ public function register_streaming_read_callback($callback)
+ {
+ $this->registered_streaming_read_callback = $callback;
+ return $this;
+ }
+
+ /**
+ * Register a callback function to execute whenever a data stream is written to using
+ * <CFRequest::streaming_write_callback()>.
+ *
+ * The user-defined callback function should accept two arguments:
+ *
+ * <ul>
+ * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
+ * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
+ * </ul>
+ *
+ * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
+ * <li>The name of a global function to execute, passed as a string.</li>
+ * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
+ * <li>An anonymous function (PHP 5.3+).</li></ul>
+ * @return $this A reference to the current instance.
+ */
+ public function register_streaming_write_callback($callback)
+ {
+ $this->registered_streaming_write_callback = $callback;
+ return $this;
+ }
+
+ /**
+ * Fetches and caches STS credentials. This is meant to be used by the constructor, and is not to be
+ * manually invoked.
+ *
+ * @param CacheCore $cache (Required) The a reference to the cache object that is being used to handle the caching.
+ * @param array $options (Required) The options that were passed into the constructor.
+ * @return mixed The data to be cached, or NULL.
+ */
+ public function cache_sts_credentials($cache, $options)
+ {
+ $token = new AmazonSTS($options);
+ $response = $token->get_session_token();
+
+ if ($response->isOK())
+ {
+ // Update the expiration
+ $expiration_time = strtotime((string) $response->body->GetSessionTokenResult->Credentials->Expiration);
+ $expiration_duration = round(($expiration_time - time()) * 0.85);
+ $cache->expire_in($expiration_duration);
+
+ // Return the important data
+ return array(
+ 'key' => (string) $response->body->GetSessionTokenResult->Credentials->AccessKeyId,
+ 'secret' => (string) $response->body->GetSessionTokenResult->Credentials->SecretAccessKey,
+ 'token' => (string) $response->body->GetSessionTokenResult->Credentials->SessionToken,
+ 'expires' => (string) $response->body->GetSessionTokenResult->Credentials->Expiration,
+ );
+ }
+
+ return null;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // SET CUSTOM CLASSES
+
+ /**
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
+ * with new functionality.
+ *
+ * The replacement class must extend from <CFUtilities>.
+ *
+ * @param string $class (Optional) The name of the new class to use for this functionality.
+ * @return $this A reference to the current instance.
+ */
+ public function set_utilities_class($class = 'CFUtilities')
+ {
+ $this->utilities_class = $class;
+ $this->util = new $this->utilities_class();
+ return $this;
+ }
+
+ /**
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
+ * with new functionality.
+ *
+ * The replacement class must extend from <CFRequest>.
+ *
+ * @param string $class (Optional) The name of the new class to use for this functionality.
+ * @param $this A reference to the current instance.
+ */
+ public function set_request_class($class = 'CFRequest')
+ {
+ $this->request_class = $class;
+ return $this;
+ }
+
+ /**
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
+ * with new functionality.
+ *
+ * The replacement class must extend from <CFResponse>.
+ *
+ * @param string $class (Optional) The name of the new class to use for this functionality.
+ * @return $this A reference to the current instance.
+ */
+ public function set_response_class($class = 'CFResponse')
+ {
+ $this->response_class = $class;
+ return $this;
+ }
+
+ /**
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
+ * with new functionality.
+ *
+ * The replacement class must extend from <CFSimpleXML>.
+ *
+ * @param string $class (Optional) The name of the new class to use for this functionality.
+ * @return $this A reference to the current instance.
+ */
+ public function set_parser_class($class = 'CFSimpleXML')
+ {
+ $this->parser_class = $class;
+ return $this;
+ }
+
+ /**
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
+ * with new functionality.
+ *
+ * The replacement class must extend from <CFBatchRequest>.
+ *
+ * @param string $class (Optional) The name of the new class to use for this functionality.
+ * @return $this A reference to the current instance.
+ */
+ public function set_batch_class($class = 'CFBatchRequest')
+ {
+ $this->batch_class = $class;
+ return $this;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // AUTHENTICATION
+
+ /**
+ * Default, shared method for authenticating a connection to AWS.
+ *
+ * @param string $operation (Required) Indicates the operation to perform.
+ * @param array $payload (Required) An associative array of parameters for authenticating. See the individual methods for allowed keys.
+ * @return CFResponse Object containing a parsed HTTP response.
+ */
+ public function authenticate($operation, $payload)
+ {
+ $original_payload = $payload;
+ $method_arguments = func_get_args();
+ $curlopts = array();
+ $return_curl_handle = false;
+
+ if (substr($operation, 0, strlen($this->operation_prefix)) !== $this->operation_prefix)
+ {
+ $operation = $this->operation_prefix . $operation;
+ }
+
+ // Extract the custom CURLOPT settings from the payload
+ if (is_array($payload) && isset($payload['curlopts']))
+ {
+ $curlopts = $payload['curlopts'];
+ unset($payload['curlopts']);
+ }
+
+ // Determine whether the response or curl handle should be returned
+ if (is_array($payload) && isset($payload['returnCurlHandle']))
+ {
+ $return_curl_handle = isset($payload['returnCurlHandle']) ? $payload['returnCurlHandle'] : false;
+ unset($payload['returnCurlHandle']);
+ }
+
+ // Use the caching flow to determine if we need to do a round-trip to the server.
+ if ($this->use_cache_flow)
+ {
+ // Generate an identifier specific to this particular set of arguments.
+ $cache_id = $this->key . '_' . get_class($this) . '_' . $operation . '_' . sha1(serialize($method_arguments));
+
+ // Instantiate the appropriate caching object.
+ $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
+
+ if ($this->delete_cache)
+ {
+ $this->use_cache_flow = false;
+ $this->delete_cache = false;
+ return $this->cache_object->delete();
+ }
+
+ // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
+ $data = $this->cache_object->response_manager(array($this, 'cache_callback'), $method_arguments);
+
+ // Parse the XML body
+ $data = $this->parse_callback($data);
+
+ // End!
+ return $data;
+ }
+
+ /*%******************************************************************************************%*/
+
+ // Signer
+ $signer = new $this->auth_class($this->hostname, $operation, $payload, $this->credentials);
+ $signer->key = $this->key;
+ $signer->secret_key = $this->secret_key;
+ $signer->auth_token = $this->auth_token;
+ $signer->api_version = $this->api_version;
+ $signer->utilities_class = $this->utilities_class;
+ $signer->request_class = $this->request_class;
+ $signer->response_class = $this->response_class;
+ $signer->use_ssl = $this->use_ssl;
+ $signer->proxy = $this->proxy;
+ $signer->util = $this->util;
+ $signer->registered_streaming_read_callback = $this->registered_streaming_read_callback;
+ $signer->registered_streaming_write_callback = $this->registered_streaming_write_callback;
+ $request = $signer->authenticate();
+
+ // Update RequestCore settings
+ $request->request_class = $this->request_class;
+ $request->response_class = $this->response_class;
+ $request->ssl_verification = $this->ssl_verification;
+
+ /*%******************************************************************************************%*/
+
+ // Debug mode
+ if ($this->debug_mode)
+ {
+ $request->debug_mode = $this->debug_mode;
+ }
+
+ // Set custom CURLOPT settings
+ if (count($curlopts))
+ {
+ $request->set_curlopts($curlopts);
+ }
+
+ // Manage the (newer) batch request API or the (older) returnCurlHandle setting.
+ if ($this->use_batch_flow)
+ {
+ $handle = $request->prep_request();
+ $this->batch_object->add($handle);
+ $this->use_batch_flow = false;
+
+ return $handle;
+ }
+ elseif ($return_curl_handle)
+ {
+ return $request->prep_request();
+ }
+
+ // Send!
+ $request->send_request();
+
+ // Prepare the response.
+ $headers = $request->get_response_header();
+ $headers['x-aws-stringtosign'] = $signer->string_to_sign;
+
+ if (isset($signer->canonical_request))
+ {
+ $headers['x-aws-canonicalrequest'] = $signer->canonical_request;
+ }
+
+ $headers['x-aws-request-headers'] = $request->request_headers;
+ $headers['x-aws-body'] = $signer->querystring;
+
+ $data = new $this->response_class($headers, ($this->parse_the_response === true) ? $this->parse_callback($request->get_response_body()) : $request->get_response_body(), $request->get_response_code());
+
+ // Was it Amazon's fault the request failed? Retry the request until we reach $max_retries.
+ if (
+ (integer) $request->get_response_code() === 500 || // Internal Error (presumably transient)
+ (integer) $request->get_response_code() === 503) // Service Unavailable (presumably transient)
+ {
+ if ($this->redirects <= $this->max_retries)
+ {
+ // Exponential backoff
+ $delay = (integer) (pow(4, $this->redirects) * 100000);
+ usleep($delay);
+ $this->redirects++;
+ $data = $this->authenticate($operation, $original_payload);
+ }
+ }
+
+ // DynamoDB has custom logic
+ elseif (
+ (integer) $request->get_response_code() === 400 &&
+ stripos((string) $request->get_response_body(), 'com.amazonaws.dynamodb.') !== false && (
+ stripos((string) $request->get_response_body(), 'ProvisionedThroughputExceededException') !== false
+ )
+ )
+ {
+ if ($this->redirects === 0)
+ {
+ $this->redirects++;
+ $data = $this->authenticate($operation, $original_payload);
+ }
+ elseif ($this->redirects <= max($this->max_retries, 10))
+ {
+ // Exponential backoff
+ $delay = (integer) (pow(2, ($this->redirects - 1)) * 50000);
+ usleep($delay);
+ $this->redirects++;
+ $data = $this->authenticate($operation, $original_payload);
+ }
+ }
+
+ $this->redirects = 0;
+ return $data;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // BATCH REQUEST LAYER
+
+ /**
+ * Specifies that the intended request should be queued for a later batch request.
+ *
+ * @param CFBatchRequest $queue (Optional) The <CFBatchRequest> instance to use for managing batch requests. If not available, it generates a new instance of <CFBatchRequest>.
+ * @return $this A reference to the current instance.
+ */
+ public function batch(CFBatchRequest &$queue = null)
+ {
+ if ($queue)
+ {
+ $this->batch_object = $queue;
+ }
+ elseif ($this->internal_batch_object)
+ {
+ $this->batch_object = &$this->internal_batch_object;
+ }
+ else
+ {
+ $this->internal_batch_object = new $this->batch_class();
+ $this->batch_object = &$this->internal_batch_object;
+ }
+
+ $this->use_batch_flow = true;
+
+ return $this;
+ }
+
+ /**
+ * Executes the batch request queue by sending all queued requests.
+ *
+ * @param boolean $clear_after_send (Optional) Whether or not to clear the batch queue after sending a request. Defaults to `true`. Set this to `false` if you are caching batch responses and want to retrieve results later.
+ * @return array An array of <CFResponse> objects.
+ */
+ public function send($clear_after_send = true)
+ {
+ if ($this->use_batch_flow)
+ {
+ // When we send the request, disable batch flow.
+ $this->use_batch_flow = false;
+
+ // If we're not caching, simply send the request.
+ if (!$this->use_cache_flow)
+ {
+ $response = $this->batch_object->send();
+ $parsed_data = array_map(array($this, 'parse_callback'), $response);
+ $parsed_data = new CFArray($parsed_data);
+
+ // Clear the queue
+ if ($clear_after_send)
+ {
+ $this->batch_object->queue = array();
+ }
+
+ return $parsed_data;
+ }
+
+ // Generate an identifier specific to this particular set of arguments.
+ $cache_id = $this->key . '_' . get_class($this) . '_' . sha1(serialize($this->batch_object));
+
+ // Instantiate the appropriate caching object.
+ $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
+
+ if ($this->delete_cache)
+ {
+ $this->use_cache_flow = false;
+ $this->delete_cache = false;
+ return $this->cache_object->delete();
+ }
+
+ // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
+ $data_set = $this->cache_object->response_manager(array($this, 'cache_callback_batch'), array($this->batch_object));
+ $parsed_data = array_map(array($this, 'parse_callback'), $data_set);
+ $parsed_data = new CFArray($parsed_data);
+
+ // Clear the queue
+ if ($clear_after_send)
+ {
+ $this->batch_object->queue = array();
+ }
+
+ // End!
+ return $parsed_data;
+ }
+
+ // Load the class
+ $null = new CFBatchRequest();
+ unset($null);
+
+ throw new CFBatchRequest_Exception('You must use $object->batch()->send()');
+ }
+
+ /**
+ * Parses a response body into a PHP object if appropriate.
+ *
+ * @param CFResponse|string $response (Required) The <CFResponse> object to parse, or an XML string that would otherwise be a response body.
+ * @param string $content_type (Optional) The content-type to use when determining how to parse the content.
+ * @return CFResponse|string A parsed <CFResponse> object, or parsed XML.
+ */
+ public function parse_callback($response, $headers = null)
+ {
+ // Bail out
+ if (!$this->parse_the_response) return $response;
+
+ // Shorten this so we have a (mostly) single code path
+ if (isset($response->body))
+ {
+ if (is_string($response->body))
+ {
+ $body = $response->body;
+ }
+ else
+ {
+ return $response;
+ }
+ }
+ elseif (is_string($response))
+ {
+ $body = $response;
+ }
+ else
+ {
+ return $response;
+ }
+
+ // Decompress gzipped content
+ if (isset($headers['content-encoding']))
+ {
+ switch (strtolower(trim($headers['content-encoding'], "\x09\x0A\x0D\x20")))
+ {
+ case 'gzip':
+ case 'x-gzip':
+ $decoder = new CFGzipDecode($body);
+ if ($decoder->parse())
+ {
+ $body = $decoder->data;
+ }
+ break;
+
+ case 'deflate':
+ if (($uncompressed = gzuncompress($body)) !== false)
+ {
+ $body = $uncompressed;
+ }
+ elseif (($uncompressed = gzinflate($body)) !== false)
+ {
+ $body = $uncompressed;
+ }
+ break;
+ }
+ }
+
+ // Look for XML cues
+ if (
+ (isset($headers['content-type']) && ($headers['content-type'] === 'text/xml' || $headers['content-type'] === 'application/xml')) || // We know it's XML
+ (!isset($headers['content-type']) && (stripos($body, '<?xml') === 0 || strpos($body, '<Error>') === 0) || preg_match('/^<(\w*) xmlns="http(s?):\/\/(\w*).amazon(aws)?.com/im', $body)) // Sniff for XML
+ )
+ {
+ // Strip the default XML namespace to simplify XPath expressions
+ $body = str_replace("xmlns=", "ns=", $body);
+
+ try {
+ // Parse the XML body
+ $body = new $this->parser_class($body);
+ }
+ catch (Exception $e)
+ {
+ throw new Parser_Exception($e->getMessage());
+ }
+ }
+ // Look for JSON cues
+ elseif (
+ (isset($headers['content-type']) && ($headers['content-type'] === 'application/json') || $headers['content-type'] === 'application/x-amz-json-1.0') || // We know it's JSON
+ (!isset($headers['content-type']) && $this->util->is_json($body)) // Sniff for JSON
+ )
+ {
+ // Normalize JSON to a CFSimpleXML object
+ $body = CFJSON::to_xml($body, $this->parser_class);
+ }
+
+ // Put the parsed data back where it goes
+ if (isset($response->body))
+ {
+ $response->body = $body;
+ }
+ else
+ {
+ $response = $body;
+ }
+
+ return $response;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // CACHING LAYER
+
+ /**
+ * Specifies that the resulting <CFResponse> object should be cached according to the settings from
+ * <set_cache_config()>.
+ *
+ * @param string|integer $expires (Required) The time the cache is to expire. Accepts a number of seconds as an integer, or an amount of time, as a string, that is understood by <php:strtotime()> (e.g. "1 hour").
+ * @param $this A reference to the current instance.
+ * @return $this
+ */
+ public function cache($expires)
+ {
+ // Die if they haven't used set_cache_config().
+ if (!$this->cache_class)
+ {
+ throw new CFRuntime_Exception('Must call set_cache_config() before using cache()');
+ }
+
+ if (is_string($expires))
+ {
+ $expires = strtotime($expires);
+ $this->cache_expires = $expires - time();
+ }
+ elseif (is_int($expires))
+ {
+ $this->cache_expires = $expires;
+ }
+
+ $this->use_cache_flow = true;
+
+ return $this;
+ }
+
+ /**
+ * The callback function that is executed when the cache doesn't exist or has expired. The response of
+ * this method is cached. Accepts identical parameters as the <authenticate()> method. Never call this
+ * method directly -- it is used internally by the caching system.
+ *
+ * @param string $operation (Required) Indicates the operation to perform.
+ * @param array $payload (Required) An associative array of parameters for authenticating. See the individual methods for allowed keys.
+ * @return CFResponse A parsed HTTP response.
+ */
+ public function cache_callback($operation, $payload)
+ {
+ // Disable the cache flow since it's already been handled.
+ $this->use_cache_flow = false;
+
+ // Make the request
+ $response = $this->authenticate($operation, $payload);
+
+ // If this is an XML document, convert it back to a string.
+ if (isset($response->body) && ($response->body instanceof SimpleXMLElement))
+ {
+ $response->body = $response->body->asXML();
+ }
+
+ return $response;
+ }
+
+ /**
+ * Used for caching the results of a batch request. Never call this method directly; it is used
+ * internally by the caching system.
+ *
+ * @param CFBatchRequest $batch (Required) The batch request object to send.
+ * @return CFResponse A parsed HTTP response.
+ */
+ public function cache_callback_batch(CFBatchRequest $batch)
+ {
+ return $batch->send();
+ }
+
+ /**
+ * Deletes a cached <CFResponse> object using the specified cache storage type.
+ *
+ * @return boolean A value of `true` if cached object exists and is successfully deleted, otherwise `false`.
+ */
+ public function delete_cache()
+ {
+ $this->use_cache_flow = true;
+ $this->delete_cache = true;
+
+ return $this;
+ }
+}
+
+
+/**
+ * Contains the functionality for auto-loading service classes.
+ */
+class CFLoader
+{
+ /*%******************************************************************************************%*/
+ // AUTO-LOADER
+
+ /**
+ * Automatically load classes that aren't included.
+ *
+ * @param string $class (Required) The classname to load.
+ * @return boolean Whether or not the file was successfully loaded.
+ */
+ public static function autoloader($class)
+ {
+ $path = dirname(__FILE__) . DIRECTORY_SEPARATOR;
+
+ // Amazon SDK classes
+ if (strstr($class, 'Amazon'))
+ {
+ if (file_exists($require_this = $path . 'services' . DIRECTORY_SEPARATOR . str_ireplace('Amazon', '', strtolower($class)) . '.class.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Utility classes
+ elseif (strstr($class, 'CF'))
+ {
+ if (file_exists($require_this = $path . 'utilities' . DIRECTORY_SEPARATOR . str_ireplace('CF', '', strtolower($class)) . '.class.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Load CacheCore
+ elseif (strstr($class, 'Cache'))
+ {
+ if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'cachecore' . DIRECTORY_SEPARATOR . strtolower($class) . '.class.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Load RequestCore
+ elseif (strstr($class, 'RequestCore') || strstr($class, 'ResponseCore'))
+ {
+ if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'requestcore' . DIRECTORY_SEPARATOR . 'requestcore.class.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Load array-to-domdocument
+ elseif (strstr($class, 'Array2DOM'))
+ {
+ if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'dom' . DIRECTORY_SEPARATOR . 'ArrayToDOMDocument.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Load Authentication Signers
+ elseif (strstr($class, 'Auth'))
+ {
+ if (file_exists($require_this = $path . 'authentication' . DIRECTORY_SEPARATOR . str_replace('auth', 'signature_', strtolower($class)) . '.class.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Load Signer interface
+ elseif ($class === 'Signer')
+ {
+ if (!interface_exists('Signable', false) &&
+ file_exists($require_this = $path . 'authentication' . DIRECTORY_SEPARATOR . 'signable.interface.php'))
+ {
+ require_once $require_this;
+ }
+
+ if (file_exists($require_this = $path . 'authentication' . DIRECTORY_SEPARATOR . 'signer.abstract.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Load Symfony YAML classes
+ elseif (strstr($class, 'sfYaml'))
+ {
+ if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'yaml' . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'sfYaml.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ return false;
+ }
+}
+
+// Register the autoloader.
+spl_autoload_register(array('CFLoader', 'autoloader'));
+
+// Don't look for any configuration files, the Amazon S3 storage backend handles configuration
+
+// /*%******************************************************************************************%*/
+// // CONFIGURATION
+//
+// // Look for include file in the same directory (e.g. `./config.inc.php`).
+// if (file_exists(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'config.inc.php'))
+// {
+// include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'config.inc.php';
+// }
+// // Fallback to `~/.aws/sdk/config.inc.php`
+// else
+// {
+// if (!isset($_ENV['HOME']) && isset($_SERVER['HOME']))
+// {
+// $_ENV['HOME'] = $_SERVER['HOME'];
+// }
+// elseif (!isset($_ENV['HOME']) && !isset($_SERVER['HOME']))
+// {
+// $_ENV['HOME'] = `cd ~ && pwd`;
+// if (!$_ENV['HOME'])
+// {
+// switch (strtolower(PHP_OS))
+// {
+// case 'darwin':
+// $_ENV['HOME'] = '/Users/' . get_current_user();
+// break;
+//
+// case 'windows':
+// case 'winnt':
+// case 'win32':
+// $_ENV['HOME'] = 'c:' . DIRECTORY_SEPARATOR . 'Documents and Settings' . DIRECTORY_SEPARATOR . get_current_user();
+// break;
+//
+// default:
+// $_ENV['HOME'] = '/home/' . get_current_user();
+// break;
+// }
+// }
+// }
+//
+// if (getenv('HOME') && file_exists(getenv('HOME') . DIRECTORY_SEPARATOR . '.aws' . DIRECTORY_SEPARATOR . 'sdk' . DIRECTORY_SEPARATOR . 'config.inc.php'))
+// {
+// include_once getenv('HOME') . DIRECTORY_SEPARATOR . '.aws' . DIRECTORY_SEPARATOR . 'sdk' . DIRECTORY_SEPARATOR . 'config.inc.php';
+// }
+// }
diff --git a/3rdparty/aws-sdk/services/s3.class.php b/3rdparty/aws-sdk/services/s3.class.php
new file mode 100755
index 00000000000..2e9e1cd52b1
--- /dev/null
+++ b/3rdparty/aws-sdk/services/s3.class.php
@@ -0,0 +1,3979 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+/**
+ * Default S3 Exception.
+ */
+class S3_Exception extends Exception {}
+
+
+/*%******************************************************************************************%*/
+// MAIN CLASS
+
+/**
+ * Amazon S3 is a web service that enables you to store data in the cloud. You can then download the data
+ * or use the data with other AWS services, such as Amazon Elastic Cloud Computer (EC2).
+ *
+ * Amazon Simple Storage Service (Amazon S3) is storage for the Internet. You can use Amazon S3 to store
+ * and retrieve any amount of data at any time, from anywhere on the web. You can accomplish these tasks
+ * using the AWS Management Console, which is a simple and intuitive web interface.
+ *
+ * To get the most out of Amazon S3, you need to understand a few simple concepts. Amazon S3 stores data
+ * as objects in buckets. An object is comprised of a file and optionally any metadata that describes
+ * that file.
+ *
+ * To store an object in Amazon S3, you upload the file you want to store to a bucket. When you upload a
+ * file, you can set permissions on the object as well as any metadata.
+ *
+ * Buckets are the containers for objects. You can have one or more buckets. For each bucket, you can control
+ * access to the bucket (who can create, delete, and list objects in the bucket), view access logs for the
+ * bucket and its objects, and choose the geographical region where Amazon S3 will store the bucket and its
+ * contents.
+ *
+ * Visit <http://aws.amazon.com/s3/> for more information.
+ *
+ * @version 2012.01.17
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/s3/ Amazon Simple Storage Service
+ * @link http://aws.amazon.com/documentation/s3/ Amazon Simple Storage Service documentation
+ */
+class AmazonS3 extends CFRuntime
+{
+ /*%******************************************************************************************%*/
+ // REGIONAL ENDPOINTS
+
+ /**
+ * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Region.
+ */
+ const REGION_US_E1 = 's3.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Region.
+ */
+ const REGION_VIRGINIA = self::REGION_US_E1;
+
+ /**
+ * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Region.
+ */
+ const REGION_US_STANDARD = self::REGION_US_E1;
+
+ /**
+ * Specify the queue URL for the US-West 1 (Northern California) Region.
+ */
+ const REGION_US_W1 = 's3-us-west-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the US-West 1 (Northern California) Region.
+ */
+ const REGION_CALIFORNIA = self::REGION_US_W1;
+
+ /**
+ * Specify the queue URL for the US-West 2 (Oregon) Region.
+ */
+ const REGION_US_W2 = 's3-us-west-2.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the US-West 2 (Oregon) Region.
+ */
+ const REGION_OREGON = self::REGION_US_W2;
+
+ /**
+ * Specify the queue URL for the EU (Ireland) Region.
+ */
+ const REGION_EU_W1 = 's3-eu-west-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the EU (Ireland) Region.
+ */
+ const REGION_IRELAND = self::REGION_EU_W1;
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Singapore) Region.
+ */
+ const REGION_APAC_SE1 = 's3-ap-southeast-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Singapore) Region.
+ */
+ const REGION_SINGAPORE = self::REGION_APAC_SE1;
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
+ */
+ const REGION_APAC_NE1 = 's3-ap-northeast-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
+ */
+ const REGION_TOKYO = self::REGION_APAC_NE1;
+
+ /**
+ * Specify the queue URL for the South America (Sao Paulo) Region.
+ */
+ const REGION_SA_E1 = 's3-sa-east-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the South America (Sao Paulo) Region.
+ */
+ const REGION_SAO_PAULO = self::REGION_SA_E1;
+
+ /**
+ * Specify the queue URL for the United States GovCloud Region.
+ */
+ const REGION_US_GOV1 = 's3-us-gov-west-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the United States GovCloud FIPS 140-2 Region.
+ */
+ const REGION_US_GOV1_FIPS = 's3-fips-us-gov-west-1.amazonaws.com';
+
+ /**
+ * The default endpoint.
+ */
+ const DEFAULT_URL = self::REGION_US_E1;
+
+
+ /*%******************************************************************************************%*/
+ // REGIONAL WEBSITE ENDPOINTS
+
+ /**
+ * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Website Region.
+ */
+ const REGION_US_E1_WEBSITE = 's3-website-us-east-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Website Region.
+ */
+ const REGION_VIRGINIA_WEBSITE = self::REGION_US_E1_WEBSITE;
+
+ /**
+ * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Website Region.
+ */
+ const REGION_US_STANDARD_WEBSITE = self::REGION_US_E1_WEBSITE;
+
+ /**
+ * Specify the queue URL for the US-West 1 (Northern California) Website Region.
+ */
+ const REGION_US_W1_WEBSITE = 's3-website-us-west-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the US-West 1 (Northern California) Website Region.
+ */
+ const REGION_CALIFORNIA_WEBSITE = self::REGION_US_W1_WEBSITE;
+
+ /**
+ * Specify the queue URL for the US-West 2 (Oregon) Website Region.
+ */
+ const REGION_US_W2_WEBSITE = 's3-website-us-west-2.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the US-West 2 (Oregon) Website Region.
+ */
+ const REGION_OREGON_WEBSITE = self::REGION_US_W2_WEBSITE;
+
+ /**
+ * Specify the queue URL for the EU (Ireland) Website Region.
+ */
+ const REGION_EU_W1_WEBSITE = 's3-website-eu-west-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the EU (Ireland) Website Region.
+ */
+ const REGION_IRELAND_WEBSITE = self::REGION_EU_W1_WEBSITE;
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Singapore) Website Region.
+ */
+ const REGION_APAC_SE1_WEBSITE = 's3-website-ap-southeast-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Singapore) Website Region.
+ */
+ const REGION_SINGAPORE_WEBSITE = self::REGION_APAC_SE1_WEBSITE;
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Japan) Website Region.
+ */
+ const REGION_APAC_NE1_WEBSITE = 's3-website-ap-northeast-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Japan) Website Region.
+ */
+ const REGION_TOKYO_WEBSITE = self::REGION_APAC_NE1_WEBSITE;
+
+ /**
+ * Specify the queue URL for the South America (Sao Paulo) Website Region.
+ */
+ const REGION_SA_E1_WEBSITE = 's3-website-sa-east-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the South America (Sao Paulo) Website Region.
+ */
+ const REGION_SAO_PAULO_WEBSITE = self::REGION_SA_E1_WEBSITE;
+
+ /**
+ * Specify the queue URL for the United States GovCloud Website Region.
+ */
+ const REGION_US_GOV1_WEBSITE = 's3-website-us-gov-west-1.amazonaws.com';
+
+
+ /*%******************************************************************************************%*/
+ // ACL
+
+ /**
+ * ACL: Owner-only read/write.
+ */
+ const ACL_PRIVATE = 'private';
+
+ /**
+ * ACL: Owner read/write, public read.
+ */
+ const ACL_PUBLIC = 'public-read';
+
+ /**
+ * ACL: Public read/write.
+ */
+ const ACL_OPEN = 'public-read-write';
+
+ /**
+ * ACL: Owner read/write, authenticated read.
+ */
+ const ACL_AUTH_READ = 'authenticated-read';
+
+ /**
+ * ACL: Bucket owner read.
+ */
+ const ACL_OWNER_READ = 'bucket-owner-read';
+
+ /**
+ * ACL: Bucket owner full control.
+ */
+ const ACL_OWNER_FULL_CONTROL = 'bucket-owner-full-control';
+
+
+ /*%******************************************************************************************%*/
+ // GRANTS
+
+ /**
+ * When applied to a bucket, grants permission to list the bucket. When applied to an object, this
+ * grants permission to read the object data and/or metadata.
+ */
+ const GRANT_READ = 'READ';
+
+ /**
+ * When applied to a bucket, grants permission to create, overwrite, and delete any object in the
+ * bucket. This permission is not supported for objects.
+ */
+ const GRANT_WRITE = 'WRITE';
+
+ /**
+ * Grants permission to read the ACL for the applicable bucket or object. The owner of a bucket or
+ * object always has this permission implicitly.
+ */
+ const GRANT_READ_ACP = 'READ_ACP';
+
+ /**
+ * Gives permission to overwrite the ACP for the applicable bucket or object. The owner of a bucket
+ * or object always has this permission implicitly. Granting this permission is equivalent to granting
+ * FULL_CONTROL because the grant recipient can make any changes to the ACP.
+ */
+ const GRANT_WRITE_ACP = 'WRITE_ACP';
+
+ /**
+ * Provides READ, WRITE, READ_ACP, and WRITE_ACP permissions. It does not convey additional rights and
+ * is provided only for convenience.
+ */
+ const GRANT_FULL_CONTROL = 'FULL_CONTROL';
+
+
+ /*%******************************************************************************************%*/
+ // USERS
+
+ /**
+ * The "AuthenticatedUsers" group for access control policies.
+ */
+ const USERS_AUTH = 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers';
+
+ /**
+ * The "AllUsers" group for access control policies.
+ */
+ const USERS_ALL = 'http://acs.amazonaws.com/groups/global/AllUsers';
+
+ /**
+ * The "LogDelivery" group for access control policies.
+ */
+ const USERS_LOGGING = 'http://acs.amazonaws.com/groups/s3/LogDelivery';
+
+
+ /*%******************************************************************************************%*/
+ // PATTERNS
+
+ /**
+ * PCRE: Match all items
+ */
+ const PCRE_ALL = '/.*/i';
+
+
+ /*%******************************************************************************************%*/
+ // STORAGE
+
+ /**
+ * Standard storage redundancy.
+ */
+ const STORAGE_STANDARD = 'STANDARD';
+
+ /**
+ * Reduced storage redundancy.
+ */
+ const STORAGE_REDUCED = 'REDUCED_REDUNDANCY';
+
+
+ /*%******************************************************************************************%*/
+ // PROPERTIES
+
+ /**
+ * The request URL.
+ */
+ public $request_url;
+
+ /**
+ * The virtual host setting.
+ */
+ public $vhost;
+
+ /**
+ * The base XML elements to use for access control policy methods.
+ */
+ public $base_acp_xml;
+
+ /**
+ * The base XML elements to use for creating buckets in regions.
+ */
+ public $base_location_constraint;
+
+ /**
+ * The base XML elements to use for logging methods.
+ */
+ public $base_logging_xml;
+
+ /**
+ * The base XML elements to use for notifications.
+ */
+ public $base_notification_xml;
+
+ /**
+ * The base XML elements to use for versioning.
+ */
+ public $base_versioning_xml;
+
+ /**
+ * The base XML elements to use for completing a multipart upload.
+ */
+ public $complete_mpu_xml;
+
+ /**
+ * The base XML elements to use for website support.
+ */
+ public $website_config_xml;
+
+ /**
+ * The base XML elements to use for multi-object delete support.
+ */
+ public $multi_object_delete_xml;
+
+ /**
+ * The base XML elements to use for object expiration support.
+ */
+ public $object_expiration_xml;
+
+ /**
+ * The DNS vs. Path-style setting.
+ */
+ public $path_style = false;
+
+ /**
+ * The state of whether the prefix change is temporary or permanent.
+ */
+ public $temporary_prefix = false;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of <AmazonS3>.
+ *
+ * @param array $options (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>certificate_authority</code> - <code>boolean</code> - Optional - Determines which Cerificate Authority file to use. A value of boolean <code>false</code> will use the Certificate Authority file available on the system. A value of boolean <code>true</code> will use the Certificate Authority provided by the SDK. Passing a file system path to a Certificate Authority file (chmodded to <code>0755</code>) will use that. Leave this set to <code>false</code> if you're not sure.</li>
+ * <li><code>credentials</code> - <code>string</code> - Optional - The name of the credential set to use for authentication.</li>
+ * <li><code>default_cache_config</code> - <code>string</code> - Optional - This option allows a preferred storage type to be configured for long-term caching. This can be changed later using the <set_cache_config()> method. Valid values are: <code>apc</code>, <code>xcache</code>, or a file system path such as <code>./cache</code> or <code>/tmp/cache/</code>.</li>
+ * <li><code>key</code> - <code>string</code> - Optional - Your AWS key, or a session key. If blank, the default credential set will be used.</li>
+ * <li><code>secret</code> - <code>string</code> - Optional - Your AWS secret key, or a session secret key. If blank, the default credential set will be used.</li>
+ * <li><code>token</code> - <code>string</code> - Optional - An AWS session token.</li></ul>
+ * @return void
+ */
+ public function __construct(array $options = array())
+ {
+ $this->vhost = null;
+ $this->api_version = '2006-03-01';
+ $this->hostname = self::DEFAULT_URL;
+
+ $this->base_acp_xml = '<?xml version="1.0" encoding="UTF-8"?><AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/latest/"></AccessControlPolicy>';
+ $this->base_location_constraint = '<?xml version="1.0" encoding="UTF-8"?><CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/' . $this->api_version . '/"><LocationConstraint></LocationConstraint></CreateBucketConfiguration>';
+ $this->base_logging_xml = '<?xml version="1.0" encoding="utf-8"?><BucketLoggingStatus xmlns="http://doc.s3.amazonaws.com/' . $this->api_version . '"></BucketLoggingStatus>';
+ $this->base_notification_xml = '<?xml version="1.0" encoding="utf-8"?><NotificationConfiguration></NotificationConfiguration>';
+ $this->base_versioning_xml = '<?xml version="1.0" encoding="utf-8"?><VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/' . $this->api_version . '/"></VersioningConfiguration>';
+ $this->complete_mpu_xml = '<?xml version="1.0" encoding="utf-8"?><CompleteMultipartUpload></CompleteMultipartUpload>';
+ $this->website_config_xml = '<?xml version="1.0" encoding="utf-8"?><WebsiteConfiguration xmlns="http://s3.amazonaws.com/doc/' . $this->api_version . '/"><IndexDocument><Suffix>index.html</Suffix></IndexDocument><ErrorDocument><Key>error.html</Key></ErrorDocument></WebsiteConfiguration>';
+ $this->multi_object_delete_xml = '<?xml version="1.0" encoding="utf-8"?><Delete></Delete>';
+ $this->object_expiration_xml = '<?xml version="1.0" encoding="utf-8"?><LifecycleConfiguration></LifecycleConfiguration>';
+
+ parent::__construct($options);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // AUTHENTICATION
+
+ /**
+ * Authenticates a connection to Amazon S3. Do not use directly unless implementing custom methods for
+ * this class.
+ *
+ * @param string $operation (Required) The name of the bucket to operate on (S3 Only).
+ * @param array $payload (Required) An associative array of parameters for authenticating. See inline comments for allowed keys.
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/S3_Authentication.html REST authentication
+ */
+ public function authenticate($operation, $payload)
+ {
+ /*
+ * Overriding or extending this class? You can pass the following "magic" keys into $opt.
+ *
+ * ## verb, resource, sub_resource and query_string ##
+ * <verb> /<resource>?<sub_resource>&<query_string>
+ * GET /filename.txt?versions&prefix=abc&max-items=1
+ *
+ * ## versionId, uploadId, partNumber, response-* ##
+ * These don't follow the same rules as above, in that the they needs to be signed, while
+ * other query_string values do not.
+ *
+ * ## curlopts ##
+ * These values get passed directly to the cURL methods in RequestCore.
+ *
+ * ## fileUpload, fileDownload, seekTo ##
+ * These are slightly modified and then passed to the cURL methods in RequestCore.
+ *
+ * ## headers ##
+ * $opt['headers'] is an array, whose keys are HTTP headers to be sent.
+ *
+ * ## body ##
+ * This is the request body that is sent to the server via PUT/POST.
+ *
+ * ## preauth ##
+ * This is a hook that tells authenticate() to generate a pre-authenticated URL.
+ *
+ * ## returnCurlHandle ##
+ * Tells authenticate() to return the cURL handle for the request instead of executing it.
+ */
+
+ // Rename variables (to overcome inheritence issues)
+ $bucket = $operation;
+ $opt = $payload;
+
+ // Validate the S3 bucket name
+ if (!$this->validate_bucketname_support($bucket))
+ {
+ // @codeCoverageIgnoreStart
+ throw new S3_Exception('S3 does not support "' . $bucket . '" as a valid bucket name. Review "Bucket Restrictions and Limitations" in the S3 Developer Guide for more information.');
+ // @codeCoverageIgnoreEnd
+ }
+
+ // Die if $opt isn't set.
+ if (!$opt) return false;
+
+ $method_arguments = func_get_args();
+
+ // Use the caching flow to determine if we need to do a round-trip to the server.
+ if ($this->use_cache_flow)
+ {
+ // Generate an identifier specific to this particular set of arguments.
+ $cache_id = $this->key . '_' . get_class($this) . '_' . $bucket . '_' . sha1(serialize($method_arguments));
+
+ // Instantiate the appropriate caching object.
+ $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
+
+ if ($this->delete_cache)
+ {
+ $this->use_cache_flow = false;
+ $this->delete_cache = false;
+ return $this->cache_object->delete();
+ }
+
+ // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
+ $data = $this->cache_object->response_manager(array($this, 'cache_callback'), $method_arguments);
+
+ if ($this->parse_the_response)
+ {
+ // Parse the XML body
+ $data = $this->parse_callback($data);
+ }
+
+ // End!
+ return $data;
+ }
+
+ // If we haven't already set a resource prefix and the bucket name isn't DNS-valid...
+ if ((!$this->resource_prefix && !$this->validate_bucketname_create($bucket)) || $this->path_style)
+ {
+ // Fall back to the older path-style URI
+ $this->set_resource_prefix('/' . $bucket);
+ $this->temporary_prefix = true;
+ }
+
+ // Determine hostname
+ $scheme = $this->use_ssl ? 'https://' : 'http://';
+ if ($this->resource_prefix || $this->path_style) // Use bucket-in-path method.
+ {
+ $hostname = $this->hostname . $this->resource_prefix . (($bucket === '' || $this->resource_prefix === '/' . $bucket) ? '' : ('/' . $bucket));
+ }
+ else
+ {
+ $hostname = $this->vhost ? $this->vhost : (($bucket === '') ? $this->hostname : ($bucket . '.') . $this->hostname);
+ }
+
+ // Get the UTC timestamp in RFC 2616 format
+ $date = gmdate(CFUtilities::DATE_FORMAT_RFC2616, time());
+
+ // Storage for request parameters.
+ $resource = '';
+ $sub_resource = '';
+ $querystringparams = array();
+ $signable_querystringparams = array();
+ $string_to_sign = '';
+ $headers = array(
+ 'Content-MD5' => '',
+ 'Content-Type' => 'application/x-www-form-urlencoded',
+ 'Date' => $date
+ );
+
+ /*%******************************************************************************************%*/
+
+ // Do we have an authentication token?
+ if ($this->auth_token)
+ {
+ $headers['X-Amz-Security-Token'] = $this->auth_token;
+ }
+
+ // Handle specific resources
+ if (isset($opt['resource']))
+ {
+ $resource .= $opt['resource'];
+ }
+
+ // Merge query string values
+ if (isset($opt['query_string']))
+ {
+ $querystringparams = array_merge($querystringparams, $opt['query_string']);
+ }
+ $query_string = $this->util->to_query_string($querystringparams);
+
+ // Merge the signable query string values. Must be alphabetical.
+ $signable_list = array(
+ 'partNumber',
+ 'response-cache-control',
+ 'response-content-disposition',
+ 'response-content-encoding',
+ 'response-content-language',
+ 'response-content-type',
+ 'response-expires',
+ 'uploadId',
+ 'versionId'
+ );
+ foreach ($signable_list as $item)
+ {
+ if (isset($opt[$item]))
+ {
+ $signable_querystringparams[$item] = $opt[$item];
+ }
+ }
+ $signable_query_string = $this->util->to_query_string($signable_querystringparams);
+
+ // Merge the HTTP headers
+ if (isset($opt['headers']))
+ {
+ $headers = array_merge($headers, $opt['headers']);
+ }
+
+ // Compile the URI to request
+ $conjunction = '?';
+ $signable_resource = '/' . str_replace('%2F', '/', rawurlencode($resource));
+ $non_signable_resource = '';
+
+ if (isset($opt['sub_resource']))
+ {
+ $signable_resource .= $conjunction . rawurlencode($opt['sub_resource']);
+ $conjunction = '&';
+ }
+ if ($signable_query_string !== '')
+ {
+ $signable_query_string = $conjunction . $signable_query_string;
+ $conjunction = '&';
+ }
+ if ($query_string !== '')
+ {
+ $non_signable_resource .= $conjunction . $query_string;
+ $conjunction = '&';
+ }
+ if (substr($hostname, -1) === substr($signable_resource, 0, 1))
+ {
+ $signable_resource = ltrim($signable_resource, '/');
+ }
+
+ $this->request_url = $scheme . $hostname . $signable_resource . $signable_query_string . $non_signable_resource;
+
+ if (isset($opt['location']))
+ {
+ $this->request_url = $opt['location'];
+ }
+
+ // Gather information to pass along to other classes.
+ $helpers = array(
+ 'utilities' => $this->utilities_class,
+ 'request' => $this->request_class,
+ 'response' => $this->response_class,
+ );
+
+ // Instantiate the request class
+ $request = new $this->request_class($this->request_url, $this->proxy, $helpers, $this->credentials);
+
+ // Update RequestCore settings
+ $request->request_class = $this->request_class;
+ $request->response_class = $this->response_class;
+ $request->ssl_verification = $this->ssl_verification;
+
+ // Pass along registered stream callbacks
+ if ($this->registered_streaming_read_callback)
+ {
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
+ }
+
+ if ($this->registered_streaming_write_callback)
+ {
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
+ }
+
+ // Streaming uploads
+ if (isset($opt['fileUpload']))
+ {
+ if (is_resource($opt['fileUpload']))
+ {
+ // Determine the length to read from the stream
+ $length = null; // From current position until EOF by default, size determined by set_read_stream()
+
+ if (isset($headers['Content-Length']))
+ {
+ $length = $headers['Content-Length'];
+ }
+ elseif (isset($opt['seekTo']))
+ {
+ // Read from seekTo until EOF by default
+ $stats = fstat($opt['fileUpload']);
+
+ if ($stats && $stats['size'] >= 0)
+ {
+ $length = $stats['size'] - (integer) $opt['seekTo'];
+ }
+ }
+
+ $request->set_read_stream($opt['fileUpload'], $length);
+
+ if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
+ {
+ $headers['Content-Type'] = 'application/octet-stream';
+ }
+ }
+ else
+ {
+ $request->set_read_file($opt['fileUpload']);
+
+ // Determine the length to read from the file
+ $length = $request->read_stream_size; // The file size by default
+
+ if (isset($headers['Content-Length']))
+ {
+ $length = $headers['Content-Length'];
+ }
+ elseif (isset($opt['seekTo']) && isset($length))
+ {
+ // Read from seekTo until EOF by default
+ $length -= (integer) $opt['seekTo'];
+ }
+
+ $request->set_read_stream_size($length);
+
+ // Attempt to guess the correct mime-type
+ if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
+ {
+ $extension = explode('.', $opt['fileUpload']);
+ $extension = array_pop($extension);
+ $mime_type = CFMimeTypes::get_mimetype($extension);
+ $headers['Content-Type'] = $mime_type;
+ }
+ }
+
+ $headers['Content-Length'] = $request->read_stream_size;
+ $headers['Content-MD5'] = '';
+ }
+
+ // Handle streaming file offsets
+ if (isset($opt['seekTo']))
+ {
+ // Pass the seek position to RequestCore
+ $request->set_seek_position((integer) $opt['seekTo']);
+ }
+
+ // Streaming downloads
+ if (isset($opt['fileDownload']))
+ {
+ if (is_resource($opt['fileDownload']))
+ {
+ $request->set_write_stream($opt['fileDownload']);
+ }
+ else
+ {
+ $request->set_write_file($opt['fileDownload']);
+ }
+ }
+
+ $curlopts = array();
+
+ // Set custom CURLOPT settings
+ if (isset($opt['curlopts']))
+ {
+ $curlopts = $opt['curlopts'];
+ }
+
+ // Debug mode
+ if ($this->debug_mode)
+ {
+ $curlopts[CURLOPT_VERBOSE] = true;
+ }
+
+ // Set the curl options.
+ if (count($curlopts))
+ {
+ $request->set_curlopts($curlopts);
+ }
+
+ // Do we have a verb?
+ if (isset($opt['verb']))
+ {
+ $request->set_method($opt['verb']);
+ $string_to_sign .= $opt['verb'] . "\n";
+ }
+
+ // Add headers and content when we have a body
+ if (isset($opt['body']))
+ {
+ $request->set_body($opt['body']);
+ $headers['Content-Length'] = strlen($opt['body']);
+
+ if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
+ {
+ $headers['Content-Type'] = 'application/octet-stream';
+ }
+
+ if (!isset($opt['NoContentMD5']) || $opt['NoContentMD5'] !== true)
+ {
+ $headers['Content-MD5'] = $this->util->hex_to_base64(md5($opt['body']));
+ }
+ }
+
+ // Handle query-string authentication
+ if (isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
+ {
+ unset($headers['Date']);
+ $headers['Content-Type'] = '';
+ $headers['Expires'] = is_int($opt['preauth']) ? $opt['preauth'] : strtotime($opt['preauth']);
+ }
+
+ // Sort headers
+ uksort($headers, 'strnatcasecmp');
+
+ // Add headers to request and compute the string to sign
+ foreach ($headers as $header_key => $header_value)
+ {
+ // Strip linebreaks from header values as they're illegal and can allow for security issues
+ $header_value = str_replace(array("\r", "\n"), '', $header_value);
+
+ // Add the header if it has a value
+ if ($header_value !== '')
+ {
+ $request->add_header($header_key, $header_value);
+ }
+
+ // Generate the string to sign
+ if (
+ strtolower($header_key) === 'content-md5' ||
+ strtolower($header_key) === 'content-type' ||
+ strtolower($header_key) === 'date' ||
+ (strtolower($header_key) === 'expires' && isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
+ )
+ {
+ $string_to_sign .= $header_value . "\n";
+ }
+ elseif (substr(strtolower($header_key), 0, 6) === 'x-amz-')
+ {
+ $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
+ }
+ }
+
+ // Add the signable resource location
+ $string_to_sign .= ($this->resource_prefix ? $this->resource_prefix : '');
+ $string_to_sign .= (($bucket === '' || $this->resource_prefix === '/' . $bucket) ? '' : ('/' . $bucket)) . $signable_resource . urldecode($signable_query_string);
+
+ // Hash the AWS secret key and generate a signature for the request.
+ $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->secret_key, true));
+ $request->add_header('Authorization', 'AWS ' . $this->key . ':' . $signature);
+
+ // If we're generating a URL, return the URL to the calling method.
+ if (isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
+ {
+ $query_params = array(
+ 'AWSAccessKeyId' => $this->key,
+ 'Expires' => $headers['Expires'],
+ 'Signature' => $signature,
+ );
+
+ // If using short-term credentials, add the token to the query string
+ if ($this->auth_token)
+ {
+ $query_params['x-amz-security-token'] = $this->auth_token;
+ }
+
+ return $this->request_url . $conjunction . http_build_query($query_params, '', '&');
+ }
+ elseif (isset($opt['preauth']))
+ {
+ return $this->request_url;
+ }
+
+ /*%******************************************************************************************%*/
+
+ // If our changes were temporary, reset them.
+ if ($this->temporary_prefix)
+ {
+ $this->temporary_prefix = false;
+ $this->resource_prefix = null;
+ }
+
+ // Manage the (newer) batch request API or the (older) returnCurlHandle setting.
+ if ($this->use_batch_flow)
+ {
+ $handle = $request->prep_request();
+ $this->batch_object->add($handle);
+ $this->use_batch_flow = false;
+
+ return $handle;
+ }
+ elseif (isset($opt['returnCurlHandle']) && $opt['returnCurlHandle'] === true)
+ {
+ return $request->prep_request();
+ }
+
+ // Send!
+ $request->send_request();
+
+ // Prepare the response
+ $headers = $request->get_response_header();
+ $headers['x-aws-request-url'] = $this->request_url;
+ $headers['x-aws-redirects'] = $this->redirects;
+ $headers['x-aws-stringtosign'] = $string_to_sign;
+ $headers['x-aws-requestheaders'] = $request->request_headers;
+
+ // Did we have a request body?
+ if (isset($opt['body']))
+ {
+ $headers['x-aws-requestbody'] = $opt['body'];
+ }
+
+ $data = new $this->response_class($headers, $this->parse_callback($request->get_response_body()), $request->get_response_code());
+
+ // Did Amazon tell us to redirect? Typically happens for multiple rapid requests EU datacenters.
+ // @see: http://docs.amazonwebservices.com/AmazonS3/latest/dev/Redirects.html
+ // @codeCoverageIgnoreStart
+ if ((integer) $request->get_response_code() === 307) // Temporary redirect to new endpoint.
+ {
+ $this->redirects++;
+ $opt['location'] = $headers['location'];
+ $data = $this->authenticate($bucket, $opt);
+ }
+
+ // Was it Amazon's fault the request failed? Retry the request until we reach $max_retries.
+ elseif ((integer) $request->get_response_code() === 500 || (integer) $request->get_response_code() === 503)
+ {
+ if ($this->redirects <= $this->max_retries)
+ {
+ // Exponential backoff
+ $delay = (integer) (pow(4, $this->redirects) * 100000);
+ usleep($delay);
+ $this->redirects++;
+ $data = $this->authenticate($bucket, $opt);
+ }
+ }
+ // @codeCoverageIgnoreEnd
+
+ // Return!
+ $this->redirects = 0;
+ return $data;
+ }
+
+ /**
+ * Validates whether or not the specified Amazon S3 bucket name is valid for DNS-style access. This
+ * method is leveraged by any method that creates buckets.
+ *
+ * @param string $bucket (Required) The name of the bucket to validate.
+ * @return boolean Whether or not the specified Amazon S3 bucket name is valid for DNS-style access. A value of <code>true</code> means that the bucket name is valid. A value of <code>false</code> means that the bucket name is invalid.
+ */
+ public function validate_bucketname_create($bucket)
+ {
+ // list_buckets() uses this. Let it pass.
+ if ($bucket === '') return true;
+
+ if (
+ ($bucket === null || $bucket === false) || // Must not be null or false
+ preg_match('/[^(a-z0-9\-\.)]/', $bucket) || // Must be in the lowercase Roman alphabet, period or hyphen
+ !preg_match('/^([a-z]|\d)/', $bucket) || // Must start with a number or letter
+ !(strlen($bucket) >= 3 && strlen($bucket) <= 63) || // Must be between 3 and 63 characters long
+ (strpos($bucket, '..') !== false) || // Bucket names cannot contain two, adjacent periods
+ (strpos($bucket, '-.') !== false) || // Bucket names cannot contain dashes next to periods
+ (strpos($bucket, '.-') !== false) || // Bucket names cannot contain dashes next to periods
+ preg_match('/(-|\.)$/', $bucket) || // Bucket names should not end with a dash or period
+ preg_match('/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/', $bucket) // Must not be formatted as an IP address
+ ) return false;
+
+ return true;
+ }
+
+ /**
+ * Validates whether or not the specified Amazon S3 bucket name is valid for path-style access. This
+ * method is leveraged by any method that reads from buckets.
+ *
+ * @param string $bucket (Required) The name of the bucket to validate.
+ * @return boolean Whether or not the bucket name is valid. A value of <code>true</code> means that the bucket name is valid. A value of <code>false</code> means that the bucket name is invalid.
+ */
+ public function validate_bucketname_support($bucket)
+ {
+ // list_buckets() uses this. Let it pass.
+ if ($bucket === '') return true;
+
+ // Validate
+ if (
+ ($bucket === null || $bucket === false) || // Must not be null or false
+ preg_match('/[^(a-z0-9_\-\.)]/i', $bucket) || // Must be in the Roman alphabet, period, hyphen or underscore
+ !preg_match('/^([a-z]|\d)/i', $bucket) || // Must start with a number or letter
+ !(strlen($bucket) >= 3 && strlen($bucket) <= 255) || // Must be between 3 and 255 characters long
+ preg_match('/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/', $bucket) // Must not be formatted as an IP address
+ ) return false;
+
+ return true;
+ }
+
+ /*%******************************************************************************************%*/
+ // SETTERS
+
+ /**
+ * Sets the region to use for subsequent Amazon S3 operations. This will also reset any prior use of
+ * <enable_path_style()>.
+ *
+ * @param string $region (Required) The region to use for subsequent Amazon S3 operations. For a complete list of REGION constants, see the <code>AmazonS3</code> Constants page in the API reference.
+ * @return $this A reference to the current instance.
+ */
+ public function set_region($region)
+ {
+ // @codeCoverageIgnoreStart
+ $this->set_hostname($region);
+
+ switch ($region)
+ {
+ case self::REGION_US_E1: // Northern Virginia
+ $this->enable_path_style(false);
+ break;
+
+ case self::REGION_EU_W1: // Ireland
+ $this->enable_path_style(); // Always use path-style access for EU endpoint.
+ break;
+
+ default:
+ $this->enable_path_style(false);
+ break;
+
+ }
+ // @codeCoverageIgnoreEnd
+
+ return $this;
+ }
+
+ /**
+ * Sets the virtual host to use in place of the default `bucket.s3.amazonaws.com` domain.
+ *
+ * @param string $vhost (Required) The virtual host to use in place of the default `bucket.s3.amazonaws.com` domain.
+ * @return $this A reference to the current instance.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/VirtualHosting.html Virtual Hosting of Buckets
+ */
+ public function set_vhost($vhost)
+ {
+ $this->vhost = $vhost;
+ return $this;
+ }
+
+ /**
+ * Enables the use of the older path-style URI access for all requests.
+ *
+ * @param string $style (Optional) Whether or not to enable path-style URI access for all requests. The default value is <code>true</code>.
+ * @return $this A reference to the current instance.
+ */
+ public function enable_path_style($style = true)
+ {
+ $this->path_style = $style;
+ return $this;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // BUCKET METHODS
+
+ /**
+ * Creates an Amazon S3 bucket.
+ *
+ * Every object stored in Amazon S3 is contained in a bucket. Buckets partition the namespace of
+ * objects stored in Amazon S3 at the top level. in a bucket, any name can be used for objects.
+ * However, bucket names must be unique across all of Amazon S3.
+ *
+ * @param string $bucket (Required) The name of the bucket to create.
+ * @param string $region (Required) The preferred geographical location for the bucket. [Allowed values: `AmazonS3::REGION_US_E1 `, `AmazonS3::REGION_US_W1`, `AmazonS3::REGION_EU_W1`, `AmazonS3::REGION_APAC_SE1`, `AmazonS3::REGION_APAC_NE1`]
+ * @param string $acl (Optional) The ACL settings for the specified bucket. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. The default value is <ACL_PRIVATE>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/UsingBucket.html Working with Amazon S3 Buckets
+ */
+ public function create_bucket($bucket, $region, $acl = self::ACL_PRIVATE, $opt = null)
+ {
+ // If the bucket contains uppercase letters...
+ if (preg_match('/[A-Z]/', $bucket))
+ {
+ // Throw a warning
+ trigger_error('Since DNS-valid bucket names cannot contain uppercase characters, "' . $bucket . '" has been automatically converted to "' . strtolower($bucket) . '"', E_USER_WARNING);
+
+ // Force the bucketname to lowercase
+ $bucket = strtolower($bucket);
+ }
+
+ // Validate the S3 bucket name for creation
+ if (!$this->validate_bucketname_create($bucket))
+ {
+ // @codeCoverageIgnoreStart
+ throw new S3_Exception('"' . $bucket . '" is not DNS-valid (i.e., <bucketname>.s3.amazonaws.com), and cannot be used as an S3 bucket name. Review "Bucket Restrictions and Limitations" in the S3 Developer Guide for more information.');
+ // @codeCoverageIgnoreEnd
+ }
+
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml',
+ 'x-amz-acl' => $acl
+ );
+
+ // Defaults
+ $this->set_region($region); // Also sets path-style
+ $xml = simplexml_load_string($this->base_location_constraint);
+
+ switch ($region)
+ {
+ case self::REGION_US_E1: // Northern Virginia
+ $opt['body'] = '';
+ break;
+
+ case self::REGION_EU_W1: // Ireland
+ $xml->LocationConstraint = 'EU';
+ $opt['body'] = $xml->asXML();
+ break;
+
+ default:
+ $xml->LocationConstraint = str_replace(array('s3-', '.amazonaws.com'), '', $region);
+ $opt['body'] = $xml->asXML();
+ break;
+ }
+
+ $response = $this->authenticate($bucket, $opt);
+
+ // Make sure we're set back to DNS-style URLs
+ $this->enable_path_style(false);
+
+ return $response;
+ }
+
+ /**
+ * Gets the region in which the specified Amazon S3 bucket is located.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function get_bucket_region($bucket, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'location';
+
+ // Authenticate to S3
+ $response = $this->authenticate($bucket, $opt);
+
+ if ($response->isOK())
+ {
+ // Handle body
+ $response->body = (string) $response->body;
+ }
+
+ return $response;
+ }
+
+ /**
+ * Gets the HTTP headers for the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function get_bucket_headers($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'HEAD';
+
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Deletes a bucket from an Amazon S3 account. A bucket must be empty before the bucket itself can be deleted.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param boolean $force (Optional) Whether to force-delete the bucket and all of its contents. The default value is <code>false</code>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return mixed A <CFResponse> object if the bucket was deleted successfully. Returns boolean <code>false</code> if otherwise.
+ */
+ public function delete_bucket($bucket, $force = false, $opt = null)
+ {
+ // Set default value
+ $success = true;
+
+ if ($force)
+ {
+ // Delete all of the items from the bucket.
+ $success = $this->delete_all_object_versions($bucket);
+ }
+
+ // As long as we were successful...
+ if ($success)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'DELETE';
+
+ return $this->authenticate($bucket, $opt);
+ }
+
+ // @codeCoverageIgnoreStart
+ return false;
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * Gets a list of all buckets contained in the caller's Amazon S3 account.
+ *
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function list_buckets($opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+
+ return $this->authenticate('', $opt);
+ }
+
+ /**
+ * Gets the access control list (ACL) settings for the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
+ */
+ public function get_bucket_acl($bucket, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'acl';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Sets the access control list (ACL) settings for the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $acl (Optional) The ACL settings for the specified bucket. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. Alternatively, an array of associative arrays. Each associative array contains an `id` and a `permission` key. The default value is <ACL_PRIVATE>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
+ */
+ public function set_bucket_acl($bucket, $acl = self::ACL_PRIVATE, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'acl';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ // Make sure these are defined.
+ // @codeCoverageIgnoreStart
+ if (!$this->credentials->canonical_id || !$this->credentials->canonical_name)
+ {
+ // Fetch the data live.
+ $canonical = $this->get_canonical_user_id();
+ $this->credentials->canonical_id = $canonical['id'];
+ $this->credentials->canonical_name = $canonical['display_name'];
+ }
+ // @codeCoverageIgnoreEnd
+
+ if (is_array($acl))
+ {
+ $opt['body'] = $this->generate_access_policy($this->credentials->canonical_id, $this->credentials->canonical_name, $acl);
+ }
+ else
+ {
+ $opt['body'] = '';
+ $opt['headers']['x-amz-acl'] = $acl;
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // OBJECT METHODS
+
+ /**
+ * Creates an Amazon S3 object. After an Amazon S3 bucket is created, objects can be stored in it.
+ *
+ * Each standard object can hold up to 5 GB of data. When an object is stored in Amazon S3, the data is streamed
+ * to multiple storage servers in multiple data centers. This ensures the data remains available in the
+ * event of internal network or hardware failure.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>body</code> - <code>string</code> - Required; Conditional - The data to be stored in the object. Either this parameter or <code>fileUpload</code> must be specified.</li>
+ * <li><code>fileUpload</code> - <code>string|resource</code> - Required; Conditional - The URL/path for the file to upload, or an open resource. Either this parameter or <code>body</code> is required.</li>
+ * <li><code>acl</code> - <code>string</code> - Optional - The ACL settings for the specified object. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. The default value is <code>ACL_PRIVATE</code>.</li>
+ * <li><code>contentType</code> - <code>string</code> - Optional - The type of content that is being sent in the body. If a file is being uploaded via <code>fileUpload</code> as a file system path, it will attempt to determine the correct mime-type based on the file extension. The default value is <code>application/octet-stream</code>.</li>
+ * <li><code>encryption</code> - <code>string</code> - Optional - The algorithm to use for encrypting the object. [Allowed values: <code>AES256</code>]</li>
+ * <li><code>headers</code> - <code>array</code> - Optional - Standard HTTP headers to send along in the request. Accepts an associative array of key-value pairs.</li>
+ * <li><code>length</code> - <code>integer</code> - Optional - The size of the object in bytes. For more information, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13">RFC 2616, section 14.13</a>. The value can also be passed to the <code>header</code> option as <code>Content-Length</code>.</li>
+ * <li><code>meta</code> - <code>array</code> - Optional - An associative array of key-value pairs. Represented by <code>x-amz-meta-:</code>. Any header starting with this prefix is considered user metadata. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.</li>
+ * <li><code>seekTo</code> - <code>integer</code> - Optional - The starting position in bytes within the file/stream to upload from.</li>
+ * <li><code>storage</code> - <code>string</code> - Optional - Whether to use Standard or Reduced Redundancy storage. [Allowed values: <code>AmazonS3::STORAGE_STANDARD</code>, <code>AmazonS3::STORAGE_REDUCED</code>]. The default value is <code>STORAGE_STANDARD</code>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
+ */
+ public function create_object($bucket, $filename, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'PUT';
+ $opt['resource'] = $filename;
+
+ // Handle content length. Can also be passed as an HTTP header.
+ if (isset($opt['length']))
+ {
+ $opt['headers']['Content-Length'] = $opt['length'];
+ unset($opt['length']);
+ }
+
+ // Handle content type. Can also be passed as an HTTP header.
+ if (isset($opt['contentType']))
+ {
+ $opt['headers']['Content-Type'] = $opt['contentType'];
+ unset($opt['contentType']);
+ }
+
+ // Handle Access Control Lists. Can also be passed as an HTTP header.
+ if (isset($opt['acl']))
+ {
+ $opt['headers']['x-amz-acl'] = $opt['acl'];
+ unset($opt['acl']);
+ }
+
+ // Handle storage settings. Can also be passed as an HTTP header.
+ if (isset($opt['storage']))
+ {
+ $opt['headers']['x-amz-storage-class'] = $opt['storage'];
+ unset($opt['storage']);
+ }
+
+ // Handle encryption settings. Can also be passed as an HTTP header.
+ if (isset($opt['encryption']))
+ {
+ $opt['headers']['x-amz-server-side-encryption'] = $opt['encryption'];
+ unset($opt['encryption']);
+ }
+
+ // Handle meta tags. Can also be passed as an HTTP header.
+ if (isset($opt['meta']))
+ {
+ foreach ($opt['meta'] as $meta_key => $meta_value)
+ {
+ // e.g., `My Meta Header` is converted to `x-amz-meta-my-meta-header`.
+ $opt['headers']['x-amz-meta-' . strtolower(str_replace(' ', '-', $meta_key))] = $meta_value;
+ }
+ unset($opt['meta']);
+ }
+
+ $opt['headers']['Expect'] = '100-continue';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Gets the contents of an Amazon S3 object in the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>etag</code> - <code>string</code> - Optional - The <code>ETag</code> header passed in from a previous request. If specified, request <code>LastModified</code> option must be specified as well. Will trigger a <code>304 Not Modified</code> status code if the file hasn't changed.</li>
+ * <li><code>fileDownload</code> - <code>string|resource</code> - Optional - The file system location to download the file to, or an open file resource. Must be a server-writable location.</li>
+ * <li><code>headers</code> - <code>array</code> - Optional - Standard HTTP headers to send along in the request. Accepts an associative array of key-value pairs.</li>
+ * <li><code>lastmodified</code> - <code>string</code> - Optional - The <code>LastModified</code> header passed in from a previous request. If specified, request <code>ETag</code> option must be specified as well. Will trigger a <code>304 Not Modified</code> status code if the file hasn't changed.</li>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>range</code> - <code>string</code> - Optional - The range of bytes to fetch from the object. Specify this parameter when downloading partial bits or completing incomplete object downloads. The specified range must be notated with a hyphen (e.g., 0-10485759). Defaults to the byte range of the complete Amazon S3 object.</li>
+ * <li><code>response</code> - <code>array</code> - Optional - Allows adjustments to specific response headers. Pass an associative array where each key is one of the following: <code>cache-control</code>, <code>content-disposition</code>, <code>content-encoding</code>, <code>content-language</code>, <code>content-type</code>, <code>expires</code>. The <code>expires</code> value should use <php:gmdate()> and be formatted with the <code>DATE_RFC2822</code> constant.</li>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object to retrieve. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function get_object($bucket, $filename, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'GET';
+ $opt['resource'] = $filename;
+
+ if (!isset($opt['headers']) || !is_array($opt['headers']))
+ {
+ $opt['headers'] = array();
+ }
+
+ if (isset($opt['lastmodified']))
+ {
+ $opt['headers']['If-Modified-Since'] = $opt['lastmodified'];
+ }
+
+ if (isset($opt['etag']))
+ {
+ $opt['headers']['If-None-Match'] = $opt['etag'];
+ }
+
+ // Partial content range
+ if (isset($opt['range']))
+ {
+ $opt['headers']['Range'] = 'bytes=' . $opt['range'];
+ }
+
+ // GET responses
+ if (isset($opt['response']))
+ {
+ foreach ($opt['response'] as $key => $value)
+ {
+ $opt['response-' . $key] = $value;
+ unset($opt['response'][$key]);
+ }
+ }
+
+ // Authenticate to S3
+ $this->parse_the_response = false;
+ $response = $this->authenticate($bucket, $opt);
+ $this->parse_the_response = true;
+
+ return $response;
+ }
+
+ /**
+ * Gets the HTTP headers for the specified Amazon S3 object.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object to retrieve. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function get_object_headers($bucket, $filename, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'HEAD';
+ $opt['resource'] = $filename;
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Deletes an Amazon S3 object from the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object to delete. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>MFASerial</code> - <code>string</code> - Optional - The serial number on the back of the Gemalto device. <code>MFASerial</code> and <code>MFAToken</code> must both be set for MFA to work.</li>
+ * <li><code>MFAToken</code> - <code>string</code> - Optional - The current token displayed on the Gemalto device. <code>MFASerial</code> and <code>MFAToken</code> must both be set for MFA to work.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://aws.amazon.com/mfa/ Multi-Factor Authentication
+ */
+ public function delete_object($bucket, $filename, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'DELETE';
+ $opt['resource'] = $filename;
+
+ // Enable MFA delete?
+ // @codeCoverageIgnoreStart
+ if (isset($opt['MFASerial']) && isset($opt['MFAToken']))
+ {
+ $opt['headers'] = array(
+ 'x-amz-mfa' => ($opt['MFASerial'] . ' ' . $opt['MFAToken'])
+ );
+ }
+ // @codeCoverageIgnoreEnd
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Deletes two or more specified Amazon S3 objects from the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>objects</code> - <code>array</code> - Required - The object references to delete from the bucket. <ul>
+ * <li><code>key</code> - <code>string</code> - Required - The name of the object (e.g., the "key") to delete. This should include the entire file path including all "subdirectories".</li>
+ * <li><code>version_id</code> - <code>string</code> - Optional - If the object is versioned, include the version ID to delete.</li>
+ * </ul></li>
+ * <li><code>quiet</code> - <code>boolean</code> - Optional - Whether or not Amazon S3 should use "Quiet" mode for this operation. A value of <code>true</code> will enable Quiet mode. A value of <code>false</code> will use Verbose mode. The default value is <code>false</code>.</li>
+ * <li><code>MFASerial</code> - <code>string</code> - Optional - The serial number on the back of the Gemalto device. <code>MFASerial</code> and <code>MFAToken</code> must both be set for MFA to work.</li>
+ * <li><code>MFAToken</code> - <code>string</code> - Optional - The current token displayed on the Gemalto device. <code>MFASerial</code> and <code>MFAToken</code> must both be set for MFA to work.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://aws.amazon.com/mfa/ Multi-Factor Authentication
+ */
+ public function delete_objects($bucket, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'POST';
+ $opt['sub_resource'] = 'delete';
+ $opt['body'] = '';
+
+ // Bail out
+ if (!isset($opt['objects']) || !is_array($opt['objects']))
+ {
+ throw new S3_Exception('The ' . __FUNCTION__ . ' method requires the "objects" option to be set as an array.');
+ }
+
+ $xml = new SimpleXMLElement($this->multi_object_delete_xml);
+
+ // Add the objects
+ foreach ($opt['objects'] as $object)
+ {
+ $xobject = $xml->addChild('Object');
+ $xobject->addChild('Key', $object['key']);
+
+ if (isset($object['version_id']))
+ {
+ $xobject->addChild('VersionId', $object['version_id']);
+ }
+ }
+
+ // Quiet mode?
+ if (isset($opt['quiet']))
+ {
+ $quiet = 'false';
+ if (is_bool($opt['quiet'])) // Boolean
+ {
+ $quiet = $opt['quiet'] ? 'true' : 'false';
+ }
+ elseif (is_string($opt['quiet'])) // String
+ {
+ $quiet = ($opt['quiet'] === 'true') ? 'true' : 'false';
+ }
+
+ $xml->addChild('Quiet', $quiet);
+ }
+
+ // Enable MFA delete?
+ // @codeCoverageIgnoreStart
+ if (isset($opt['MFASerial']) && isset($opt['MFAToken']))
+ {
+ $opt['headers'] = array(
+ 'x-amz-mfa' => ($opt['MFASerial'] . ' ' . $opt['MFAToken'])
+ );
+ }
+ // @codeCoverageIgnoreEnd
+
+ $opt['body'] = $xml->asXML();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Gets a list of all Amazon S3 objects in the specified bucket.
+ *
+ * NOTE: <strong>This method is paginated</strong>, and will not return more than <code>max-keys</code> keys. If you want to retrieve a list of all keys, you will need to make multiple calls to this function using the <code>marker</code> option to specify the pagination offset (the key of the last processed key--lexically ordered) and the <code>IsTruncated</code> response key to detect when all results have been processed. See: <a href="http://docs.amazonwebservices.com/AmazonS3/latest/API/index.html?RESTBucketGET.html">the S3 REST documentation for get_bucket</a> for more information.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>delimiter</code> - <code>string</code> - Optional - Keys that contain the same string between the prefix and the first occurrence of the delimiter will be rolled up into a single result element in the CommonPrefixes collection.</li>
+ * <li><code>marker</code> - <code>string</code> - Optional - Restricts the response to contain results that only occur alphabetically after the value of the marker.</li>
+ * <li><code>max-keys</code> - <code>string</code> - Optional - The maximum number of results returned by the method call. The returned list will contain no more results than the specified value, but may return fewer. The default value is 1000.</li>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>prefix</code> - <code>string</code> - Optional - Restricts the response to contain results that begin only with the specified prefix.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function list_objects($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'GET';
+
+ foreach (array('delimiter', 'marker', 'max-keys', 'prefix') as $param)
+ {
+ if (isset($opt[$param]))
+ {
+ $opt['query_string'][$param] = $opt[$param];
+ unset($opt[$param]);
+ }
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Copies an Amazon S3 object to a new location, whether in the same Amazon S3 region, bucket, or otherwise.
+ *
+ * @param array $source (Required) The bucket and file name to copy from. The following keys must be set: <ul>
+ * <li><code>bucket</code> - <code>string</code> - Required - Specifies the name of the bucket containing the source object.</li>
+ * <li><code>filename</code> - <code>string</code> - Required - Specifies the file name of the source object to copy.</li></ul>
+ * @param array $dest (Required) The bucket and file name to copy to. The following keys must be set: <ul>
+ * <li><code>bucket</code> - <code>string</code> - Required - Specifies the name of the bucket to copy the object to.</li>
+ * <li><code>filename</code> - <code>string</code> - Required - Specifies the file name to copy the object to.</li></ul>
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>acl</code> - <code>string</code> - Optional - The ACL settings for the specified object. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. Alternatively, an array of associative arrays. Each associative array contains an <code>id</code> and a <code>permission</code> key. The default value is <code>ACL_PRIVATE</code>.</li>
+ * <li><code>encryption</code> - <code>string</code> - Optional - The algorithm to use for encrypting the object. [Allowed values: <code>AES256</code>]</li>
+ * <li><code>storage</code> - <code>string</code> - Optional - Whether to use Standard or Reduced Redundancy storage. [Allowed values: <code>AmazonS3::STORAGE_STANDARD</code>, <code>AmazonS3::STORAGE_REDUCED</code>]. The default value is <code>STORAGE_STANDARD</code>.</li>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object to copy. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>ifMatch</code> - <code>string</code> - Optional - The ETag header from a previous request. Copies the object if its entity tag (ETag) matches the specified tag; otherwise, the request returns a <code>412</code> HTTP status code error (precondition failed). Used in conjunction with <code>ifUnmodifiedSince</code>.</li>
+ * <li><code>ifUnmodifiedSince</code> - <code>string</code> - Optional - The LastModified header from a previous request. Copies the object if it hasn't been modified since the specified time; otherwise, the request returns a <code>412</code> HTTP status code error (precondition failed). Used in conjunction with <code>ifMatch</code>.</li>
+ * <li><code>ifNoneMatch</code> - <code>string</code> - Optional - The ETag header from a previous request. Copies the object if its entity tag (ETag) is different than the specified ETag; otherwise, the request returns a <code>412</code> HTTP status code error (failed condition). Used in conjunction with <code>ifModifiedSince</code>.</li>
+ * <li><code>ifModifiedSince</code> - <code>string</code> - Optional - The LastModified header from a previous request. Copies the object if it has been modified since the specified time; otherwise, the request returns a <code>412</code> HTTP status code error (failed condition). Used in conjunction with <code>ifNoneMatch</code>.</li>
+ * <li><code>headers</code> - <code>array</code> - Optional - Standard HTTP headers to send along in the request. Accepts an associative array of key-value pairs.</li>
+ * <li><code>meta</code> - <code>array</code> - Optional - Associative array of key-value pairs. Represented by <code>x-amz-meta-:</code> Any header starting with this prefix is considered user metadata. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.</li>
+ * <li><code>metadataDirective</code> - <code>string</code> - Optional - Accepts either COPY or REPLACE. You will likely never need to use this, as it manages itself with no issues.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/API/RESTObjectCOPY.html Copying Amazon S3 Objects
+ */
+ public function copy_object($source, $dest, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $batch = array();
+
+ // Add this to our request
+ $opt['verb'] = 'PUT';
+ $opt['resource'] = $dest['filename'];
+ $opt['body'] = '';
+
+ // Handle copy source
+ if (isset($source['bucket']) && isset($source['filename']))
+ {
+ $opt['headers']['x-amz-copy-source'] = '/' . $source['bucket'] . '/' . rawurlencode($source['filename'])
+ . (isset($opt['versionId']) ? ('?' . 'versionId=' . rawurlencode($opt['versionId'])) : ''); // Append the versionId to copy, if available
+ unset($opt['versionId']);
+
+ // Determine if we need to lookup the pre-existing content-type.
+ if (
+ (!$this->use_batch_flow && !isset($opt['returnCurlHandle'])) &&
+ !in_array(strtolower('content-type'), array_map('strtolower', array_keys($opt['headers'])))
+ )
+ {
+ $response = $this->get_object_headers($source['bucket'], $source['filename']);
+ if ($response->isOK())
+ {
+ $opt['headers']['Content-Type'] = $response->header['content-type'];
+ }
+ }
+ }
+
+ // Handle metadata directive
+ $opt['headers']['x-amz-metadata-directive'] = 'COPY';
+ if ($source['bucket'] === $dest['bucket'] && $source['filename'] === $dest['filename'])
+ {
+ $opt['headers']['x-amz-metadata-directive'] = 'REPLACE';
+ }
+ if (isset($opt['metadataDirective']))
+ {
+ $opt['headers']['x-amz-metadata-directive'] = $opt['metadataDirective'];
+ unset($opt['metadataDirective']);
+ }
+
+ // Handle Access Control Lists. Can also pass canned ACLs as an HTTP header.
+ if (isset($opt['acl']) && is_array($opt['acl']))
+ {
+ $batch[] = $this->set_object_acl($dest['bucket'], $dest['filename'], $opt['acl'], array(
+ 'returnCurlHandle' => true
+ ));
+ unset($opt['acl']);
+ }
+ elseif (isset($opt['acl']))
+ {
+ $opt['headers']['x-amz-acl'] = $opt['acl'];
+ unset($opt['acl']);
+ }
+
+ // Handle storage settings. Can also be passed as an HTTP header.
+ if (isset($opt['storage']))
+ {
+ $opt['headers']['x-amz-storage-class'] = $opt['storage'];
+ unset($opt['storage']);
+ }
+
+ // Handle encryption settings. Can also be passed as an HTTP header.
+ if (isset($opt['encryption']))
+ {
+ $opt['headers']['x-amz-server-side-encryption'] = $opt['encryption'];
+ unset($opt['encryption']);
+ }
+
+ // Handle conditional-copy parameters
+ if (isset($opt['ifMatch']))
+ {
+ $opt['headers']['x-amz-copy-source-if-match'] = $opt['ifMatch'];
+ unset($opt['ifMatch']);
+ }
+ if (isset($opt['ifNoneMatch']))
+ {
+ $opt['headers']['x-amz-copy-source-if-none-match'] = $opt['ifNoneMatch'];
+ unset($opt['ifNoneMatch']);
+ }
+ if (isset($opt['ifUnmodifiedSince']))
+ {
+ $opt['headers']['x-amz-copy-source-if-unmodified-since'] = $opt['ifUnmodifiedSince'];
+ unset($opt['ifUnmodifiedSince']);
+ }
+ if (isset($opt['ifModifiedSince']))
+ {
+ $opt['headers']['x-amz-copy-source-if-modified-since'] = $opt['ifModifiedSince'];
+ unset($opt['ifModifiedSince']);
+ }
+
+ // Handle meta tags. Can also be passed as an HTTP header.
+ if (isset($opt['meta']))
+ {
+ foreach ($opt['meta'] as $meta_key => $meta_value)
+ {
+ // e.g., `My Meta Header` is converted to `x-amz-meta-my-meta-header`.
+ $opt['headers']['x-amz-meta-' . strtolower(str_replace(' ', '-', $meta_key))] = $meta_value;
+ }
+ unset($opt['meta']);
+ }
+
+ // Authenticate to S3
+ $response = $this->authenticate($dest['bucket'], $opt);
+
+ // Attempt to reset ACLs
+ $http = new RequestCore();
+ $http->send_multi_request($batch);
+
+ return $response;
+ }
+
+ /**
+ * Updates an Amazon S3 object with new headers or other metadata. To replace the content of the
+ * specified Amazon S3 object, call <create_object()> with the same bucket and file name parameters.
+ *
+ * @param string $bucket (Required) The name of the bucket that contains the source file.
+ * @param string $filename (Required) The source file name that you want to update.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>acl</code> - <code>string</code> - Optional - The ACL settings for the specified object. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. The default value is <ACL_PRIVATE>.</li>
+ * <li><code>headers</code> - <code>array</code> - Optional - Standard HTTP headers to send along in the request. Accepts an associative array of key-value pairs.</li>
+ * <li><code>meta</code> - <code>array</code> - Optional - An associative array of key-value pairs. Any header with the <code>x-amz-meta-</code> prefix is considered user metadata and is stored with the Amazon S3 object. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/API/RESTObjectCOPY.html Copying Amazon S3 Objects
+ */
+ public function update_object($bucket, $filename, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['metadataDirective'] = 'REPLACE';
+
+ // Authenticate to S3
+ return $this->copy_object(
+ array('bucket' => $bucket, 'filename' => $filename),
+ array('bucket' => $bucket, 'filename' => $filename),
+ $opt
+ );
+ }
+
+
+ /*%******************************************************************************************%*/
+ // ACCESS CONTROL LISTS
+
+ /**
+ * Gets the access control list (ACL) settings for the specified Amazon S3 object.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object to retrieve. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
+ */
+ public function get_object_acl($bucket, $filename, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['resource'] = $filename;
+ $opt['sub_resource'] = 'acl';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Sets the access control list (ACL) settings for the specified Amazon S3 object.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param string $acl (Optional) The ACL settings for the specified object. Accepts any of the following constants: [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. Alternatively, an array of associative arrays. Each associative array contains an <code>id</code> and a <code>permission</code> key. The default value is <code>ACL_PRIVATE</code>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
+ */
+ public function set_object_acl($bucket, $filename, $acl = self::ACL_PRIVATE, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['resource'] = $filename;
+ $opt['sub_resource'] = 'acl';
+
+ // Retrieve the original metadata
+ $metadata = $this->get_object_metadata($bucket, $filename);
+ if ($metadata && $metadata['ContentType'])
+ {
+ $opt['headers']['Content-Type'] = $metadata['ContentType'];
+ }
+ if ($metadata && $metadata['StorageClass'])
+ {
+ $opt['headers']['x-amz-storage-class'] = $metadata['StorageClass'];
+ }
+
+ // Make sure these are defined.
+ // @codeCoverageIgnoreStart
+ if (!$this->credentials->canonical_id || !$this->credentials->canonical_name)
+ {
+ // Fetch the data live.
+ $canonical = $this->get_canonical_user_id();
+ $this->credentials->canonical_id = $canonical['id'];
+ $this->credentials->canonical_name = $canonical['display_name'];
+ }
+ // @codeCoverageIgnoreEnd
+
+ if (is_array($acl))
+ {
+ $opt['body'] = $this->generate_access_policy($this->credentials->canonical_id, $this->credentials->canonical_name, $acl);
+ }
+ else
+ {
+ $opt['body'] = '';
+ $opt['headers']['x-amz-acl'] = $acl;
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Generates the XML to be used for the Access Control Policy.
+ *
+ * @param string $canonical_id (Required) The canonical ID for the bucket owner. This is provided as the `id` return value from <get_canonical_user_id()>.
+ * @param string $canonical_name (Required) The canonical display name for the bucket owner. This is provided as the `display_name` value from <get_canonical_user_id()>.
+ * @param array $users (Optional) An array of associative arrays. Each associative array contains an `id` value and a `permission` value.
+ * @return string Access Control Policy XML.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/S3_ACLs.html Access Control Lists
+ */
+ public function generate_access_policy($canonical_id, $canonical_name, $users)
+ {
+ $xml = simplexml_load_string($this->base_acp_xml);
+ $owner = $xml->addChild('Owner');
+ $owner->addChild('ID', $canonical_id);
+ $owner->addChild('DisplayName', $canonical_name);
+ $acl = $xml->addChild('AccessControlList');
+
+ foreach ($users as $user)
+ {
+ $grant = $acl->addChild('Grant');
+ $grantee = $grant->addChild('Grantee');
+
+ switch ($user['id'])
+ {
+ // Authorized Users
+ case self::USERS_AUTH:
+ $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('URI', self::USERS_AUTH);
+ break;
+
+ // All Users
+ case self::USERS_ALL:
+ $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('URI', self::USERS_ALL);
+ break;
+
+ // The Logging User
+ case self::USERS_LOGGING:
+ $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('URI', self::USERS_LOGGING);
+ break;
+
+ // Email Address or Canonical Id
+ default:
+ if (strpos($user['id'], '@'))
+ {
+ $grantee->addAttribute('xsi:type', 'AmazonCustomerByEmail', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('EmailAddress', $user['id']);
+ }
+ else
+ {
+ // Assume Canonical Id
+ $grantee->addAttribute('xsi:type', 'CanonicalUser', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('ID', $user['id']);
+ }
+ break;
+ }
+
+ $grant->addChild('Permission', $user['permission']);
+ }
+
+ return $xml->asXML();
+ }
+
+
+ /*%******************************************************************************************%*/
+ // LOGGING METHODS
+
+ /**
+ * Gets the access logs associated with the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use. Pass a `null` value when using the <set_vhost()> method.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/ServerLogs.html Server Access Logging
+ */
+ public function get_logs($bucket, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'logging';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Enables access logging for the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to enable logging for. Pass a `null` value when using the <set_vhost()> method.
+ * @param string $target_bucket (Required) The name of the bucket to store the logs in.
+ * @param string $target_prefix (Required) The prefix to give to the log file names.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>users</code> - <code>array</code> - Optional - An array of associative arrays specifying any user to give access to. Each associative array contains an <code>id</code> and <code>permission</code> value.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/LoggingAPI.html Server Access Logging Configuration API
+ */
+ public function enable_logging($bucket, $target_bucket, $target_prefix, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'logging';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ $xml = simplexml_load_string($this->base_logging_xml);
+ $LoggingEnabled = $xml->addChild('LoggingEnabled');
+ $LoggingEnabled->addChild('TargetBucket', $target_bucket);
+ $LoggingEnabled->addChild('TargetPrefix', $target_prefix);
+ $TargetGrants = $LoggingEnabled->addChild('TargetGrants');
+
+ if (isset($opt['users']) && is_array($opt['users']))
+ {
+ foreach ($opt['users'] as $user)
+ {
+ $grant = $TargetGrants->addChild('Grant');
+ $grantee = $grant->addChild('Grantee');
+
+ switch ($user['id'])
+ {
+ // Authorized Users
+ case self::USERS_AUTH:
+ $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('URI', self::USERS_AUTH);
+ break;
+
+ // All Users
+ case self::USERS_ALL:
+ $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('URI', self::USERS_ALL);
+ break;
+
+ // The Logging User
+ case self::USERS_LOGGING:
+ $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('URI', self::USERS_LOGGING);
+ break;
+
+ // Email Address or Canonical Id
+ default:
+ if (strpos($user['id'], '@'))
+ {
+ $grantee->addAttribute('xsi:type', 'AmazonCustomerByEmail', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('EmailAddress', $user['id']);
+ }
+ else
+ {
+ // Assume Canonical Id
+ $grantee->addAttribute('xsi:type', 'CanonicalUser', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('ID', $user['id']);
+ }
+ break;
+ }
+
+ $grant->addChild('Permission', $user['permission']);
+ }
+ }
+
+ $opt['body'] = $xml->asXML();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Disables access logging for the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use. Pass `null` if using <set_vhost()>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/LoggingAPI.html Server Access Logging Configuration API
+ */
+ public function disable_logging($bucket, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'logging';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+ $opt['body'] = $this->base_logging_xml;
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // CONVENIENCE METHODS
+
+ /**
+ * Gets whether or not the specified Amazon S3 bucket exists in Amazon S3. This includes buckets
+ * that do not belong to the caller.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @return boolean A value of <code>true</code> if the bucket exists, or a value of <code>false</code> if it does not.
+ */
+ public function if_bucket_exists($bucket)
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ $header = $this->get_bucket_headers($bucket);
+ return (bool) $header->isOK();
+ }
+
+ /**
+ * Gets whether or not the specified Amazon S3 object exists in the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @return boolean A value of <code>true</code> if the object exists, or a value of <code>false</code> if it does not.
+ */
+ public function if_object_exists($bucket, $filename)
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ $header = $this->get_object_headers($bucket, $filename);
+
+ if ($header->isOK()) { return true; }
+ elseif ($header->status === 404) { return false; }
+
+ // @codeCoverageIgnoreStart
+ return null;
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * Gets whether or not the specified Amazon S3 bucket has a bucket policy associated with it.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @return boolean A value of <code>true</code> if a bucket policy exists, or a value of <code>false</code> if one does not.
+ */
+ public function if_bucket_policy_exists($bucket)
+ {
+ if ($this->use_batch_flow)
+ {
+ // @codeCoverageIgnoreStart
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ // @codeCoverageIgnoreEnd
+ }
+
+ $response = $this->get_bucket_policy($bucket);
+
+ if ($response->isOK()) { return true; }
+ elseif ($response->status === 404) { return false; }
+
+ // @codeCoverageIgnoreStart
+ return null;
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * Gets the number of Amazon S3 objects in the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @return integer The number of Amazon S3 objects in the bucket.
+ */
+ public function get_bucket_object_count($bucket)
+ {
+ if ($this->use_batch_flow)
+ {
+ // @codeCoverageIgnoreStart
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ // @codeCoverageIgnoreEnd
+ }
+
+ return count($this->get_object_list($bucket));
+ }
+
+ /**
+ * Gets the cumulative file size of the contents of the Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param boolean $friendly_format (Optional) A value of <code>true</code> will format the return value to 2 decimal points using the largest possible unit (i.e., 3.42 GB). A value of <code>false</code> will format the return value as the raw number of bytes.
+ * @return integer|string The number of bytes as an integer, or the friendly format as a string.
+ */
+ public function get_bucket_filesize($bucket, $friendly_format = false)
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ $filesize = 0;
+ $list = $this->list_objects($bucket);
+
+ foreach ($list->body->Contents as $filename)
+ {
+ $filesize += (integer) $filename->Size;
+ }
+
+ while ((string) $list->body->IsTruncated === 'true')
+ {
+ $body = (array) $list->body;
+ $list = $this->list_objects($bucket, array(
+ 'marker' => (string) end($body['Contents'])->Key
+ ));
+
+ foreach ($list->body->Contents as $object)
+ {
+ $filesize += (integer) $object->Size;
+ }
+ }
+
+ if ($friendly_format)
+ {
+ $filesize = $this->util->size_readable($filesize);
+ }
+
+ return $filesize;
+ }
+
+ /**
+ * Gets the file size of the specified Amazon S3 object.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param boolean $friendly_format (Optional) A value of <code>true</code> will format the return value to 2 decimal points using the largest possible unit (i.e., 3.42 GB). A value of <code>false</code> will format the return value as the raw number of bytes.
+ * @return integer|string The number of bytes as an integer, or the friendly format as a string.
+ */
+ public function get_object_filesize($bucket, $filename, $friendly_format = false)
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ $object = $this->get_object_headers($bucket, $filename);
+ $filesize = (integer) $object->header['content-length'];
+
+ if ($friendly_format)
+ {
+ $filesize = $this->util->size_readable($filesize);
+ }
+
+ return $filesize;
+ }
+
+ /**
+ * Changes the content type for an existing Amazon S3 object.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param string $contentType (Required) The content-type to apply to the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function change_content_type($bucket, $filename, $contentType, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Retrieve the original metadata
+ $metadata = $this->get_object_metadata($bucket, $filename);
+ if ($metadata && $metadata['ACL'])
+ {
+ $opt['acl'] = $metadata['ACL'];
+ }
+ if ($metadata && $metadata['StorageClass'])
+ {
+ $opt['headers']['x-amz-storage-class'] = $metadata['StorageClass'];
+ }
+
+ // Merge optional parameters
+ $opt = array_merge_recursive(array(
+ 'headers' => array(
+ 'Content-Type' => $contentType
+ ),
+ 'metadataDirective' => 'COPY'
+ ), $opt);
+
+ return $this->copy_object(
+ array('bucket' => $bucket, 'filename' => $filename),
+ array('bucket' => $bucket, 'filename' => $filename),
+ $opt
+ );
+ }
+
+ /**
+ * Changes the storage redundancy for an existing object.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param string $storage (Required) The storage setting to apply to the object. [Allowed values: <code>AmazonS3::STORAGE_STANDARD</code>, <code>AmazonS3::STORAGE_REDUCED</code>]
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function change_storage_redundancy($bucket, $filename, $storage, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Retrieve the original metadata
+ $metadata = $this->get_object_metadata($bucket, $filename);
+ if ($metadata && $metadata['ACL'])
+ {
+ $opt['acl'] = $metadata['ACL'];
+ }
+ if ($metadata && $metadata['ContentType'])
+ {
+ $opt['headers']['Content-Type'] = $metadata['ContentType'];
+ }
+
+ // Merge optional parameters
+ $opt = array_merge(array(
+ 'storage' => $storage,
+ 'metadataDirective' => 'COPY',
+ ), $opt);
+
+ return $this->copy_object(
+ array('bucket' => $bucket, 'filename' => $filename),
+ array('bucket' => $bucket, 'filename' => $filename),
+ $opt
+ );
+ }
+
+ /**
+ * Gets a simplified list of bucket names on an Amazon S3 account.
+ *
+ * @param string $pcre (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the bucket names against.
+ * @return array The list of matching bucket names. If there are no results, the method will return an empty array.
+ * @link http://php.net/pcre Regular Expressions (Perl-Compatible)
+ */
+ public function get_bucket_list($pcre = null)
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ // Get a list of buckets.
+ $list = $this->list_buckets();
+ if ($list = $list->body->query('descendant-or-self::Name'))
+ {
+ $list = $list->map_string($pcre);
+ return $list;
+ }
+
+ // @codeCoverageIgnoreStart
+ return array();
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * Gets a simplified list of Amazon S3 object file names contained in a bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>delimiter</code> - <code>string</code> - Optional - Keys that contain the same string between the prefix and the first occurrence of the delimiter will be rolled up into a single result element in the CommonPrefixes collection.</li>
+ * <li><code>marker</code> - <code>string</code> - Optional - Restricts the response to contain results that only occur alphabetically after the value of the marker.</li>
+ * <li><code>max-keys</code> - <code>integer</code> - Optional - The maximum number of results returned by the method call. The returned list will contain no more results than the specified value, but may return less. A value of zero is treated as if you did not specify max-keys.</li>
+ * <li><code>pcre</code> - <code>string</code> - Optional - A Perl-Compatible Regular Expression (PCRE) to filter the names against. This is applied only AFTER any native Amazon S3 filtering from specified <code>prefix</code>, <code>marker</code>, <code>max-keys</code>, or <code>delimiter</code> values are applied.</li>
+ * <li><code>prefix</code> - <code>string</code> - Optional - Restricts the response to contain results that begin only with the specified prefix.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * @return array The list of matching object names. If there are no results, the method will return an empty array.
+ * @link http://php.net/pcre Regular Expressions (Perl-Compatible)
+ */
+ public function get_object_list($bucket, $opt = null)
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ if (!$opt) $opt = array();
+ unset($opt['returnCurlHandle']); // This would cause problems
+
+ // Set some default values
+ $pcre = isset($opt['pcre']) ? $opt['pcre'] : null;
+ $max_keys = (isset($opt['max-keys']) && is_int($opt['max-keys'])) ? $opt['max-keys'] : null;
+ $objects = array();
+
+ if (!$max_keys)
+ {
+ // No max-keys specified. Get everything.
+ do
+ {
+ $list = $this->list_objects($bucket, $opt);
+ if ($keys = $list->body->query('descendant-or-self::Key')->map_string($pcre))
+ {
+ $objects = array_merge($objects, $keys);
+ }
+
+ $body = (array) $list->body;
+ $opt = array_merge($opt, array(
+ 'marker' => (isset($body['Contents']) && is_array($body['Contents'])) ?
+ ((string) end($body['Contents'])->Key) :
+ ((string) $list->body->Contents->Key)
+ ));
+ }
+ while ((string) $list->body->IsTruncated === 'true');
+ }
+ else
+ {
+ // Max-keys specified. Approximate number of loops and make the requests.
+
+ $max_keys = $opt['max-keys'];
+ $loops = ceil($max_keys / 1000);
+
+ do
+ {
+ $list = $this->list_objects($bucket, $opt);
+ $keys = $list->body->query('descendant-or-self::Key')->map_string($pcre);
+
+ if ($count = count($keys))
+ {
+ $objects = array_merge($objects, $keys);
+
+ if ($count < 1000)
+ {
+ break;
+ }
+ }
+
+ if ($max_keys > 1000)
+ {
+ $max_keys -= 1000;
+ }
+
+ $body = (array) $list->body;
+ $opt = array_merge($opt, array(
+ 'max-keys' => $max_keys,
+ 'marker' => (isset($body['Contents']) && is_array($body['Contents'])) ?
+ ((string) end($body['Contents'])->Key) :
+ ((string) $list->body->Contents->Key)
+ ));
+ }
+ while (--$loops);
+ }
+
+ return $objects;
+ }
+
+ /**
+ * Deletes all Amazon S3 objects inside the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $pcre (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the names against. The default value is <PCRE_ALL>.
+ * @return boolean A value of <code>true</code> means that all objects were successfully deleted. A value of <code>false</code> means that at least one object failed to delete.
+ * @link http://php.net/pcre Regular Expressions (Perl-Compatible)
+ */
+ public function delete_all_objects($bucket, $pcre = self::PCRE_ALL)
+ {
+ // Collect all matches
+ $list = $this->get_object_list($bucket, array('pcre' => $pcre));
+
+ // As long as we have at least one match...
+ if (count($list) > 0)
+ {
+ $objects = array();
+
+ foreach ($list as $object)
+ {
+ $objects[] = array('key' => $object);
+ }
+
+ $batch = new CFBatchRequest();
+ $batch->use_credentials($this->credentials);
+
+ foreach (array_chunk($objects, 1000) as $object_set)
+ {
+ $this->batch($batch)->delete_objects($bucket, array(
+ 'objects' => $object_set
+ ));
+ }
+
+ $responses = $this->batch($batch)->send();
+ $is_ok = true;
+
+ foreach ($responses as $response)
+ {
+ if (!$response->isOK() || isset($response->body->Error))
+ {
+ $is_ok = false;
+ }
+ }
+
+ return $is_ok;
+ }
+
+ // If there are no matches, return true
+ return true;
+ }
+
+ /**
+ * Deletes all of the versions of all Amazon S3 objects inside the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $pcre (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the names against. The default value is <PCRE_ALL>.
+ * @return boolean A value of <code>true</code> means that all object versions were successfully deleted. A value of <code>false</code> means that at least one object/version failed to delete.
+ * @link http://php.net/pcre Regular Expressions (Perl-Compatible)
+ */
+ public function delete_all_object_versions($bucket, $pcre = null)
+ {
+ // Instantiate
+ $versions = $this->list_bucket_object_versions($bucket);
+
+ // Gather all nodes together into a single array
+ if ($versions->body->DeleteMarker() && $versions->body->Version())
+ {
+ $markers = array_merge($versions->body->DeleteMarker()->getArrayCopy(), $versions->body->Version()->getArrayCopy());
+ }
+ elseif ($versions->body->DeleteMarker())
+ {
+ $markers = $versions->body->DeleteMarker()->getArrayCopy();
+ }
+ elseif ($versions->body->Version())
+ {
+ $markers = $versions->body->Version()->getArrayCopy();
+ }
+ else
+ {
+ $markers = array();
+ }
+
+ while ((string) $versions->body->IsTruncated === 'true')
+ {
+ $versions = $this->list_bucket_object_versions($bucket, array(
+ 'key-marker' => (string) $versions->body->NextKeyMarker
+ ));
+
+ // Gather all nodes together into a single array
+ if ($versions->body->DeleteMarker() && $versions->body->Version())
+ {
+ $markers = array_merge($markers, $versions->body->DeleteMarker()->getArrayCopy(), $versions->body->Version()->getArrayCopy());
+ }
+ elseif ($versions->body->DeleteMarker())
+ {
+ $markers = array_merge($markers, $versions->body->DeleteMarker()->getArrayCopy());
+ }
+ elseif ($versions->body->Version())
+ {
+ $markers = array_merge($markers, $versions->body->Version()->getArrayCopy());
+ }
+ }
+
+ $objects = array();
+
+ // Loop through markers
+ foreach ($markers as $marker)
+ {
+ if ($pcre)
+ {
+ if (preg_match($pcre, (string) $marker->Key))
+ {
+ $xx = array('key' => (string) $marker->Key);
+ if ((string) $marker->VersionId !== 'null')
+ {
+ $xx['version_id'] = (string) $marker->VersionId;
+ }
+ $objects[] = $xx;
+ unset($xx);
+ }
+ }
+ else
+ {
+ $xx = array('key' => (string) $marker->Key);
+ if ((string) $marker->VersionId !== 'null')
+ {
+ $xx['version_id'] = (string) $marker->VersionId;
+ }
+ $objects[] = $xx;
+ unset($xx);
+ }
+ }
+
+ $batch = new CFBatchRequest();
+ $batch->use_credentials($this->credentials);
+
+ foreach (array_chunk($objects, 1000) as $object_set)
+ {
+ $this->batch($batch)->delete_objects($bucket, array(
+ 'objects' => $object_set
+ ));
+ }
+
+ $responses = $this->batch($batch)->send();
+ $is_ok = true;
+
+ foreach ($responses as $response)
+ {
+ if (!$response->isOK() || isset($response->body->Error))
+ {
+ $is_ok = false;
+ }
+ }
+
+ return $is_ok;
+ }
+
+ /**
+ * Gets the collective metadata for the given Amazon S3 object.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the Amazon S3 object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object to retrieve. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return mixed If the object exists, the method returns the collective metadata for the Amazon S3 object. If the object does not exist, the method returns boolean <code>false</code>.
+ */
+ public function get_object_metadata($bucket, $filename, $opt = null)
+ {
+ $batch = new CFBatchRequest();
+ $this->batch($batch)->get_object_acl($bucket, $filename); // Get ACL info
+ $this->batch($batch)->get_object_headers($bucket, $filename); // Get content-type
+ $this->batch($batch)->list_objects($bucket, array( // Get other metadata
+ 'max-keys' => 1,
+ 'prefix' => $filename
+ ));
+ $response = $this->batch($batch)->send();
+
+ // Fail if any requests were unsuccessful
+ if (!$response->areOK())
+ {
+ return false;
+ }
+
+ $data = array(
+ 'ACL' => array(),
+ 'ContentType' => null,
+ 'ETag' => null,
+ 'Headers' => null,
+ 'Key' => null,
+ 'LastModified' => null,
+ 'Owner' => array(),
+ 'Size' => null,
+ 'StorageClass' => null,
+ );
+
+ // Add the content type
+ $data['ContentType'] = (string) $response[1]->header['content-type'];
+
+ // Add the other metadata (including storage type)
+ $contents = json_decode(json_encode($response[2]->body->query('descendant-or-self::Contents')->first()), true);
+ $data = array_merge($data, (is_array($contents) ? $contents : array()));
+
+ // Add ACL info
+ $grants = $response[0]->body->query('descendant-or-self::Grant');
+ $max = count($grants);
+
+ // Add raw header info
+ $data['Headers'] = $response[1]->header;
+ foreach (array('_info', 'x-amz-id-2', 'x-amz-request-id', 'cneonction', 'server', 'content-length', 'content-type', 'etag') as $header)
+ {
+ unset($data['Headers'][$header]);
+ }
+ ksort($data['Headers']);
+
+ if (count($grants) > 0)
+ {
+ foreach ($grants as $grant)
+ {
+ $dgrant = array(
+ 'id' => (string) $this->util->try_these(array('ID', 'URI'), $grant->Grantee),
+ 'permission' => (string) $grant->Permission
+ );
+
+ $data['ACL'][] = $dgrant;
+ }
+ }
+
+ return $data;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // URLS
+
+ /**
+ * Gets the web-accessible URL for the Amazon S3 object or generates a time-limited signed request for
+ * a private file.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the Amazon S3 object.
+ * @param integer|string $preauth (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>https</code> - <code>boolean</code> - Optional - Set to <code>true</code> if you would like the URL be in https mode. Otherwise, the default behavior is always to use http regardless of your SSL settings.
+ * <li><code>method</code> - <code>string</code> - Optional - The HTTP method to use for the request. Defaults to a value of <code>GET</code>.</li>
+ * <li><code>response</code> - <code>array</code> - Optional - Allows adjustments to specific response headers. Pass an associative array where each key is one of the following: <code>cache-control</code>, <code>content-disposition</code>, <code>content-encoding</code>, <code>content-language</code>, <code>content-type</code>, <code>expires</code>. The <code>expires</code> value should use <php:gmdate()> and be formatted with the <code>DATE_RFC2822</code> constant.</li>
+ * <li><code>torrent</code> - <code>boolean</code> - Optional - A value of <code>true</code> will return a URL to a torrent of the Amazon S3 object. A value of <code>false</code> will return a non-torrent URL. Defaults to <code>false</code>.</li>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return string The file URL, with authentication and/or torrent parameters if requested.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/S3_QSAuth.html Using Query String Authentication
+ */
+ public function get_object_url($bucket, $filename, $preauth = 0, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = isset($opt['method']) ? $opt['method'] : 'GET';
+ $opt['resource'] = $filename;
+ $opt['preauth'] = $preauth;
+
+ if (isset($opt['torrent']) && $opt['torrent'])
+ {
+ $opt['sub_resource'] = 'torrent';
+ unset($opt['torrent']);
+ }
+
+ // GET responses
+ if (isset($opt['response']))
+ {
+ foreach ($opt['response'] as $key => $value)
+ {
+ $opt['response-' . $key] = $value;
+ unset($opt['response'][$key]);
+ }
+ }
+
+ // Determine whether or not to use SSL
+ $use_ssl = isset($opt['https']) ? (bool) $opt['https'] : false;
+ unset($opt['https']);
+ $current_use_ssl_setting = $this->use_ssl;
+
+ // Authenticate to S3
+ $this->use_ssl = $use_ssl;
+ $response = $this->authenticate($bucket, $opt);
+ $this->use_ssl = $current_use_ssl_setting;
+
+ return $response;
+ }
+
+ /**
+ * Gets the web-accessible URL to a torrent of the Amazon S3 object. The Amazon S3 object's access
+ * control list settings (ACL) MUST be set to <ACL_PUBLIC> for a valid URL to be returned.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param integer|string $preauth (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.
+ * @return string The torrent URL, with authentication parameters if requested.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?S3TorrentRetrieve.html Using BitTorrent to Retrieve Objects Stored in Amazon S3
+ */
+ public function get_torrent_url($bucket, $filename, $preauth = 0)
+ {
+ return $this->get_object_url($bucket, $filename, $preauth, array(
+ 'torrent' => true
+ ));
+ }
+
+
+ /*%******************************************************************************************%*/
+ // VERSIONING
+
+ /**
+ * Enables versioning support for the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>MFASerial</code> - string (Optional) The serial number on the back of the Gemalto device. <code>MFASerial</code>, <code>MFAToken</code> and <code>MFAStatus</code> must all be set for MFA to work.</li>
+ * <li><code>MFAToken</code> - string (Optional) The current token displayed on the Gemalto device. <code>MFASerial</code>, <code>MFAToken</code> and <code>MFAStatus</code> must all be set for MFA to work.</li>
+ * <li><code>MFAStatus</code> - string (Optional) The MFA Delete status. Can be <code>Enabled</code> or <code>Disabled</code>. <code>MFASerial</code>, <code>MFAToken</code> and <code>MFAStatus</code> must all be set for MFA to work.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://aws.amazon.com/mfa/ Multi-Factor Authentication
+ */
+ public function enable_versioning($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'versioning';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ $xml = simplexml_load_string($this->base_versioning_xml);
+ $xml->addChild('Status', 'Enabled');
+
+ // Enable MFA delete?
+ // @codeCoverageIgnoreStart
+ if (isset($opt['MFASerial']) && isset($opt['MFAToken']) && isset($opt['MFAStatus']))
+ {
+ $xml->addChild('MfaDelete', $opt['MFAStatus']);
+ $opt['headers']['x-amz-mfa'] = ($opt['MFASerial'] . ' ' . $opt['MFAToken']);
+ }
+ // @codeCoverageIgnoreEnd
+
+ $opt['body'] = $xml->asXML();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Disables versioning support for the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>MFASerial</code> - <code>string</code> - Optional - The serial number on the back of the Gemalto device. <code>MFASerial</code>, <code>MFAToken</code> and <code>MFAStatus</code> must all be set for MFA to work.</li>
+ * <li><code>MFAToken</code> - <code>string</code> - Optional - The current token displayed on the Gemalto device. <code>MFASerial</code>, <code>MFAToken</code> and <code>MFAStatus</code> must all be set for MFA to work.</li>
+ * <li><code>MFAStatus</code> - <code>string</code> - Optional - The MFA Delete status. Can be <code>Enabled</code> or <code>Disabled</code>. <code>MFASerial</code>, <code>MFAToken</code> and <code>MFAStatus</code> must all be set for MFA to work.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://aws.amazon.com/mfa/ Multi-Factor Authentication
+ */
+ public function disable_versioning($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'versioning';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ $xml = simplexml_load_string($this->base_versioning_xml);
+ $xml->addChild('Status', 'Suspended');
+
+ // Enable MFA delete?
+ // @codeCoverageIgnoreStart
+ if (isset($opt['MFASerial']) && isset($opt['MFAToken']) && isset($opt['MFAStatus']))
+ {
+ $xml->addChild('MfaDelete', $opt['MFAStatus']);
+ $opt['headers']['x-amz-mfa'] = ($opt['MFASerial'] . ' ' . $opt['MFAToken']);
+ }
+ // @codeCoverageIgnoreEnd
+
+ $opt['body'] = $xml->asXML();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Gets an Amazon S3 bucket's versioning status.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function get_versioning_status($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'versioning';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Gets a list of all the versions of Amazon S3 objects in the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>delimiter</code> - <code>string</code> - Optional - Unicode string parameter. Keys that contain the same string between the prefix and the first occurrence of the delimiter will be rolled up into a single result element in the CommonPrefixes collection.</li>
+ * <li><code>key-marker</code> - <code>string</code> - Optional - Restricts the response to contain results that only occur alphabetically after the value of the <code>key-marker</code>.</li>
+ * <li><code>max-keys</code> - <code>string</code> - Optional - Limits the number of results returned in response to your query. Will return no more than this number of results, but possibly less.</li>
+ * <li><code>prefix</code> - <code>string</code> - Optional - Restricts the response to only contain results that begin with the specified prefix.</li>
+ * <li><code>version-id-marker</code> - <code>string</code> - Optional - Restricts the response to contain results that only occur alphabetically after the value of the <code>version-id-marker</code>.</li>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function list_bucket_object_versions($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'versions';
+
+ foreach (array('delimiter', 'key-marker', 'max-keys', 'prefix', 'version-id-marker') as $param)
+ {
+ if (isset($opt[$param]))
+ {
+ $opt['query_string'][$param] = $opt[$param];
+ unset($opt[$param]);
+ }
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // BUCKET POLICIES
+
+ /**
+ * Sets the policy sub-resource for the specified Amazon S3 bucket. The specified policy replaces any
+ * policy the bucket already has.
+ *
+ * To perform this operation, the caller must be authorized to set a policy for the bucket and have
+ * PutPolicy permissions. If the caller does not have PutPolicy permissions for the bucket, Amazon S3
+ * returns a `403 Access Denied` error. If the caller has the correct permissions but has not been
+ * authorized by the bucket owner, Amazon S3 returns a `405 Method Not Allowed` error.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param CFPolicy $policy (Required) The JSON policy to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/AccessPolicyLanguage.html Appendix: The Access Policy Language
+ */
+ public function set_bucket_policy($bucket, CFPolicy $policy, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'policy';
+ $opt['body'] = $policy->get_json();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Gets the policy of the specified Amazon S3 bucket.
+ *
+ * To use this operation, the caller must have GetPolicy permissions for the specified bucket and must be
+ * the bucket owner. If the caller does not have GetPolicy permissions, this method will generate a
+ * `403 Access Denied` error. If the caller has the correct permissions but is not the bucket owner, this
+ * method will generate a `405 Method Not Allowed` error. If the bucket does not have a policy defined for
+ * it, this method will generate a `404 Policy Not Found` error.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function get_bucket_policy($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'policy';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Deletes the bucket policy for the specified Amazon S3 bucket. To delete the policy, the caller must
+ * be the bucket owner and have `DeletePolicy` permissions for the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response. If you do not have `DeletePolicy` permissions, Amazon S3 returns a `403 Access Denied` error. If you have the correct permissions, but are not the bucket owner, Amazon S3 returns a `405 Method Not Allowed` error. If the bucket doesn't have a policy, Amazon S3 returns a `204 No Content` error.
+ */
+ public function delete_bucket_policy($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'DELETE';
+ $opt['sub_resource'] = 'policy';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // BUCKET NOTIFICATIONS
+
+ /**
+ * Enables notifications of specified events for an Amazon S3 bucket. Currently, the
+ * `s3:ReducedRedundancyLostObject` event is the only event supported for notifications. The
+ * `s3:ReducedRedundancyLostObject` event is triggered when Amazon S3 detects that it has lost all
+ * copies of an Amazon S3 object and can no longer service requests for that object.
+ *
+ * If the bucket owner and Amazon SNS topic owner are the same, the bucket owner has permission to
+ * publish notifications to the topic by default. Otherwise, the owner of the topic must create a
+ * policy to enable the bucket owner to publish to the topic.
+ *
+ * By default, only the bucket owner can configure notifications on a bucket. However, bucket owners
+ * can use bucket policies to grant permission to other users to set this configuration with the
+ * `s3:PutBucketNotification` permission.
+ *
+ * After a PUT operation is called to configure notifications on a bucket, Amazon S3 publishes a test
+ * notification to ensure that the topic exists and that the bucket owner has permission to publish
+ * to the specified topic. If the notification is successfully published to the SNS topic, the PUT
+ * operation updates the bucket configuration and returns the 200 OK responses with a
+ * `x-amz-sns-test-message-id` header containing the message ID of the test notification sent to topic.
+ *
+ * @param string $bucket (Required) The name of the bucket to create bucket notifications for.
+ * @param string $topic_arn (Required) The SNS topic ARN to send notifications to.
+ * @param string $event (Required) The event type to listen for.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/NotificationHowTo.html Setting Up Notification of Bucket Events
+ */
+ public function create_bucket_notification($bucket, $topic_arn, $event, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'notification';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ $xml = simplexml_load_string($this->base_notification_xml);
+ $topic_config = $xml->addChild('TopicConfiguration');
+ $topic_config->addChild('Topic', $topic_arn);
+ $topic_config->addChild('Event', $event);
+
+ $opt['body'] = $xml->asXML();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Gets the notification configuration of a bucket. Currently, the `s3:ReducedRedundancyLostObject` event
+ * is the only event supported for notifications. The `s3:ReducedRedundancyLostObject` event is triggered
+ * when Amazon S3 detects that it has lost all replicas of a Reduced Redundancy Storage object and can no
+ * longer service requests for that object.
+ *
+ * If notifications are not enabled on the bucket, the operation returns an empty
+ * `NotificatonConfiguration` element.
+ *
+ * By default, you must be the bucket owner to read the notification configuration of a bucket. However,
+ * the bucket owner can use a bucket policy to grant permission to other users to read this configuration
+ * with the `s3:GetBucketNotification` permission.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/NotificationHowTo.html Setting Up Notification of Bucket Events
+ */
+ public function get_bucket_notifications($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'notification';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Empties the list of SNS topics to send notifications to.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/NotificationHowTo.html Setting Up Notification of Bucket Events
+ */
+ public function delete_bucket_notification($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'notification';
+ $opt['body'] = $this->base_notification_xml;
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // MULTIPART UPLOAD
+
+ /**
+ * Calculates the correct values for sequentially reading a file for multipart upload. This method should
+ * be used in conjunction with <upload_part()>.
+ *
+ * @param integer $filesize (Required) The size in bytes of the entire file.
+ * @param integer $part_size (Required) The size in bytes of the part of the file to send.
+ * @return array An array containing key-value pairs. The keys are `seekTo` and `length`.
+ */
+ public function get_multipart_counts($filesize, $part_size)
+ {
+ $i = 0;
+ $sizecount = $filesize;
+ $values = array();
+
+ while ($sizecount > 0)
+ {
+ $sizecount -= $part_size;
+ $values[] = array(
+ 'seekTo' => ($part_size * $i),
+ 'length' => (($sizecount > 0) ? $part_size : ($sizecount + $part_size)),
+ );
+ $i++;
+ }
+
+ return $values;
+ }
+
+ /**
+ * Initiates a multipart upload and returns an `UploadId`.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>acl</code> - <code>string</code> - Optional - The ACL settings for the specified object. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. The default value is <code>ACL_PRIVATE</code>.</li>
+ * <li><code>contentType</code> - <code>string</code> - Optional - The type of content that is being sent. The default value is <code>application/octet-stream</code>.</li>
+ * <li><code>encryption</code> - <code>string</code> - Optional - The algorithm to use for encrypting the object. [Allowed values: <code>AES256</code>]</li>
+ * <li><code>headers</code> - <code>array</code> - Optional - Standard HTTP headers to send along in the request. Accepts an associative array of key-value pairs.</li>
+ * <li><code>meta</code> - <code>array</code> - Optional - An associative array of key-value pairs. Any header starting with <code>x-amz-meta-:</code> is considered user metadata. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.</li>
+ * <li><code>storage</code> - <code>string</code> - Optional - Whether to use Standard or Reduced Redundancy storage. [Allowed values: <code>AmazonS3::STORAGE_STANDARD</code>, <code>AmazonS3::STORAGE_REDUCED</code>]. The default value is <code>STORAGE_STANDARD</code>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
+ */
+ public function initiate_multipart_upload($bucket, $filename, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'POST';
+ $opt['resource'] = $filename;
+ $opt['sub_resource'] = 'uploads';
+ $opt['body'] = '';
+
+ // Handle content type. Can also be passed as an HTTP header.
+ if (isset($opt['contentType']))
+ {
+ $opt['headers']['Content-Type'] = $opt['contentType'];
+ unset($opt['contentType']);
+ }
+
+ // Set a default content type.
+ if (!isset($opt['headers']['Content-Type']))
+ {
+ $opt['headers']['Content-Type'] = 'application/octet-stream';
+ }
+
+ // Handle Access Control Lists. Can also be passed as an HTTP header.
+ if (isset($opt['acl']))
+ {
+ $opt['headers']['x-amz-acl'] = $opt['acl'];
+ unset($opt['acl']);
+ }
+
+ // Handle storage settings. Can also be passed as an HTTP header.
+ if (isset($opt['storage']))
+ {
+ $opt['headers']['x-amz-storage-class'] = $opt['storage'];
+ unset($opt['storage']);
+ }
+
+ // Handle encryption settings. Can also be passed as an HTTP header.
+ if (isset($opt['encryption']))
+ {
+ $opt['headers']['x-amz-server-side-encryption'] = $opt['encryption'];
+ unset($opt['encryption']);
+ }
+
+ // Handle meta tags. Can also be passed as an HTTP header.
+ if (isset($opt['meta']))
+ {
+ foreach ($opt['meta'] as $meta_key => $meta_value)
+ {
+ // e.g., `My Meta Header` is converted to `x-amz-meta-my-meta-header`.
+ $opt['headers']['x-amz-meta-' . strtolower(str_replace(' ', '-', $meta_key))] = $meta_value;
+ }
+ unset($opt['meta']);
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Uploads a single part of a multipart upload. The part size cannot be smaller than 5 MB
+ * or larger than 5 TB. A multipart upload can have no more than 10,000 parts.
+ *
+ * Amazon S3 charges for storage as well as requests to the service. Smaller part sizes (and more
+ * requests) allow for faster failures and better upload reliability. Larger part sizes (and fewer
+ * requests) costs slightly less but has lower upload reliability.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param string $upload_id (Required) The upload ID identifying the multipart upload whose parts are being listed. The upload ID is retrieved from a call to <initiate_multipart_upload()>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>fileUpload</code> - <code>string|resource</code> - Required - The URL/path for the file to upload or an open resource.</li>
+ * <li><code>partNumber</code> - <code>integer</code> - Required - The part number order of the multipart upload.</li>
+ * <li><code>expect</code> - <code>string</code> - Optional - Specifies that the SDK not send the request body until it receives an acknowledgement. If the message is rejected based on the headers, the body of the message is not sent. For more information, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.20">RFC 2616, section 14.20</a>. The value can also be passed to the <code>header</code> option as <code>Expect</code>. [Allowed values: <code>100-continue</code>]</li>
+ * <li><code>headers</code> - <code>array</code> - Optional - Standard HTTP headers to send along in the request. Accepts an associative array of key-value pairs.</li>
+ * <li><code>length</code> - <code>integer</code> - Optional - The size of the part in bytes. For more information, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13">RFC 2616, section 14.13</a>. The value can also be passed to the <code>header</code> option as <code>Content-Length</code>.</li>
+ * <li><code>md5</code> - <code>string</code> - Optional - The base64 encoded 128-bit MD5 digest of the part data. This header can be used as a message integrity check to verify that the part data is the same data that was originally sent. Although it is optional, we recommend using this mechanism as an end-to-end integrity check. For more information, see <a href="http://www.ietf.org/rfc/rfc1864.txt">RFC 1864</a>. The value can also be passed to the <code>header</code> option as <code>Content-MD5</code>.</li>
+ * <li><code>seekTo</code> - <code>integer</code> - Optional - The starting position in bytes for the piece of the file/stream to upload.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function upload_part($bucket, $filename, $upload_id, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'PUT';
+ $opt['resource'] = $filename;
+ $opt['uploadId'] = $upload_id;
+
+ if (!isset($opt['fileUpload']) || !isset($opt['partNumber']))
+ {
+ throw new S3_Exception('The `fileUpload` and `partNumber` options are both required in ' . __FUNCTION__ . '().');
+ }
+
+ // Handle expectation. Can also be passed as an HTTP header.
+ if (isset($opt['expect']))
+ {
+ $opt['headers']['Expect'] = $opt['expect'];
+ unset($opt['expect']);
+ }
+
+ // Handle content length. Can also be passed as an HTTP header.
+ if (isset($opt['length']))
+ {
+ $opt['headers']['Content-Length'] = $opt['length'];
+ unset($opt['length']);
+ }
+
+ // Handle content md5. Can also be passed as an HTTP header.
+ if (isset($opt['md5']))
+ {
+ $opt['headers']['Content-MD5'] = $opt['md5'];
+ unset($opt['md5']);
+ }
+
+ $opt['headers']['Expect'] = '100-continue';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Lists the completed parts of an in-progress multipart upload.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param string $upload_id (Required) The upload ID identifying the multipart upload whose parts are being listed. The upload ID is retrieved from a call to <initiate_multipart_upload()>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>max-parts</code> - <code>integer</code> - Optional - The maximum number of parts to return in the response body.</li>
+ * <li><code>part-number-marker</code> - <code>string</code> - Optional - Restricts the response to contain results that only occur numerically after the value of the <code>part-number-marker</code>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function list_parts($bucket, $filename, $upload_id, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'GET';
+ $opt['resource'] = $filename;
+ $opt['uploadId'] = $upload_id;
+ $opt['query_string'] = array();
+
+ foreach (array('max-parts', 'part-number-marker') as $param)
+ {
+ if (isset($opt[$param]))
+ {
+ $opt['query_string'][$param] = $opt[$param];
+ unset($opt[$param]);
+ }
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Aborts an in-progress multipart upload. This operation cannot be reversed.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param string $upload_id (Required) The upload ID identifying the multipart upload whose parts are being listed. The upload ID is retrieved from a call to <initiate_multipart_upload()>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function abort_multipart_upload($bucket, $filename, $upload_id, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'DELETE';
+ $opt['resource'] = $filename;
+ $opt['uploadId'] = $upload_id;
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Completes an in-progress multipart upload. A multipart upload is completed by describing the part
+ * numbers and corresponding ETag values in order, and submitting that data to Amazon S3 as an XML document.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param string $upload_id (Required) The upload ID identifying the multipart upload whose parts are being listed. The upload ID is retrieved from a call to <initiate_multipart_upload()>.
+ * @param string|array|SimpleXMLElement|CFResponse $parts (Required) The completion XML document. This document can be provided in multiple ways; as a string of XML, as a <php:SimpleXMLElement> object representing the XML document, as an indexed array of associative arrays where the keys are <code>PartNumber</code> and <code>ETag</code>, or as a <CFResponse> object returned by <list_parts()>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function complete_multipart_upload($bucket, $filename, $upload_id, $parts, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'POST';
+ $opt['resource'] = $filename;
+ $opt['uploadId'] = $upload_id;
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ // Disable Content-MD5 calculation for this operation
+ $opt['NoContentMD5'] = true;
+
+ if (is_string($parts))
+ {
+ // Assume it's the intended XML.
+ $opt['body'] = $parts;
+ }
+ elseif ($parts instanceof SimpleXMLElement)
+ {
+ // Assume it's a SimpleXMLElement object representing the XML.
+ $opt['body'] = $parts->asXML();
+ }
+ elseif (is_array($parts) || $parts instanceof CFResponse)
+ {
+ $xml = simplexml_load_string($this->complete_mpu_xml);
+
+ if (is_array($parts))
+ {
+ // Generate the appropriate XML.
+ foreach ($parts as $node)
+ {
+ $part = $xml->addChild('Part');
+ $part->addChild('PartNumber', $node['PartNumber']);
+ $part->addChild('ETag', $node['ETag']);
+ }
+
+ }
+ elseif ($parts instanceof CFResponse)
+ {
+ // Assume it's a response from list_parts().
+ foreach ($parts->body->Part as $node)
+ {
+ $part = $xml->addChild('Part');
+ $part->addChild('PartNumber', (string) $node->PartNumber);
+ $part->addChild('ETag', (string) $node->ETag);
+ }
+ }
+
+ $opt['body'] = $xml->asXML();
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Lists the in-progress multipart uploads.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>delimiter</code> - <code>string</code> - Optional - Keys that contain the same string between the prefix and the first occurrence of the delimiter will be rolled up into a single result element in the CommonPrefixes collection.</li>
+ * <li><code>key-marker</code> - <code>string</code> - Optional - Restricts the response to contain results that only occur alphabetically after the value of the <code>key-marker</code>. If used in conjunction with <code>upload-id-marker</code>, the results will be filtered to include keys whose upload ID is alphabetically after the value of <code>upload-id-marker</code>.</li>
+ * <li><code>upload-id-marker</code> - <code>string</code> - Optional - Restricts the response to contain results that only occur alphabetically after the value of the <code>upload-id-marker</code>. Must be used in conjunction with <code>key-marker</code>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function list_multipart_uploads($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'uploads';
+
+ foreach (array('key-marker', 'max-uploads', 'upload-id-marker') as $param)
+ {
+ if (isset($opt[$param]))
+ {
+ $opt['query_string'][$param] = $opt[$param];
+ unset($opt[$param]);
+ }
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Since Amazon S3's standard <copy_object()> operation only supports copying objects that are smaller than
+ * 5 GB, the ability to copy large objects (greater than 5 GB) requires the use of "Multipart Copy".
+ *
+ * Copying large objects requires the developer to initiate a new multipart "upload", copy pieces of the
+ * large object (specifying a range of bytes up to 5 GB from the large source file), then complete the
+ * multipart "upload".
+ *
+ * NOTE: <strong>This is a synchronous operation</strong>, not an <em>asynchronous</em> operation, which means
+ * that Amazon S3 will not return a response for this operation until the copy has completed across the Amazon
+ * S3 server fleet. Copying objects within a single region will complete more quickly than copying objects
+ * <em>across</em> regions. The synchronous nature of this operation is different from other services where
+ * responses are typically returned immediately, even if the operation itself has not yet been completed on
+ * the server-side.
+ *
+ * @param array $source (Required) The bucket and file name to copy from. The following keys must be set: <ul>
+ * <li><code>bucket</code> - <code>string</code> - Required - Specifies the name of the bucket containing the source object.</li>
+ * <li><code>filename</code> - <code>string</code> - Required - Specifies the file name of the source object to copy.</li></ul>
+ * @param array $dest (Required) The bucket and file name to copy to. The following keys must be set: <ul>
+ * <li><code>bucket</code> - <code>string</code> - Required - Specifies the name of the bucket to copy the object to.</li>
+ * <li><code>filename</code> - <code>string</code> - Required - Specifies the file name to copy the object to.</li></ul>
+ * @param string $upload_id (Required) The upload ID identifying the multipart upload whose parts are being listed. The upload ID is retrieved from a call to <initiate_multipart_upload()>.
+ * @param integer $part_number (Required) A part number uniquely identifies a part and defines its position within the destination object. When you complete a multipart upload, a complete object is created by concatenating parts in ascending order based on part number. If you copy a new part using the same part number as a previously copied/uploaded part, the previously written part is overwritten.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>ifMatch</code> - <code>string</code> - Optional - The ETag header from a previous request. Copies the object if its entity tag (ETag) matches the specified tag; otherwise, the request returns a <code>412</code> HTTP status code error (precondition failed). Used in conjunction with <code>ifUnmodifiedSince</code>.</li>
+ * <li><code>ifUnmodifiedSince</code> - <code>string</code> - Optional - The LastModified header from a previous request. Copies the object if it hasn't been modified since the specified time; otherwise, the request returns a <code>412</code> HTTP status code error (precondition failed). Used in conjunction with <code>ifMatch</code>.</li>
+ * <li><code>ifNoneMatch</code> - <code>string</code> - Optional - The ETag header from a previous request. Copies the object if its entity tag (ETag) is different than the specified ETag; otherwise, the request returns a <code>412</code> HTTP status code error (failed condition). Used in conjunction with <code>ifModifiedSince</code>.</li>
+ * <li><code>ifModifiedSince</code> - <code>string</code> - Optional - The LastModified header from a previous request. Copies the object if it has been modified since the specified time; otherwise, the request returns a <code>412</code> HTTP status code error (failed condition). Used in conjunction with <code>ifNoneMatch</code>.</li>
+ * <li><code>range</code> - <code>string</code> - Optional - The range of bytes to copy from the object. Specify this parameter when copying partial bits. The specified range must be notated with a hyphen (e.g., 0-10485759). Defaults to the byte range of the complete Amazon S3 object.</li>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object to copy. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function copy_part($source, $dest, $upload_id, $part_number, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'PUT';
+ $opt['resource'] = $dest['filename'];
+ $opt['uploadId'] = $upload_id;
+ $opt['partNumber'] = $part_number;
+
+ // Handle copy source
+ if (isset($source['bucket']) && isset($source['filename']))
+ {
+ $opt['headers']['x-amz-copy-source'] = '/' . $source['bucket'] . '/' . rawurlencode($source['filename'])
+ . (isset($opt['versionId']) ? ('?' . 'versionId=' . rawurlencode($opt['versionId'])) : ''); // Append the versionId to copy, if available
+ unset($opt['versionId']);
+ }
+
+ // Handle conditional-copy parameters
+ if (isset($opt['ifMatch']))
+ {
+ $opt['headers']['x-amz-copy-source-if-match'] = $opt['ifMatch'];
+ unset($opt['ifMatch']);
+ }
+ if (isset($opt['ifNoneMatch']))
+ {
+ $opt['headers']['x-amz-copy-source-if-none-match'] = $opt['ifNoneMatch'];
+ unset($opt['ifNoneMatch']);
+ }
+ if (isset($opt['ifUnmodifiedSince']))
+ {
+ $opt['headers']['x-amz-copy-source-if-unmodified-since'] = $opt['ifUnmodifiedSince'];
+ unset($opt['ifUnmodifiedSince']);
+ }
+ if (isset($opt['ifModifiedSince']))
+ {
+ $opt['headers']['x-amz-copy-source-if-modified-since'] = $opt['ifModifiedSince'];
+ unset($opt['ifModifiedSince']);
+ }
+
+ // Partial content range
+ if (isset($opt['range']))
+ {
+ $opt['headers']['x-amz-copy-source-range'] = 'bytes=' . $opt['range'];
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($dest['bucket'], $opt);
+ }
+
+ /**
+ * Creates an Amazon S3 object using the multipart upload APIs. It is analogous to <create_object()>.
+ *
+ * While each individual part of a multipart upload can hold up to 5 GB of data, this method limits the
+ * part size to a maximum of 500 MB. The combined size of all parts can not exceed 5 TB of data. When an
+ * object is stored in Amazon S3, the data is streamed to multiple storage servers in multiple data
+ * centers. This ensures the data remains available in the event of internal network or hardware failure.
+ *
+ * Amazon S3 charges for storage as well as requests to the service. Smaller part sizes (and more
+ * requests) allow for faster failures and better upload reliability. Larger part sizes (and fewer
+ * requests) costs slightly less but has lower upload reliability.
+ *
+ * In certain cases with large objects, it's possible for this method to attempt to open more file system
+ * connections than allowed by the OS. In this case, either
+ * <a href="https://forums.aws.amazon.com/thread.jspa?threadID=70216">increase the number of connections
+ * allowed</a> or increase the value of the <code>partSize</code> parameter to use a larger part size.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>fileUpload</code> - <code>string|resource</code> - Required - The URL/path for the file to upload, or an open resource.</li>
+ * <li><code>acl</code> - <code>string</code> - Optional - The ACL settings for the specified object. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. The default value is <code>ACL_PRIVATE</code>.</li>
+ * <li><code>contentType</code> - <code>string</code> - Optional - The type of content that is being sent in the body. The default value is <code>application/octet-stream</code>.</li>
+ * <li><code>headers</code> - <code>array</code> - Optional - Standard HTTP headers to send along in the request. Accepts an associative array of key-value pairs.</li>
+ * <li><code>length</code> - <code>integer</code> - Optional - The size of the object in bytes. For more information, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13">RFC 2616, section 14.13</a>. The value can also be passed to the <code>header</code> option as <code>Content-Length</code>.</li>
+ * <li><code>limit</code> - <code>integer</code> - Optional - The maximum number of concurrent uploads done by cURL. Gets passed to <code>CFBatchRequest</code>.</li>
+ * <li><code>meta</code> - <code>array</code> - Optional - An associative array of key-value pairs. Any header starting with <code>x-amz-meta-:</code> is considered user metadata. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.</li>
+ * <li><code>partSize</code> - <code>integer</code> - Optional - The size of an individual part. The size may not be smaller than 5 MB or larger than 500 MB. The default value is 50 MB.</li>
+ * <li><code>seekTo</code> - <code>integer</code> - Optional - The starting position in bytes for the first piece of the file/stream to upload.</li>
+ * <li><code>storage</code> - <code>string</code> - Optional - Whether to use Standard or Reduced Redundancy storage. [Allowed values: <code>AmazonS3::STORAGE_STANDARD</code>, <code>AmazonS3::STORAGE_REDUCED</code>]. The default value is <code>STORAGE_STANDARD</code>.</li>
+ * <li><code>uploadId</code> - <code>string</code> - Optional - An upload ID identifying an existing multipart upload to use. If this option is not set, one will be created automatically.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
+ */
+ public function create_mpu_object($bucket, $filename, $opt = null)
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ if (!$opt) $opt = array();
+
+ // Handle content length. Can also be passed as an HTTP header.
+ if (isset($opt['length']))
+ {
+ $opt['headers']['Content-Length'] = $opt['length'];
+ unset($opt['length']);
+ }
+
+ if (!isset($opt['fileUpload']))
+ {
+ throw new S3_Exception('The `fileUpload` option is required in ' . __FUNCTION__ . '().');
+ }
+ elseif (is_resource($opt['fileUpload']))
+ {
+ $opt['limit'] = 1; // We can only read from this one resource.
+ $upload_position = isset($opt['seekTo']) ? (integer) $opt['seekTo'] : ftell($opt['fileUpload']);
+ $upload_filesize = isset($opt['headers']['Content-Length']) ? (integer) $opt['headers']['Content-Length'] : null;
+
+ if (!isset($upload_filesize) && $upload_position !== false)
+ {
+ $stats = fstat($opt['fileUpload']);
+
+ if ($stats && $stats['size'] >= 0)
+ {
+ $upload_filesize = $stats['size'] - $upload_position;
+ }
+ }
+ }
+ else
+ {
+ $upload_position = isset($opt['seekTo']) ? (integer) $opt['seekTo'] : 0;
+
+ if (isset($opt['headers']['Content-Length']))
+ {
+ $upload_filesize = (integer) $opt['headers']['Content-Length'];
+ }
+ else
+ {
+ $upload_filesize = filesize($opt['fileUpload']);
+
+ if ($upload_filesize !== false)
+ {
+ $upload_filesize -= $upload_position;
+ }
+ }
+ }
+
+ if ($upload_position === false || !isset($upload_filesize) || $upload_filesize === false || $upload_filesize < 0)
+ {
+ throw new S3_Exception('The size of `fileUpload` cannot be determined in ' . __FUNCTION__ . '().');
+ }
+
+ // Handle part size
+ if (isset($opt['partSize']))
+ {
+ // If less that 5 MB...
+ if ((integer) $opt['partSize'] < 5242880)
+ {
+ $opt['partSize'] = 5242880; // 5 MB
+ }
+ // If more than 500 MB...
+ elseif ((integer) $opt['partSize'] > 524288000)
+ {
+ $opt['partSize'] = 524288000; // 500 MB
+ }
+ }
+ else
+ {
+ $opt['partSize'] = 52428800; // 50 MB
+ }
+
+ // If the upload size is smaller than the piece size, failover to create_object().
+ if ($upload_filesize < $opt['partSize'] && !isset($opt['uploadId']))
+ {
+ return $this->create_object($bucket, $filename, $opt);
+ }
+
+ // Initiate multipart upload
+ if (isset($opt['uploadId']))
+ {
+ $upload_id = $opt['uploadId'];
+ }
+ else
+ {
+ // Compose options for initiate_multipart_upload().
+ $_opt = array();
+ foreach (array('contentType', 'acl', 'storage', 'headers', 'meta') as $param)
+ {
+ if (isset($opt[$param]))
+ {
+ $_opt[$param] = $opt[$param];
+ }
+ }
+
+ $upload = $this->initiate_multipart_upload($bucket, $filename, $_opt);
+ if (!$upload->isOK())
+ {
+ return $upload;
+ }
+
+ // Fetch the UploadId
+ $upload_id = (string) $upload->body->UploadId;
+ }
+
+ // Get the list of pieces
+ $pieces = $this->get_multipart_counts($upload_filesize, (integer) $opt['partSize']);
+
+ // Queue batch requests
+ $batch = new CFBatchRequest(isset($opt['limit']) ? (integer) $opt['limit'] : null);
+ foreach ($pieces as $i => $piece)
+ {
+ $this->batch($batch)->upload_part($bucket, $filename, $upload_id, array(
+ 'expect' => '100-continue',
+ 'fileUpload' => $opt['fileUpload'],
+ 'partNumber' => ($i + 1),
+ 'seekTo' => $upload_position + (integer) $piece['seekTo'],
+ 'length' => (integer) $piece['length'],
+ ));
+ }
+
+ // Send batch requests
+ $batch_responses = $this->batch($batch)->send();
+ if (!$batch_responses->areOK())
+ {
+ return $batch_responses;
+ }
+
+ // Compose completion XML
+ $parts = array();
+ foreach ($batch_responses as $i => $response)
+ {
+ $parts[] = array('PartNumber' => ($i + 1), 'ETag' => $response->header['etag']);
+ }
+
+ return $this->complete_multipart_upload($bucket, $filename, $upload_id, $parts);
+ }
+
+ /**
+ * Aborts all multipart uploads initiated before the specified date. This operation cannot be reversed.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string|integer $when (Optional) The time and date to use for comparison. Accepts any value that <php:strtotime()> understands.
+ * @return CFArray A <CFArray> containing a series of 0 or more <CFResponse> objects, containing a parsed HTTP response.
+ */
+ public function abort_multipart_uploads_by_date($bucket, $when = null)
+ {
+ if ($this->use_batch_flow)
+ {
+ // @codeCoverageIgnoreStart
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ // @codeCoverageIgnoreEnd
+ }
+
+ $when = $when ? $when : time();
+ $handles = array();
+ $data = $this->list_multipart_uploads($bucket)->body;
+ $when = is_int($when) ? $when : strtotime($when);
+
+ if (!($data instanceof CFSimpleXML))
+ {
+ return false;
+ }
+
+ $list = $data->query('descendant-or-self::Upload/Initiated');
+
+ if (count($list) > 0)
+ {
+ foreach ($list as $node)
+ {
+ if (strtotime((string) $node) < $when)
+ {
+ $q = new CFBatchRequest();
+ $parent = $node->parent();
+
+ $upload_id = $parent
+ ->query('descendant-or-self::UploadId')
+ ->first()
+ ->to_string();
+
+ $filename = $parent
+ ->query('descendant-or-self::Key')
+ ->first()
+ ->to_string();
+
+ $handles[] = $this->abort_multipart_upload($bucket, $filename, $upload_id, array(
+ 'returnCurlHandle' => true
+ ));
+ }
+ }
+
+ $http = new CFRequest();
+ $responses = $http->send_multi_request($handles);
+
+ if (is_array($responses) && count($responses) > 0)
+ {
+ return new CFArray($responses);
+ }
+ }
+
+ return new CFArray();
+ }
+
+
+ /*%******************************************************************************************%*/
+ // WEBSITE CONFIGURATION
+
+ /**
+ * Enables and configures an Amazon S3 website using the corresponding bucket as the content source.
+ * The website will have one default domain name associated with it, which is the bucket name. If you
+ * attempt to configure an Amazon S3 website for a bucket whose name is not compatible with DNS,
+ * Amazon S3 returns an <code>InvalidBucketName</code> error. For more information on bucket names and DNS,
+ * refer to <a href="http://docs.amazonwebservices.com/AmazonS3/latest/dev/BucketRestrictions.html">Bucket Restrictions and Limitations.</a>
+ *
+ * To visit the bucket as a website a new endpoint is created in the following pattern:
+ * <code>http://&lt;bucketName&gt;.s3-website-&lt;region&gt;.amazonaws.com</code>. This is a sample URL
+ * for a bucket called <code>example-bucket</code> in the <code>us-east-1</code> region.
+ * (e.g., <code>http://example-bucket.s3-website-us-east-1.amazonaws.com</code>)
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>indexDocument</code> - <code>string</code> - Optional - The file path to use as the root document. The default value is <code>index.html</code>.</li>
+ * <li><code>errorDocument</code> - <code>string</code> - Optional - The file path to use as the error document. The default value is <code>error.html</code>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function create_website_config($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'website';
+
+ $xml = simplexml_load_string($this->website_config_xml);
+ if (isset($opt['indexDocument']))
+ {
+ $xml->IndexDocument->Suffix = $opt['indexDocument'];
+ }
+ if (isset($opt['errorDocument']))
+ {
+ $xml->ErrorDocument->Key = $opt['errorDocument'];
+ }
+
+ $opt['body'] = $xml->asXML();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Retrieves the website configuration for a bucket. The contents of this response are identical to the
+ * content submitted by the user during the website creation operation. If a website configuration has
+ * never been set, Amazon S3 will return a 404 error.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function get_website_config($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'website';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Removes the website configuration for a bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function delete_website_config($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'DELETE';
+ $opt['sub_resource'] = 'website';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // OBJECT EXPIRATION
+
+ /**
+ * Enables the ability to specify an expiry period for objects when an object should be deleted,
+ * measured as number of days from creation time. Amazon S3 guarantees that the object will be
+ * deleted when the expiration time is passed.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>rules</code> - <code>string</code> - Required - The object expiration rule-sets to apply to the bucket. <ul>
+ * <li><code>x</code> - <code>array</code> - Required - This represents a simple array index. <ul>
+ * <li><code>id</code> - <code>string</code> - Optional - Unique identifier for the rule. The value cannot be longer than 255 characters.
+ * <li><code>prefix</code> - <code>string</code> - Required - The Amazon S3 object prefix which targets the file(s) for expiration.</li>
+ * <li><code>expiration</code> - <code>array</code> - Required - The container for the unit of measurement by which the expiration time is calculated. <ul>
+ * <li><code>days</code> - <code>integer</code> - Required - The number of days until the targetted objects expire from the bucket.</li>
+ * </ul></li>
+ * <li><code>enabled</code> - <code>boolean</code> - Optional - Whether or not to enable this rule-set. A value of <code>true</code> enables the rule-set. A value of <code>false</code> disables the rule-set. The default value is <code>true</code>.</li>
+ * </ul></li>
+ * </ul></li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function create_object_expiration_config($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'lifecycle';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ $xml = simplexml_load_string($this->object_expiration_xml, $this->parser_class);
+
+ if (isset($opt['rules']) && is_array($opt['rules']) && count($opt['rules']))
+ {
+ foreach ($opt['rules'] as $rule)
+ {
+ $xrule = $xml->addChild('Rule');
+
+ // ID
+ if (isset($rule['id']))
+ {
+ if (strlen($rule['id']) > 255)
+ {
+ throw new S3_Exception('The "id" for a rule must not be more than 255 characters in the ' . __FUNCTION__ . ' method.');
+ }
+
+ $xrule->addChild('ID', $rule['id']);
+ }
+
+ // Prefix
+ if (isset($rule['prefix']))
+ {
+ $xrule->addChild('Prefix', $rule['prefix']);
+ }
+ else
+ {
+ throw new S3_Exception('Each rule requires a "prefix" in the ' . __FUNCTION__ . ' method.');
+ }
+
+ // Status
+ $enabled = 'Enabled';
+ if (isset($rule['enabled']))
+ {
+ if (is_bool($rule['enabled'])) // Boolean
+ {
+ $enabled = $rule['enabled'] ? 'Enabled' : 'Disabled';
+ }
+ elseif (is_string($rule['enabled'])) // String
+ {
+ $enabled = (strtolower($rule['enabled']) === 'true') ? 'Enabled' : 'Disabled';
+ }
+
+ $xrule->addChild('Status', $enabled);
+ }
+ else
+ {
+ $xrule->addChild('Status', 'Enabled');
+ }
+
+ // Expiration
+ if (isset($rule['expiration']))
+ {
+ $xexpiration = $xrule->addChild('Expiration');
+
+ if (isset($rule['expiration']['days']))
+ {
+ $xexpiration->addChild('Days', $rule['expiration']['days']);
+ }
+ }
+ else
+ {
+ throw new S3_Exception('Each rule requires a "expiration" in the ' . __FUNCTION__ . ' method.');
+ }
+ }
+ }
+
+ $opt['body'] = $xml->asXML();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ public function get_object_expiration_config($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'lifecycle';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ public function delete_object_expiration_config($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'DELETE';
+ $opt['sub_resource'] = 'lifecycle';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // MISCELLANEOUS
+
+ /**
+ * Gets the canonical user ID and display name from the Amazon S3 server.
+ *
+ * @return array An associative array containing the `id` and `display_name` values.
+ */
+ public function get_canonical_user_id()
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ $id = $this->list_buckets();
+
+ return array(
+ 'id' => (string) $id->body->Owner->ID,
+ 'display_name' => (string) $id->body->Owner->DisplayName
+ );
+ }
+
+ /**
+ * Loads and registers the S3StreamWrapper class as a stream wrapper.
+ *
+ * @param string $protocol (Optional) The name of the protocol to register.
+ * @return boolean Whether or not the registration succeeded.
+ */
+ public function register_stream_wrapper($protocol = 's3')
+ {
+ require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'extensions'
+ . DIRECTORY_SEPARATOR . 's3streamwrapper.class.php';
+
+ return S3StreamWrapper::register($this, $protocol);
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/array.class.php b/3rdparty/aws-sdk/utilities/array.class.php
new file mode 100644
index 00000000000..dea673546f8
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/array.class.php
@@ -0,0 +1,312 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * The <CFArray> object extends PHP's built-in <php:ArrayObject> object by providing convenience methods for
+ * rapidly manipulating array data. Specifically, the `CFArray` object is intended for working with
+ * <CFResponse> and <CFSimpleXML> objects that are returned by AWS services.
+ *
+ * @version 2012.01.17
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ * @link http://php.net/ArrayObject ArrayObject
+ */
+class CFArray extends ArrayObject
+{
+ /**
+ * Constructs a new instance of <CFArray>.
+ *
+ * @param mixed $input (Optional) The input parameter accepts an array or an Object. The default value is an empty array.
+ * @param integer $flags (Optional) Flags to control the behavior of the ArrayObject object. Defaults to <STD_PROP_LIST>.
+ * @param string $iterator_class (Optional) Specify the class that will be used for iteration of the <php:ArrayObject> object. <php:ArrayIterator> is the default class used.
+ * @return mixed Either an array of matches, or a single <CFSimpleXML> element.
+ */
+ public function __construct($input = array(), $flags = self::STD_PROP_LIST, $iterator_class = 'ArrayIterator')
+ {
+ // Provide a default value
+ $input = $input ? $input : array();
+
+ try {
+ return parent::__construct($input, $flags, $iterator_class);
+ }
+ catch (InvalidArgumentException $e)
+ {
+ throw new CFArray_Exception($e->getMessage());
+ }
+ }
+
+ /**
+ * Alternate approach to constructing a new instance. Supports chaining.
+ *
+ * @param mixed $input (Optional) The input parameter accepts an array or an Object. The default value is an empty array.
+ * @param integer $flags (Optional) Flags to control the behavior of the ArrayObject object. Defaults to <STD_PROP_LIST>.
+ * @param string $iterator_class (Optional) Specify the class that will be used for iteration of the <php:ArrayObject> object. <php:ArrayIterator> is the default class used.
+ * @return mixed Either an array of matches, or a single <CFSimpleXML> element.
+ */
+ public static function init($input = array(), $flags = self::STD_PROP_LIST, $iterator_class = 'ArrayIterator')
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '<'))
+ {
+ throw new Exception('PHP 5.3 or newer is required to instantiate a new class with CLASS::init().');
+ }
+
+ $self = get_called_class();
+ return new $self($input, $flags, $iterator_class);
+ }
+
+ /**
+ * Handles how the object is rendered when cast as a string.
+ *
+ * @return string The word "Array".
+ */
+ public function __toString()
+ {
+ return 'Array';
+ }
+
+
+ /*%******************************************************************************************%*/
+ // REFORMATTING
+
+ /**
+ * Maps each element in the <CFArray> object as an integer.
+ *
+ * @return array The contents of the <CFArray> object mapped as integers.
+ */
+ public function map_integer()
+ {
+ return array_map('intval', $this->getArrayCopy());
+ }
+
+ /**
+ * Maps each element in the CFArray object as a string.
+ *
+ * @param string $pcre (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the names against.
+ * @return array The contents of the <CFArray> object mapped as strings. If there are no results, the method will return an empty array.
+ */
+ public function map_string($pcre = null)
+ {
+ $list = array_map('strval', $this->getArrayCopy());
+ $dlist = array();
+
+ if ($pcre)
+ {
+ foreach ($list as $item)
+ {
+ $dlist[] = preg_match($pcre, $item) ? $item : null;
+ }
+
+ $list = array_values(array_filter($dlist));
+ }
+
+ return $list;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // CONFIRMATION
+
+ /**
+ * Verifies that _all_ responses were successful. A single failed request will cause <areOK()> to return false. Equivalent to <CFResponse::isOK()>, except it applies to all responses.
+ *
+ * @return boolean Whether _all_ requests were successful or not.
+ */
+ public function areOK()
+ {
+ $dlist = array();
+ $list = $this->getArrayCopy();
+
+ foreach ($list as $response)
+ {
+ if ($response instanceof CFResponse)
+ {
+ $dlist[] = $response->isOK();
+ }
+ }
+
+ return (array_search(false, $dlist, true) !== false) ? false : true;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // ITERATING AND EXECUTING
+
+ /**
+ * Iterates over a <CFArray> object, and executes a function for each matched element.
+ *
+ * The callback function takes three parameters: <ul>
+ * <li><code>$item</code> - <code>mixed</code> - Optional - The individual node in the array.</li>
+ * <li><code>$key</code> - <code>mixed</code> - Optional - The key for the array node.</li>
+ * <li><code>$bind</code> - <code>mixed</code> - Optional - The variable that was passed into the $bind parameter.</li></ul>
+ *
+ * @param string|function $callback (Required) The callback function to execute. PHP 5.3 or newer can use an anonymous function.
+ * @param mixed $bind (Optional) A variable from the calling scope to pass-by-reference into the local scope of the callback function.
+ * @return CFArray The original <CFArray> object.
+ */
+ public function each($callback, &$bind = null)
+ {
+ $items = $this->getArrayCopy();
+
+ foreach ($items as $key => &$item)
+ {
+ $callback($item, $key, $bind);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Passes each element in the current <CFArray> object through a function, and produces a new <CFArray> object containing the return values.
+ *
+ * The callback function takes three parameters: <ul>
+ * <li><code>$item</code> - <code>mixed</code> - Optional - The individual node in the array.</li>
+ * <li><code>$key</code> - <code>mixed</code> - Optional - The key for the array node.</li>
+ * <li><code>$bind</code> - <code>mixed</code> - Optional - The variable that was passed into the $bind parameter.</li></ul>
+ *
+ * @param string|function $callback (Required) The callback function to execute. PHP 5.3 or newer can use an anonymous function.
+ * @param mixed $bind (Optional) A variable from the calling scope to pass-by-reference into the local scope of the callback function.
+ * @return CFArray A new <CFArray> object containing the return values.
+ */
+ public function map($callback, &$bind = null)
+ {
+ $items = $this->getArrayCopy();
+ $collect = array();
+
+ foreach ($items as $key => &$item)
+ {
+ $collect[] = $callback($item, $key, $bind);
+ }
+
+ return new CFArray($collect);
+ }
+
+ /**
+ * Filters the list of nodes by passing each value in the current <CFArray> object through a function. The node will be removed if the function returns `false`.
+ *
+ * The callback function takes three parameters: <ul>
+ * <li><code>$item</code> - <code>mixed</code> - Optional - The individual node in the array.</li>
+ * <li><code>$key</code> - <code>mixed</code> - Optional - The key for the array node.</li>
+ * <li><code>$bind</code> - <code>mixed</code> - Optional - The variable that was passed into the $bind parameter.</li></ul>
+ *
+ * @param string|function $callback (Required) The callback function to execute. PHP 5.3 or newer can use an anonymous function.
+ * @param mixed $bind (Optional) A variable from the calling scope to pass-by-reference into the local scope of the callback function.
+ * @return CFArray A new <CFArray> object containing the return values.
+ */
+ public function filter($callback, &$bind = null)
+ {
+ $items = $this->getArrayCopy();
+ $collect = array();
+
+ foreach ($items as $key => &$item)
+ {
+ if ($callback($item, $key, $bind) !== false)
+ {
+ $collect[] = $item;
+ }
+ }
+
+ return new CFArray($collect);
+ }
+
+ /**
+ * Alias for <filter()>. This functionality was incorrectly named _reduce_ in earlier versions of the SDK.
+ *
+ * @param string|function $callback (Required) The callback function to execute. PHP 5.3 or newer can use an anonymous function.
+ * @param mixed $bind (Optional) A variable from the calling scope to pass-by-reference into the local scope of the callback function.
+ * @return CFArray A new <CFArray> object containing the return values.
+ */
+ public function reduce($callback, &$bind = null)
+ {
+ return $this->filter($callback, $bind);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // TRAVERSAL
+
+ /**
+ * Gets the first result in the array.
+ *
+ * @return mixed The first result in the <CFArray> object. Returns `false` if there are no items in the array.
+ */
+ public function first()
+ {
+ $items = $this->getArrayCopy();
+ return count($items) ? $items[0] : false;
+ }
+
+ /**
+ * Gets the last result in the array.
+ *
+ * @return mixed The last result in the <CFArray> object. Returns `false` if there are no items in the array.
+ */
+ public function last()
+ {
+ $items = $this->getArrayCopy();
+ return count($items) ? end($items) : false;
+ }
+
+ /**
+ * Removes all `null` values from an array.
+ *
+ * @return CFArray A new <CFArray> object containing the non-null values.
+ */
+ public function compress()
+ {
+ return new CFArray(array_filter($this->getArrayCopy()));
+ }
+
+ /**
+ * Reindexes the array, starting from zero.
+ *
+ * @return CFArray A new <CFArray> object with indexes starting at zero.
+ */
+ public function reindex()
+ {
+ return new CFArray(array_values($this->getArrayCopy()));
+ }
+
+
+ /*%******************************************************************************************%*/
+ // ALTERNATE FORMATS
+
+ /**
+ * Gets the current XML node as a JSON string.
+ *
+ * @return string The current XML node as a JSON string.
+ */
+ public function to_json()
+ {
+ return json_encode($this->getArrayCopy());
+ }
+
+ /**
+ * Gets the current XML node as a YAML string.
+ *
+ * @return string The current XML node as a YAML string.
+ */
+ public function to_yaml()
+ {
+ return sfYaml::dump($this->getArrayCopy(), 5);
+ }
+}
+
+class CFArray_Exception extends Exception {}
diff --git a/3rdparty/aws-sdk/utilities/batchrequest.class.php b/3rdparty/aws-sdk/utilities/batchrequest.class.php
new file mode 100644
index 00000000000..978283471a4
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/batchrequest.class.php
@@ -0,0 +1,126 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+/**
+ * Default CFBatchRequest Exception.
+ */
+class CFBatchRequest_Exception extends Exception {}
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Simplifies the flow involved with managing and executing a batch request queue. Batch requesting is the
+ * ability to queue up a series of requests and execute them all in parallel. This allows for faster
+ * application performance when a lot of requests are involved.
+ *
+ * @version 2011.12.02
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFBatchRequest extends CFRuntime
+{
+ /**
+ * Stores the cURL handles that are to be processed.
+ */
+ public $queue;
+
+ /**
+ * Stores the size of the request window.
+ */
+ public $limit;
+
+ /**
+ * The proxy to use for connecting.
+ */
+ public $proxy = null;
+
+ /**
+ * The helpers to use when connecting.
+ */
+ public $helpers = null;
+
+ /**
+ * The active credential set.
+ */
+ public $credentials;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param integer $limit (Optional) The size of the request window. Defaults to unlimited.
+ * @return boolean `false` if no valid values are set, otherwise `true`.
+ */
+ public function __construct($limit = null)
+ {
+ $this->queue = array();
+ $this->limit = $limit ? $limit : -1;
+ $this->credentials = new CFCredential(array());
+ return $this;
+ }
+
+ /**
+ * Sets the AWS credentials to use for the batch request.
+ *
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return $this A reference to the current instance.
+ */
+ public function use_credentials(CFCredential $credentials)
+ {
+ $this->credentials = $credentials;
+ return $this;
+ }
+
+ /**
+ * Adds a new cURL handle to the request queue.
+ *
+ * @param resource $handle (Required) A cURL resource to add to the queue.
+ * @return $this A reference to the current instance.
+ */
+ public function add($handle)
+ {
+ $this->queue[] = $handle;
+ return $this;
+ }
+
+ /**
+ * Executes the batch request queue.
+ *
+ * @param array $opt (DO NOT USE) Enabled for compatibility with the method this overrides, although any values passed will be ignored.
+ * @return array An indexed array of <CFResponse> objects.
+ */
+ public function send($opt = null)
+ {
+ $http = new $this->request_class(null, $this->proxy, null, $this->credentials);
+
+ // Make the request
+ $response = $http->send_multi_request($this->queue, array(
+ 'limit' => $this->limit
+ ));
+
+ return $response;
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/complextype.class.php b/3rdparty/aws-sdk/utilities/complextype.class.php
new file mode 100644
index 00000000000..e0509b9e368
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/complextype.class.php
@@ -0,0 +1,123 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Contains utility methods used for converting array, JSON, and YAML data types into query string keys.
+ *
+ * @version 2010.11.11
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFComplexType
+{
+ /**
+ * Takes a JSON object, as a string, to convert to query string keys.
+ *
+ * @param string $json (Required) A JSON object. The JSON string should use canonical rules (e.g., double quotes, quoted keys) as is required by PHP's <php:json_encode()> function.
+ * @param string $member (Optional) The name of the "member" property that AWS uses for lists in certain services. Defaults to an empty string.
+ * @param string $default_key (Optional) The default key to use when the value for `$data` is a string. Defaults to an empty string.
+ * @return array The option group parameters to merge into another method's `$opt` parameter.
+ */
+ public static function json($json, $member = '', $default_key = '')
+ {
+ return self::option_group(json_decode($json, true), $member, $default_key);
+ }
+
+ /**
+ * Takes a YAML object, as a string, to convert to query string keys.
+ *
+ * @param string $yaml (Required) A YAML object.
+ * @param string $member (Optional) The name of the "member" property that AWS uses for lists in certain services. Defaults to an empty string.
+ * @param string $default_key (Optional) The default key to use when the value for `$data` is a string. Defaults to an empty string.
+ * @return array The option group parameters to merge into another method's `$opt` parameter.
+ */
+ public static function yaml($yaml, $member = '', $default_key = '')
+ {
+ return self::option_group(sfYaml::load($yaml), $member, $default_key);
+ }
+
+ /**
+ * Takes an associative array to convert to query string keys.
+ *
+ * @param array $map (Required) An associative array.
+ * @param string $member (Optional) The name of the "member" property that AWS uses for lists in certain services. Defaults to an empty string.
+ * @param string $default_key (Optional) The default key to use when the value for `$data` is a string. Defaults to an empty string.
+ * @return array The option group parameters to merge into another method's `$opt` parameter.
+ */
+ public static function map($map, $member = '', $default_key = '')
+ {
+ return self::option_group($map, $member, $default_key);
+ }
+
+ /**
+ * A protected method that is used by <json()>, <yaml()> and <map()>.
+ *
+ * @param string|array $data (Required) The data to iterate over.
+ * @param string $member (Optional) The name of the "member" property that AWS uses for lists in certain services. Defaults to an empty string.
+ * @param string $key (Optional) The default key to use when the value for `$data` is a string. Defaults to an empty string.
+ * @param array $out (Optional) INTERNAL ONLY. The array that contains the calculated values up to this point.
+ * @return array The option group parameters to merge into another method's `$opt` parameter.
+ */
+ public static function option_group($data, $member = '', $key = '', &$out = array())
+ {
+ $reset = $key;
+
+ if (is_array($data))
+ {
+ foreach ($data as $k => $v)
+ {
+ // Avoid 0-based indexes.
+ if (is_int($k))
+ {
+ $k = $k + 1;
+
+ if ($member !== '')
+ {
+ $key .= '.' . $member;
+ }
+ }
+
+ $key .= ($key === '' ? $k : '.' . $k);
+
+ if (is_array($v))
+ {
+ self::option_group($v, $member, $key, $out);
+ }
+ elseif ($v instanceof CFStepConfig)
+ {
+ self::option_group($v->get_config(), $member, $key, $out);
+ }
+ else
+ {
+ $out[$key] = $v;
+ }
+
+ $key = $reset;
+ }
+ }
+ else
+ {
+ $out[$key] = $data;
+ }
+
+ return $out;
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/credential.class.php b/3rdparty/aws-sdk/utilities/credential.class.php
new file mode 100644
index 00000000000..05c0ffcf6d8
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/credential.class.php
@@ -0,0 +1,157 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * The <CFCredential> class represents an individual credential set.
+ *
+ * @version 2011.11.15
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFCredential implements ArrayAccess
+{
+ /**
+ * Stores the internal <php:ArrayObject> representation of the collection.
+ */
+ private $collection;
+
+ /**
+ * Default getter. Enables syntax such as $object->method->chained_method();. Also supports
+ * $object->key. Matching methods are prioritized over matching keys.
+ *
+ * @param string $name (Required) The name of the method to execute or key to retrieve.
+ * @return mixed The results of calling the function <code>$name()</code>, or the value of the key <code>$object[$name]</code>.
+ */
+ public function __get($name)
+ {
+ return $this[$name];
+ }
+
+ /**
+ * Default setter.
+ *
+ * @param string $name (Required) The name of the method to execute.
+ * @param string $value (Required) The value to pass to the method.
+ * @return mixed The results of calling the function, <code>$name</code>.
+ */
+ public function __set($name, $value)
+ {
+ $this[$name] = $value;
+ return $this;
+ }
+
+ /**
+ * Create a clone of the object.
+ *
+ * @return CFCredential A clone of the current instance.
+ */
+ public function __clone()
+ {
+ $this->collection = clone $this->collection;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of the <CFCredential> class.
+ */
+ public function __construct($value = array())
+ {
+ $this->collection = new ArrayObject($value, ArrayObject::ARRAY_AS_PROPS);
+ }
+
+ /**
+ * Check whether or not a specific offset exists.
+ *
+ * @param integer $offset (Required) The location in the collection to verify the existence of.
+ * @return boolean A value of <code>true</code> indicates that the collection offset exists. A value of <code>false</code> indicates that it does not.
+ */
+ public function offsetExists($offset)
+ {
+ return $this->collection->offsetExists($offset);
+ }
+
+ /**
+ * Get the value for a specific offset.
+ *
+ * @param integer $offset (Required) The location in the collection to retrieve the value for.
+ * @return mixed The value of the collection offset. <code>NULL</code> is returned if the offset does not exist.
+ */
+ public function offsetGet($offset)
+ {
+ if ($this->collection->offsetExists($offset))
+ {
+ return $this->collection->offsetGet($offset);
+ }
+
+ return null;
+ }
+
+ /**
+ * Set the value for a specific offset.
+ *
+ * @param integer $offset (Required) The location in the collection to set a new value for.
+ * @param mixed $value (Required) The new value for the collection location.
+ * @return CFCredential A reference to the current collection.
+ */
+ public function offsetSet($offset, $value)
+ {
+ $this->collection->offsetSet($offset, $value);
+ return $this;
+ }
+
+ /**
+ * Unset the value for a specific offset.
+ *
+ * @param integer $offset (Required) The location in the collection to unset.
+ * @return CFCredential A reference to the current collection.
+ */
+ public function offsetUnset($offset)
+ {
+ $this->collection->offsetUnset($offset);
+ return $this;
+ }
+
+ /**
+ * Merge another instance of <CFCredential> onto this one.
+ *
+ * @param CFCredential $credential (Required) Another instance of <CFCredential>.
+ * @return CFCredential A reference to the current collection.
+ */
+ public function merge(CFCredential $credential)
+ {
+ $merged = array_merge($this->to_array(), $credential->to_array());
+ $this->collection->exchangeArray($merged);
+ return $this;
+ }
+
+ /**
+ * Retrieves the data as a standard array.
+ *
+ * @return array The data as an array.
+ */
+ public function to_array()
+ {
+ return $this->collection->getArrayCopy();
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/credentials.class.php b/3rdparty/aws-sdk/utilities/credentials.class.php
new file mode 100644
index 00000000000..2504a081b23
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/credentials.class.php
@@ -0,0 +1,125 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * The <CFCredentials> class enables developers to easily switch between multiple sets of credentials.
+ *
+ * @version 2011.11.15
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFCredentials
+{
+ /**
+ * The key used to specify the default credential set
+ */
+ const DEFAULT_KEY = '@default';
+
+ /**
+ * The key used to identify inherited credentials
+ */
+ const INHERIT_KEY = '@inherit';
+
+ /**
+ * Stores the credentials
+ */
+ protected static $credentials = array();
+
+ /**
+ * Prevents this class from being constructed
+ */
+ final private function __construct() {}
+
+ /**
+ * Stores the credentials for re-use.
+ *
+ * @param array $credential_sets (Required) The named credential sets that should be made available to the application.
+ * @return void
+ */
+ public static function set(array $credential_sets)
+ {
+ // Make sure a default credential set is specified or can be inferred
+ if (count($credential_sets) === 1)
+ {
+ $credential_sets[self::DEFAULT_KEY] = reset($credential_sets);
+ }
+ elseif (!isset($credential_sets[self::DEFAULT_KEY]))
+ {
+ throw new CFCredentials_Exception('If more than one credential set is provided, a default credential set (identified by the key "' . self::DEFAULT_KEY . '") must be specified.');
+ }
+
+ // Resolve any @inherit tags
+ foreach ($credential_sets as $credential_name => &$credential_set)
+ {
+ if (is_array($credential_set))
+ {
+ foreach ($credential_set as $credential_key => &$credential_value)
+ {
+ if ($credential_key === self::INHERIT_KEY)
+ {
+ if (!isset($credential_sets[$credential_value]))
+ {
+ throw new CFCredentials_Exception('The credential set, "' . $credential_value . '", does not exist and cannot be inherited.');
+ }
+
+ $credential_set = array_merge($credential_sets[$credential_value], $credential_set);
+ unset($credential_set[self::INHERIT_KEY]);
+ }
+ }
+ }
+ }
+
+ // Normalize the value of the @default credential set
+ $default = $credential_sets[self::DEFAULT_KEY];
+ if (is_string($default))
+ {
+ if (!isset($credential_sets[$default]))
+ {
+ throw new CFCredentials_Exception('The credential set, "' . $default . '", does not exist and cannot be used as the default credential set.');
+ }
+
+ $credential_sets[self::DEFAULT_KEY] = $credential_sets[$default];
+ }
+
+ // Store the credentials
+ self::$credentials = $credential_sets;
+ }
+
+ /**
+ * Retrieves the requested credentials from the internal credential store.
+ *
+ * @param string $credential_set (Optional) The name of the credential set to retrieve. The default value is set in DEFAULT_KEY.
+ * @return stdClass A stdClass object where the properties represent the keys that were provided.
+ */
+ public static function get($credential_name = self::DEFAULT_KEY)
+ {
+ // Make sure the credential set exists
+ if (!isset(self::$credentials[$credential_name]))
+ {
+ throw new CFCredentials_Exception('The credential set, "' . $credential_name . '", does not exist and cannot be retrieved.');
+ }
+
+ // Return the credential set as an object
+ return new CFCredential(self::$credentials[$credential_name]);
+ }
+}
+
+class CFCredentials_Exception extends Exception {}
diff --git a/3rdparty/aws-sdk/utilities/gzipdecode.class.php b/3rdparty/aws-sdk/utilities/gzipdecode.class.php
new file mode 100644
index 00000000000..f80822a7048
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/gzipdecode.class.php
@@ -0,0 +1,377 @@
+<?php
+/*
+ * Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+/**
+ * SimplePie
+ *
+ * A PHP-Based RSS and Atom Feed Framework.
+ * Takes the hard work out of managing a complete RSS/Atom solution.
+ *
+ * Copyright (c) 2004-2010, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * * Neither the name of the SimplePie Team nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package SimplePie
+ * @version 1.3-dev
+ * @copyright 2004-2010 Ryan Parman, Geoffrey Sneddon, Ryan McCue
+ * @author Ryan Parman
+ * @author Geoffrey Sneddon
+ * @author Ryan McCue
+ * @link http://simplepie.org/ SimplePie
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @todo phpDoc comments
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Handles a variety of primary and edge cases around gzip/deflate decoding in PHP.
+ *
+ * @version 2011.02.21
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ * @link https://github.com/simplepie/simplepie/blob/master/SimplePie/gzdecode.php SimplePie_gzdecode
+ */
+class CFGzipDecode
+{
+ /**
+ * Compressed data
+ *
+ * @access private
+ * @see gzdecode::$data
+ */
+ public $compressed_data;
+
+ /**
+ * Size of compressed data
+ *
+ * @access private
+ */
+ public $compressed_size;
+
+ /**
+ * Minimum size of a valid gzip string
+ *
+ * @access private
+ */
+ public $min_compressed_size = 18;
+
+ /**
+ * Current position of pointer
+ *
+ * @access private
+ */
+ public $position = 0;
+
+ /**
+ * Flags (FLG)
+ *
+ * @access private
+ */
+ public $flags;
+
+ /**
+ * Uncompressed data
+ *
+ * @access public
+ * @see gzdecode::$compressed_data
+ */
+ public $data;
+
+ /**
+ * Modified time
+ *
+ * @access public
+ */
+ public $MTIME;
+
+ /**
+ * Extra Flags
+ *
+ * @access public
+ */
+ public $XFL;
+
+ /**
+ * Operating System
+ *
+ * @access public
+ */
+ public $OS;
+
+ /**
+ * Subfield ID 1
+ *
+ * @access public
+ * @see gzdecode::$extra_field
+ * @see gzdecode::$SI2
+ */
+ public $SI1;
+
+ /**
+ * Subfield ID 2
+ *
+ * @access public
+ * @see gzdecode::$extra_field
+ * @see gzdecode::$SI1
+ */
+ public $SI2;
+
+ /**
+ * Extra field content
+ *
+ * @access public
+ * @see gzdecode::$SI1
+ * @see gzdecode::$SI2
+ */
+ public $extra_field;
+
+ /**
+ * Original filename
+ *
+ * @access public
+ */
+ public $filename;
+
+ /**
+ * Human readable comment
+ *
+ * @access public
+ */
+ public $comment;
+
+ /**
+ * Don't allow anything to be set
+ *
+ * @access public
+ */
+ public function __set($name, $value)
+ {
+ trigger_error("Cannot write property $name", E_USER_ERROR);
+ }
+
+ /**
+ * Set the compressed string and related properties
+ *
+ * @access public
+ */
+ public function __construct($data)
+ {
+ $this->compressed_data = $data;
+ $this->compressed_size = strlen($data);
+ }
+
+ /**
+ * Decode the GZIP stream
+ *
+ * @access public
+ */
+ public function parse()
+ {
+ if ($this->compressed_size >= $this->min_compressed_size)
+ {
+ // Check ID1, ID2, and CM
+ if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
+ {
+ return false;
+ }
+
+ // Get the FLG (FLaGs)
+ $this->flags = ord($this->compressed_data[3]);
+
+ // FLG bits above (1 << 4) are reserved
+ if ($this->flags > 0x1F)
+ {
+ return false;
+ }
+
+ // Advance the pointer after the above
+ $this->position += 4;
+
+ // MTIME
+ $mtime = substr($this->compressed_data, $this->position, 4);
+ // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
+ if (current(unpack('S', "\x00\x01")) === 1)
+ {
+ $mtime = strrev($mtime);
+ }
+ $this->MTIME = current(unpack('l', $mtime));
+ $this->position += 4;
+
+ // Get the XFL (eXtra FLags)
+ $this->XFL = ord($this->compressed_data[$this->position++]);
+
+ // Get the OS (Operating System)
+ $this->OS = ord($this->compressed_data[$this->position++]);
+
+ // Parse the FEXTRA
+ if ($this->flags & 4)
+ {
+ // Read subfield IDs
+ $this->SI1 = $this->compressed_data[$this->position++];
+ $this->SI2 = $this->compressed_data[$this->position++];
+
+ // SI2 set to zero is reserved for future use
+ if ($this->SI2 === "\x00")
+ {
+ return false;
+ }
+
+ // Get the length of the extra field
+ $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
+ $position += 2;
+
+ // Check the length of the string is still valid
+ $this->min_compressed_size += $len + 4;
+ if ($this->compressed_size >= $this->min_compressed_size)
+ {
+ // Set the extra field to the given data
+ $this->extra_field = substr($this->compressed_data, $this->position, $len);
+ $this->position += $len;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // Parse the FNAME
+ if ($this->flags & 8)
+ {
+ // Get the length of the filename
+ $len = strcspn($this->compressed_data, "\x00", $this->position);
+
+ // Check the length of the string is still valid
+ $this->min_compressed_size += $len + 1;
+ if ($this->compressed_size >= $this->min_compressed_size)
+ {
+ // Set the original filename to the given string
+ $this->filename = substr($this->compressed_data, $this->position, $len);
+ $this->position += $len + 1;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // Parse the FCOMMENT
+ if ($this->flags & 16)
+ {
+ // Get the length of the comment
+ $len = strcspn($this->compressed_data, "\x00", $this->position);
+
+ // Check the length of the string is still valid
+ $this->min_compressed_size += $len + 1;
+ if ($this->compressed_size >= $this->min_compressed_size)
+ {
+ // Set the original comment to the given string
+ $this->comment = substr($this->compressed_data, $this->position, $len);
+ $this->position += $len + 1;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // Parse the FHCRC
+ if ($this->flags & 2)
+ {
+ // Check the length of the string is still valid
+ $this->min_compressed_size += $len + 2;
+ if ($this->compressed_size >= $this->min_compressed_size)
+ {
+ // Read the CRC
+ $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
+
+ // Check the CRC matches
+ if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
+ {
+ $this->position += 2;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // Decompress the actual data
+ if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
+ {
+ return false;
+ }
+ else
+ {
+ $this->position = $this->compressed_size - 8;
+ }
+
+ // Check CRC of data
+ $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
+ $this->position += 4;
+ /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
+ {
+ return false;
+ }*/
+
+ // Check ISIZE of data
+ $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
+ $this->position += 4;
+ if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
+ {
+ return false;
+ }
+
+ // Wow, against all odds, we've actually got a valid gzip string
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/hadoopbase.class.php b/3rdparty/aws-sdk/utilities/hadoopbase.class.php
new file mode 100644
index 00000000000..eb8bc5c3a81
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/hadoopbase.class.php
@@ -0,0 +1,67 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Contains core functionality for Hadoop helpers.
+ *
+ * @version 2011.05.03
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ * @link http://hadoop.apache.org Apache Hadoop
+ */
+class CFHadoopBase
+{
+ /**
+ * Runs a specified script on the master node of your cluster.
+ *
+ * @param string $script (Required) The script to run with `script-runner.jar`.
+ * @param array $args (Optional) An indexed array of arguments to pass to the script.
+ * @return array A standard array that is intended to be passed into a <CFStepConfig> object.
+ */
+ public static function script_runner($script, $args = null)
+ {
+ if (!$args) $args = array();
+ array_unshift($args, $script);
+
+ return array(
+ 'Jar' => 's3://us-east-1.elasticmapreduce/libs/script-runner/script-runner.jar',
+ 'Args' => $args
+ );
+ }
+
+ /**
+ * Prepares a Hive or Pig script before passing it to the script runner.
+ *
+ * @param string $type (Required) The type of script to run. [Allowed values: `hive`, `pig`].
+ * @param array $args (Optional) An indexed array of arguments to pass to the script.
+ * @return array A standard array that is intended to be passed into a <CFStepConfig> object.
+ * @link http://hive.apache.org Apache Hive
+ * @link http://pig.apache.org Apache Pig
+ */
+ public static function hive_pig_script($type, $args = null)
+ {
+ if (!$args) $args = array();
+ $args = is_array($args) ? $args : array($args);
+ $args = array_merge(array('--base-path', 's3://us-east-1.elasticmapreduce/libs/' . $type . '/'), $args);
+
+ return self::script_runner('s3://us-east-1.elasticmapreduce/libs/' . $type . '/' . $type . '-script', $args);
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/hadoopbootstrap.class.php b/3rdparty/aws-sdk/utilities/hadoopbootstrap.class.php
new file mode 100644
index 00000000000..baaa0c08d4b
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/hadoopbootstrap.class.php
@@ -0,0 +1,127 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Contains a set of pre-built Amazon EMR Hadoop Bootstrap Actions.
+ *
+ * @version 2011.05.03
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ * @link http://hadoop.apache.org Apache Hadoop
+ */
+class CFHadoopBootstrap extends CFHadoopBase
+{
+ // Config file types
+ const CONFIG_SITE = 'S';
+ const CONFIG_DEFAULT = 'D';
+ const CONFIG_CORE = 'C';
+ const CONFIG_HDFS = 'H';
+ const CONFIG_MAPREDUCE = 'M';
+
+ // Daemon types
+ const DAEMON_NAME_NODE = 'namenode';
+ const DAEMON_DATA_NODE = 'datanode';
+ const DAEMON_JOB_TRACKER = 'jobtracker';
+ const DAEMON_TASK_TRACKER = 'tasktracker';
+ const DAEMON_CLIENT = 'client';
+
+ /**
+ * Create a new run-if bootstrap action which lets you conditionally run bootstrap actions.
+ *
+ * @param string $condition (Required) The condition to evaluate. If <code>true</code>, the bootstrap action executes.
+ * @param array $args (Optional) An indexed array of arguments to pass to the script.
+ * @return array A configuration set to be provided when running a job flow.
+ */
+ public static function run_if($condition, $args = null)
+ {
+ if (!$args) $args = array();
+ $args = is_array($args) ? $args : array($args);
+
+ return self::script_runner('s3://us-east-1.elasticmapreduce/bootstrap-actions/run-if', $args);
+ }
+
+ /**
+ * Specify options to merge with Hadoop's default configuration.
+ *
+ * @param string $file (Required) The Hadoop configuration file to merge with. [Allowed values: <code>CFHadoopBootstrap::CONFIG_SITE</code>, <code>CFHadoopBootstrap::CONFIG_DEFAULT</code>, <code>CFHadoopBootstrap::CONFIG_CORE</code>, <code>CFHadoopBootstrap::CONFIG_HDFS</code>, <code>CFHadoopBootstrap::CONFIG_MAPREDUCE</code>]
+ * @param string|array $config (Required) This can either be an XML file in S3 (as <code>s3://bucket/path</code>), or an associative array of key-value pairs.
+ * @return array A configuration set to be provided when running a job flow.
+ */
+ public static function configure($file, $config)
+ {
+ $args = array();
+ $file_arg = '-' . $file;
+
+ if (is_string($config))
+ {
+ $args[] = $file_arg;
+ $args[] = $config;
+ }
+ elseif (is_array($config))
+ {
+ foreach ($config as $key => $value)
+ {
+ $args[] = $file_arg;
+ $args[] = $key . '=' . $value;
+ }
+ }
+
+ return self::script_runner('s3://us-east-1.elasticmapreduce/bootstrap-actions/configure-hadoop', $args);
+ }
+
+ /**
+ * Create a new bootstrap action which lets you configure Hadoop's daemons. The options are written to
+ * the <code>hadoop-user-env.sh</code> file.
+ *
+ * @param string $daemon_type (Required) The Hadoop daemon to configure.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>HeapSize</code> - <code>integer</code> - Optional - The requested heap size of the daemon, in megabytes.</li>
+ * <li><code>CLIOptions</code> - <code>string</code> - Optional - Additional Java command line arguments to pass to the daemon.</li>
+ * <li><code>Replace</code> - <code>boolean</code> - Optional - Whether or not the file should be replaced. A value of <code>true</code> will replace the existing configuration file. A value of <code>false</code> will append the options to the configuration file.</li></ul>
+ * @return array A configuration set to be provided when running a job flow.
+ */
+ public static function daemon($daemon_type, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $args = array();
+
+ foreach ($opt as $key => $value)
+ {
+ switch ($key)
+ {
+ case 'HeapSize':
+ $args[] = '--' . $daemon_type . '-heap-size=' . $value;
+ break;
+ case 'CLIOptions':
+ $args[] = '--' . $daemon_type . '-opts="' . $value . '"';
+ break;
+ case 'Replace':
+ if ((is_string($value) && $value === 'true') || (is_bool($value) && $value === true))
+ {
+ $args[] = '--replace';
+ }
+ break;
+ }
+ }
+
+ return self::script_runner('s3://us-east-1.elasticmapreduce/bootstrap-actions/configure-daemons', $args);
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/hadoopstep.class.php b/3rdparty/aws-sdk/utilities/hadoopstep.class.php
new file mode 100644
index 00000000000..2371e007489
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/hadoopstep.class.php
@@ -0,0 +1,98 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Contains a set of pre-built Amazon EMR Hadoop steps.
+ *
+ * @version 2011.05.03
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ * @link http://hadoop.apache.org Apache Hadoop
+ */
+class CFHadoopStep extends CFHadoopBase
+{
+ /**
+ * When ran as the first step in your job flow, enables the Hadoop debugging UI in the AWS
+ * Management Console.
+ *
+ * @return array A standard array that is intended to be passed into a <CFStepConfig> object.
+ */
+ public static function enable_debugging()
+ {
+ return self::script_runner('s3://us-east-1.elasticmapreduce/libs/state-pusher/0.1/fetch');
+ }
+
+ /**
+ * Step that installs Hive on your job flow.
+ *
+ * @return array A standard array that is intended to be passed into a <CFStepConfig> object.
+ * @link http://hive.apache.org Apache Hive
+ */
+ public static function install_hive()
+ {
+ return self::hive_pig_script('hive', '--install-hive');
+ }
+
+ /**
+ * Step that runs a Hive script on your job flow.
+ *
+ * @param string $script (Required) The script to run with `script-runner.jar`.
+ * @param array $args (Optional) An indexed array of arguments to pass to the script.
+ * @return array A standard array that is intended to be passed into a <CFStepConfig> object.
+ * @link http://hive.apache.org Apache Hive
+ */
+ public static function run_hive_script($script, $args = null)
+ {
+ if (!$args) $args = array();
+ $args = is_array($args) ? $args : array($args);
+ $args = array_merge(array('--run-hive-script', '--args', '-f', $script), $args);
+
+ return self::hive_pig_script('hive', $args);
+ }
+
+ /**
+ * Step that installs Pig on your job flow.
+ *
+ * @return array A standard array that is intended to be passed into a <CFStepConfig> object.
+ * @link http://pig.apache.org Apache Pig
+ */
+ public static function install_pig()
+ {
+ return self::hive_pig_script('pig', '--install-pig');
+ }
+
+ /**
+ * Step that runs a Pig script on your job flow.
+ *
+ * @param string $script (Required) The script to run with `script-runner.jar`.
+ * @param array $args (Optional) An indexed array of arguments to pass to the script.
+ * @return array A standard array that is intended to be passed into a <CFStepConfig> object.
+ * @link http://pig.apache.org Apache Pig
+ */
+ public static function run_pig_script($script, $args = null)
+ {
+ if (!$args) $args = array();
+ $args = is_array($args) ? $args : array($args);
+ $args = array_merge(array('--run-pig-script', '--args', '-f', $script), $args);
+
+ return self::hive_pig_script('pig', $args);
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/info.class.php b/3rdparty/aws-sdk/utilities/info.class.php
new file mode 100644
index 00000000000..2ba289a5f01
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/info.class.php
@@ -0,0 +1,69 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Contains a series of methods that provide information about the SDK.
+ *
+ * @version 2010.10.01
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFInfo
+{
+ /**
+ * Gets information about the web service APIs that the SDK supports.
+ *
+ * @return array An associative array containing service classes and API versions.
+ */
+ public static function api_support()
+ {
+ $existing_classes = get_declared_classes();
+
+ foreach (glob(dirname(dirname(__FILE__)) . '/services/*.class.php') as $file)
+ {
+ include $file;
+ }
+
+ $with_sdk_classes = get_declared_classes();
+ $new_classes = array_diff($with_sdk_classes, $existing_classes);
+ $filtered_classes = array();
+ $collect = array();
+
+ foreach ($new_classes as $class)
+ {
+ if (strpos($class, 'Amazon') !== false)
+ {
+ $filtered_classes[] = $class;
+ }
+ }
+
+ $filtered_classes = array_values($filtered_classes);
+
+ foreach ($filtered_classes as $class)
+ {
+ $obj = new $class();
+ $collect[get_class($obj)] = $obj->api_version;
+ unset($obj);
+ }
+
+ return $collect;
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/json.class.php b/3rdparty/aws-sdk/utilities/json.class.php
new file mode 100644
index 00000000000..dfa83839863
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/json.class.php
@@ -0,0 +1,89 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Handles the conversion of data from JSON to other formats.
+ *
+ * @version 2012.01.27
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFJSON
+{
+ /**
+ * Converts a JSON string to a CFSimpleXML object.
+ *
+ * @param string|array $json (Required) Pass either a valid JSON-formatted string, or an associative array.
+ * @param string $parser (Optional) The name of the class to use to parse the XML. This class should extend <code>SimpleXMLElement</code>. Has a default value of <code>CFSimpleXML</code>.
+ * @return CFSimpleXML An XML representation of the data.
+ */
+ public static function to_xml($json, $parser = 'CFSimpleXML')
+ {
+ // If we haven't parsed the JSON, do it
+ if (!is_array($json))
+ {
+ // Handle the case of JSON-encoded NULL value
+ if ($json === 'null')
+ {
+ $json = null;
+ }
+ else
+ {
+ $json = json_decode($json, true);
+
+ if (function_exists('json_last_error'))
+ {
+ // Did we encounter an error?
+ switch (json_last_error())
+ {
+ case JSON_ERROR_DEPTH:
+ throw new JSON_Exception('Maximum stack depth exceeded.');
+
+ case JSON_ERROR_CTRL_CHAR:
+ throw new JSON_Exception('Unexpected control character found.');
+
+ case JSON_ERROR_SYNTAX:
+ throw new JSON_Exception('Syntax error; Malformed JSON.');
+
+ case JSON_ERROR_STATE_MISMATCH:
+ throw new JSON_Exception('Invalid or malformed JSON.');
+ }
+ }
+ // json_last_error() not available?
+ elseif ($json === null)
+ {
+ throw new JSON_Exception('Unknown JSON error. Be sure to validate your JSON and read the notes on http://php.net/json_decode.');
+ }
+ }
+ }
+
+ // Hand off for the recursive work
+ $string = Array2DOM::arrayToXMLString($json, 'rootElement', true);
+
+ return simplexml_load_string($string, $parser, LIBXML_NOCDATA);
+ }
+}
+
+
+/**
+ * Default JSON Exception.
+ */
+class JSON_Exception extends Exception {}
diff --git a/3rdparty/aws-sdk/utilities/manifest.class.php b/3rdparty/aws-sdk/utilities/manifest.class.php
new file mode 100644
index 00000000000..82410a328db
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/manifest.class.php
@@ -0,0 +1,54 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Simplifies the process of generating manifests for the AWS Import/Export service.
+ *
+ * @version 2010.11.22
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFManifest
+{
+
+ /**
+ * Takes a JSON object as a string to convert to a YAML manifest.
+ *
+ * @param string $json (Required) A JSON object. The JSON string should use canonical rules (e.g., double quotes, quoted keys) as is required by PHP's <php:json_encode()> function.
+ * @return string A YAML manifest document.
+ */
+ public static function json($json)
+ {
+ $map = json_decode($json, true);
+ return sfYaml::dump($map);
+ }
+
+ /**
+ * Takes an associative array to convert to a YAML manifest.
+ *
+ * @param array $map (Required) An associative array.
+ * @return string A YAML manifest document.
+ */
+ public static function map($map)
+ {
+ return sfYaml::dump($map);
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/mimetypes.class.php b/3rdparty/aws-sdk/utilities/mimetypes.class.php
new file mode 100644
index 00000000000..5fa23d3942a
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/mimetypes.class.php
@@ -0,0 +1,223 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Simplifies the process of looking up the content-types for a variety of file extensions.
+ *
+ * @version 2010.07.20
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFMimeTypes
+{
+ /**
+ * Map of the extension-to-mime-types that we support.
+ */
+ public static $mime_types = array(
+ '3gp' => 'video/3gpp',
+ 'ai' => 'application/postscript',
+ 'aif' => 'audio/x-aiff',
+ 'aifc' => 'audio/x-aiff',
+ 'aiff' => 'audio/x-aiff',
+ 'asc' => 'text/plain',
+ 'atom' => 'application/atom+xml',
+ 'au' => 'audio/basic',
+ 'avi' => 'video/x-msvideo',
+ 'bcpio' => 'application/x-bcpio',
+ 'bin' => 'application/octet-stream',
+ 'bmp' => 'image/bmp',
+ 'cdf' => 'application/x-netcdf',
+ 'cgm' => 'image/cgm',
+ 'class' => 'application/octet-stream',
+ 'cpio' => 'application/x-cpio',
+ 'cpt' => 'application/mac-compactpro',
+ 'csh' => 'application/x-csh',
+ 'css' => 'text/css',
+ 'dcr' => 'application/x-director',
+ 'dif' => 'video/x-dv',
+ 'dir' => 'application/x-director',
+ 'djv' => 'image/vnd.djvu',
+ 'djvu' => 'image/vnd.djvu',
+ 'dll' => 'application/octet-stream',
+ 'dmg' => 'application/octet-stream',
+ 'dms' => 'application/octet-stream',
+ 'doc' => 'application/msword',
+ 'dtd' => 'application/xml-dtd',
+ 'dv' => 'video/x-dv',
+ 'dvi' => 'application/x-dvi',
+ 'dxr' => 'application/x-director',
+ 'eps' => 'application/postscript',
+ 'etx' => 'text/x-setext',
+ 'exe' => 'application/octet-stream',
+ 'ez' => 'application/andrew-inset',
+ 'flv' => 'video/x-flv',
+ 'gif' => 'image/gif',
+ 'gram' => 'application/srgs',
+ 'grxml' => 'application/srgs+xml',
+ 'gtar' => 'application/x-gtar',
+ 'gz' => 'application/x-gzip',
+ 'hdf' => 'application/x-hdf',
+ 'hqx' => 'application/mac-binhex40',
+ 'htm' => 'text/html',
+ 'html' => 'text/html',
+ 'ice' => 'x-conference/x-cooltalk',
+ 'ico' => 'image/x-icon',
+ 'ics' => 'text/calendar',
+ 'ief' => 'image/ief',
+ 'ifb' => 'text/calendar',
+ 'iges' => 'model/iges',
+ 'igs' => 'model/iges',
+ 'jnlp' => 'application/x-java-jnlp-file',
+ 'jp2' => 'image/jp2',
+ 'jpe' => 'image/jpeg',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'js' => 'application/x-javascript',
+ 'kar' => 'audio/midi',
+ 'latex' => 'application/x-latex',
+ 'lha' => 'application/octet-stream',
+ 'lzh' => 'application/octet-stream',
+ 'm3u' => 'audio/x-mpegurl',
+ 'm4a' => 'audio/mp4a-latm',
+ 'm4p' => 'audio/mp4a-latm',
+ 'm4u' => 'video/vnd.mpegurl',
+ 'm4v' => 'video/x-m4v',
+ 'mac' => 'image/x-macpaint',
+ 'man' => 'application/x-troff-man',
+ 'mathml' => 'application/mathml+xml',
+ 'me' => 'application/x-troff-me',
+ 'mesh' => 'model/mesh',
+ 'mid' => 'audio/midi',
+ 'midi' => 'audio/midi',
+ 'mif' => 'application/vnd.mif',
+ 'mov' => 'video/quicktime',
+ 'movie' => 'video/x-sgi-movie',
+ 'mp2' => 'audio/mpeg',
+ 'mp3' => 'audio/mpeg',
+ 'mp4' => 'video/mp4',
+ 'mpe' => 'video/mpeg',
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'mpga' => 'audio/mpeg',
+ 'ms' => 'application/x-troff-ms',
+ 'msh' => 'model/mesh',
+ 'mxu' => 'video/vnd.mpegurl',
+ 'nc' => 'application/x-netcdf',
+ 'oda' => 'application/oda',
+ 'ogg' => 'application/ogg',
+ 'ogv' => 'video/ogv',
+ 'pbm' => 'image/x-portable-bitmap',
+ 'pct' => 'image/pict',
+ 'pdb' => 'chemical/x-pdb',
+ 'pdf' => 'application/pdf',
+ 'pgm' => 'image/x-portable-graymap',
+ 'pgn' => 'application/x-chess-pgn',
+ 'pic' => 'image/pict',
+ 'pict' => 'image/pict',
+ 'png' => 'image/png',
+ 'pnm' => 'image/x-portable-anymap',
+ 'pnt' => 'image/x-macpaint',
+ 'pntg' => 'image/x-macpaint',
+ 'ppm' => 'image/x-portable-pixmap',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'ps' => 'application/postscript',
+ 'qt' => 'video/quicktime',
+ 'qti' => 'image/x-quicktime',
+ 'qtif' => 'image/x-quicktime',
+ 'ra' => 'audio/x-pn-realaudio',
+ 'ram' => 'audio/x-pn-realaudio',
+ 'ras' => 'image/x-cmu-raster',
+ 'rdf' => 'application/rdf+xml',
+ 'rgb' => 'image/x-rgb',
+ 'rm' => 'application/vnd.rn-realmedia',
+ 'roff' => 'application/x-troff',
+ 'rtf' => 'text/rtf',
+ 'rtx' => 'text/richtext',
+ 'sgm' => 'text/sgml',
+ 'sgml' => 'text/sgml',
+ 'sh' => 'application/x-sh',
+ 'shar' => 'application/x-shar',
+ 'silo' => 'model/mesh',
+ 'sit' => 'application/x-stuffit',
+ 'skd' => 'application/x-koan',
+ 'skm' => 'application/x-koan',
+ 'skp' => 'application/x-koan',
+ 'skt' => 'application/x-koan',
+ 'smi' => 'application/smil',
+ 'smil' => 'application/smil',
+ 'snd' => 'audio/basic',
+ 'so' => 'application/octet-stream',
+ 'spl' => 'application/x-futuresplash',
+ 'src' => 'application/x-wais-source',
+ 'sv4cpio' => 'application/x-sv4cpio',
+ 'sv4crc' => 'application/x-sv4crc',
+ 'svg' => 'image/svg+xml',
+ 'swf' => 'application/x-shockwave-flash',
+ 't' => 'application/x-troff',
+ 'tar' => 'application/x-tar',
+ 'tcl' => 'application/x-tcl',
+ 'tex' => 'application/x-tex',
+ 'texi' => 'application/x-texinfo',
+ 'texinfo' => 'application/x-texinfo',
+ 'tif' => 'image/tiff',
+ 'tiff' => 'image/tiff',
+ 'tr' => 'application/x-troff',
+ 'tsv' => 'text/tab-separated-values',
+ 'txt' => 'text/plain',
+ 'ustar' => 'application/x-ustar',
+ 'vcd' => 'application/x-cdlink',
+ 'vrml' => 'model/vrml',
+ 'vxml' => 'application/voicexml+xml',
+ 'wav' => 'audio/x-wav',
+ 'wbmp' => 'image/vnd.wap.wbmp',
+ 'wbxml' => 'application/vnd.wap.wbxml',
+ 'webm' => 'video/webm',
+ 'wml' => 'text/vnd.wap.wml',
+ 'wmlc' => 'application/vnd.wap.wmlc',
+ 'wmls' => 'text/vnd.wap.wmlscript',
+ 'wmlsc' => 'application/vnd.wap.wmlscriptc',
+ 'wmv' => 'video/x-ms-wmv',
+ 'wrl' => 'model/vrml',
+ 'xbm' => 'image/x-xbitmap',
+ 'xht' => 'application/xhtml+xml',
+ 'xhtml' => 'application/xhtml+xml',
+ 'xls' => 'application/vnd.ms-excel',
+ 'xml' => 'application/xml',
+ 'xpm' => 'image/x-xpixmap',
+ 'xsl' => 'application/xml',
+ 'xslt' => 'application/xslt+xml',
+ 'xul' => 'application/vnd.mozilla.xul+xml',
+ 'xwd' => 'image/x-xwindowdump',
+ 'xyz' => 'chemical/x-xyz',
+ 'zip' => 'application/zip',
+ );
+
+ /**
+ * Attempt to match the file extension to a known mime-type.
+ *
+ * @param string $ext (Required) The file extension to attempt to map.
+ * @return string The mime-type to use for the file extension.
+ */
+ public static function get_mimetype($ext)
+ {
+ return (isset(self::$mime_types[$ext]) ? self::$mime_types[$ext] : 'application/octet-stream');
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/policy.class.php b/3rdparty/aws-sdk/utilities/policy.class.php
new file mode 100644
index 00000000000..9c53fee0d72
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/policy.class.php
@@ -0,0 +1,134 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Simplifies the process of signing JSON policy documents.
+ *
+ * @version 2011.04.25
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFPolicy
+{
+ /**
+ * Stores the object that contains the authentication credentials.
+ */
+ public $auth;
+
+ /**
+ * Stores the policy object that we're working with.
+ */
+ public $json_policy;
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param CFRuntime $auth (Required) An instance of any authenticated AWS object that is an instance of <CFRuntime> (e.g. <AmazonEC2>, <AmazonS3>).
+ * @param string|array $policy (Required) The associative array representing the S3 policy to use, or a string of JSON content.
+ * @return $this A reference to the current instance.
+ * @link http://docs.amazonwebservices.com/AmazonS3/2006-03-01/dev/index.html?HTTPPOSTForms.html S3 Policies
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?AccessPolicyLanguage.html Access Policy Language
+ */
+ public function __construct($auth, $policy)
+ {
+ $this->auth = $auth;
+
+ if (is_array($policy)) // We received an associative array...
+ {
+ $this->json_policy = json_encode($policy);
+ }
+ else // We received a valid, parseable JSON string...
+ {
+ $this->json_policy = json_encode(json_decode($policy, true));
+ }
+
+ return $this;
+ }
+
+ /**
+ * Alternate approach to constructing a new instance. Supports chaining.
+ *
+ * @param CFRuntime $auth (Required) An instance of any authenticated AWS object that is an instance of <CFRuntime> (e.g. <AmazonEC2>, <AmazonS3>).
+ * @param string|array $policy (Required) The associative array representing the S3 policy to use, or a string of JSON content.
+ * @return $this A reference to the current instance.
+ */
+ public static function init($auth, $policy)
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '<'))
+ {
+ throw new Exception('PHP 5.3 or newer is required to instantiate a new class with CLASS::init().');
+ }
+
+ $self = get_called_class();
+ return new $self($auth, $policy);
+ }
+
+ /**
+ * Get the key from the authenticated instance.
+ *
+ * @return string The key from the authenticated instance.
+ */
+ public function get_key()
+ {
+ return $this->auth->key;
+ }
+
+ /**
+ * Base64-encodes the JSON string.
+ *
+ * @return string The Base64-encoded version of the JSON string.
+ */
+ public function get_policy()
+ {
+ return base64_encode($this->json_policy);
+ }
+
+ /**
+ * Gets the JSON string with the whitespace removed.
+ *
+ * @return string The JSON string without extraneous whitespace.
+ */
+ public function get_json()
+ {
+ return $this->json_policy;
+ }
+
+ /**
+ * Gets the JSON string with the whitespace removed.
+ *
+ * @return string The Base64-encoded, signed JSON string.
+ */
+ public function get_policy_signature()
+ {
+ return base64_encode(hash_hmac('sha1', $this->get_policy(), $this->auth->secret_key));
+ }
+
+ /**
+ * Decode a policy that was returned from the service.
+ *
+ * @param string $response (Required) The policy returned by AWS that you want to decode into an object.
+ * @return string The Base64-encoded, signed JSON string.
+ */
+ public static function decode_policy($response)
+ {
+ return json_decode(urldecode($response), true);
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/request.class.php b/3rdparty/aws-sdk/utilities/request.class.php
new file mode 100644
index 00000000000..8e049fb5169
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/request.class.php
@@ -0,0 +1,70 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Wraps the underlying `RequestCore` class with some AWS-specific customizations.
+ *
+ * @version 2011.12.02
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFRequest extends RequestCore
+{
+ /**
+ * The default class to use for HTTP Requests (defaults to <CFRequest>).
+ */
+ public $request_class = 'CFRequest';
+
+ /**
+ * The default class to use for HTTP Responses (defaults to <CFResponse>).
+ */
+ public $response_class = 'CFResponse';
+
+ /**
+ * The active credential set.
+ */
+ public $credentials;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $url (Optional) The URL to request or service endpoint to query.
+ * @param string $proxy (Optional) The faux-url to use for proxy settings. Takes the following format: `proxy://user:pass@hostname:port`
+ * @param array $helpers (Optional) An associative array of classnames to use for request, and response functionality. Gets passed in automatically by the calling class.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return $this A reference to the current instance.
+ */
+ public function __construct($url = null, $proxy = null, $helpers = null, CFCredential $credentials = null)
+ {
+ parent::__construct($url, $proxy, $helpers);
+
+ // Standard settings for all requests
+ $this->set_useragent(CFRUNTIME_USERAGENT);
+ $this->credentials = $credentials;
+ $this->cacert_location = ($this->credentials['certificate_authority'] ? $this->credentials['certificate_authority'] : false);
+
+ return $this;
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/response.class.php b/3rdparty/aws-sdk/utilities/response.class.php
new file mode 100644
index 00000000000..740d55d5d94
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/response.class.php
@@ -0,0 +1,29 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Wraps the underlying `ResponseCore` class with some AWS-specific customizations.
+ *
+ * @version 2010.10.11
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFResponse extends ResponseCore {}
diff --git a/3rdparty/aws-sdk/utilities/simplexml.class.php b/3rdparty/aws-sdk/utilities/simplexml.class.php
new file mode 100644
index 00000000000..ba93b9ea3c0
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/simplexml.class.php
@@ -0,0 +1,248 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Wraps the underlying `SimpleXMLIterator` class with enhancements for rapidly traversing the DOM tree,
+ * converting types, and comparisons.
+ *
+ * @version 2012.01.17
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ * @link http://php.net/SimpleXML SimpleXML
+ */
+class CFSimpleXML extends SimpleXMLIterator
+{
+ /**
+ * Stores the namespace name to use in XPath queries.
+ */
+ public $xml_ns;
+
+ /**
+ * Stores the namespace URI to use in XPath queries.
+ */
+ public $xml_ns_url;
+
+ /**
+ * Catches requests made to methods that don't exist. Specifically, looks for child nodes via XPath.
+ *
+ * @param string $name (Required) The name of the method.
+ * @param array $arguments (Required) The arguments passed to the method.
+ * @return mixed Either an array of matches, or a single <CFSimpleXML> element.
+ */
+ public function __call($name, $arguments)
+ {
+ // Remap $this
+ $self = $this;
+
+ // Re-base the XML
+ $self = new CFSimpleXML($self->asXML());
+
+ // Determine XPath query
+ $self->xpath_expression = 'descendant-or-self::' . $name;
+
+ // Get the results and augment with CFArray
+ $results = $self->xpath($self->xpath_expression);
+ if (!count($results)) return false;
+ $results = new CFArray($results);
+
+ // If an integer was passed, return only that result
+ if (isset($arguments[0]) && is_int($arguments[0]))
+ {
+ if (isset($results[$arguments[0]]))
+ {
+ return $results[$arguments[0]];
+ }
+
+ return false;
+ }
+
+ return $results;
+ }
+
+ /**
+ * Alternate approach to constructing a new instance. Supports chaining.
+ *
+ * @param string $data (Required) A well-formed XML string or the path or URL to an XML document if $data_is_url is <code>true</code>.
+ * @param integer $options (Optional) Used to specify additional LibXML parameters. The default value is <code>0</code>.
+ * @param boolean $data_is_url (Optional) Specify a value of <code>true</code> to specify that data is a path or URL to an XML document instead of string data. The default value is <code>false</code>.
+ * @param string $ns (Optional) The XML namespace to return values for.
+ * @param boolean $is_prefix (Optional) (No description provided by PHP.net.)
+ * @return CFSimpleXML Creates a new <CFSimpleXML> element.
+ */
+ public static function init($data, $options = 0, $data_is_url, $ns, $is_prefix = false)
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '<'))
+ {
+ throw new Exception('PHP 5.3 or newer is required to instantiate a new class with CLASS::init().');
+ }
+
+ $self = get_called_class();
+ return new $self($data, $options, $data_is_url, $ns, $is_prefix);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // TRAVERSAL
+
+ /**
+ * Wraps the results of an XPath query in a <CFArray> object.
+ *
+ * @param string $expr (Required) The XPath expression to use to query the XML response.
+ * @return CFArray A <CFArray> object containing the results of the XPath query.
+ */
+ public function query($expr)
+ {
+ return new CFArray($this->xpath($expr));
+ }
+
+ /**
+ * Gets the parent or a preferred ancestor of the current element.
+ *
+ * @param string $node (Optional) Name of the ancestor element to match and return.
+ * @return CFSimpleXML A <CFSimpleXML> object containing the requested node.
+ */
+ public function parent($node = null)
+ {
+ if ($node)
+ {
+ $parents = $this->xpath('ancestor-or-self::' . $node);
+ }
+ else
+ {
+ $parents = $this->xpath('parent::*');
+ }
+
+ return $parents[0];
+ }
+
+
+ /*%******************************************************************************************%*/
+ // ALTERNATE FORMATS
+
+ /**
+ * Gets the current XML node as a true string.
+ *
+ * @return string The current XML node as a true string.
+ */
+ public function to_string()
+ {
+ return (string) $this;
+ }
+
+ /**
+ * Gets the current XML node as <CFArray>, a child class of PHP's <php:ArrayObject> class.
+ *
+ * @return CFArray The current XML node as a <CFArray> object.
+ */
+ public function to_array()
+ {
+ return new CFArray(json_decode(json_encode($this), true));
+ }
+
+ /**
+ * Gets the current XML node as a stdClass object.
+ *
+ * @return array The current XML node as a stdClass object.
+ */
+ public function to_stdClass()
+ {
+ return json_decode(json_encode($this));
+ }
+
+ /**
+ * Gets the current XML node as a JSON string.
+ *
+ * @return string The current XML node as a JSON string.
+ */
+ public function to_json()
+ {
+ return json_encode($this);
+ }
+
+ /**
+ * Gets the current XML node as a YAML string.
+ *
+ * @return string The current XML node as a YAML string.
+ */
+ public function to_yaml()
+ {
+ return sfYaml::dump(json_decode(json_encode($this), true), 5);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // COMPARISONS
+
+ /**
+ * Whether or not the current node exactly matches the compared value.
+ *
+ * @param string $value (Required) The value to compare the current node to.
+ * @return boolean Whether or not the current node exactly matches the compared value.
+ */
+ public function is($value)
+ {
+ return ((string) $this === $value);
+ }
+
+ /**
+ * Whether or not the current node contains the compared value.
+ *
+ * @param string $value (Required) The value to use to determine whether it is contained within the node.
+ * @return boolean Whether or not the current node contains the compared value.
+ */
+ public function contains($value)
+ {
+ return (stripos((string) $this, $value) !== false);
+ }
+
+ /**
+ * Whether or not the current node matches the regular expression pattern.
+ *
+ * @param string $pattern (Required) The pattern to match the current node against.
+ * @return boolean Whether or not the current node matches the pattern.
+ */
+ public function matches($pattern)
+ {
+ return (bool) preg_match($pattern, (string) $this);
+ }
+
+ /**
+ * Whether or not the current node starts with the compared value.
+ *
+ * @param string $value (Required) The value to compare the current node to.
+ * @return boolean Whether or not the current node starts with the compared value.
+ */
+ public function starts_with($value)
+ {
+ return $this->matches("@^$value@u");
+ }
+
+ /**
+ * Whether or not the current node ends with the compared value.
+ *
+ * @param string $value (Required) The value to compare the current node to.
+ * @return boolean Whether or not the current node ends with the compared value.
+ */
+ public function ends_with($value)
+ {
+ return $this->matches("@$value$@u");
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/stacktemplate.class.php b/3rdparty/aws-sdk/utilities/stacktemplate.class.php
new file mode 100644
index 00000000000..1e29ef34036
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/stacktemplate.class.php
@@ -0,0 +1,52 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Simplifies the process of preparing JSON stack templates.
+ *
+ * @version 2011.02.03
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFStackTemplate
+{
+ /**
+ * Removes whitespace from a JSON template.
+ *
+ * @param string $template (Required) A JSON representation of the stack template. Must have <a href="http://docs.php.net/manual/en/function.json-decode.php#refsect1-function.json-decode-examples">strict JSON-specific formatting</a>.
+ * @return string A JSON representation of the template.
+ */
+ public static function json($template)
+ {
+ return json_encode(json_decode($template, true));
+ }
+
+ /**
+ * Converts an associative array (map) of the template into a JSON string.
+ *
+ * @param array $template (Required) An associative array that maps directly to its JSON counterpart.
+ * @return string A JSON representation of the template.
+ */
+ public static function map($template)
+ {
+ return json_encode($template);
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/stepconfig.class.php b/3rdparty/aws-sdk/utilities/stepconfig.class.php
new file mode 100644
index 00000000000..71492995f44
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/stepconfig.class.php
@@ -0,0 +1,91 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Contains functionality for simplifying Amazon EMR Hadoop steps.
+ *
+ * @version 2010.11.16
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFStepConfig
+{
+
+ /**
+ * Stores the configuration map.
+ */
+ public $config;
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param array $config (Required) An associative array representing the Hadoop step configuration.
+ * @return $this A reference to the current instance.
+ */
+ public function __construct($config)
+ {
+ // Handle Hadoop jar arguments
+ if (isset($config['HadoopJarStep']['Args']) && $args = $config['HadoopJarStep']['Args'])
+ {
+ $config['HadoopJarStep']['Args'] = is_array($args) ? $args : array($args);
+ }
+
+ $this->config = $config;
+ }
+
+ /**
+ * Constructs a new instance of this class, and allows chaining.
+ *
+ * @param array $config (Required) An associative array representing the Hadoop step configuration.
+ * @return $this A reference to the current instance.
+ */
+ public static function init($config)
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '<'))
+ {
+ throw new Exception('PHP 5.3 or newer is required to instantiate a new class with CLASS::init().');
+ }
+
+ $self = get_called_class();
+ return new $self($config);
+ }
+
+ /**
+ * Returns a JSON representation of the object when typecast as a string.
+ *
+ * @return string A JSON representation of the object.
+ * @link http://www.php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring PHP Magic Methods
+ */
+ public function __toString()
+ {
+ return json_encode($this->config);
+ }
+
+ /**
+ * Returns the configuration data.
+ *
+ * @return array The configuration data.
+ */
+ public function get_config()
+ {
+ return $this->config;
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/utilities.class.php b/3rdparty/aws-sdk/utilities/utilities.class.php
new file mode 100755
index 00000000000..d4d1120abff
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/utilities.class.php
@@ -0,0 +1,399 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Contains a set of utility methods for connecting to, and working with, AWS.
+ *
+ * @version 2010.09.30
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFUtilities
+{
+
+ /*%******************************************************************************************%*/
+ // CONSTANTS
+
+ /**
+ * Define the RFC 2616-compliant date format.
+ */
+ const DATE_FORMAT_RFC2616 = 'D, d M Y H:i:s \G\M\T';
+
+ /**
+ * Define the ISO-8601-compliant date format.
+ */
+ const DATE_FORMAT_ISO8601 = 'Y-m-d\TH:i:s\Z';
+
+ /**
+ * Define the MySQL-compliant date format.
+ */
+ const DATE_FORMAT_MYSQL = 'Y-m-d H:i:s';
+
+ /**
+ * Define the Signature v4 date format.
+ */
+ const DATE_FORMAT_SIGV4 = 'Ymd\THis\Z';
+
+
+ /*%******************************************************************************************%*/
+ // METHODS
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @return $this A reference to the current instance.
+ */
+ public function __construct()
+ {
+ return $this;
+ }
+
+ /**
+ * Retrieves the value of a class constant, while avoiding the `T_PAAMAYIM_NEKUDOTAYIM` error. Misspelled because `const` is a reserved word.
+ *
+ * @param object $class (Required) An instance of the class containing the constant.
+ * @param string $const (Required) The name of the constant to retrieve.
+ * @return mixed The value of the class constant.
+ */
+ public function konst($class, $const)
+ {
+ if (is_string($class))
+ {
+ $ref = new ReflectionClass($class);
+ }
+ else
+ {
+ $ref = new ReflectionObject($class);
+ }
+
+ return $ref->getConstant($const);
+ }
+
+ /**
+ * Convert a HEX value to Base64.
+ *
+ * @param string $str (Required) Value to convert.
+ * @return string Base64-encoded string.
+ */
+ public function hex_to_base64($str)
+ {
+ $raw = '';
+
+ for ($i = 0; $i < strlen($str); $i += 2)
+ {
+ $raw .= chr(hexdec(substr($str, $i, 2)));
+ }
+
+ return base64_encode($raw);
+ }
+
+ /**
+ * Convert an associative array into a query string.
+ *
+ * @param array $array (Required) Array to convert.
+ * @return string URL-friendly query string.
+ */
+ public function to_query_string($array)
+ {
+ $temp = array();
+
+ foreach ($array as $key => $value)
+ {
+ if (is_string($key) && !is_array($value))
+ {
+ $temp[] = rawurlencode($key) . '=' . rawurlencode($value);
+ }
+ }
+
+ return implode('&', $temp);
+ }
+
+ /**
+ * Convert an associative array into a sign-able string.
+ *
+ * @param array $array (Required) Array to convert.
+ * @return string URL-friendly sign-able string.
+ */
+ public function to_signable_string($array)
+ {
+ $t = array();
+
+ foreach ($array as $k => $v)
+ {
+ $t[] = $this->encode_signature2($k) . '=' . $this->encode_signature2($v);
+ }
+
+ return implode('&', $t);
+ }
+
+ /**
+ * Encode the value according to RFC 3986.
+ *
+ * @param string $string (Required) String to convert.
+ * @return string URL-friendly sign-able string.
+ */
+ public function encode_signature2($string)
+ {
+ $string = rawurlencode($string);
+ return str_replace('%7E', '~', $string);
+ }
+
+ /**
+ * Convert a query string into an associative array. Multiple, identical keys will become an indexed array.
+ *
+ * @param string $qs (Required) Query string to convert.
+ * @return array Associative array of keys and values.
+ */
+ public function query_to_array($qs)
+ {
+ $query = explode('&', $qs);
+ $data = array();
+
+ foreach ($query as $q)
+ {
+ $q = explode('=', $q);
+
+ if (isset($data[$q[0]]) && is_array($data[$q[0]]))
+ {
+ $data[$q[0]][] = urldecode($q[1]);
+ }
+ else if (isset($data[$q[0]]) && !is_array($data[$q[0]]))
+ {
+ $data[$q[0]] = array($data[$q[0]]);
+ $data[$q[0]][] = urldecode($q[1]);
+ }
+ else
+ {
+ $data[urldecode($q[0])] = urldecode($q[1]);
+ }
+ }
+ return $data;
+ }
+
+ /**
+ * Return human readable file sizes.
+ *
+ * @author Aidan Lister <aidan@php.net>
+ * @author Ryan Parman <ryan@getcloudfusion.com>
+ * @license http://www.php.net/license/3_01.txt PHP License
+ * @param integer $size (Required) Filesize in bytes.
+ * @param string $unit (Optional) The maximum unit to use. Defaults to the largest appropriate unit.
+ * @param string $default (Optional) The format for the return string. Defaults to `%01.2f %s`.
+ * @return string The human-readable file size.
+ * @link http://aidanlister.com/repos/v/function.size_readable.php Original Function
+ */
+ public function size_readable($size, $unit = null, $default = null)
+ {
+ // Units
+ $sizes = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB');
+ $mod = 1024;
+ $ii = count($sizes) - 1;
+
+ // Max unit
+ $unit = array_search((string) $unit, $sizes);
+ if ($unit === null || $unit === false)
+ {
+ $unit = $ii;
+ }
+
+ // Return string
+ if ($default === null)
+ {
+ $default = '%01.2f %s';
+ }
+
+ // Loop
+ $i = 0;
+ while ($unit != $i && $size >= 1024 && $i < $ii)
+ {
+ $size /= $mod;
+ $i++;
+ }
+
+ return sprintf($default, $size, $sizes[$i]);
+ }
+
+ /**
+ * Convert a number of seconds into Hours:Minutes:Seconds.
+ *
+ * @param integer $seconds (Required) The number of seconds to convert.
+ * @return string The formatted time.
+ */
+ public function time_hms($seconds)
+ {
+ $time = '';
+
+ // First pass
+ $hours = (int) ($seconds / 3600);
+ $seconds = $seconds % 3600;
+ $minutes = (int) ($seconds / 60);
+ $seconds = $seconds % 60;
+
+ // Cleanup
+ $time .= ($hours) ? $hours . ':' : '';
+ $time .= ($minutes < 10 && $hours > 0) ? '0' . $minutes : $minutes;
+ $time .= ':';
+ $time .= ($seconds < 10) ? '0' . $seconds : $seconds;
+
+ return $time;
+ }
+
+ /**
+ * Returns the first value that is set. Based on [Try.these()](http://api.prototypejs.org/language/Try/these/) from [Prototype](http://prototypejs.org).
+ *
+ * @param array $attrs (Required) The attributes to test, as strings. Intended for testing properties of the $base object, but also works with variables if you place an @ symbol at the beginning of the command.
+ * @param object $base (Optional) The base object to use, if any.
+ * @param mixed $default (Optional) What to return if there are no matches. Defaults to `null`.
+ * @return mixed Either a matching property of a given object, boolean `false`, or any other data type you might choose.
+ */
+ public function try_these($attrs, $base = null, $default = null)
+ {
+ if ($base)
+ {
+ foreach ($attrs as $attr)
+ {
+ if (isset($base->$attr))
+ {
+ return $base->$attr;
+ }
+ }
+ }
+ else
+ {
+ foreach ($attrs as $attr)
+ {
+ if (isset($attr))
+ {
+ return $attr;
+ }
+ }
+ }
+
+ return $default;
+ }
+
+ /**
+ * Can be removed once all calls are updated.
+ *
+ * @deprecated Use <php:json_encode()> instead.
+ * @param mixed $obj (Required) The PHP object to convert into a JSON string.
+ * @return string A JSON string.
+ */
+ public function json_encode($obj)
+ {
+ return json_encode($obj);
+ }
+
+ /**
+ * Converts a SimpleXML response to an array structure.
+ *
+ * @param ResponseCore $response (Required) A response value.
+ * @return array The response value as a standard, multi-dimensional array.
+ */
+ public function convert_response_to_array(ResponseCore $response)
+ {
+ return json_decode(json_encode($response), true);
+ }
+
+ /**
+ * Checks to see if a date stamp is ISO-8601 formatted, and if not, makes it so.
+ *
+ * @param string $datestamp (Required) A date stamp, or a string that can be parsed into a date stamp.
+ * @return string An ISO-8601 formatted date stamp.
+ */
+ public function convert_date_to_iso8601($datestamp)
+ {
+ if (!preg_match('/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}((\+|-)\d{2}:\d{2}|Z)/m', $datestamp))
+ {
+ return gmdate(self::DATE_FORMAT_ISO8601, strtotime($datestamp));
+ }
+
+ return $datestamp;
+ }
+
+ /**
+ * Determines whether the data is Base64 encoded or not.
+ *
+ * @license http://us.php.net/manual/en/function.base64-decode.php#81425 PHP License
+ * @param string $s (Required) The string to test.
+ * @return boolean Whether the string is Base64 encoded or not.
+ */
+ public function is_base64($s)
+ {
+ return (bool) preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $s);
+ }
+
+ /**
+ * Determines whether the data is a JSON string or not.
+ *
+ * @param string $s (Required) The string to test.
+ * @return boolean Whether the string is a valid JSON object or not.
+ */
+ public function is_json($s)
+ {
+ return !!(json_decode($s) instanceof stdClass);
+ }
+
+ /**
+ * Decodes `\uXXXX` entities into their real unicode character equivalents.
+ *
+ * @param string $s (Required) The string to decode.
+ * @return string The decoded string.
+ */
+ public function decode_uhex($s)
+ {
+ preg_match_all('/\\\u([0-9a-f]{4})/i', $s, $matches);
+ $matches = $matches[count($matches) - 1];
+ $map = array();
+
+ foreach ($matches as $match)
+ {
+ if (!isset($map[$match]))
+ {
+ $map['\u' . $match] = html_entity_decode('&#' . hexdec($match) . ';', ENT_NOQUOTES, 'UTF-8');
+ }
+ }
+
+ return str_replace(array_keys($map), $map, $s);
+ }
+
+ /**
+ * Generates a random GUID.
+ *
+ * @author Alix Axel <http://www.php.net/manual/en/function.com-create-guid.php#99425>
+ * @license http://www.php.net/license/3_01.txt PHP License
+ * @return string A random GUID.
+ */
+ public function generate_guid()
+ {
+ return sprintf(
+ '%04X%04X-%04X-%04X-%04X-%04X%04X%04X',
+ mt_rand(0, 65535),
+ mt_rand(0, 65535),
+ mt_rand(0, 65535),
+ mt_rand(16384, 20479),
+ mt_rand(32768, 49151),
+ mt_rand(0, 65535),
+ mt_rand(0, 65535),
+ mt_rand(0, 65535)
+ );
+ }
+}
diff --git a/3rdparty/mediawiki/CSSMin.php b/3rdparty/mediawiki/CSSMin.php
new file mode 100644
index 00000000000..e9c2badf62b
--- /dev/null
+++ b/3rdparty/mediawiki/CSSMin.php
@@ -0,0 +1,228 @@
+<?php
+/**
+ * Minification of CSS stylesheets.
+ *
+ * Copyright 2010 Wikimedia Foundation
+ *
+ * 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.
+ *
+ * @file
+ * @version 0.1.1 -- 2010-09-11
+ * @author Trevor Parscal <tparscal@wikimedia.org>
+ * @copyright Copyright 2010 Wikimedia Foundation
+ * @license http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+/**
+ * Transforms CSS data
+ *
+ * This class provides minification, URL remapping, URL extracting, and data-URL embedding.
+ */
+class CSSMin {
+
+ /* Constants */
+
+ /**
+ * Maximum file size to still qualify for in-line embedding as a data-URI
+ *
+ * 24,576 is used because Internet Explorer has a 32,768 byte limit for data URIs,
+ * which when base64 encoded will result in a 1/3 increase in size.
+ */
+ const EMBED_SIZE_LIMIT = 24576;
+ const URL_REGEX = 'url\(\s*[\'"]?(?P<file>[^\?\)\'"]*)(?P<query>\??[^\)\'"]*)[\'"]?\s*\)';
+
+ /* Protected Static Members */
+
+ /** @var array List of common image files extensions and mime-types */
+ protected static $mimeTypes = array(
+ 'gif' => 'image/gif',
+ 'jpe' => 'image/jpeg',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'png' => 'image/png',
+ 'tif' => 'image/tiff',
+ 'tiff' => 'image/tiff',
+ 'xbm' => 'image/x-xbitmap',
+ );
+
+ /* Static Methods */
+
+ /**
+ * Gets a list of local file paths which are referenced in a CSS style sheet
+ *
+ * @param $source string CSS data to remap
+ * @param $path string File path where the source was read from (optional)
+ * @return array List of local file references
+ */
+ public static function getLocalFileReferences( $source, $path = null ) {
+ $files = array();
+ $rFlags = PREG_OFFSET_CAPTURE | PREG_SET_ORDER;
+ if ( preg_match_all( '/' . self::URL_REGEX . '/', $source, $matches, $rFlags ) ) {
+ foreach ( $matches as $match ) {
+ $file = ( isset( $path )
+ ? rtrim( $path, '/' ) . '/'
+ : '' ) . "{$match['file'][0]}";
+
+ // Only proceed if we can access the file
+ if ( !is_null( $path ) && file_exists( $file ) ) {
+ $files[] = $file;
+ }
+ }
+ }
+ return $files;
+ }
+
+ /**
+ * @param $file string
+ * @return bool|string
+ */
+ protected static function getMimeType( $file ) {
+ $realpath = realpath( $file );
+ // Try a couple of different ways to get the mime-type of a file, in order of
+ // preference
+ if (
+ $realpath
+ && function_exists( 'finfo_file' )
+ && function_exists( 'finfo_open' )
+ && defined( 'FILEINFO_MIME_TYPE' )
+ ) {
+ // As of PHP 5.3, this is how you get the mime-type of a file; it uses the Fileinfo
+ // PECL extension
+ return finfo_file( finfo_open( FILEINFO_MIME_TYPE ), $realpath );
+ } elseif ( function_exists( 'mime_content_type' ) ) {
+ // Before this was deprecated in PHP 5.3, this was how you got the mime-type of a file
+ return mime_content_type( $file );
+ } else {
+ // Worst-case scenario has happened, use the file extension to infer the mime-type
+ $ext = strtolower( pathinfo( $file, PATHINFO_EXTENSION ) );
+ if ( isset( self::$mimeTypes[$ext] ) ) {
+ return self::$mimeTypes[$ext];
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Remaps CSS URL paths and automatically embeds data URIs for URL rules
+ * preceded by an /* @embed * / comment
+ *
+ * @param $source string CSS data to remap
+ * @param $local string File path where the source was read from
+ * @param $remote string URL path to the file
+ * @param $embedData bool If false, never do any data URI embedding, even if / * @embed * / is found
+ * @return string Remapped CSS data
+ */
+ public static function remap( $source, $local, $remote, $embedData = true ) {
+ $pattern = '/((?P<embed>\s*\/\*\s*\@embed\s*\*\/)(?P<pre>[^\;\}]*))?' .
+ self::URL_REGEX . '(?P<post>[^;]*)[\;]?/';
+ $offset = 0;
+ while ( preg_match( $pattern, $source, $match, PREG_OFFSET_CAPTURE, $offset ) ) {
+ // Skip fully-qualified URLs and data URIs
+ $urlScheme = parse_url( $match['file'][0], PHP_URL_SCHEME );
+ if ( $urlScheme ) {
+ // Move the offset to the end of the match, leaving it alone
+ $offset = $match[0][1] + strlen( $match[0][0] );
+ continue;
+ }
+ // URLs with absolute paths like /w/index.php need to be expanded
+ // to absolute URLs but otherwise left alone
+ if ( $match['file'][0] !== '' && $match['file'][0][0] === '/' ) {
+ // Replace the file path with an expanded (possibly protocol-relative) URL
+ // ...but only if wfExpandUrl() is even available.
+ // This will not be the case if we're running outside of MW
+ $lengthIncrease = 0;
+ if ( function_exists( 'wfExpandUrl' ) ) {
+ $expanded = wfExpandUrl( $match['file'][0], PROTO_RELATIVE );
+ $origLength = strlen( $match['file'][0] );
+ $lengthIncrease = strlen( $expanded ) - $origLength;
+ $source = substr_replace( $source, $expanded,
+ $match['file'][1], $origLength
+ );
+ }
+ // Move the offset to the end of the match, leaving it alone
+ $offset = $match[0][1] + strlen( $match[0][0] ) + $lengthIncrease;
+ continue;
+ }
+ // Shortcuts
+ $embed = $match['embed'][0];
+ $pre = $match['pre'][0];
+ $post = $match['post'][0];
+ $query = $match['query'][0];
+ $url = "{$remote}/{$match['file'][0]}";
+ $file = "{$local}/{$match['file'][0]}";
+ // bug 27052 - Guard against double slashes, because foo//../bar
+ // apparently resolves to foo/bar on (some?) clients
+ $url = preg_replace( '#([^:])//+#', '\1/', $url );
+ $replacement = false;
+ if ( $local !== false && file_exists( $file ) ) {
+ // Add version parameter as a time-stamp in ISO 8601 format,
+ // using Z for the timezone, meaning GMT
+ $url .= '?' . gmdate( 'Y-m-d\TH:i:s\Z', round( filemtime( $file ), -2 ) );
+ // Embedding requires a bit of extra processing, so let's skip that if we can
+ if ( $embedData && $embed ) {
+ $type = self::getMimeType( $file );
+ // Detect when URLs were preceeded with embed tags, and also verify file size is
+ // below the limit
+ if (
+ $type
+ && $match['embed'][1] > 0
+ && filesize( $file ) < self::EMBED_SIZE_LIMIT
+ ) {
+ // Strip off any trailing = symbols (makes browsers freak out)
+ $data = base64_encode( file_get_contents( $file ) );
+ // Build 2 CSS properties; one which uses a base64 encoded data URI in place
+ // of the @embed comment to try and retain line-number integrity, and the
+ // other with a remapped an versioned URL and an Internet Explorer hack
+ // making it ignored in all browsers that support data URIs
+ $replacement = "{$pre}url(data:{$type};base64,{$data}){$post};";
+ $replacement .= "{$pre}url({$url}){$post}!ie;";
+ }
+ }
+ if ( $replacement === false ) {
+ // Assume that all paths are relative to $remote, and make them absolute
+ $replacement = "{$embed}{$pre}url({$url}){$post};";
+ }
+ } elseif ( $local === false ) {
+ // Assume that all paths are relative to $remote, and make them absolute
+ $replacement = "{$embed}{$pre}url({$url}{$query}){$post};";
+ }
+ if ( $replacement !== false ) {
+ // Perform replacement on the source
+ $source = substr_replace(
+ $source, $replacement, $match[0][1], strlen( $match[0][0] )
+ );
+ // Move the offset to the end of the replacement in the source
+ $offset = $match[0][1] + strlen( $replacement );
+ continue;
+ }
+ // Move the offset to the end of the match, leaving it alone
+ $offset = $match[0][1] + strlen( $match[0][0] );
+ }
+ return $source;
+ }
+
+ /**
+ * Removes whitespace from CSS data
+ *
+ * @param $css string CSS data to minify
+ * @return string Minified CSS data
+ */
+ public static function minify( $css ) {
+ return trim(
+ str_replace(
+ array( '; ', ': ', ' {', '{ ', ', ', '} ', ';}' ),
+ array( ';', ':', '{', '{', ',', '}', '}' ),
+ preg_replace( array( '/\s+/', '/\/\*.*?\*\//s' ), array( ' ', '' ), $css )
+ )
+ );
+ }
+}
diff --git a/3rdparty/mediawiki/JavaScriptMinifier.php b/3rdparty/mediawiki/JavaScriptMinifier.php
new file mode 100644
index 00000000000..db5326c7cfb
--- /dev/null
+++ b/3rdparty/mediawiki/JavaScriptMinifier.php
@@ -0,0 +1,606 @@
+<?php
+/**
+ * JavaScript Minifier
+ *
+ * @file
+ * @author Paul Copperman <paul.copperman@gmail.com>
+ * @license Choose any of Apache, MIT, GPL, LGPL
+ */
+
+/**
+ * This class is meant to safely minify javascript code, while leaving syntactically correct
+ * programs intact. Other libraries, such as JSMin require a certain coding style to work
+ * correctly. OTOH, libraries like jsminplus, that do parse the code correctly are rather
+ * slow, because they construct a complete parse tree before outputting the code minified.
+ * So this class is meant to allow arbitrary (but syntactically correct) input, while being
+ * fast enough to be used for on-the-fly minifying.
+ */
+class JavaScriptMinifier {
+
+ /* Class constants */
+ /* Parsing states.
+ * The state machine is only necessary to decide whether to parse a slash as division
+ * operator or as regexp literal.
+ * States are named after the next expected item. We only distinguish states when the
+ * distinction is relevant for our purpose.
+ */
+ const STATEMENT = 0;
+ const CONDITION = 1;
+ const PROPERTY_ASSIGNMENT = 2;
+ const EXPRESSION = 3;
+ const EXPRESSION_NO_NL = 4; // only relevant for semicolon insertion
+ const EXPRESSION_OP = 5;
+ const EXPRESSION_FUNC = 6;
+ const EXPRESSION_TERNARY = 7; // used to determine the role of a colon
+ const EXPRESSION_TERNARY_OP = 8;
+ const EXPRESSION_TERNARY_FUNC = 9;
+ const PAREN_EXPRESSION = 10; // expression which is not on the top level
+ const PAREN_EXPRESSION_OP = 11;
+ const PAREN_EXPRESSION_FUNC = 12;
+ const PROPERTY_EXPRESSION = 13; // expression which is within an object literal
+ const PROPERTY_EXPRESSION_OP = 14;
+ const PROPERTY_EXPRESSION_FUNC = 15;
+
+ /* Token types */
+ const TYPE_UN_OP = 1; // unary operators
+ const TYPE_INCR_OP = 2; // ++ and --
+ const TYPE_BIN_OP = 3; // binary operators
+ const TYPE_ADD_OP = 4; // + and - which can be either unary or binary ops
+ const TYPE_HOOK = 5; // ?
+ const TYPE_COLON = 6; // :
+ const TYPE_COMMA = 7; // ,
+ const TYPE_SEMICOLON = 8; // ;
+ const TYPE_BRACE_OPEN = 9; // {
+ const TYPE_BRACE_CLOSE = 10; // }
+ const TYPE_PAREN_OPEN = 11; // ( and [
+ const TYPE_PAREN_CLOSE = 12; // ) and ]
+ const TYPE_RETURN = 13; // keywords: break, continue, return, throw
+ const TYPE_IF = 14; // keywords: catch, for, with, switch, while, if
+ const TYPE_DO = 15; // keywords: case, var, finally, else, do, try
+ const TYPE_FUNC = 16; // keywords: function
+ const TYPE_LITERAL = 17; // all literals, identifiers and unrecognised tokens
+
+ // Sanity limit to avoid excessive memory usage
+ const STACK_LIMIT = 1000;
+
+ /* Static functions */
+
+ /**
+ * Returns minified JavaScript code.
+ *
+ * NOTE: $maxLineLength isn't a strict maximum. Longer lines will be produced when
+ * literals (e.g. quoted strings) longer than $maxLineLength are encountered
+ * or when required to guard against semicolon insertion.
+ *
+ * @param $s String JavaScript code to minify
+ * @param $statementsOnOwnLine Bool Whether to put each statement on its own line
+ * @param $maxLineLength Int Maximum length of a single line, or -1 for no maximum.
+ * @return String Minified code
+ */
+ public static function minify( $s, $statementsOnOwnLine = false, $maxLineLength = 1000 ) {
+ // First we declare a few tables that contain our parsing rules
+
+ // $opChars : characters, which can be combined without whitespace in between them
+ $opChars = array(
+ '!' => true,
+ '"' => true,
+ '%' => true,
+ '&' => true,
+ "'" => true,
+ '(' => true,
+ ')' => true,
+ '*' => true,
+ '+' => true,
+ ',' => true,
+ '-' => true,
+ '.' => true,
+ '/' => true,
+ ':' => true,
+ ';' => true,
+ '<' => true,
+ '=' => true,
+ '>' => true,
+ '?' => true,
+ '[' => true,
+ ']' => true,
+ '^' => true,
+ '{' => true,
+ '|' => true,
+ '}' => true,
+ '~' => true
+ );
+
+ // $tokenTypes : maps keywords and operators to their corresponding token type
+ $tokenTypes = array(
+ '!' => self::TYPE_UN_OP,
+ '~' => self::TYPE_UN_OP,
+ 'delete' => self::TYPE_UN_OP,
+ 'new' => self::TYPE_UN_OP,
+ 'typeof' => self::TYPE_UN_OP,
+ 'void' => self::TYPE_UN_OP,
+ '++' => self::TYPE_INCR_OP,
+ '--' => self::TYPE_INCR_OP,
+ '!=' => self::TYPE_BIN_OP,
+ '!==' => self::TYPE_BIN_OP,
+ '%' => self::TYPE_BIN_OP,
+ '%=' => self::TYPE_BIN_OP,
+ '&' => self::TYPE_BIN_OP,
+ '&&' => self::TYPE_BIN_OP,
+ '&=' => self::TYPE_BIN_OP,
+ '*' => self::TYPE_BIN_OP,
+ '*=' => self::TYPE_BIN_OP,
+ '+=' => self::TYPE_BIN_OP,
+ '-=' => self::TYPE_BIN_OP,
+ '.' => self::TYPE_BIN_OP,
+ '/' => self::TYPE_BIN_OP,
+ '/=' => self::TYPE_BIN_OP,
+ '<' => self::TYPE_BIN_OP,
+ '<<' => self::TYPE_BIN_OP,
+ '<<=' => self::TYPE_BIN_OP,
+ '<=' => self::TYPE_BIN_OP,
+ '=' => self::TYPE_BIN_OP,
+ '==' => self::TYPE_BIN_OP,
+ '===' => self::TYPE_BIN_OP,
+ '>' => self::TYPE_BIN_OP,
+ '>=' => self::TYPE_BIN_OP,
+ '>>' => self::TYPE_BIN_OP,
+ '>>=' => self::TYPE_BIN_OP,
+ '>>>' => self::TYPE_BIN_OP,
+ '>>>=' => self::TYPE_BIN_OP,
+ '^' => self::TYPE_BIN_OP,
+ '^=' => self::TYPE_BIN_OP,
+ '|' => self::TYPE_BIN_OP,
+ '|=' => self::TYPE_BIN_OP,
+ '||' => self::TYPE_BIN_OP,
+ 'in' => self::TYPE_BIN_OP,
+ 'instanceof' => self::TYPE_BIN_OP,
+ '+' => self::TYPE_ADD_OP,
+ '-' => self::TYPE_ADD_OP,
+ '?' => self::TYPE_HOOK,
+ ':' => self::TYPE_COLON,
+ ',' => self::TYPE_COMMA,
+ ';' => self::TYPE_SEMICOLON,
+ '{' => self::TYPE_BRACE_OPEN,
+ '}' => self::TYPE_BRACE_CLOSE,
+ '(' => self::TYPE_PAREN_OPEN,
+ '[' => self::TYPE_PAREN_OPEN,
+ ')' => self::TYPE_PAREN_CLOSE,
+ ']' => self::TYPE_PAREN_CLOSE,
+ 'break' => self::TYPE_RETURN,
+ 'continue' => self::TYPE_RETURN,
+ 'return' => self::TYPE_RETURN,
+ 'throw' => self::TYPE_RETURN,
+ 'catch' => self::TYPE_IF,
+ 'for' => self::TYPE_IF,
+ 'if' => self::TYPE_IF,
+ 'switch' => self::TYPE_IF,
+ 'while' => self::TYPE_IF,
+ 'with' => self::TYPE_IF,
+ 'case' => self::TYPE_DO,
+ 'do' => self::TYPE_DO,
+ 'else' => self::TYPE_DO,
+ 'finally' => self::TYPE_DO,
+ 'try' => self::TYPE_DO,
+ 'var' => self::TYPE_DO,
+ 'function' => self::TYPE_FUNC
+ );
+
+ // $goto : This is the main table for our state machine. For every state/token pair
+ // the following state is defined. When no rule exists for a given pair,
+ // the state is left unchanged.
+ $goto = array(
+ self::STATEMENT => array(
+ self::TYPE_UN_OP => self::EXPRESSION,
+ self::TYPE_INCR_OP => self::EXPRESSION,
+ self::TYPE_ADD_OP => self::EXPRESSION,
+ self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
+ self::TYPE_RETURN => self::EXPRESSION_NO_NL,
+ self::TYPE_IF => self::CONDITION,
+ self::TYPE_FUNC => self::CONDITION,
+ self::TYPE_LITERAL => self::EXPRESSION_OP
+ ),
+ self::CONDITION => array(
+ self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
+ ),
+ self::PROPERTY_ASSIGNMENT => array(
+ self::TYPE_COLON => self::PROPERTY_EXPRESSION,
+ self::TYPE_BRACE_OPEN => self::STATEMENT
+ ),
+ self::EXPRESSION => array(
+ self::TYPE_SEMICOLON => self::STATEMENT,
+ self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
+ self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
+ self::TYPE_FUNC => self::EXPRESSION_FUNC,
+ self::TYPE_LITERAL => self::EXPRESSION_OP
+ ),
+ self::EXPRESSION_NO_NL => array(
+ self::TYPE_SEMICOLON => self::STATEMENT,
+ self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
+ self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
+ self::TYPE_FUNC => self::EXPRESSION_FUNC,
+ self::TYPE_LITERAL => self::EXPRESSION_OP
+ ),
+ self::EXPRESSION_OP => array(
+ self::TYPE_BIN_OP => self::EXPRESSION,
+ self::TYPE_ADD_OP => self::EXPRESSION,
+ self::TYPE_HOOK => self::EXPRESSION_TERNARY,
+ self::TYPE_COLON => self::STATEMENT,
+ self::TYPE_COMMA => self::EXPRESSION,
+ self::TYPE_SEMICOLON => self::STATEMENT,
+ self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
+ ),
+ self::EXPRESSION_FUNC => array(
+ self::TYPE_BRACE_OPEN => self::STATEMENT
+ ),
+ self::EXPRESSION_TERNARY => array(
+ self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
+ self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
+ self::TYPE_FUNC => self::EXPRESSION_TERNARY_FUNC,
+ self::TYPE_LITERAL => self::EXPRESSION_TERNARY_OP
+ ),
+ self::EXPRESSION_TERNARY_OP => array(
+ self::TYPE_BIN_OP => self::EXPRESSION_TERNARY,
+ self::TYPE_ADD_OP => self::EXPRESSION_TERNARY,
+ self::TYPE_HOOK => self::EXPRESSION_TERNARY,
+ self::TYPE_COMMA => self::EXPRESSION_TERNARY,
+ self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
+ ),
+ self::EXPRESSION_TERNARY_FUNC => array(
+ self::TYPE_BRACE_OPEN => self::STATEMENT
+ ),
+ self::PAREN_EXPRESSION => array(
+ self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
+ self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
+ self::TYPE_FUNC => self::PAREN_EXPRESSION_FUNC,
+ self::TYPE_LITERAL => self::PAREN_EXPRESSION_OP
+ ),
+ self::PAREN_EXPRESSION_OP => array(
+ self::TYPE_BIN_OP => self::PAREN_EXPRESSION,
+ self::TYPE_ADD_OP => self::PAREN_EXPRESSION,
+ self::TYPE_HOOK => self::PAREN_EXPRESSION,
+ self::TYPE_COLON => self::PAREN_EXPRESSION,
+ self::TYPE_COMMA => self::PAREN_EXPRESSION,
+ self::TYPE_SEMICOLON => self::PAREN_EXPRESSION,
+ self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
+ ),
+ self::PAREN_EXPRESSION_FUNC => array(
+ self::TYPE_BRACE_OPEN => self::STATEMENT
+ ),
+ self::PROPERTY_EXPRESSION => array(
+ self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT,
+ self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION,
+ self::TYPE_FUNC => self::PROPERTY_EXPRESSION_FUNC,
+ self::TYPE_LITERAL => self::PROPERTY_EXPRESSION_OP
+ ),
+ self::PROPERTY_EXPRESSION_OP => array(
+ self::TYPE_BIN_OP => self::PROPERTY_EXPRESSION,
+ self::TYPE_ADD_OP => self::PROPERTY_EXPRESSION,
+ self::TYPE_HOOK => self::PROPERTY_EXPRESSION,
+ self::TYPE_COMMA => self::PROPERTY_ASSIGNMENT,
+ self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION
+ ),
+ self::PROPERTY_EXPRESSION_FUNC => array(
+ self::TYPE_BRACE_OPEN => self::STATEMENT
+ )
+ );
+
+ // $push : This table contains the rules for when to push a state onto the stack.
+ // The pushed state is the state to return to when the corresponding
+ // closing token is found
+ $push = array(
+ self::STATEMENT => array(
+ self::TYPE_BRACE_OPEN => self::STATEMENT,
+ self::TYPE_PAREN_OPEN => self::EXPRESSION_OP
+ ),
+ self::CONDITION => array(
+ self::TYPE_PAREN_OPEN => self::STATEMENT
+ ),
+ self::PROPERTY_ASSIGNMENT => array(
+ self::TYPE_BRACE_OPEN => self::PROPERTY_ASSIGNMENT
+ ),
+ self::EXPRESSION => array(
+ self::TYPE_BRACE_OPEN => self::EXPRESSION_OP,
+ self::TYPE_PAREN_OPEN => self::EXPRESSION_OP
+ ),
+ self::EXPRESSION_NO_NL => array(
+ self::TYPE_BRACE_OPEN => self::EXPRESSION_OP,
+ self::TYPE_PAREN_OPEN => self::EXPRESSION_OP
+ ),
+ self::EXPRESSION_OP => array(
+ self::TYPE_HOOK => self::EXPRESSION,
+ self::TYPE_PAREN_OPEN => self::EXPRESSION_OP
+ ),
+ self::EXPRESSION_FUNC => array(
+ self::TYPE_BRACE_OPEN => self::EXPRESSION_OP
+ ),
+ self::EXPRESSION_TERNARY => array(
+ self::TYPE_BRACE_OPEN => self::EXPRESSION_TERNARY_OP,
+ self::TYPE_PAREN_OPEN => self::EXPRESSION_TERNARY_OP
+ ),
+ self::EXPRESSION_TERNARY_OP => array(
+ self::TYPE_HOOK => self::EXPRESSION_TERNARY,
+ self::TYPE_PAREN_OPEN => self::EXPRESSION_TERNARY_OP
+ ),
+ self::EXPRESSION_TERNARY_FUNC => array(
+ self::TYPE_BRACE_OPEN => self::EXPRESSION_TERNARY_OP
+ ),
+ self::PAREN_EXPRESSION => array(
+ self::TYPE_BRACE_OPEN => self::PAREN_EXPRESSION_OP,
+ self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION_OP
+ ),
+ self::PAREN_EXPRESSION_OP => array(
+ self::TYPE_PAREN_OPEN => self::PAREN_EXPRESSION_OP
+ ),
+ self::PAREN_EXPRESSION_FUNC => array(
+ self::TYPE_BRACE_OPEN => self::PAREN_EXPRESSION_OP
+ ),
+ self::PROPERTY_EXPRESSION => array(
+ self::TYPE_BRACE_OPEN => self::PROPERTY_EXPRESSION_OP,
+ self::TYPE_PAREN_OPEN => self::PROPERTY_EXPRESSION_OP
+ ),
+ self::PROPERTY_EXPRESSION_OP => array(
+ self::TYPE_PAREN_OPEN => self::PROPERTY_EXPRESSION_OP
+ ),
+ self::PROPERTY_EXPRESSION_FUNC => array(
+ self::TYPE_BRACE_OPEN => self::PROPERTY_EXPRESSION_OP
+ )
+ );
+
+ // $pop : Rules for when to pop a state from the stack
+ $pop = array(
+ self::STATEMENT => array( self::TYPE_BRACE_CLOSE => true ),
+ self::PROPERTY_ASSIGNMENT => array( self::TYPE_BRACE_CLOSE => true ),
+ self::EXPRESSION => array( self::TYPE_BRACE_CLOSE => true ),
+ self::EXPRESSION_NO_NL => array( self::TYPE_BRACE_CLOSE => true ),
+ self::EXPRESSION_OP => array( self::TYPE_BRACE_CLOSE => true ),
+ self::EXPRESSION_TERNARY_OP => array( self::TYPE_COLON => true ),
+ self::PAREN_EXPRESSION => array( self::TYPE_PAREN_CLOSE => true ),
+ self::PAREN_EXPRESSION_OP => array( self::TYPE_PAREN_CLOSE => true ),
+ self::PROPERTY_EXPRESSION => array( self::TYPE_BRACE_CLOSE => true ),
+ self::PROPERTY_EXPRESSION_OP => array( self::TYPE_BRACE_CLOSE => true )
+ );
+
+ // $semicolon : Rules for when a semicolon insertion is appropriate
+ $semicolon = array(
+ self::EXPRESSION_NO_NL => array(
+ self::TYPE_UN_OP => true,
+ self::TYPE_INCR_OP => true,
+ self::TYPE_ADD_OP => true,
+ self::TYPE_BRACE_OPEN => true,
+ self::TYPE_PAREN_OPEN => true,
+ self::TYPE_RETURN => true,
+ self::TYPE_IF => true,
+ self::TYPE_DO => true,
+ self::TYPE_FUNC => true,
+ self::TYPE_LITERAL => true
+ ),
+ self::EXPRESSION_OP => array(
+ self::TYPE_UN_OP => true,
+ self::TYPE_INCR_OP => true,
+ self::TYPE_BRACE_OPEN => true,
+ self::TYPE_RETURN => true,
+ self::TYPE_IF => true,
+ self::TYPE_DO => true,
+ self::TYPE_FUNC => true,
+ self::TYPE_LITERAL => true
+ )
+ );
+
+ // Rules for when newlines should be inserted if
+ // $statementsOnOwnLine is enabled.
+ // $newlineBefore is checked before switching state,
+ // $newlineAfter is checked after
+ $newlineBefore = array(
+ self::STATEMENT => array(
+ self::TYPE_BRACE_CLOSE => true,
+ ),
+ );
+ $newlineAfter = array(
+ self::STATEMENT => array(
+ self::TYPE_BRACE_OPEN => true,
+ self::TYPE_PAREN_CLOSE => true,
+ self::TYPE_SEMICOLON => true,
+ ),
+ );
+
+ // $divStates : Contains all states that can be followed by a division operator
+ $divStates = array(
+ self::EXPRESSION_OP => true,
+ self::EXPRESSION_TERNARY_OP => true,
+ self::PAREN_EXPRESSION_OP => true,
+ self::PROPERTY_EXPRESSION_OP => true
+ );
+
+ // Here's where the minifying takes place: Loop through the input, looking for tokens
+ // and output them to $out, taking actions to the above defined rules when appropriate.
+ $out = '';
+ $pos = 0;
+ $length = strlen( $s );
+ $lineLength = 0;
+ $newlineFound = true;
+ $state = self::STATEMENT;
+ $stack = array();
+ $last = ';'; // Pretend that we have seen a semicolon yet
+ while( $pos < $length ) {
+ // First, skip over any whitespace and multiline comments, recording whether we
+ // found any newline character
+ $skip = strspn( $s, " \t\n\r\xb\xc", $pos );
+ if( !$skip ) {
+ $ch = $s[$pos];
+ if( $ch === '/' && substr( $s, $pos, 2 ) === '/*' ) {
+ // Multiline comment. Search for the end token or EOT.
+ $end = strpos( $s, '*/', $pos + 2 );
+ $skip = $end === false ? $length - $pos : $end - $pos + 2;
+ }
+ }
+ if( $skip ) {
+ // The semicolon insertion mechanism needs to know whether there was a newline
+ // between two tokens, so record it now.
+ if( !$newlineFound && strcspn( $s, "\r\n", $pos, $skip ) !== $skip ) {
+ $newlineFound = true;
+ }
+ $pos += $skip;
+ continue;
+ }
+ // Handle C++-style comments and html comments, which are treated as single line
+ // comments by the browser, regardless of whether the end tag is on the same line.
+ // Handle --> the same way, but only if it's at the beginning of the line
+ if( ( $ch === '/' && substr( $s, $pos, 2 ) === '//' )
+ || ( $ch === '<' && substr( $s, $pos, 4 ) === '<!--' )
+ || ( $ch === '-' && $newlineFound && substr( $s, $pos, 3 ) === '-->' )
+ ) {
+ $pos += strcspn( $s, "\r\n", $pos );
+ continue;
+ }
+
+ // Find out which kind of token we're handling. $end will point past the end of it.
+ $end = $pos + 1;
+ // Handle string literals
+ if( $ch === "'" || $ch === '"' ) {
+ // Search to the end of the string literal, skipping over backslash escapes
+ $search = $ch . '\\';
+ do{
+ $end += strcspn( $s, $search, $end ) + 2;
+ } while( $end - 2 < $length && $s[$end - 2] === '\\' );
+ $end--;
+ // We have to distinguish between regexp literals and division operators
+ // A division operator is only possible in certain states
+ } elseif( $ch === '/' && !isset( $divStates[$state] ) ) {
+ // Regexp literal, search to the end, skipping over backslash escapes and
+ // character classes
+ for( ; ; ) {
+ do{
+ $end += strcspn( $s, '/[\\', $end ) + 2;
+ } while( $end - 2 < $length && $s[$end - 2] === '\\' );
+ $end--;
+ if( $end - 1 >= $length || $s[$end - 1] === '/' ) {
+ break;
+ }
+ do{
+ $end += strcspn( $s, ']\\', $end ) + 2;
+ } while( $end - 2 < $length && $s[$end - 2] === '\\' );
+ $end--;
+ };
+ // Search past the regexp modifiers (gi)
+ while( $end < $length && ctype_alpha( $s[$end] ) ) {
+ $end++;
+ }
+ } elseif(
+ $ch === '0'
+ && ($pos + 1 < $length) && ($s[$pos + 1] === 'x' || $s[$pos + 1] === 'X' )
+ ) {
+ // Hex numeric literal
+ $end++; // x or X
+ $len = strspn( $s, '0123456789ABCDEFabcdef', $end );
+ if ( !$len ) {
+ return self::parseError($s, $pos, 'Expected a hexadecimal number but found ' . substr( $s, $pos, 5 ) . '...' );
+ }
+ $end += $len;
+ } elseif(
+ ctype_digit( $ch )
+ || ( $ch === '.' && $pos + 1 < $length && ctype_digit( $s[$pos + 1] ) )
+ ) {
+ $end += strspn( $s, '0123456789', $end );
+ $decimal = strspn( $s, '.', $end );
+ if ($decimal) {
+ if ( $decimal > 2 ) {
+ return self::parseError($s, $end, 'The number has too many decimal points' );
+ }
+ $end += strspn( $s, '0123456789', $end + 1 ) + $decimal;
+ }
+ $exponent = strspn( $s, 'eE', $end );
+ if( $exponent ) {
+ if ( $exponent > 1 ) {
+ return self::parseError($s, $end, 'Number with several E' );
+ }
+ $end++;
+
+ // + sign is optional; - sign is required.
+ $end += strspn( $s, '-+', $end );
+ $len = strspn( $s, '0123456789', $end );
+ if ( !$len ) {
+ return self::parseError($s, $pos, 'No decimal digits after e, how many zeroes should be added?' );
+ }
+ $end += $len;
+ }
+ } elseif( isset( $opChars[$ch] ) ) {
+ // Punctuation character. Search for the longest matching operator.
+ while(
+ $end < $length
+ && isset( $tokenTypes[substr( $s, $pos, $end - $pos + 1 )] )
+ ) {
+ $end++;
+ }
+ } else {
+ // Identifier or reserved word. Search for the end by excluding whitespace and
+ // punctuation.
+ $end += strcspn( $s, " \t\n.;,=<>+-{}()[]?:*/%'\"!&|^~\xb\xc\r", $end );
+ }
+
+ // Now get the token type from our type array
+ $token = substr( $s, $pos, $end - $pos ); // so $end - $pos == strlen( $token )
+ $type = isset( $tokenTypes[$token] ) ? $tokenTypes[$token] : self::TYPE_LITERAL;
+
+ if( $newlineFound && isset( $semicolon[$state][$type] ) ) {
+ // This token triggers the semicolon insertion mechanism of javascript. While we
+ // could add the ; token here ourselves, keeping the newline has a few advantages.
+ $out .= "\n";
+ $state = self::STATEMENT;
+ $lineLength = 0;
+ } elseif( $maxLineLength > 0 && $lineLength + $end - $pos > $maxLineLength &&
+ !isset( $semicolon[$state][$type] ) && $type !== self::TYPE_INCR_OP )
+ {
+ // This line would get too long if we added $token, so add a newline first.
+ // Only do this if it won't trigger semicolon insertion and if it won't
+ // put a postfix increment operator on its own line, which is illegal in js.
+ $out .= "\n";
+ $lineLength = 0;
+ // Check, whether we have to separate the token from the last one with whitespace
+ } elseif( !isset( $opChars[$last] ) && !isset( $opChars[$ch] ) ) {
+ $out .= ' ';
+ $lineLength++;
+ // Don't accidentally create ++, -- or // tokens
+ } elseif( $last === $ch && ( $ch === '+' || $ch === '-' || $ch === '/' ) ) {
+ $out .= ' ';
+ $lineLength++;
+ }
+
+ $out .= $token;
+ $lineLength += $end - $pos; // += strlen( $token )
+ $last = $s[$end - 1];
+ $pos = $end;
+ $newlineFound = false;
+
+ // Output a newline after the token if required
+ // This is checked before AND after switching state
+ $newlineAdded = false;
+ if ( $statementsOnOwnLine && !$newlineAdded && isset( $newlineBefore[$state][$type] ) ) {
+ $out .= "\n";
+ $lineLength = 0;
+ $newlineAdded = true;
+ }
+
+ // Now that we have output our token, transition into the new state.
+ if( isset( $push[$state][$type] ) && count( $stack ) < self::STACK_LIMIT ) {
+ $stack[] = $push[$state][$type];
+ }
+ if( $stack && isset( $pop[$state][$type] ) ) {
+ $state = array_pop( $stack );
+ } elseif( isset( $goto[$state][$type] ) ) {
+ $state = $goto[$state][$type];
+ }
+
+ // Check for newline insertion again
+ if ( $statementsOnOwnLine && !$newlineAdded && isset( $newlineAfter[$state][$type] ) ) {
+ $out .= "\n";
+ $lineLength = 0;
+ }
+ }
+ return $out;
+ }
+
+ static function parseError($fullJavascript, $position, $errorMsg) {
+ // TODO: Handle the error: trigger_error, throw exception, return false...
+ return false;
+ }
+}
diff --git a/3rdparty/miniColors/GPL-LICENSE.txt b/3rdparty/miniColors/GPL-LICENSE.txt
new file mode 100644
index 00000000000..11dddd00ef0
--- /dev/null
+++ b/3rdparty/miniColors/GPL-LICENSE.txt
@@ -0,0 +1,278 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
diff --git a/3rdparty/miniColors/MIT-LICENSE.txt b/3rdparty/miniColors/MIT-LICENSE.txt
new file mode 100644
index 00000000000..ec6f7581576
--- /dev/null
+++ b/3rdparty/miniColors/MIT-LICENSE.txt
@@ -0,0 +1,20 @@
+Copyright (c) Cory LaViska
+
+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.
diff --git a/3rdparty/miniColors/css/images/colors.png b/3rdparty/miniColors/css/images/colors.png
new file mode 100755
index 00000000000..1b4f819d8d9
--- /dev/null
+++ b/3rdparty/miniColors/css/images/colors.png
Binary files differ
diff --git a/3rdparty/miniColors/css/images/trigger.png b/3rdparty/miniColors/css/images/trigger.png
new file mode 100755
index 00000000000..8c169fd6053
--- /dev/null
+++ b/3rdparty/miniColors/css/images/trigger.png
Binary files differ
diff --git a/3rdparty/miniColors/css/jquery.miniColors.css b/3rdparty/miniColors/css/jquery.miniColors.css
new file mode 100755
index 00000000000..381bc1dc065
--- /dev/null
+++ b/3rdparty/miniColors/css/jquery.miniColors.css
@@ -0,0 +1,81 @@
+.miniColors-trigger {
+ height: 22px;
+ width: 22px;
+ background: url(images/trigger.png) center no-repeat;
+ vertical-align: middle;
+ margin: 0 .25em;
+ display: inline-block;
+ outline: none;
+}
+
+.miniColors-selector {
+ position: absolute;
+ width: 175px;
+ height: 150px;
+ background: #FFF;
+ border: solid 1px #BBB;
+ -moz-box-shadow: 0 0 6px rgba(0, 0, 0, .25);
+ -webkit-box-shadow: 0 0 6px rgba(0, 0, 0, .25);
+ box-shadow: 0 0 6px rgba(0, 0, 0, .25);
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ border-radius: 5px;
+ padding: 5px;
+ z-index: 999999;
+}
+
+.miniColors-selector.black {
+ background: #000;
+ border-color: #000;
+}
+
+.miniColors-colors {
+ position: absolute;
+ top: 5px;
+ left: 5px;
+ width: 150px;
+ height: 150px;
+ background: url(images/colors.png) right no-repeat;
+ cursor: crosshair;
+}
+
+.miniColors-hues {
+ position: absolute;
+ top: 5px;
+ left: 160px;
+ width: 20px;
+ height: 150px;
+ background: url(images/colors.png) left no-repeat;
+ cursor: crosshair;
+}
+
+.miniColors-colorPicker {
+ position: absolute;
+ width: 9px;
+ height: 9px;
+ border: 1px solid #fff;
+ -moz-border-radius: 11px;
+ -webkit-border-radius: 11px;
+ border-radius: 11px;
+}
+.miniColors-colorPicker-inner {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 7px;
+ height: 7px;
+ border: 1px solid #000;
+ -moz-border-radius: 9px;
+ -webkit-border-radius: 9px;
+ border-radius: 9px;
+}
+
+.miniColors-huePicker {
+ position: absolute;
+ left: -3px;
+ width: 24px;
+ height: 1px;
+ border: 1px solid #fff;
+ border-radius: 2px;
+ background: #000;
+} \ No newline at end of file
diff --git a/3rdparty/miniColors/js/jquery.miniColors.js b/3rdparty/miniColors/js/jquery.miniColors.js
new file mode 100755
index 00000000000..187db3fa84e
--- /dev/null
+++ b/3rdparty/miniColors/js/jquery.miniColors.js
@@ -0,0 +1,580 @@
+/*
+ * jQuery miniColors: A small color selector
+ *
+ * Copyright 2011 Cory LaViska for A Beautiful Site, LLC. (http://abeautifulsite.net/)
+ *
+ * Dual licensed under the MIT or GPL Version 2 licenses
+ *
+*/
+if(jQuery) (function($) {
+
+ $.extend($.fn, {
+
+ miniColors: function(o, data) {
+
+ var create = function(input, o, data) {
+ //
+ // Creates a new instance of the miniColors selector
+ //
+
+ // Determine initial color (defaults to white)
+ var color = expandHex(input.val());
+ if( !color ) color = 'ffffff';
+ var hsb = hex2hsb(color);
+
+ // Create trigger
+ var trigger = $('<a class="miniColors-trigger" style="background-color: #' + color + '" href="#"></a>');
+ trigger.insertAfter(input);
+
+ // Set input data and update attributes
+ input
+ .addClass('miniColors')
+ .data('original-maxlength', input.attr('maxlength') || null)
+ .data('original-autocomplete', input.attr('autocomplete') || null)
+ .data('letterCase', 'uppercase')
+ .data('trigger', trigger)
+ .data('hsb', hsb)
+ .data('change', o.change ? o.change : null)
+ .data('close', o.close ? o.close : null)
+ .data('open', o.open ? o.open : null)
+ .attr('maxlength', 7)
+ .attr('autocomplete', 'off')
+ .val('#' + convertCase(color, o.letterCase));
+
+ // Handle options
+ if( o.readonly ) input.prop('readonly', true);
+ if( o.disabled ) disable(input);
+
+ // Show selector when trigger is clicked
+ trigger.bind('click.miniColors', function(event) {
+ event.preventDefault();
+ if( input.val() === '' ) input.val('#');
+ show(input);
+
+ });
+
+ // Show selector when input receives focus
+ input.bind('focus.miniColors', function(event) {
+ if( input.val() === '' ) input.val('#');
+ show(input);
+ });
+
+ // Hide on blur
+ input.bind('blur.miniColors', function(event) {
+ var hex = expandHex( hsb2hex(input.data('hsb')) );
+ input.val( hex ? '#' + convertCase(hex, input.data('letterCase')) : '' );
+ });
+
+ // Hide when tabbing out of the input
+ input.bind('keydown.miniColors', function(event) {
+ if( event.keyCode === 9 ) hide(input);
+ });
+
+ // Update when color is typed in
+ input.bind('keyup.miniColors', function(event) {
+ setColorFromInput(input);
+ });
+
+ // Handle pasting
+ input.bind('paste.miniColors', function(event) {
+ // Short pause to wait for paste to complete
+ setTimeout( function() {
+ setColorFromInput(input);
+ }, 5);
+ });
+
+ };
+
+ var destroy = function(input) {
+ //
+ // Destroys an active instance of the miniColors selector
+ //
+
+ hide();
+ input = $(input);
+
+ // Restore to original state
+ input.data('trigger').remove();
+ input
+ .attr('autocomplete', input.data('original-autocomplete'))
+ .attr('maxlength', input.data('original-maxlength'))
+ .removeData()
+ .removeClass('miniColors')
+ .unbind('.miniColors');
+ $(document).unbind('.miniColors');
+ };
+
+ var enable = function(input) {
+ //
+ // Enables the input control and the selector
+ //
+ input
+ .prop('disabled', false)
+ .data('trigger')
+ .css('opacity', 1);
+ };
+
+ var disable = function(input) {
+ //
+ // Disables the input control and the selector
+ //
+ hide(input);
+ input
+ .prop('disabled', true)
+ .data('trigger')
+ .css('opacity', 0.5);
+ };
+
+ var show = function(input) {
+ //
+ // Shows the miniColors selector
+ //
+ if( input.prop('disabled') ) return false;
+
+ // Hide all other instances
+ hide();
+
+ // Generate the selector
+ var selector = $('<div class="miniColors-selector"></div>');
+ selector
+ .append('<div class="miniColors-colors" style="background-color: #FFF;"><div class="miniColors-colorPicker"><div class="miniColors-colorPicker-inner"></div></div>')
+ .append('<div class="miniColors-hues"><div class="miniColors-huePicker"></div></div>')
+ .css({
+ top: input.is(':visible') ? input.offset().top + input.outerHeight() : input.data('trigger').offset().top + input.data('trigger').outerHeight(),
+ left: input.is(':visible') ? input.offset().left : input.data('trigger').offset().left,
+ display: 'none'
+ })
+ .addClass( input.attr('class') );
+
+ // Set background for colors
+ var hsb = input.data('hsb');
+ selector
+ .find('.miniColors-colors')
+ .css('backgroundColor', '#' + hsb2hex({ h: hsb.h, s: 100, b: 100 }));
+
+ // Set colorPicker position
+ var colorPosition = input.data('colorPosition');
+ if( !colorPosition ) colorPosition = getColorPositionFromHSB(hsb);
+ selector.find('.miniColors-colorPicker')
+ .css('top', colorPosition.y + 'px')
+ .css('left', colorPosition.x + 'px');
+
+ // Set huePicker position
+ var huePosition = input.data('huePosition');
+ if( !huePosition ) huePosition = getHuePositionFromHSB(hsb);
+ selector.find('.miniColors-huePicker').css('top', huePosition.y + 'px');
+
+ // Set input data
+ input
+ .data('selector', selector)
+ .data('huePicker', selector.find('.miniColors-huePicker'))
+ .data('colorPicker', selector.find('.miniColors-colorPicker'))
+ .data('mousebutton', 0);
+
+ $('BODY').append(selector);
+ selector.fadeIn(100);
+
+ // Prevent text selection in IE
+ selector.bind('selectstart', function() { return false; });
+
+ $(document).bind('mousedown.miniColors touchstart.miniColors', function(event) {
+
+ input.data('mousebutton', 1);
+ var testSubject = $(event.target).parents().andSelf();
+
+ if( testSubject.hasClass('miniColors-colors') ) {
+ event.preventDefault();
+ input.data('moving', 'colors');
+ moveColor(input, event);
+ }
+
+ if( testSubject.hasClass('miniColors-hues') ) {
+ event.preventDefault();
+ input.data('moving', 'hues');
+ moveHue(input, event);
+ }
+
+ if( testSubject.hasClass('miniColors-selector') ) {
+ event.preventDefault();
+ return;
+ }
+
+ if( testSubject.hasClass('miniColors') ) return;
+
+ hide(input);
+ });
+
+ $(document)
+ .bind('mouseup.miniColors touchend.miniColors', function(event) {
+ event.preventDefault();
+ input.data('mousebutton', 0).removeData('moving');
+ })
+ .bind('mousemove.miniColors touchmove.miniColors', function(event) {
+ event.preventDefault();
+ if( input.data('mousebutton') === 1 ) {
+ if( input.data('moving') === 'colors' ) moveColor(input, event);
+ if( input.data('moving') === 'hues' ) moveHue(input, event);
+ }
+ });
+
+ // Fire open callback
+ if( input.data('open') ) {
+ input.data('open').call(input.get(0), '#' + hsb2hex(hsb), hsb2rgb(hsb));
+ }
+
+ };
+
+ var hide = function(input) {
+
+ //
+ // Hides one or more miniColors selectors
+ //
+
+ // Hide all other instances if input isn't specified
+ if( !input ) input = '.miniColors';
+
+ $(input).each( function() {
+ var selector = $(this).data('selector');
+ $(this).removeData('selector');
+ $(selector).fadeOut(100, function() {
+ // Fire close callback
+ if( input.data('close') ) {
+ var hsb = input.data('hsb'), hex = hsb2hex(hsb);
+ input.data('close').call(input.get(0), '#' + hex, hsb2rgb(hsb));
+ }
+ $(this).remove();
+ });
+ });
+
+ $(document).unbind('.miniColors');
+
+ };
+
+ var moveColor = function(input, event) {
+
+ var colorPicker = input.data('colorPicker');
+
+ colorPicker.hide();
+
+ var position = {
+ x: event.pageX,
+ y: event.pageY
+ };
+
+ // Touch support
+ if( event.originalEvent.changedTouches ) {
+ position.x = event.originalEvent.changedTouches[0].pageX;
+ position.y = event.originalEvent.changedTouches[0].pageY;
+ }
+ position.x = position.x - input.data('selector').find('.miniColors-colors').offset().left - 5;
+ position.y = position.y - input.data('selector').find('.miniColors-colors').offset().top - 5;
+ if( position.x <= -5 ) position.x = -5;
+ if( position.x >= 144 ) position.x = 144;
+ if( position.y <= -5 ) position.y = -5;
+ if( position.y >= 144 ) position.y = 144;
+
+ input.data('colorPosition', position);
+ colorPicker.css('left', position.x).css('top', position.y).show();
+
+ // Calculate saturation
+ var s = Math.round((position.x + 5) * 0.67);
+ if( s < 0 ) s = 0;
+ if( s > 100 ) s = 100;
+
+ // Calculate brightness
+ var b = 100 - Math.round((position.y + 5) * 0.67);
+ if( b < 0 ) b = 0;
+ if( b > 100 ) b = 100;
+
+ // Update HSB values
+ var hsb = input.data('hsb');
+ hsb.s = s;
+ hsb.b = b;
+
+ // Set color
+ setColor(input, hsb, true);
+ };
+
+ var moveHue = function(input, event) {
+
+ var huePicker = input.data('huePicker');
+
+ huePicker.hide();
+
+ var position = {
+ y: event.pageY
+ };
+
+ // Touch support
+ if( event.originalEvent.changedTouches ) {
+ position.y = event.originalEvent.changedTouches[0].pageY;
+ }
+
+ position.y = position.y - input.data('selector').find('.miniColors-colors').offset().top - 1;
+ if( position.y <= -1 ) position.y = -1;
+ if( position.y >= 149 ) position.y = 149;
+ input.data('huePosition', position);
+ huePicker.css('top', position.y).show();
+
+ // Calculate hue
+ var h = Math.round((150 - position.y - 1) * 2.4);
+ if( h < 0 ) h = 0;
+ if( h > 360 ) h = 360;
+
+ // Update HSB values
+ var hsb = input.data('hsb');
+ hsb.h = h;
+
+ // Set color
+ setColor(input, hsb, true);
+
+ };
+
+ var setColor = function(input, hsb, updateInput) {
+ input.data('hsb', hsb);
+ var hex = hsb2hex(hsb);
+ if( updateInput ) input.val( '#' + convertCase(hex, input.data('letterCase')) );
+ input.data('trigger').css('backgroundColor', '#' + hex);
+ if( input.data('selector') ) input.data('selector').find('.miniColors-colors').css('backgroundColor', '#' + hsb2hex({ h: hsb.h, s: 100, b: 100 }));
+
+ // Fire change callback
+ if( input.data('change') ) {
+ if( hex === input.data('lastChange') ) return;
+ input.data('change').call(input.get(0), '#' + hex, hsb2rgb(hsb));
+ input.data('lastChange', hex);
+ }
+
+ };
+
+ var setColorFromInput = function(input) {
+
+ input.val('#' + cleanHex(input.val()));
+ var hex = expandHex(input.val());
+ if( !hex ) return false;
+
+ // Get HSB equivalent
+ var hsb = hex2hsb(hex);
+
+ // If color is the same, no change required
+ var currentHSB = input.data('hsb');
+ if( hsb.h === currentHSB.h && hsb.s === currentHSB.s && hsb.b === currentHSB.b ) return true;
+
+ // Set colorPicker position
+ var colorPosition = getColorPositionFromHSB(hsb);
+ var colorPicker = $(input.data('colorPicker'));
+ colorPicker.css('top', colorPosition.y + 'px').css('left', colorPosition.x + 'px');
+ input.data('colorPosition', colorPosition);
+
+ // Set huePosition position
+ var huePosition = getHuePositionFromHSB(hsb);
+ var huePicker = $(input.data('huePicker'));
+ huePicker.css('top', huePosition.y + 'px');
+ input.data('huePosition', huePosition);
+
+ setColor(input, hsb);
+
+ return true;
+
+ };
+
+ var convertCase = function(string, letterCase) {
+ if( letterCase === 'lowercase' ) return string.toLowerCase();
+ if( letterCase === 'uppercase' ) return string.toUpperCase();
+ return string;
+ };
+
+ var getColorPositionFromHSB = function(hsb) {
+ var x = Math.ceil(hsb.s / 0.67);
+ if( x < 0 ) x = 0;
+ if( x > 150 ) x = 150;
+ var y = 150 - Math.ceil(hsb.b / 0.67);
+ if( y < 0 ) y = 0;
+ if( y > 150 ) y = 150;
+ return { x: x - 5, y: y - 5 };
+ };
+
+ var getHuePositionFromHSB = function(hsb) {
+ var y = 150 - (hsb.h / 2.4);
+ if( y < 0 ) h = 0;
+ if( y > 150 ) h = 150;
+ return { y: y - 1 };
+ };
+
+ var cleanHex = function(hex) {
+ return hex.replace(/[^A-F0-9]/ig, '');
+ };
+
+ var expandHex = function(hex) {
+ hex = cleanHex(hex);
+ if( !hex ) return null;
+ if( hex.length === 3 ) hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
+ return hex.length === 6 ? hex : null;
+ };
+
+ var hsb2rgb = function(hsb) {
+ var rgb = {};
+ var h = Math.round(hsb.h);
+ var s = Math.round(hsb.s*255/100);
+ var v = Math.round(hsb.b*255/100);
+ if(s === 0) {
+ rgb.r = rgb.g = rgb.b = v;
+ } else {
+ var t1 = v;
+ var t2 = (255 - s) * v / 255;
+ var t3 = (t1 - t2) * (h % 60) / 60;
+ if( h === 360 ) h = 0;
+ if( h < 60 ) { rgb.r = t1; rgb.b = t2; rgb.g = t2 + t3; }
+ else if( h < 120 ) {rgb.g = t1; rgb.b = t2; rgb.r = t1 - t3; }
+ else if( h < 180 ) {rgb.g = t1; rgb.r = t2; rgb.b = t2 + t3; }
+ else if( h < 240 ) {rgb.b = t1; rgb.r = t2; rgb.g = t1 - t3; }
+ else if( h < 300 ) {rgb.b = t1; rgb.g = t2; rgb.r = t2 + t3; }
+ else if( h < 360 ) {rgb.r = t1; rgb.g = t2; rgb.b = t1 - t3; }
+ else { rgb.r = 0; rgb.g = 0; rgb.b = 0; }
+ }
+ return {
+ r: Math.round(rgb.r),
+ g: Math.round(rgb.g),
+ b: Math.round(rgb.b)
+ };
+ };
+
+ var rgb2hex = function(rgb) {
+ var hex = [
+ rgb.r.toString(16),
+ rgb.g.toString(16),
+ rgb.b.toString(16)
+ ];
+ $.each(hex, function(nr, val) {
+ if (val.length === 1) hex[nr] = '0' + val;
+ });
+ return hex.join('');
+ };
+
+ var hex2rgb = function(hex) {
+ hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
+
+ return {
+ r: hex >> 16,
+ g: (hex & 0x00FF00) >> 8,
+ b: (hex & 0x0000FF)
+ };
+ };
+
+ var rgb2hsb = function(rgb) {
+ var hsb = { h: 0, s: 0, b: 0 };
+ var min = Math.min(rgb.r, rgb.g, rgb.b);
+ var max = Math.max(rgb.r, rgb.g, rgb.b);
+ var delta = max - min;
+ hsb.b = max;
+ hsb.s = max !== 0 ? 255 * delta / max : 0;
+ if( hsb.s !== 0 ) {
+ if( rgb.r === max ) {
+ hsb.h = (rgb.g - rgb.b) / delta;
+ } else if( rgb.g === max ) {
+ hsb.h = 2 + (rgb.b - rgb.r) / delta;
+ } else {
+ hsb.h = 4 + (rgb.r - rgb.g) / delta;
+ }
+ } else {
+ hsb.h = -1;
+ }
+ hsb.h *= 60;
+ if( hsb.h < 0 ) {
+ hsb.h += 360;
+ }
+ hsb.s *= 100/255;
+ hsb.b *= 100/255;
+ return hsb;
+ };
+
+ var hex2hsb = function(hex) {
+ var hsb = rgb2hsb(hex2rgb(hex));
+ // Zero out hue marker for black, white, and grays (saturation === 0)
+ if( hsb.s === 0 ) hsb.h = 360;
+ return hsb;
+ };
+
+ var hsb2hex = function(hsb) {
+ return rgb2hex(hsb2rgb(hsb));
+ };
+
+
+ // Handle calls to $([selector]).miniColors()
+ switch(o) {
+
+ case 'readonly':
+
+ $(this).each( function() {
+ if( !$(this).hasClass('miniColors') ) return;
+ $(this).prop('readonly', data);
+ });
+
+ return $(this);
+
+ case 'disabled':
+
+ $(this).each( function() {
+ if( !$(this).hasClass('miniColors') ) return;
+ if( data ) {
+ disable($(this));
+ } else {
+ enable($(this));
+ }
+ });
+
+ return $(this);
+
+ case 'value':
+
+ // Getter
+ if( data === undefined ) {
+ if( !$(this).hasClass('miniColors') ) return;
+ var input = $(this),
+ hex = expandHex(input.val());
+ return hex ? '#' + convertCase(hex, input.data('letterCase')) : null;
+ }
+
+ // Setter
+ $(this).each( function() {
+ if( !$(this).hasClass('miniColors') ) return;
+ $(this).val(data);
+ setColorFromInput($(this));
+ });
+
+ return $(this);
+
+ case 'destroy':
+
+ $(this).each( function() {
+ if( !$(this).hasClass('miniColors') ) return;
+ destroy($(this));
+ });
+
+ return $(this);
+
+ default:
+
+ if( !o ) o = {};
+
+ $(this).each( function() {
+
+ // Must be called on an input element
+ if( $(this)[0].tagName.toLowerCase() !== 'input' ) return;
+
+ // If a trigger is present, the control was already created
+ if( $(this).data('trigger') ) return;
+
+ // Create the control
+ create($(this), o, data);
+
+ });
+
+ return $(this);
+
+ }
+
+ }
+
+ });
+
+})(jQuery); \ No newline at end of file
diff --git a/3rdparty/miniColors/js/jquery.miniColors.min.js b/3rdparty/miniColors/js/jquery.miniColors.min.js
new file mode 100755
index 00000000000..c00e0ace6b5
--- /dev/null
+++ b/3rdparty/miniColors/js/jquery.miniColors.min.js
@@ -0,0 +1,9 @@
+/*
+ * jQuery miniColors: A small color selector
+ *
+ * Copyright 2011 Cory LaViska for A Beautiful Site, LLC. (http://abeautifulsite.net/)
+ *
+ * Dual licensed under the MIT or GPL Version 2 licenses
+ *
+*/
+if(jQuery)(function($){$.extend($.fn,{miniColors:function(o,data){var create=function(input,o,data){var color=expandHex(input.val());if(!color)color='ffffff';var hsb=hex2hsb(color);var trigger=$('<a class="miniColors-trigger" style="background-color: #'+color+'" href="#"></a>');trigger.insertAfter(input);input.addClass('miniColors').data('original-maxlength',input.attr('maxlength')||null).data('original-autocomplete',input.attr('autocomplete')||null).data('letterCase','uppercase').data('trigger',trigger).data('hsb',hsb).data('change',o.change?o.change:null).data('close',o.close?o.close:null).data('open',o.open?o.open:null).attr('maxlength',7).attr('autocomplete','off').val('#'+convertCase(color,o.letterCase));if(o.readonly)input.prop('readonly',true);if(o.disabled)disable(input);trigger.bind('click.miniColors',function(event){event.preventDefault();if(input.val()==='')input.val('#');show(input)});input.bind('focus.miniColors',function(event){if(input.val()==='')input.val('#');show(input)});input.bind('blur.miniColors',function(event){var hex=expandHex(hsb2hex(input.data('hsb')));input.val(hex?'#'+convertCase(hex,input.data('letterCase')):'')});input.bind('keydown.miniColors',function(event){if(event.keyCode===9)hide(input)});input.bind('keyup.miniColors',function(event){setColorFromInput(input)});input.bind('paste.miniColors',function(event){setTimeout(function(){setColorFromInput(input)},5)})};var destroy=function(input){hide();input=$(input);input.data('trigger').remove();input.attr('autocomplete',input.data('original-autocomplete')).attr('maxlength',input.data('original-maxlength')).removeData().removeClass('miniColors').unbind('.miniColors');$(document).unbind('.miniColors')};var enable=function(input){input.prop('disabled',false).data('trigger').css('opacity',1)};var disable=function(input){hide(input);input.prop('disabled',true).data('trigger').css('opacity',0.5)};var show=function(input){if(input.prop('disabled'))return false;hide();var selector=$('<div class="miniColors-selector"></div>');selector.append('<div class="miniColors-colors" style="background-color: #FFF;"><div class="miniColors-colorPicker"><div class="miniColors-colorPicker-inner"></div></div>').append('<div class="miniColors-hues"><div class="miniColors-huePicker"></div></div>').css({top:input.is(':visible')?input.offset().top+input.outerHeight():input.data('trigger').offset().top+input.data('trigger').outerHeight(),left:input.is(':visible')?input.offset().left:input.data('trigger').offset().left,display:'none'}).addClass(input.attr('class'));var hsb=input.data('hsb');selector.find('.miniColors-colors').css('backgroundColor','#'+hsb2hex({h:hsb.h,s:100,b:100}));var colorPosition=input.data('colorPosition');if(!colorPosition)colorPosition=getColorPositionFromHSB(hsb);selector.find('.miniColors-colorPicker').css('top',colorPosition.y+'px').css('left',colorPosition.x+'px');var huePosition=input.data('huePosition');if(!huePosition)huePosition=getHuePositionFromHSB(hsb);selector.find('.miniColors-huePicker').css('top',huePosition.y+'px');input.data('selector',selector).data('huePicker',selector.find('.miniColors-huePicker')).data('colorPicker',selector.find('.miniColors-colorPicker')).data('mousebutton',0);$('BODY').append(selector);selector.fadeIn(100);selector.bind('selectstart',function(){return false});$(document).bind('mousedown.miniColors touchstart.miniColors',function(event){input.data('mousebutton',1);var testSubject=$(event.target).parents().andSelf();if(testSubject.hasClass('miniColors-colors')){event.preventDefault();input.data('moving','colors');moveColor(input,event)}if(testSubject.hasClass('miniColors-hues')){event.preventDefault();input.data('moving','hues');moveHue(input,event)}if(testSubject.hasClass('miniColors-selector')){event.preventDefault();return}if(testSubject.hasClass('miniColors'))return;hide(input)});$(document).bind('mouseup.miniColors touchend.miniColors',function(event){event.preventDefault();input.data('mousebutton',0).removeData('moving')}).bind('mousemove.miniColors touchmove.miniColors',function(event){event.preventDefault();if(input.data('mousebutton')===1){if(input.data('moving')==='colors')moveColor(input,event);if(input.data('moving')==='hues')moveHue(input,event)}});if(input.data('open')){input.data('open').call(input.get(0),'#'+hsb2hex(hsb),hsb2rgb(hsb))}};var hide=function(input){if(!input)input='.miniColors';$(input).each(function(){var selector=$(this).data('selector');$(this).removeData('selector');$(selector).fadeOut(100,function(){if(input.data('close')){var hsb=input.data('hsb'),hex=hsb2hex(hsb);input.data('close').call(input.get(0),'#'+hex,hsb2rgb(hsb))}$(this).remove()})});$(document).unbind('.miniColors')};var moveColor=function(input,event){var colorPicker=input.data('colorPicker');colorPicker.hide();var position={x:event.pageX,y:event.pageY};if(event.originalEvent.changedTouches){position.x=event.originalEvent.changedTouches[0].pageX;position.y=event.originalEvent.changedTouches[0].pageY}position.x=position.x-input.data('selector').find('.miniColors-colors').offset().left-5;position.y=position.y-input.data('selector').find('.miniColors-colors').offset().top-5;if(position.x<=-5)position.x=-5;if(position.x>=144)position.x=144;if(position.y<=-5)position.y=-5;if(position.y>=144)position.y=144;input.data('colorPosition',position);colorPicker.css('left',position.x).css('top',position.y).show();var s=Math.round((position.x+5)*0.67);if(s<0)s=0;if(s>100)s=100;var b=100-Math.round((position.y+5)*0.67);if(b<0)b=0;if(b>100)b=100;var hsb=input.data('hsb');hsb.s=s;hsb.b=b;setColor(input,hsb,true)};var moveHue=function(input,event){var huePicker=input.data('huePicker');huePicker.hide();var position={y:event.pageY};if(event.originalEvent.changedTouches){position.y=event.originalEvent.changedTouches[0].pageY}position.y=position.y-input.data('selector').find('.miniColors-colors').offset().top-1;if(position.y<=-1)position.y=-1;if(position.y>=149)position.y=149;input.data('huePosition',position);huePicker.css('top',position.y).show();var h=Math.round((150-position.y-1)*2.4);if(h<0)h=0;if(h>360)h=360;var hsb=input.data('hsb');hsb.h=h;setColor(input,hsb,true)};var setColor=function(input,hsb,updateInput){input.data('hsb',hsb);var hex=hsb2hex(hsb);if(updateInput)input.val('#'+convertCase(hex,input.data('letterCase')));input.data('trigger').css('backgroundColor','#'+hex);if(input.data('selector'))input.data('selector').find('.miniColors-colors').css('backgroundColor','#'+hsb2hex({h:hsb.h,s:100,b:100}));if(input.data('change')){if(hex===input.data('lastChange'))return;input.data('change').call(input.get(0),'#'+hex,hsb2rgb(hsb));input.data('lastChange',hex)}};var setColorFromInput=function(input){input.val('#'+cleanHex(input.val()));var hex=expandHex(input.val());if(!hex)return false;var hsb=hex2hsb(hex);var currentHSB=input.data('hsb');if(hsb.h===currentHSB.h&&hsb.s===currentHSB.s&&hsb.b===currentHSB.b)return true;var colorPosition=getColorPositionFromHSB(hsb);var colorPicker=$(input.data('colorPicker'));colorPicker.css('top',colorPosition.y+'px').css('left',colorPosition.x+'px');input.data('colorPosition',colorPosition);var huePosition=getHuePositionFromHSB(hsb);var huePicker=$(input.data('huePicker'));huePicker.css('top',huePosition.y+'px');input.data('huePosition',huePosition);setColor(input,hsb);return true};var convertCase=function(string,letterCase){if(letterCase==='lowercase')return string.toLowerCase();if(letterCase==='uppercase')return string.toUpperCase();return string};var getColorPositionFromHSB=function(hsb){var x=Math.ceil(hsb.s/0.67);if(x<0)x=0;if(x>150)x=150;var y=150-Math.ceil(hsb.b/0.67);if(y<0)y=0;if(y>150)y=150;return{x:x-5,y:y-5}};var getHuePositionFromHSB=function(hsb){var y=150-(hsb.h/2.4);if(y<0)h=0;if(y>150)h=150;return{y:y-1}};var cleanHex=function(hex){return hex.replace(/[^A-F0-9]/ig,'')};var expandHex=function(hex){hex=cleanHex(hex);if(!hex)return null;if(hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];return hex.length===6?hex:null};var hsb2rgb=function(hsb){var rgb={};var h=Math.round(hsb.h);var s=Math.round(hsb.s*255/100);var v=Math.round(hsb.b*255/100);if(s===0){rgb.r=rgb.g=rgb.b=v}else{var t1=v;var t2=(255-s)*v/255;var t3=(t1-t2)*(h%60)/60;if(h===360)h=0;if(h<60){rgb.r=t1;rgb.b=t2;rgb.g=t2+t3}else if(h<120){rgb.g=t1;rgb.b=t2;rgb.r=t1-t3}else if(h<180){rgb.g=t1;rgb.r=t2;rgb.b=t2+t3}else if(h<240){rgb.b=t1;rgb.r=t2;rgb.g=t1-t3}else if(h<300){rgb.b=t1;rgb.g=t2;rgb.r=t2+t3}else if(h<360){rgb.r=t1;rgb.g=t2;rgb.b=t1-t3}else{rgb.r=0;rgb.g=0;rgb.b=0}}return{r:Math.round(rgb.r),g:Math.round(rgb.g),b:Math.round(rgb.b)}};var rgb2hex=function(rgb){var hex=[rgb.r.toString(16),rgb.g.toString(16),rgb.b.toString(16)];$.each(hex,function(nr,val){if(val.length===1)hex[nr]='0'+val});return hex.join('')};var hex2rgb=function(hex){hex=parseInt(((hex.indexOf('#')>-1)?hex.substring(1):hex),16);return{r:hex>>16,g:(hex&0x00FF00)>>8,b:(hex&0x0000FF)}};var rgb2hsb=function(rgb){var hsb={h:0,s:0,b:0};var min=Math.min(rgb.r,rgb.g,rgb.b);var max=Math.max(rgb.r,rgb.g,rgb.b);var delta=max-min;hsb.b=max;hsb.s=max!==0?255*delta/max:0;if(hsb.s!==0){if(rgb.r===max){hsb.h=(rgb.g-rgb.b)/delta}else if(rgb.g===max){hsb.h=2+(rgb.b-rgb.r)/delta}else{hsb.h=4+(rgb.r-rgb.g)/delta}}else{hsb.h=-1}hsb.h*=60;if(hsb.h<0){hsb.h+=360}hsb.s*=100/255;hsb.b*=100/255;return hsb};var hex2hsb=function(hex){var hsb=rgb2hsb(hex2rgb(hex));if(hsb.s===0)hsb.h=360;return hsb};var hsb2hex=function(hsb){return rgb2hex(hsb2rgb(hsb))};switch(o){case'readonly':$(this).each(function(){if(!$(this).hasClass('miniColors'))return;$(this).prop('readonly',data)});return $(this);case'disabled':$(this).each(function(){if(!$(this).hasClass('miniColors'))return;if(data){disable($(this))}else{enable($(this))}});return $(this);case'value':if(data===undefined){if(!$(this).hasClass('miniColors'))return;var input=$(this),hex=expandHex(input.val());return hex?'#'+convertCase(hex,input.data('letterCase')):null}$(this).each(function(){if(!$(this).hasClass('miniColors'))return;$(this).val(data);setColorFromInput($(this))});return $(this);case'destroy':$(this).each(function(){if(!$(this).hasClass('miniColors'))return;destroy($(this))});return $(this);default:if(!o)o={};$(this).each(function(){if($(this)[0].tagName.toLowerCase()!=='input')return;if($(this).data('trigger'))return;create($(this),o,data)});return $(this)}}})})(jQuery); \ No newline at end of file
diff --git a/3rdparty/openid/class.openid.v3.php b/3rdparty/openid/class.openid.v3.php
new file mode 100644
index 00000000000..eeb31986659
--- /dev/null
+++ b/3rdparty/openid/class.openid.v3.php
@@ -0,0 +1,326 @@
+<?php
+/*
+ FREE TO USE
+ Under License: GPLv3
+ Simple OpenID PHP Class
+
+ Some modifications by Eddie Roosenmaallen, eddie@roosenmaallen.com
+
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+This Class was written to make easy for you to integrate OpenID on your website.
+This is just a client, which checks for user's identity. This Class Requires CURL Module.
+It should be easy to use some other HTTP Request Method, but remember, often OpenID servers
+are using SSL.
+We need to be able to perform SSL Verification on the background to check for valid signature.
+
+HOW TO USE THIS CLASS:
+ STEP 1)
+ $openid = new SimpleOpenID;
+ :: SET IDENTITY ::
+ $openid->SetIdentity($_POST['openid_url']);
+ :: SET RETURN URL ::
+ $openid->SetApprovedURL('http://www.yoursite.com/return.php'); // Script which handles a response from OpenID Server
+ :: SET TRUST ROOT ::
+ $openid->SetTrustRoot('http://www.yoursite.com/');
+ :: FETCH SERVER URL FROM IDENTITY PAGE :: [Note: It is recomended to cache this (Session, Cookie, Database)]
+ $openid->GetOpenIDServer(); // Returns false if server is not found
+ :: REDIRECT USER TO OPEN ID SERVER FOR APPROVAL ::
+
+ :: (OPTIONAL) SET OPENID SERVER ::
+ $openid->SetOpenIDServer($server_url); // If you have cached previously this, you don't have to call GetOpenIDServer and set value this directly
+
+ STEP 2)
+ Once user gets returned we must validate signature
+ :: VALIDATE REQUEST ::
+ true|false = $openid->ValidateWithServer();
+
+ ERRORS:
+ array = $openid->GetError(); // Get latest Error code
+
+ FIELDS:
+ OpenID allowes you to retreive a profile. To set what fields you'd like to get use (accepts either string or array):
+ $openid->SetRequiredFields(array('email','fullname','dob','gender','postcode','country','language','timezone'));
+ or
+ $openid->SetOptionalFields('postcode');
+
+IMPORTANT TIPS:
+OPENID as is now, is not trust system. It is a great single-sign on method. If you want to
+store information about OpenID in your database for later use, make sure you handle url identities
+properly.
+ For example:
+ https://steve.myopenid.com/
+ https://steve.myopenid.com
+ http://steve.myopenid.com/
+ http://steve.myopenid.com
+ ... are representing one single user. Some OpenIDs can be in format openidserver.com/users/user/ - keep this in mind when storing identities
+
+ To help you store an OpenID in your DB, you can use function:
+ $openid_db_safe = $openid->OpenID_Standarize($upenid);
+ This may not be comatible with current specs, but it works in current enviroment. Use this function to get openid
+ in one format like steve.myopenid.com (without trailing slashes and http/https).
+ Use output to insert Identity to database. Don't use this for validation - it may fail.
+
+*/
+
+class SimpleOpenID{
+ var $openid_url_identity;
+ var $URLs = array();
+ var $error = array();
+ var $fields = array(
+ 'required' => array(),
+ 'optional' => array(),
+ );
+
+ function SimpleOpenID(){
+ if (!function_exists('curl_exec')) {
+ die('Error: Class SimpleOpenID requires curl extension to work');
+ }
+ }
+ function SetOpenIDServer($a){
+ $this->URLs['openid_server'] = $a;
+ }
+ function SetTrustRoot($a){
+ $this->URLs['trust_root'] = $a;
+ }
+ function SetCancelURL($a){
+ $this->URLs['cancel'] = $a;
+ }
+ function SetApprovedURL($a){
+ $this->URLs['approved'] = $a;
+ }
+ function SetRequiredFields($a){
+ if (is_array($a)){
+ $this->fields['required'] = $a;
+ }else{
+ $this->fields['required'][] = $a;
+ }
+ }
+ function SetOptionalFields($a){
+ if (is_array($a)){
+ $this->fields['optional'] = $a;
+ }else{
+ $this->fields['optional'][] = $a;
+ }
+ }
+ function SetIdentity($a){ // Set Identity URL
+ if ((stripos($a, 'http://') === false)
+ && (stripos($a, 'https://') === false)){
+ $a = 'http://'.$a;
+ }
+/*
+ $u = parse_url(trim($a));
+ if (!isset($u['path'])){
+ $u['path'] = '/';
+ }else if(substr($u['path'],-1,1) == '/'){
+ $u['path'] = substr($u['path'], 0, strlen($u['path'])-1);
+ }
+ if (isset($u['query'])){ // If there is a query string, then use identity as is
+ $identity = $a;
+ }else{
+ $identity = $u['scheme'] . '://' . $u['host'] . $u['path'];
+ }
+//*/
+ $this->openid_url_identity = $a;
+ }
+ function GetIdentity(){ // Get Identity
+ return $this->openid_url_identity;
+ }
+ function GetError(){
+ $e = $this->error;
+ return array('code'=>$e[0],'description'=>$e[1]);
+ }
+
+ function ErrorStore($code, $desc = null){
+ $errs['OPENID_NOSERVERSFOUND'] = 'Cannot find OpenID Server TAG on Identity page.';
+ if ($desc == null){
+ $desc = $errs[$code];
+ }
+ $this->error = array($code,$desc);
+ }
+
+ function IsError(){
+ if (count($this->error) > 0){
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+ function splitResponse($response) {
+ $r = array();
+ $response = explode("\n", $response);
+ foreach($response as $line) {
+ $line = trim($line);
+ if ($line != "") {
+ list($key, $value) = explode(":", $line, 2);
+ $r[trim($key)] = trim($value);
+ }
+ }
+ return $r;
+ }
+
+ function OpenID_Standarize($openid_identity = null){
+ if ($openid_identity === null)
+ $openid_identity = $this->openid_url_identity;
+
+ $u = parse_url(strtolower(trim($openid_identity)));
+
+ if (!isset($u['path']) || ($u['path'] == '/')) {
+ $u['path'] = '';
+ }
+ if(substr($u['path'],-1,1) == '/'){
+ $u['path'] = substr($u['path'], 0, strlen($u['path'])-1);
+ }
+ if (isset($u['query'])){ // If there is a query string, then use identity as is
+ return $u['host'] . $u['path'] . '?' . $u['query'];
+ }else{
+ return $u['host'] . $u['path'];
+ }
+ }
+
+ function array2url($arr){ // converts associated array to URL Query String
+ if (!is_array($arr)){
+ return false;
+ }
+ $query = '';
+ foreach($arr as $key => $value){
+ $query .= $key . "=" . $value . "&";
+ }
+ return $query;
+ }
+ function FSOCK_Request($url, $method="GET", $params = ""){
+ $fp = fsockopen("ssl://www.myopenid.com", 443, $errno, $errstr, 3); // Connection timeout is 3 seconds
+ if (!$fp) {
+ $this->ErrorStore('OPENID_SOCKETERROR', $errstr);
+ return false;
+ } else {
+ $request = $method . " /server HTTP/1.0\r\n";
+ $request .= "User-Agent: Simple OpenID PHP Class (http://www.phpclasses.org/simple_openid)\r\n";
+ $request .= "Connection: close\r\n\r\n";
+ fwrite($fp, $request);
+ stream_set_timeout($fp, 4); // Connection response timeout is 4 seconds
+ $res = fread($fp, 2000);
+ $info = stream_get_meta_data($fp);
+ fclose($fp);
+
+ if ($info['timed_out']) {
+ $this->ErrorStore('OPENID_SOCKETTIMEOUT');
+ } else {
+ return $res;
+ }
+ }
+ }
+ function CURL_Request($url, $method="GET", $params = "") { // Remember, SSL MUST BE SUPPORTED
+ if (is_array($params)) $params = $this->array2url($params);
+ $curl = curl_init($url . ($method == "GET" && $params != "" ? "?" . $params : ""));
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($curl, CURLOPT_HEADER, false);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($curl, CURLOPT_HTTPGET, ($method == "GET"));
+ curl_setopt($curl, CURLOPT_POST, ($method == "POST"));
+ if ($method == "POST") curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ $response = curl_exec($curl);
+
+ if (curl_errno($curl) == 0){
+ $response;
+ }else{
+ $this->ErrorStore('OPENID_CURL', curl_error($curl));
+ }
+ return $response;
+ }
+
+ function HTML2OpenIDServer($content) {
+ $get = array();
+
+ // Get details of their OpenID server and (optional) delegate
+ preg_match_all('/<link[^>]*rel=[\'"](openid2.provider )?openid.server[\'"][^>]*href=[\'"]([^\'"]+)[\'"][^>]*\/?>/i', $content, $matches1);
+ preg_match_all('/<link[^>]*href=\'"([^\'"]+)[\'"][^>]*rel=[\'"](openid2.provider )?openid.server[\'"][^>]*\/?>/i', $content, $matches2);
+ $servers = array_merge($matches1[2], $matches2[1]);
+
+ preg_match_all('/<link[^>]*rel=[\'"]openid.delegate[\'"][^>]*href=[\'"]([^\'"]+)[\'"][^>]*\/?>/i', $content, $matches1);
+
+ preg_match_all('/<link[^>]*href=[\'"]([^\'"]+)[\'"][^>]*rel=[\'"]openid.delegate[\'"][^>]*\/?>/i', $content, $matches2);
+
+ $delegates = array_merge($matches1[1], $matches2[1]);
+
+ $ret = array($servers, $delegates);
+ return $ret;
+ }
+
+ function GetOpenIDServer(){
+ $response = $this->CURL_Request($this->openid_url_identity);
+ list($servers, $delegates) = $this->HTML2OpenIDServer($response);
+ if (count($servers) == 0){
+ $this->ErrorStore('OPENID_NOSERVERSFOUND');
+ return false;
+ }
+ if (isset($delegates[0])
+ && ($delegates[0] != "")){
+ $this->SetIdentity($delegates[0]);
+ }
+ $this->SetOpenIDServer($servers[0]);
+ return $servers[0];
+ }
+
+ function GetRedirectURL(){
+ $params = array();
+ $params['openid.return_to'] = urlencode($this->URLs['approved']);
+ $params['openid.mode'] = 'checkid_setup';
+ $params['openid.identity'] = urlencode($this->openid_url_identity);
+ $params['openid.trust_root'] = urlencode($this->URLs['trust_root']);
+
+ if (isset($this->fields['required'])
+ && (count($this->fields['required']) > 0)) {
+ $params['openid.sreg.required'] = implode(',',$this->fields['required']);
+ }
+ if (isset($this->fields['optional'])
+ && (count($this->fields['optional']) > 0)) {
+ $params['openid.sreg.optional'] = implode(',',$this->fields['optional']);
+ }
+ return $this->URLs['openid_server'] . "?". $this->array2url($params);
+ }
+
+ function Redirect(){
+ $redirect_to = $this->GetRedirectURL();
+ if (headers_sent()){ // Use JavaScript to redirect if content has been previously sent (not recommended, but safe)
+ echo '<script language="JavaScript" type="text/javascript">window.location=\'';
+ echo $redirect_to;
+ echo '\';</script>';
+ }else{ // Default Header Redirect
+ header('Location: ' . $redirect_to);
+ }
+ }
+
+ function ValidateWithServer(){
+ $params = array(
+ 'openid.assoc_handle' => urlencode($_GET['openid_assoc_handle']),
+ 'openid.signed' => urlencode($_GET['openid_signed']),
+ 'openid.sig' => urlencode($_GET['openid_sig'])
+ );
+ // Send only required parameters to confirm validity
+ $arr_signed = explode(",",str_replace('sreg.','sreg_',$_GET['openid_signed']));
+ for ($i=0; $i<count($arr_signed); $i++){
+ $s = str_replace('sreg_','sreg.', $arr_signed[$i]);
+ $c = $_GET['openid_' . $arr_signed[$i]];
+ // if ($c != ""){
+ $params['openid.' . $s] = urlencode($c);
+ // }
+ }
+ $params['openid.mode'] = "check_authentication";
+
+ $openid_server = $this->GetOpenIDServer();
+ if ($openid_server == false){
+ return false;
+ }
+ $response = $this->CURL_Request($openid_server,'POST',$params);
+ $data = $this->splitResponse($response);
+
+ if ($data['is_valid'] == "true") {
+ return true;
+ }else{
+ return false;
+ }
+ }
+}
diff --git a/3rdparty/openid/phpmyid.php b/3rdparty/openid/phpmyid.php
new file mode 100644
index 00000000000..13fd31c47ca
--- /dev/null
+++ b/3rdparty/openid/phpmyid.php
@@ -0,0 +1,1707 @@
+<?php
+// PLEASE DO NOT EDIT THIS FILE UNLESS YOU KNOW WHAT YOU ARE DOING!
+
+/**
+ * phpMyID - A standalone, single user, OpenID Identity Provider
+ *
+ * @package phpMyID
+ * @author CJ Niemira <siege (at) siege (dot) org>
+ * @copyright 2006-2008
+ * @license http://www.gnu.org/licenses/gpl.html GNU Public License
+ * @url http://siege.org/projects/phpMyID
+ * @version 0.9
+ */
+
+/**
+ * Set a constant to indicate that phpMyID is running
+ */
+define('PHPMYID_STARTED', true);
+
+/**
+ * List the known types and modes
+ * @name $known
+ * @global array $GLOBALS['known']
+ */
+$GLOBALS['known'] = array(
+ 'assoc_types' => array('HMAC-SHA1'),
+
+ 'openid_modes' => array('accept',
+ 'associate',
+ 'authorize',
+ 'cancel',
+ 'checkid_immediate',
+ 'checkid_setup',
+ 'check_authentication',
+ 'error',
+ 'id_res',
+ 'login',
+ 'logout',
+ 'test'),
+
+ 'session_types' => array('',
+ 'DH-SHA1'),
+
+ 'bigmath_types' => array('DH-SHA1'),
+);
+
+/**
+ * Defined by OpenID spec
+ * @name $g
+ * @global integer $GLOBALS['g']
+ */
+$GLOBALS['g'] = 2;
+
+/**
+ * Defined by OpenID spec
+ * @name $p
+ * @global integer $GLOBALS['p']
+ */
+$GLOBALS['p'] = '155172898181473697471232257763715539915724801966915404479707' .
+'7953140576293785419175806512274236981889937278161526466314385615958256881888' .
+'8995127215884267541995034125870655654980358010487053768147672651325574704076' .
+'5857479291291572334510643245094715007229621094194349783925984760375594985848' .
+'253359305585439638443';
+
+
+// Runmode functions
+
+/**
+ * Allow the user to accept trust on a URL
+ * @global array $profile
+ */
+function accept_mode () {
+ global $profile;
+
+ // this is a user session
+ user_session();
+
+ // the user needs refresh urls in their session to access this mode
+ if (! isset($_SESSION['post_accept_url']) || ! isset($_SESSION['cancel_accept_url']) || ! isset($_SESSION['unaccepted_url']))
+ error_500('You may not access this mode directly.');
+
+ // has the user accepted the trust_root?
+ $accepted = @strlen($_REQUEST['accepted'])
+ ? $_REQUEST['accepted']
+ : null;
+
+ // if so, refresh back to post_accept_url
+ if ($accepted === 'yes') {
+ $_SESSION['accepted_url'] = $_SESSION['unaccepted_url'];
+ wrap_redirect($_SESSION['post_accept_url']);
+
+ // if they rejected it, return to the client
+ } elseif ($accepted === 'no') {
+ wrap_redirect($_SESSION['cancel_accept_url']);
+ }
+
+ // if neither, offer the trust request
+ $q = strpos($profile['req_url'], '?') ? '&' : '?';
+ $yes = $profile['req_url'] . $q . 'accepted=yes';
+ $no = $profile['req_url'] . $q . 'accepted=no';
+
+ wrap_html('The client site you are attempting to log into has requested that you trust the following URL:<br/><b>' . $_SESSION['unaccepted_url'] . '</b><br/><br/>Do you wish to continue?<br/><a href="' . $yes . '">Yes</a> | <a href="' . $no . '">No</a>');
+}
+
+/** * Perform an association with a consumer
+ * @global array $known
+ * @global array $profile
+ * @global integer $g
+ * @global integer $p
+ */
+function associate_mode () {
+ global $g, $known, $p, $profile;
+
+ // Validate the request
+ if (! isset($_REQUEST['openid_mode']) || $_REQUEST['openid_mode'] != 'associate')
+ error_400();
+
+ // Get the request options, using defaults as necessary
+ $assoc_type = (@strlen($_REQUEST['openid_assoc_type'])
+ && in_array($_REQUEST['openid_assoc_type'], $known['assoc_types']))
+ ? $_REQUEST['openid_assoc_type']
+ : 'HMAC-SHA1';
+
+ $session_type = (@strlen($_REQUEST['openid_session_type'])
+ && in_array($_REQUEST['openid_session_type'], $known['session_types']))
+ ? $_REQUEST['openid_session_type']
+ : '';
+
+ $dh_modulus = (@strlen($_REQUEST['openid_dh_modulus']))
+ ? long(base64_decode($_REQUEST['openid_dh_modulus']))
+ : ($session_type == 'DH-SHA1'
+ ? $p
+ : null);
+
+ $dh_gen = (@strlen($_REQUEST['openid_dh_gen']))
+ ? long(base64_decode($_REQUEST['openid_dh_gen']))
+ : ($session_type == 'DH-SHA1'
+ ? $g
+ : null);
+
+ $dh_consumer_public = (@strlen($_REQUEST['openid_dh_consumer_public']))
+ ? $_REQUEST['openid_dh_consumer_public']
+ : ($session_type == 'DH-SHA1'
+ ? error_post('dh_consumer_public was not specified')
+ : null);
+
+ $lifetime = time() + $profile['lifetime'];
+
+ // Create standard keys
+ $keys = array(
+ 'assoc_type' => $assoc_type,
+ 'expires_in' => $profile['lifetime']
+ );
+
+ // If I can't handle bigmath, default to plaintext sessions
+ if (in_array($session_type, $known['bigmath_types']) && $profile['use_bigmath'] === false)
+ $session_type = null;
+
+ // Add response keys based on the session type
+ switch ($session_type) {
+ case 'DH-SHA1':
+ // Create the associate id and shared secret now
+ list ($assoc_handle, $shared_secret) = new_assoc($lifetime);
+
+ // Compute the Diffie-Hellman stuff
+ $private_key = random($dh_modulus);
+ $public_key = bmpowmod($dh_gen, $private_key, $dh_modulus);
+ $remote_key = long(base64_decode($dh_consumer_public));
+ $ss = bmpowmod($remote_key, $private_key, $dh_modulus);
+
+ $keys['assoc_handle'] = $assoc_handle;
+ $keys['session_type'] = $session_type;
+ $keys['dh_server_public'] = base64_encode(bin($public_key));
+ $keys['enc_mac_key'] = base64_encode(x_or(sha1_20(bin($ss)), $shared_secret));
+
+ break;
+
+ default:
+ // Create the associate id and shared secret now
+ list ($assoc_handle, $shared_secret) = new_assoc($lifetime);
+
+ $keys['assoc_handle'] = $assoc_handle;
+ $keys['mac_key'] = base64_encode($shared_secret);
+ }
+
+ // Return the keys
+ wrap_kv($keys);
+}
+
+
+/**
+ * Perform a user authorization
+ * @global array $profile
+ */
+function authorize_mode () {
+ global $profile;
+ global $USERNAME;
+ global $IDENTITY;
+
+ // this is a user session
+
+ // the user needs refresh urls in their session to access this mode
+ if (! isset($_SESSION['post_auth_url']) || ! isset($_SESSION['cancel_auth_url']))
+ error_500('You may not access this mode directly.');
+
+ $profile['idp_url']=$IDENTITY;
+ if (isset($_SERVER['PHP_AUTH_USER']) && $profile['authorized'] === false && $_SERVER['PHP_AUTH_USER']==$USERNAME) {
+ if (OCP\User::checkPassword($USERNAME, $_SERVER['PHP_AUTH_PW'])) {// successful login!
+ // return to the refresh url if they get in
+ $_SESSION['openid_auth']=true;
+ $_SESSION['openid_user']=$USERNAME;
+ wrap_redirect($_SESSION['post_auth_url']);
+
+ // failed login
+ } else {
+ $_SESSION['failures']++;
+ debug('Login failed');
+ debug('Fail count: ' . $_SESSION['failures']);
+ }
+
+ }
+
+ // if we get this far the user is not authorized, so send the headers
+ $uid = uniqid(mt_rand(1,9));
+ $_SESSION['uniqid'] = $uid;
+
+// debug('Prompting user to log in. Stale? ' . $stale);
+ header('HTTP/1.0 401 Unauthorized');
+// header(sprintf('WWW-Authenticate: Digest qop="auth-int, auth", realm="%s", domain="%s", nonce="%s", opaque="%s", stale="%s", algorithm="MD5"', $profile['auth_realm'], $profile['auth_domain'], $uid, md5($profile['auth_realm']), $stale ? 'true' : 'false'));
+ header('WWW-Authenticate: Basic realm="ownCloud"');
+ $q = strpos($_SESSION['cancel_auth_url'], '?') ? '&' : '?';
+ wrap_refresh($_SESSION['cancel_auth_url'] . $q . 'openid.mode=cancel');
+// die('401 Unauthorized');
+}
+
+
+/**
+ * Handle a consumer's request for cancellation.
+ */
+function cancel_mode () {
+ wrap_html('Request cancelled.');
+}
+
+
+/**
+ * Handle a consumer's request to see if the user is authenticated
+ */
+function check_authentication_mode () {
+ // Validate the request
+ if (! isset($_REQUEST['openid_mode']) || $_REQUEST['openid_mode'] != 'check_authentication')
+ error_400();
+
+ $assoc_handle = @strlen($_REQUEST['openid_assoc_handle'])
+ ? $_REQUEST['openid_assoc_handle']
+ : error_post('Missing assoc_handle');
+
+ $sig = @strlen($_REQUEST['openid_sig'])
+ ? $_REQUEST['openid_sig']
+ : error_post('Missing sig');
+
+ $signed = @strlen($_REQUEST['openid_signed'])
+ ? $_REQUEST['openid_signed']
+ : error_post('Missing signed');
+
+ // Prepare the return keys
+ $keys = array(
+ 'openid.mode' => 'id_res'
+ );
+
+ // Invalidate the assoc handle if we need to
+ if (@strlen($_REQUEST['openid_invalidate_handle'])) {
+ destroy_assoc_handle($_REQUEST['openid_invalidate_handle']);
+
+ $keys['invalidate_handle'] = $_REQUEST['openid_invalidate_handle'];
+ }
+
+ // Validate the sig by recreating the kv pair and signing
+ $_REQUEST['openid_mode'] = 'id_res';
+ $tokens = '';
+ foreach (explode(',', $signed) as $param) {
+ $post = preg_replace('/\./', '_', $param);
+ $tokens .= sprintf("%s:%s\n", $param, $_REQUEST['openid_' . $post]);
+ }
+
+ // Add the sreg stuff, if we've got it
+ if (isset($sreg_required)) {
+ foreach (explode(',', $sreg_required) as $key) {
+ if (! isset($sreg[$key]))
+ continue;
+ $skey = 'sreg.' . $key;
+
+ $tokens .= sprintf("%s:%s\n", $skey, $sreg[$key]);
+ $keys[$skey] = $sreg[$key];
+ $fields[] = $skey;
+ }
+ }
+
+ // Look up the consumer's shared_secret and timeout
+ list ($shared_secret, $expires) = secret($assoc_handle);
+
+ // if I can't verify the assoc_handle, or if it's expired
+ if ($shared_secret == false || (is_numeric($expires) && $expires < time())) {
+ $keys['is_valid'] = 'false';
+
+ } else {
+ $ok = base64_encode(hmac($shared_secret, $tokens));
+ $keys['is_valid'] = ($sig == $ok) ? 'true' : 'false';
+ }
+
+ // Return the keys
+ wrap_kv($keys);
+}
+
+
+/**
+ * Handle a consumer's request to see if the end user is logged in
+ * @global array $known
+ * @global array $profile
+ * @global array $sreg
+ */
+function checkid ( $wait ) {
+ global $known, $profile, $sreg;
+ global $USERNAME;
+
+ // This is a user session
+ user_session();
+
+ // Get the options, use defaults as necessary
+ $return_to = isset($_REQUEST['openid_return_to'])
+ ? $_REQUEST['openid_return_to']
+ : error_400('Missing return_to');
+
+ $identity = isset($_REQUEST['openid_identity'])
+ ? $_REQUEST['openid_identity']
+ : error_get($return_to, 'Missing identity');
+
+ $assoc_handle = isset($_REQUEST['openid_assoc_handle'])
+ ? $_REQUEST['openid_assoc_handle']
+ : null;
+
+ $trust_root = isset($_REQUEST['openid_trust_root'])
+ ? $_REQUEST['openid_trust_root']
+ : $return_to;
+
+ $sreg_required = isset($_REQUEST['openid_sreg_required'])
+ ? $_REQUEST['openid_sreg.required']
+ : '';
+
+ $sreg_optional = isset($_REQUEST['openid_sreg_optional'])
+ ? $_REQUEST['openid_sreg.optional']
+ : '';
+
+ // determine the cancel url
+ $q = strpos($return_to, '?') ? '&' : '?';
+ $cancel_url = $return_to . $q . 'openid.mode=cancel';
+
+ // required and optional make no difference to us
+ $sreg_required .= ',' . $sreg_optional;
+ // do the trust_root analysis
+ if ($trust_root != $return_to) {
+ // the urls are not the same, be sure return decends from trust
+ if (! url_descends($return_to, $trust_root))
+ error_500('Invalid trust_root: "' . $trust_root . '"');
+
+ }
+
+ // transfer the user to the url accept mode if they're paranoid
+ if ($wait == 1 && isset($profile['paranoid']) && $profile['paranoid'] === true && (! isset($_SESSION['accepted_url']) || $_SESSION['accepted_url'] != $trust_root)) {
+ $_SESSION['cancel_accept_url'] = $cancel_url;
+ $_SESSION['post_accept_url'] = $profile['req_url'];
+ $_SESSION['unaccepted_url'] = $trust_root;
+
+ debug('Transferring to acceptance mode.');
+ debug('Cancel URL: ' . $_SESSION['cancel_accept_url']);
+ debug('Post URL: ' . $_SESSION['post_accept_url']);
+
+ $q = strpos($profile['idp_url'], '?') ? '&' : '?';
+ wrap_redirect($profile['idp_url'] . $q . 'openid.mode=accept');
+ }
+
+ // make sure i am this identifier
+// if ($identity != $profile['idp_url']) {
+// debug("Invalid identity: $identity");
+// debug("IdP URL: " . $profile['idp_url']);
+// error_get($return_to, "Invalid identity: '$identity'");
+// }
+
+ // begin setting up return keys
+ $keys = array(
+ 'mode' => 'id_res'
+ );
+
+ // if the user is not logged in, transfer to the authorization mode
+ if ($USERNAME=='' || $_SESSION['openid_auth'] === false || $USERNAME != $_SESSION['openid_user']) {
+ // users can only be logged in to one url at a time
+ $_SESSION['openid_user'] = null;
+ $_SESSION['auth_url'] = null;
+
+ if ($wait) {
+ unset($_SESSION['uniqid']);
+
+ $_SESSION['cancel_auth_url'] = $cancel_url;
+ $_SESSION['post_auth_url'] = $profile['req_url'];
+
+ debug('Transferring to authorization mode.');
+ debug('Cancel URL: ' . $_SESSION['cancel_auth_url']);
+ debug('Post URL: ' . $_SESSION['post_auth_url']);
+
+ $q = strpos($profile['idp_url'], '?') ? '&' : '?';
+ wrap_redirect($profile['idp_url'] . $q . 'openid.mode=authorize');
+ } else {
+ $keys['user_setup_url'] = $profile['idp_url'];
+ }
+
+ // the user is logged in
+ } else {
+ // remove the refresh URLs if set
+ unset($_SESSION['cancel_auth_url']);
+ unset($_SESSION['post_auth_url']);
+
+ // check the assoc handle
+ list($shared_secret, $expires) = secret($assoc_handle);
+
+ // if I can't verify the assoc_handle, or if it's expired
+ if ($shared_secret == false || (is_numeric($expires) && $expires < time())) {
+ debug("Session expired or missing key: $expires < " . time());
+ if ($assoc_handle != null) {
+ $keys['invalidate_handle'] = $assoc_handle;
+ destroy_assoc_handle($assoc_handle);
+ }
+
+ $lifetime = time() + $profile['lifetime'];
+ list ($assoc_handle, $shared_secret) = new_assoc($lifetime);
+ }
+
+ $keys['identity'] = $profile['idp_url'];
+ $keys['assoc_handle'] = $assoc_handle;
+ $keys['return_to'] = $return_to;
+
+ $fields = array_keys($keys);
+ $tokens = '';
+ foreach ($fields as $key)
+ $tokens .= sprintf("%s:%s\n", $key, $keys[$key]);
+
+ // add sreg keys
+ foreach (explode(',', $sreg_required) as $key) {
+ if (! isset($sreg[$key]))
+ continue;
+ $skey = 'sreg.' . $key;
+
+ $tokens .= sprintf("%s:%s\n", $skey, $sreg[$key]);
+ $keys[$skey] = $sreg[$key];
+ $fields[] = $skey;
+ }
+
+ $keys['signed'] = implode(',', $fields);
+ $keys['sig'] = base64_encode(hmac($shared_secret, $tokens));
+ }
+
+ wrap_keyed_redirect($return_to, $keys);
+}
+
+
+/**
+ * Handle a consumer's request to see if the user is already logged in
+ */
+function checkid_immediate_mode () {
+ if (! isset($_REQUEST['openid_mode']) || $_REQUEST['openid_mode'] != 'checkid_immediate')
+ error_500();
+
+ checkid(false);
+}
+
+
+/**
+ * Handle a consumer's request to see if the user is logged in, but be willing
+ * to wait for them to perform a login if they're not
+ */
+function checkid_setup_mode () {
+ if (! isset($_REQUEST['openid_mode']) || $_REQUEST['openid_mode'] != 'checkid_setup')
+ error_500();
+
+ checkid(true);
+}
+
+
+/**
+ * Handle errors
+ */
+function error_mode () {
+ isset($_REQUEST['openid_error'])
+ ? wrap_html($_REQUEST['openid_error'])
+ : error_500();
+}
+
+
+/**
+ * Show a user if they are logged in or not
+ * @global array $profile
+ */
+function id_res_mode () {
+ global $profile;
+
+ user_session();
+
+ if ($profile['authorized'])
+ wrap_html('You are logged in as ' . $_SESSION['auth_username']);
+
+ wrap_html('You are not logged in');
+}
+
+
+/**
+ * Allow a user to perform a static login
+ * @global array $profile
+ */
+function login_mode () {
+ global $profile;
+
+ user_session();
+
+ if ($profile['authorized'])
+ id_res_mode();
+
+ $keys = array(
+ 'mode' => 'checkid_setup',
+ 'identity' => $profile['idp_url'],
+ 'return_to' => $profile['idp_url']
+ );
+
+ wrap_keyed_redirect($profile['idp_url'], $keys);
+}
+
+
+/**
+ * Allow a user to perform a static logout
+ * @global array $profile
+ */
+function logout_mode () {
+ global $profile;
+
+ user_session();
+
+ if (! $profile['authorized'])
+ wrap_html('You were not logged in');
+
+ $_SESSION = array();
+ session_destroy();
+ debug('User session destroyed.');
+
+ header('HTTP/1.0 401 Unauthorized');
+ wrap_redirect($profile['idp_url']);
+}
+
+
+/**
+ * The default information screen
+ * @global array $profile
+ */
+function no_mode () {
+ global $USERNAME, $profile;
+ $tmpl = new OCP\Template( 'user_openid', 'nomode', 'guest' );
+ if(substr($profile['req_url'],-1,1)!=='/'){//the identity should always end with a /
+ $profile['req_url'].='/';
+ }
+ $tmpl->addHeader('link',array('rel'=>'openid.server', 'href'=>$profile['req_url']));
+ $tmpl->addHeader('link',array('rel'=>'openid.delegate', 'href'=>$profile['idp_url']));
+ $tmpl->assign('user',$USERNAME);
+ $tmpl->printPage();
+}
+
+
+/**
+ * Testing for setup
+ * @global array $profile
+ */
+function test_mode () {
+ global $profile, $p, $g;
+
+ if ($profile['allow_test'] != true)
+ error_403();
+
+ @ini_set('max_execution_time', 180);
+
+ $test_expire = time() + 120;
+ $test_ss_enc = 'W7hvmld2yEYdDb0fHfSkKhQX+PM=';
+ $test_ss = base64_decode($test_ss_enc);
+ $test_token = "alpha:bravo\ncharlie:delta\necho:foxtrot";
+ $test_server_private = '11263846781670293092494395517924811173145217135753406847875706165886322533899689335716152496005807017390233667003995430954419468996805220211293016296351031812246187748601293733816011832462964410766956326501185504714561648498549481477143603650090931135412673422192550825523386522507656442905243832471167330268';
+ $test_client_public = base64_decode('AL63zqI5a5p8HdXZF5hFu8p+P9GOb816HcHuvNOhqrgkKdA3fO4XEzmldlb37nv3+xqMBgWj6gxT7vfuFerEZLBvuWyVvR7IOGZmx0BAByoq3fxYd3Fpe2Coxngs015vK37otmH8e83YyyGo5Qua/NAf13yz1PVuJ5Ctk7E+YdVc');
+
+ $res = array();
+
+ // bcmath
+ $res['bcmath'] = extension_loaded('bcmath')
+ ? 'pass' : 'warn - not loaded';
+
+ // gmp
+ if ($profile['allow_gmp']) {
+ $res['gmp'] = extension_loaded('gmp')
+ ? 'pass' : 'warn - not loaded';
+ } else {
+ $res['gmp'] = 'pass - n/a';
+ }
+
+ // get_temp_dir
+ $res['logfile'] = is_writable($profile['logfile'])
+ ? 'pass' : "warn - log is not writable";
+
+ // session & new_assoc
+ user_session();
+ list($test_assoc, $test_new_ss) = new_assoc($test_expire);
+ $res['session'] = ($test_assoc != session_id())
+ ? 'pass' : 'fail';
+
+ // secret
+ @session_unregister('shared_secret');
+ list($check, $check2) = secret($test_assoc);
+ $res['secret'] = ($check == $test_new_ss)
+ ? 'pass' : 'fail';
+
+ // expire
+ $res['expire'] = ($check2 <= $test_expire)
+ ? 'pass' : 'fail';
+
+ // base64
+ $res['base64'] = (base64_encode($test_ss) == $test_ss_enc)
+ ? 'pass' : 'fail';
+
+ // hmac
+ $test_sig = base64_decode('/VXgHvZAOdoz/OTa5+XJXzSGhjs=');
+ $check = hmac($test_ss, $test_token);
+ $res['hmac'] = ($check == $test_sig)
+ ? 'pass' : sprintf("fail - '%s'", base64_encode($check));
+
+ if ($profile['use_bigmath']) {
+ // bigmath powmod
+ $test_server_public = '102773334773637418574009974502372885384288396853657336911033649141556441102566075470916498748591002884433213640712303846640842555822818660704173387461364443541327856226098159843042567251113889701110175072389560896826887426539315893475252988846151505416694218615764823146765717947374855806613410142231092856731';
+ $check = bmpowmod($g, $test_server_private, $p);
+ $res['bmpowmod-1'] = ($check == $test_server_public)
+ ? 'pass' : sprintf("fail - '%s'", $check);
+
+ // long
+ $test_client_long = '133926731803116519408547886573524294471756220428015419404483437186057383311250738749035616354107518232016420809434801736658109316293127101479053449990587221774635063166689561125137927607200322073086097478667514042144489248048756916881344442393090205172004842481037581607299263456852036730858519133859409417564';
+ $res['long'] = (long($test_client_public) == $test_client_long)
+ ? 'pass' : 'fail';
+
+ // bigmath powmod 2
+ $test_client_share = '19333275433742428703546496981182797556056709274486796259858099992516081822015362253491867310832140733686713353304595602619444380387600756677924791671971324290032515367930532292542300647858206600215875069588627551090223949962823532134061941805446571307168890255137575975911397744471376862555181588554632928402';
+ $check = bmpowmod($test_client_long, $test_server_private, $p);
+ $res['bmpowmod-2'] = ($check == $test_client_share)
+ ? 'pass' : sprintf("fail - '%s'", $check);
+
+ // bin
+ $test_client_mac_s1 = base64_decode('G4gQQkYM6QmAzhKbVKSBahFesPL0nL3F2MREVwEtnVRRYI0ifl9zmPklwTcvURt3QTiGBd+9Dn3ESLk5qka6IO5xnILcIoBT8nnGVPiOZvTygfuzKp4tQ2mXuIATJoa7oXRGmBWtlSdFapH5Zt6NJj4B83XF/jzZiRwdYuK4HJI=');
+ $check = bin($test_client_share);
+ $res['bin'] = ($check == $test_client_mac_s1)
+ ? 'pass' : sprintf("fail - '%s'", base64_encode($check));
+
+ } else {
+ $res['bigmath'] = 'fail - big math functions are not available.';
+ }
+
+ // sha1_20
+ $test_client_mac_s1 = base64_decode('G4gQQkYM6QmAzhKbVKSBahFesPL0nL3F2MREVwEtnVRRYI0ifl9zmPklwTcvURt3QTiGBd+9Dn3ESLk5qka6IO5xnILcIoBT8nnGVPiOZvTygfuzKp4tQ2mXuIATJoa7oXRGmBWtlSdFapH5Zt6NJj4B83XF/jzZiRwdYuK4HJI=');
+ $test_client_mac_s2 = base64_decode('0Mb2t9d/HvAZyuhbARJPYdx3+v4=');
+ $check = sha1_20($test_client_mac_s1);
+ $res['sha1_20'] = ($check == $test_client_mac_s2)
+ ? 'pass' : sprintf("fail - '%s'", base64_encode($check));
+
+ // x_or
+ $test_client_mac_s3 = base64_decode('i36ZLYAJ1rYEx1VEHObrS8hgAg0=');
+ $check = x_or($test_client_mac_s2, $test_ss);
+ $res['x_or'] = ($check == $test_client_mac_s3)
+ ? 'pass' : sprintf("fail - '%s'", base64_encode($check));
+
+ $out = "<table border=1 cellpadding=4>\n";
+ foreach ($res as $test => $stat) {
+ $code = substr($stat, 0, 4);
+ $color = ($code == 'pass') ? '#9f9'
+ : (($code == 'warn') ? '#ff9' : '#f99');
+ $out .= sprintf("<tr><th>%s</th><td style='background:%s'>%s</td></tr>\n", $test, $color, $stat);
+ }
+ $out .= "</table>";
+
+ wrap_html( $out );
+}
+
+
+// Support functions
+
+/**
+ * Prefix the keys of an array with 'openid.'
+ * @param array $array
+ * @return array
+ */
+function append_openid ($array) {
+ $keys = array_keys($array);
+ $vals = array_values($array);
+
+ $r = array();
+ for ($i=0; $i<sizeof($keys); $i++)
+ $r['openid.' . $keys[$i]] = $vals[$i];
+ return $r;
+}
+
+/**
+ * Create a big math addition function
+ * @param string $l
+ * @param string $r
+ * @return string
+ * @url http://www.icosaedro.it/bigint Inspired by
+ */
+function bmadd($l, $r) {
+ if (function_exists('bcadd'))
+ return bcadd($l, $r);
+
+ global $profile;
+ if ($profile['use_gmp'])
+ return gmp_strval(gmp_add($l, $r));
+
+ $l = strval($l); $r = strval($r);
+ $ll = strlen($l); $rl = strlen($r);
+ if ($ll < $rl) {
+ $l = str_repeat("0", $rl-$ll) . $l;
+ $o = $rl;
+
+ } elseif ( $ll > $rl ) {
+ $r = str_repeat("0", $ll-$rl) . $r;
+ $o = $ll;
+
+ } else {
+ $o = $ll;
+ }
+
+ $v = '';
+ $carry = 0;
+
+ for ($i = $o-1; $i >= 0; $i--) {
+ $d = (int)$l[$i] + (int)$r[$i] + $carry;
+ if ($d <= 9) {
+ $carry = 0;
+
+ } else {
+ $carry = 1;
+ $d -= 10;
+ }
+ $v = (string) $d . $v;
+ }
+
+ if ($carry > 0)
+ $v = "1" . $v;
+
+ return $v;
+}
+
+/**
+ * Create a big math comparison function
+ * @param string $l
+ * @param string $r
+ * @return string
+ */
+function bmcomp($l, $r) {
+ if (function_exists('bccomp'))
+ return bccomp($l, $r);
+
+ global $profile;
+ if ($profile['use_gmp'])
+ return gmp_strval(gmp_cmp($l, $r));
+
+ $l = strval($l); $r = strval($r);
+ $ll = strlen($l); $lr = strlen($r);
+ if ($ll != $lr)
+ return ($ll > $lr) ? 1 : -1;
+
+ return strcmp($l, $r);
+}
+
+/**
+ * Create a big math division function
+ * @param string $l
+ * @param string $r
+ * @param int $z
+ * @return string
+ * @url http://www.icosaedro.it/bigint Inspired by
+ */
+function bmdiv($l, $r, $z = 0) {
+ if (function_exists('bcdiv'))
+ return ($z == 0) ? bcdiv($l, $r) : bcmod($l, $r);
+
+ global $profile;
+ if ($profile['use_gmp'])
+ return gmp_strval(($z == 0) ? gmp_div_q($l, $r) : gmp_mod($l, $r));
+
+ $l = strval($l); $r = strval($r);
+ $v = '0';
+
+ while (true) {
+ if( bmcomp($l, $r) < 0 )
+ break;
+
+ $delta = strlen($l) - strlen($r);
+ if ($delta >= 1) {
+ $zeroes = str_repeat("0", $delta);
+ $r2 = $r . $zeroes;
+
+ if (strcmp($l, $r2) >= 0) {
+ $v = bmadd($v, "1" . $zeroes);
+ $l = bmsub($l, $r2);
+
+ } else {
+ $zeroes = str_repeat("0", $delta - 1);
+ $v = bmadd($v, "1" . $zeroes);
+ $l = bmsub($l, $r . $zeroes);
+ }
+
+ } else {
+ $l = bmsub($l, $r);
+ $v = bmadd($v, "1");
+ }
+ }
+
+ return ($z == 0) ? $v : $l;
+}
+
+/**
+ * Create a big math multiplication function
+ * @param string $l
+ * @param string $r
+ * @return string
+ * @url http://www.icosaedro.it/bigint Inspired by
+ */
+function bmmul($l, $r) {
+ if (function_exists('bcmul'))
+ return bcmul($l, $r);
+
+ global $profile;
+ if ($profile['use_gmp'])
+ return gmp_strval(gmp_mul($l, $r));
+
+ $l = strval($l); $r = strval($r);
+
+ $v = '0';
+ $z = '';
+
+ for( $i = strlen($r)-1; $i >= 0; $i-- ){
+ $bd = (int) $r[$i];
+ $carry = 0;
+ $p = "";
+ for( $j = strlen($l)-1; $j >= 0; $j-- ){
+ $ad = (int) $l[$j];
+ $pd = $ad * $bd + $carry;
+ if( $pd <= 9 ){
+ $carry = 0;
+ } else {
+ $carry = (int) ($pd / 10);
+ $pd = $pd % 10;
+ }
+ $p = (string) $pd . $p;
+ }
+ if( $carry > 0 )
+ $p = (string) $carry . $p;
+ $p = $p . $z;
+ $z .= "0";
+ $v = bmadd($v, $p);
+ }
+
+ return $v;
+}
+
+/**
+ * Create a big math modulus function
+ * @param string $value
+ * @param string $mod
+ * @return string
+ */
+function bmmod( $value, $mod ) {
+ if (function_exists('bcmod'))
+ return bcmod($value, $mod);
+
+ global $profile;
+ if ($profile['use_gmp'])
+ return gmp_strval(gmp_mod($value, $mod));
+
+ $r = bmdiv($value, $mod, 1);
+ return $r;
+}
+
+/**
+ * Create a big math power function
+ * @param string $value
+ * @param string $exponent
+ * @return string
+ */
+function bmpow ($value, $exponent) {
+ if (function_exists('bcpow'))
+ return bcpow($value, $exponent);
+
+ global $profile;
+ if ($profile['use_gmp'])
+ return gmp_strval(gmp_pow($value, $exponent));
+
+ $r = '1';
+ while ($exponent) {
+ $r = bmmul($r, $value, 100);
+ $exponent--;
+ }
+ return (string)rtrim($r, '0.');
+}
+
+/**
+ * Create a big math 'powmod' function
+ * @param string $value
+ * @param string $exponent
+ * @param string $mod
+ * @return string
+ * @url http://php.net/manual/en/function.bcpowmod.php#72704 Borrowed from
+ */
+function bmpowmod ($value, $exponent, $mod) {
+ if (function_exists('bcpowmod'))
+ return bcpowmod($value, $exponent, $mod);
+
+ global $profile;
+ if ($profile['use_gmp'])
+ return gmp_strval(gmp_powm($value, $exponent, $mod));
+
+ $r = '';
+ while ($exponent != '0') {
+ $t = bmmod($exponent, '4096');
+ $r = substr("000000000000" . decbin(intval($t)), -12) . $r;
+ $exponent = bmdiv($exponent, '4096');
+ }
+
+ $r = preg_replace("!^0+!","",$r);
+
+ if ($r == '')
+ $r = '0';
+ $value = bmmod($value, $mod);
+ $erb = strrev($r);
+ $q = '1';
+ $a[0] = $value;
+
+ for ($i = 1; $i < strlen($erb); $i++) {
+ $a[$i] = bmmod( bmmul($a[$i-1], $a[$i-1]), $mod );
+ }
+
+ for ($i = 0; $i < strlen($erb); $i++) {
+ if ($erb[$i] == "1") {
+ $q = bmmod( bmmul($q, $a[$i]), $mod );
+ }
+ }
+
+ return($q);
+}
+
+/**
+ * Create a big math subtraction function
+ * @param string $l
+ * @param string $r
+ * @return string
+ * @url http://www.icosaedro.it/bigint Inspired by
+ */
+function bmsub($l, $r) {
+ if (function_exists('bcsub'))
+ return bcsub($l, $r);
+
+ global $profile;
+ if ($profile['use_gmp'])
+ return gmp_strval(gmp_sub($l, $r));
+
+
+ $l = strval($l); $r = strval($r);
+ $ll = strlen($l); $rl = strlen($r);
+
+ if ($ll < $rl) {
+ $l = str_repeat("0", $rl-$ll) . $l;
+ $o = $rl;
+ } elseif ( $ll > $rl ) {
+ $r = str_repeat("0", $ll-$rl) . (string)$r;
+ $o = $ll;
+ } else {
+ $o = $ll;
+ }
+
+ if (strcmp($l, $r) >= 0) {
+ $sign = '';
+ } else {
+ $x = $l; $l = $r; $r = $x;
+ $sign = '-';
+ }
+
+ $v = '';
+ $carry = 0;
+
+ for ($i = $o-1; $i >= 0; $i--) {
+ $d = ($l[$i] - $r[$i]) - $carry;
+ if ($d < 0) {
+ $carry = 1;
+ $d += 10;
+ } else {
+ $carry = 0;
+ }
+ $v = (string) $d . $v;
+ }
+
+ return $sign . ltrim($v, '0');
+}
+
+
+/**
+ * Get a binary value
+ * @param integer $n
+ * @return string
+ * @url http://openidenabled.com Borrowed from PHP-OpenID
+ */
+function bin ($n) {
+ $bytes = array();
+ while (bmcomp($n, 0) > 0) {
+ array_unshift($bytes, bmmod($n, 256));
+ $n = bmdiv($n, bmpow(2,8));
+ }
+
+ if ($bytes && ($bytes[0] > 127))
+ array_unshift($bytes, 0);
+
+ $b = '';
+ foreach ($bytes as $byte)
+ $b .= pack('C', $byte);
+
+ return $b;
+}
+
+
+/**
+ * Debug logging
+ * @param mixed $x
+ * @param string $m
+ */
+function debug ($x, $m = null) {
+ global $profile;
+
+ if (! isset($profile['debug']) || $profile['debug'] === false)
+ return true;
+
+ if (! is_writable(dirname($profile['logfile'])) &! is_writable($profile['logfile']))
+ error_500('Cannot write to debug log: ' . $profile['logfile']);
+
+ if (is_array($x)) {
+ ob_start();
+ print_r($x);
+ $x = $m . ($m != null ? "\n" : '') . ob_get_clean();
+
+ } else {
+ $x .= "\n";
+ }
+}
+
+
+/**
+ * Destroy a consumer's assoc handle
+ * @param string $id
+ */
+function destroy_assoc_handle ( $id ) {
+ debug("Destroying session: $id");
+
+ $sid = session_id();
+ session_write_close();
+
+ session_id($id);
+ if (OCP\Config::getSystemValue( "forcessl", false )) {
+ ini_set("session.cookie_secure", "on");
+ }
+ session_start();
+ session_destroy();
+
+ session_id($sid);
+ session_start();
+}
+
+
+/**
+ * Return an error message to the user
+ * @param string $message
+ */
+function error_400 ( $message = 'Bad Request' ) {
+ header("HTTP/1.1 400 Bad Request");
+ wrap_html($message);
+}
+
+
+/**
+ * Return an error message to the user
+ * @param string $message
+ */
+function error_403 ( $message = 'Forbidden' ) {
+ header("HTTP/1.1 403 Forbidden");
+ wrap_html($message);
+}
+
+
+/**
+ * Return an error message to the user
+ * @param string $message
+ */
+function error_500 ( $message = 'Internal Server Error' ) {
+ header("HTTP/1.1 500 Internal Server Error");
+ wrap_html($message);
+}
+
+
+/**
+ * Return an error message to the consumer
+ * @param string $message
+ */
+function error_get ( $url, $message = 'Bad Request') {
+ wrap_keyed_redirect($url, array('mode' => 'error', 'error' => $message));
+}
+
+
+/**
+ * Return an error message to the consumer
+ * @param string $message
+ */
+function error_post ( $message = 'Bad Request' ) {
+ header("HTTP/1.1 400 Bad Request");
+ echo ('error:' . $message);
+ exit(0);
+}
+
+
+/**
+ * Do an HMAC
+ * @param string $key
+ * @param string $data
+ * @param string $hash
+ * @return string
+ * @url http://php.net/manual/en/function.sha1.php#39492 Borrowed from
+ */
+function hmac($key, $data, $hash = 'sha1_20') {
+ $blocksize=64;
+
+ if (strlen($key) > $blocksize)
+ $key = $hash($key);
+
+ $key = str_pad($key, $blocksize,chr(0x00));
+ $ipad = str_repeat(chr(0x36),$blocksize);
+ $opad = str_repeat(chr(0x5c),$blocksize);
+
+ $h1 = $hash(($key ^ $ipad) . $data);
+ $hmac = $hash(($key ^ $opad) . $h1);
+ return $hmac;
+}
+
+
+if (! function_exists('http_build_query')) {
+/**
+ * Create function if missing
+ * @param array $array
+ * @return string
+ */
+function http_build_query ($array) {
+ $r = array();
+ foreach ($array as $key => $val)
+ $r[] = sprintf('%s=%s', urlencode($key), urlencode($val));
+ return implode('&', $r);
+}}
+
+
+/**
+ * Turn a binary back into a long
+ * @param string $b
+ * @return integer
+ * @url http://openidenabled.com Borrowed from PHP-OpenID
+ */
+function long($b) {
+ $bytes = array_merge(unpack('C*', $b));
+ $n = 0;
+ foreach ($bytes as $byte) {
+ $n = bmmul($n, bmpow(2,8));
+ $n = bmadd($n, $byte);
+ }
+ return $n;
+}
+
+
+/**
+ * Create a new consumer association
+ * @param integer $expiration
+ * @return array
+ */
+function new_assoc ( $expiration ) {
+ if (isset($_SESSION) && is_array($_SESSION)) {
+ $sid = session_id();
+ $dat = session_encode();
+ session_write_close();
+ }
+
+ if (OCP\Config::getSystemValue( "forcessl", false )) {
+ ini_set("session.cookie_secure", "on");
+ }
+ session_start();
+ session_regenerate_id('false');
+
+ $id = session_id();
+ $shared_secret = new_secret();
+ debug('Started new assoc session: ' . $id);
+
+ $_SESSION = array();
+ $_SESSION['expiration'] = $expiration;
+ $_SESSION['shared_secret'] = base64_encode($shared_secret);
+
+ session_write_close();
+
+ if (isset($sid)) {
+ session_id($sid);
+ session_start();
+ $_SESSION = array();
+ session_decode($dat);
+ }
+
+ return array($id, $shared_secret);
+}
+
+
+/**
+ * Create a new shared secret
+ * @return string
+ */
+function new_secret () {
+ $r = '';
+ for($i=0; $i<20; $i++)
+ $r .= chr(mt_rand(0, 255));
+
+ debug("Generated new key: hash = '" . md5($r) . "', length = '" . strlen($r) . "'");
+ return $r;
+}
+
+
+/**
+ * Random number generation
+ * @param integer max
+ * @return integer
+ */
+function random ( $max ) {
+ if (strlen($max) < 4)
+ return mt_rand(1, $max - 1);
+
+ $r = '';
+ for($i=1; $i<strlen($max) - 1; $i++)
+ $r .= mt_rand(0,9);
+ $r .= mt_rand(1,9);
+
+ return $r;
+}
+
+/**
+ * Get the shared secret and expiration time for the specified assoc_handle
+ * @param string $handle assoc_handle to look up
+ * @return array (shared_secret, expiration_time)
+ */
+function secret ( $handle ) {
+ if (! preg_match('/^\w+$/', $handle))
+ return array(false, 0);
+
+ if (isset($_SESSION) && is_array($_SESSION)) {
+ $sid = session_id();
+ $dat = session_encode();
+ session_write_close();
+ }
+
+ session_id($handle);
+ if (OCP\Config::getSystemValue( "forcessl", false )) {
+ ini_set("session.cookie_secure", "on");
+ }
+ session_start();
+ debug('Started session to acquire key: ' . session_id());
+
+ $secret = isset($_SESSION['shared_secret'])
+ ? base64_decode($_SESSION['shared_secret'])
+ : false;
+
+ $expiration = isset($_SESSION['expiration'])
+ ? $_SESSION['expiration']
+ : null;
+
+ session_write_close();
+
+ if (isset($sid)) {
+ session_id($sid);
+ session_start();
+ $_SESSION = array();
+ session_decode($dat);
+ }
+
+ debug("Found key: hash = '" . md5($secret) . "', length = '" . strlen($secret) . "', expiration = '$expiration'");
+ return array($secret, $expiration);
+}
+
+
+/**
+ * Do an internal self check
+ * @global array $profile
+ * @global array $sreg
+ */
+function self_check () {
+ global $profile, $sreg;
+
+// if (! isset($profile) || ! is_array($profile))
+// error_500('No configuration found, you shouldn\'t access this file directly.');
+
+ if (version_compare(phpversion(), '4.2.0', 'lt'))
+ error_500('The required minimum version of PHP is 4.2.0, you are running ' . phpversion());
+
+ $extension_r = array('session', 'pcre');
+ foreach ($extension_r as $x) {
+ if (! extension_loaded($x))
+ @dl($x);
+ if (! extension_loaded($x))
+ error_500("Required extension '$x' is missing.");
+ }
+
+// $extension_b = array('suhosin');
+// foreach ($extension_b as $x) {
+// if (extension_loaded($x) &! $profile["allow_$x"])
+// error_500("phpMyID is not compatible with '$x'");
+// }
+//
+// $keys = array('auth_username', 'auth_password');
+// foreach ($keys as $key) {
+// if (! array_key_exists($key, $profile))
+// error_500("'$key' is missing from your profile.");
+// }
+
+ if (! isset($sreg) || ! is_array($sreg))
+ $sreg = array();
+}
+
+
+/**
+ * Do SHA1 20 byte encryption
+ * @param string $v
+ * @return string
+ * @url http://openidenabled.com Borrowed from PHP-OpenID
+ */
+function sha1_20 ($v) {
+ if (version_compare(phpversion(), '5.0.0', 'ge'))
+ return sha1($v, true);
+
+ $hex = sha1($v);
+ $r = '';
+ for ($i = 0; $i < 40; $i += 2) {
+ $hexcode = substr($hex, $i, 2);
+ $charcode = base_convert($hexcode, 16, 10);
+ $r .= chr($charcode);
+ }
+ return $r;
+}
+
+
+/**
+ * Look for the point of differentiation in two strings
+ * @param string $a
+ * @param string $b
+ * @return int
+ */
+function str_diff_at ($a, $b) {
+ if ($a == $b)
+ return -1;
+ $n = min(strlen($a), strlen($b));
+ for ($i = 0; $i < $n; $i++)
+ if ($a[$i] != $b[$i])
+ return $i;
+ return $n;
+}
+
+/**
+ * Determine if a child URL actually decends from the parent, and that the
+ * parent is a good URL.
+ * THIS IS EXPERIMENTAL
+ * @param string $parent
+ * @param string $child
+ * @return bool
+ */
+function url_descends ( $child, $parent ) {
+ if ($child == $parent)
+ return true;
+
+ $keys = array();
+ $parts = array();
+
+ $req = array('scheme', 'host');
+ $bad = array('fragment', 'pass', 'user');
+
+ foreach (array('parent', 'child') as $name) {
+ $parts[$name] = @parse_url($$name);
+ if ($parts[$name] === false)
+ return false;
+
+ $keys[$name] = array_keys($parts[$name]);
+
+ if (array_intersect($keys[$name], $req) != $req)
+ return false;
+
+ if (array_intersect($keys[$name], $bad) != array())
+ return false;
+
+ if (! preg_match('/^https?$/i', strtolower($parts[$name]['scheme'])))
+ return false;
+
+ if (! array_key_exists('port', $parts[$name]))
+ $parts[$name]['port'] = (strtolower($parts[$name]['scheme']) == 'https') ? 443 : 80;
+
+ if (! array_key_exists('path', $parts[$name]))
+ $parts[$name]['path'] = '/';
+ }
+
+ // port and scheme must match
+ if ($parts['parent']['scheme'] != $parts['child']['scheme'] ||
+ $parts['parent']['port'] != $parts['child']['port'])
+ return false;
+
+ // compare the hosts by reversing the strings
+ $cr_host = strtolower(strrev($parts['child']['host']));
+ $pr_host = strtolower(strrev($parts['parent']['host']));
+
+ $break = str_diff_at($cr_host, $pr_host);
+ if ($break >= 0 && ($pr_host[$break] != '*' || substr_count(substr($pr_host, 0, $break), '.') < 2))
+ return false;
+
+ // now compare the paths
+ $break = str_diff_at($parts['child']['path'], $parts['parent']['path']);
+ if ($break >= 0
+ && ($break < strlen($parts['parent']['path']) && $parts['parent']['path'][$break] != '*')
+ || ($break > strlen($parts['child']['path'])))
+ return false;
+
+ return true;
+}
+
+
+/**
+ * Create a user session
+ * @global array $profile
+ * @global array $proto
+ */
+function user_session () {
+ global $proto, $profile;
+
+ session_name('phpMyID_Server');
+ if (OCP\Config::getSystemValue( "forcessl", false )) {
+ ini_set("session.cookie_secure", "on");
+ }
+ @session_start();
+
+ $profile['authorized'] = (isset($_SESSION['auth_username'])
+ && $_SESSION['auth_username'] == $profile['auth_username'])
+ ? true
+ : false;
+
+ debug('Started user session: ' . session_id() . ' Auth? ' . $profile['authorized']);
+}
+
+
+/**
+ * Return HTML
+ * @global string $charset
+ * @param string $message
+ */
+function wrap_html ( $message ) {
+ global $charset, $profile;
+ header('Content-Type: text/html; charset=' . $charset);
+ $html= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+<title>phpMyID</title>
+<link rel="openid.server" href="' . $profile['req_url'] . '" />
+<link rel="openid.delegate" href="' . $profile['idp_url'] . '" />
+' . implode("\n", $profile['opt_headers']) . '
+<meta name="charset" content="' . $charset . '" />
+<meta name="robots" content="noindex,nofollow" />
+</head>
+<body>
+<p>' . $message . '</p>
+</body>
+</html>
+';
+ echo $html;
+ exit(0);
+}
+
+
+/**
+ * Return a key-value pair in plain text
+ * @global string $charset
+ * @param array $keys
+ */
+function wrap_kv ( $keys ) {
+ global $charset;
+
+ debug($keys, 'Wrapped key/vals');
+ header('Content-Type: text/plain; charset=' . $charset);
+ foreach ($keys as $key => $value)
+ printf("%s:%s\n", $key, $value);
+
+ exit(0);
+}
+
+
+/**
+ * Redirect, with OpenID keys
+ * @param string $url
+ * @param array @keys
+ */
+function wrap_keyed_redirect ($url, $keys) {
+ $keys = append_openid($keys);
+ debug($keys, 'Location keys');
+
+ $q = strpos($url, '?') ? '&' : '?';
+ wrap_redirect($url . $q . http_build_query($keys));
+}
+
+
+/**
+ * Redirect the browser
+ * @global string $charset
+ * @param string $url
+ */
+function wrap_redirect ($url) {
+ header('HTTP/1.1 302 Found');
+ header('Location: ' . $url);
+ debug('Location: ' . $url);
+ exit(0);
+}
+
+/**
+ * Return an HTML refresh
+ * @global string $charset
+ * @param string $url
+ */
+function wrap_refresh ($url) {
+ global $charset;
+
+ header('Content-Type: text/html; charset=' . $charset);
+ echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+<title>phpMyID</title>
+<meta http-equiv="refresh" content="0;url=' . $url . '">
+</head>
+<body>
+<p>Redirecting to <a href="' . $url . '">' . $url . '</a></p>
+</body>
+</html>
+';
+
+ debug('Refresh: ' . $url);
+ exit(0);
+}
+
+
+/**
+ * Implement binary x_or
+ * @param string $a
+ * @param string $b
+ * @return string
+ */
+function x_or ($a, $b) {
+ $r = "";
+
+ for ($i = 0; $i < strlen($b); $i++)
+ $r .= $a[$i] ^ $b[$i];
+ debug("Xor size: " . strlen($r));
+ return $r;
+}
+
+
+
+/*
+ * App Initialization
+ */
+// Determine the charset to use
+$GLOBALS['charset'] = 'iso-8859-1';
+
+// Set the internal encoding
+if (function_exists('mb_internal_encoding'))
+ mb_internal_encoding($charset);
+
+// Avoid problems with non-default arg_separator.output settings
+// Credit for this goes to user 'prelog' on the forums
+ini_set('arg_separator.output', '&');
+
+// Do a check to be sure everything is set up correctly
+self_check();
+
+
+/**
+ * Determine the HTTP request port
+ * @name $port
+ * @global integer $GLOBALS['port']
+ */
+$GLOBALS['port'] = ((isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on' && $_SERVER['SERVER_PORT'] == 443)
+ || $_SERVER['SERVER_PORT'] == 80)
+ ? ''
+ : ':' . $_SERVER['SERVER_PORT'];
+
+
+/**
+ * Determine the HTTP request protocol
+ * @name $proto
+ * @global string $GLOBALS['proto']
+ */
+$GLOBALS['proto'] = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? 'https' : 'http';
+
+// Set the authorization state - DO NOT OVERRIDE
+$profile['authorized'] = false;
+
+global $IDENTITY;
+global $USERNAME;
+
+// Set a default IDP URL
+if (! array_key_exists('idp_url', $profile))
+ $profile['idp_url'] = $IDENTITY;
+
+//Determine the requested URL - DO NOT OVERRIDE
+$profile['req_url'] = sprintf("%s://%s%s",
+ $proto,
+ OCP\Util::getServerHost(),
+// $port,//host already includes the path
+ $_SERVER["REQUEST_URI"]);
+
+
+// Set the default allowance for testing
+if (! array_key_exists('allow_test', $profile))
+ $profile['allow_test'] = false;
+
+// Set the default allowance for gmp
+if (! array_key_exists('allow_gmp', $profile))
+ $profile['allow_gmp'] = false;
+
+// Set the default force bigmath - BAD IDEA to override this
+if (! array_key_exists('force_bigmath', $profile))
+ $profile['force_bigmath'] = false;
+
+// Determine if GMP is usable
+$profile['use_gmp'] = (extension_loaded('gmp') && $profile['allow_gmp']) ? true : false;
+
+// Determine if I can perform big math functions
+$profile['use_bigmath'] = (extension_loaded('bcmath') || $profile['use_gmp'] || $profile['force_bigmath']) ? true : false;
+
+// Set a default authentication domain
+if (! array_key_exists('auth_domain', $profile))
+ $profile['auth_domain'] = $profile['req_url'] . ' ' . $profile['idp_url'];
+
+// Set a default authentication realm
+if (! array_key_exists('auth_realm', $profile))
+ $profile['auth_realm'] = 'ownCloud';
+
+// Determine the realm for digest authentication - DO NOT OVERRIDE
+$profile['php_realm'] = $profile['auth_realm'] . (ini_get('safe_mode') ? '-' . getmyuid() : '');
+
+// Set a default lifetime - the lesser of GC and cache time
+if (! array_key_exists('lifetime', $profile)) {
+ $sce = session_cache_expire() * 60;
+ $gcm = ini_get('session.gc_maxlifetime');
+ $profile['lifetime'] = $sce < $gcm ? $sce : $gcm;
+}
+
+// Set a default log file
+if (! array_key_exists('logfile', $profile))
+ $profile['logfile'] = get_temp_dir() . DIRECTORY_SEPARATOR . $profile['auth_realm'] . '.debug.log';
+
+
+/*
+ * Optional Initialization
+ */
+// Setup optional headers
+$profile['opt_headers'] = array();
+
+// Determine if I should add microid stuff
+if (array_key_exists('microid', $profile)) {
+ $hash = sha1($profile['idp_url']);
+ $values = is_array($profile['microid']) ? $profile['microid'] : array($profile['microid']);
+
+ foreach ($values as $microid) {
+ preg_match('/^([a-z]+)/i', $microid, $mtx);
+ $profile['opt_headers'][] = sprintf('<meta name="microid" content="%s+%s:sha1:%s" />', $mtx[1], $proto, sha1(sha1($microid) . $hash));
+ }
+}
+
+// Determine if I should add pavatar stuff
+if (array_key_exists('pavatar', $profile))
+ $profile['opt_headers'][] = sprintf('<link rel="pavatar" href="%s" />', $profile['pavatar']);
+
+
+/*
+ * Do it
+ */
+// Decide which runmode, based on user request or default
+$run_mode = (isset($_REQUEST['openid_mode'])
+ && in_array($_REQUEST['openid_mode'], $known['openid_modes']))
+ ? $_REQUEST['openid_mode']
+ : 'no';
+
+// Run in the determined runmode
+debug("Run mode: $run_mode at: " . time());
+debug($_REQUEST, 'Request params');
+call_user_func($run_mode . '_mode');
diff --git a/3rdparty/when/MIT-LICENSE.txt b/3rdparty/when/MIT-LICENSE.txt
deleted file mode 100644
index b4429c89ac1..00000000000
--- a/3rdparty/when/MIT-LICENSE.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-License
-
-Copyright (c) 2010 Thomas Planer
-
-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. \ No newline at end of file
diff --git a/3rdparty/when/When.php b/3rdparty/when/When.php
deleted file mode 100644
index d54f296ed61..00000000000
--- a/3rdparty/when/When.php
+++ /dev/null
@@ -1,731 +0,0 @@
-<?php
-/**
- * Name: When
- * Author: Thomas Planer <tplaner@gmail.com>
- * Location: http://github.com/tplaner/When
- * Created: September 2010
- * Description: Determines the next date of recursion given an iCalendar "rrule" like pattern.
- * Requirements: PHP 5.3+ - makes extensive use of the Date and Time library (http://us2.php.net/manual/en/book.datetime.php)
- */
-class When
-{
- protected $frequency;
-
- protected $start_date;
- protected $try_date;
-
- protected $end_date;
-
- protected $gobymonth;
- protected $bymonth;
-
- protected $gobyweekno;
- protected $byweekno;
-
- protected $gobyyearday;
- protected $byyearday;
-
- protected $gobymonthday;
- protected $bymonthday;
-
- protected $gobyday;
- protected $byday;
-
- protected $gobysetpos;
- protected $bysetpos;
-
- protected $suggestions;
-
- protected $count;
- protected $counter;
-
- protected $goenddate;
-
- protected $interval;
-
- protected $wkst;
-
- protected $valid_week_days;
- protected $valid_frequency;
-
- /**
- * __construct
- */
- public function __construct()
- {
- $this->frequency = null;
-
- $this->gobymonth = false;
- $this->bymonth = range(1,12);
-
- $this->gobymonthday = false;
- $this->bymonthday = range(1,31);
-
- $this->gobyday = false;
- // setup the valid week days (0 = sunday)
- $this->byday = range(0,6);
-
- $this->gobyyearday = false;
- $this->byyearday = range(0,366);
-
- $this->gobysetpos = false;
- $this->bysetpos = range(1,366);
-
- $this->gobyweekno = false;
- // setup the range for valid weeks
- $this->byweekno = range(0,54);
-
- $this->suggestions = array();
-
- // this will be set if a count() is specified
- $this->count = 0;
- // how many *valid* results we returned
- $this->counter = 0;
-
- // max date we'll return
- $this->end_date = new DateTime('9999-12-31');
-
- // the interval to increase the pattern by
- $this->interval = 1;
-
- // what day does the week start on? (0 = sunday)
- $this->wkst = 0;
-
- $this->valid_week_days = array('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA');
-
- $this->valid_frequency = array('SECONDLY', 'MINUTELY', 'HOURLY', 'DAILY', 'WEEKLY', 'MONTHLY', 'YEARLY');
- }
-
- /**
- * @param DateTime|string $start_date of the recursion - also is the first return value.
- * @param string $frequency of the recrusion, valid frequencies: secondly, minutely, hourly, daily, weekly, monthly, yearly
- */
- public function recur($start_date, $frequency = "daily")
- {
- try
- {
- if(is_object($start_date))
- {
- $this->start_date = clone $start_date;
- }
- else
- {
- // timestamps within the RFC have a 'Z' at the end of them, remove this.
- $start_date = trim($start_date, 'Z');
- $this->start_date = new DateTime($start_date);
- }
-
- $this->try_date = clone $this->start_date;
- }
- catch(Exception $e)
- {
- throw new InvalidArgumentException('Invalid start date DateTime: ' . $e);
- }
-
- $this->freq($frequency);
-
- return $this;
- }
-
- public function freq($frequency)
- {
- if(in_array(strtoupper($frequency), $this->valid_frequency))
- {
- $this->frequency = strtoupper($frequency);
- }
- else
- {
- throw new InvalidArgumentException('Invalid frequency type.');
- }
-
- return $this;
- }
-
- // accepts an rrule directly
- public function rrule($rrule)
- {
- // strip off a trailing semi-colon
- $rrule = trim($rrule, ";");
-
- $parts = explode(";", $rrule);
-
- foreach($parts as $part)
- {
- list($rule, $param) = explode("=", $part);
-
- $rule = strtoupper($rule);
- $param = strtoupper($param);
-
- switch($rule)
- {
- case "FREQ":
- $this->frequency = $param;
- break;
- case "UNTIL":
- $this->until($param);
- break;
- case "COUNT":
- $this->count($param);
- break;
- case "INTERVAL":
- $this->interval($param);
- break;
- case "BYDAY":
- $params = explode(",", $param);
- $this->byday($params);
- break;
- case "BYMONTHDAY":
- $params = explode(",", $param);
- $this->bymonthday($params);
- break;
- case "BYYEARDAY":
- $params = explode(",", $param);
- $this->byyearday($params);
- break;
- case "BYWEEKNO":
- $params = explode(",", $param);
- $this->byweekno($params);
- break;
- case "BYMONTH":
- $params = explode(",", $param);
- $this->bymonth($params);
- break;
- case "BYSETPOS":
- $params = explode(",", $param);
- $this->bysetpos($params);
- break;
- case "WKST":
- $this->wkst($param);
- break;
- }
- }
-
- return $this;
- }
-
- //max number of items to return based on the pattern
- public function count($count)
- {
- $this->count = (int)$count;
-
- return $this;
- }
-
- // how often the recurrence rule repeats
- public function interval($interval)
- {
- $this->interval = (int)$interval;
-
- return $this;
- }
-
- // starting day of the week
- public function wkst($day)
- {
- switch($day)
- {
- case 'SU':
- $this->wkst = 0;
- break;
- case 'MO':
- $this->wkst = 1;
- break;
- case 'TU':
- $this->wkst = 2;
- break;
- case 'WE':
- $this->wkst = 3;
- break;
- case 'TH':
- $this->wkst = 4;
- break;
- case 'FR':
- $this->wkst = 5;
- break;
- case 'SA':
- $this->wkst = 6;
- break;
- }
-
- return $this;
- }
-
- // max date
- public function until($end_date)
- {
- try
- {
- if(is_object($end_date))
- {
- $this->end_date = clone $end_date;
- }
- else
- {
- // timestamps within the RFC have a 'Z' at the end of them, remove this.
- $end_date = trim($end_date, 'Z');
- $this->end_date = new DateTime($end_date);
- }
- }
- catch(Exception $e)
- {
- throw new InvalidArgumentException('Invalid end date DateTime: ' . $e);
- }
-
- return $this;
- }
-
- public function bymonth($months)
- {
- if(is_array($months))
- {
- $this->gobymonth = true;
- $this->bymonth = $months;
- }
-
- return $this;
- }
-
- public function bymonthday($days)
- {
- if(is_array($days))
- {
- $this->gobymonthday = true;
- $this->bymonthday = $days;
- }
-
- return $this;
- }
-
- public function byweekno($weeks)
- {
- $this->gobyweekno = true;
-
- if(is_array($weeks))
- {
- $this->byweekno = $weeks;
- }
-
- return $this;
- }
-
- public function bysetpos($days)
- {
- $this->gobysetpos = true;
-
- if(is_array($days))
- {
- $this->bysetpos = $days;
- }
-
- return $this;
- }
-
- public function byday($days)
- {
- $this->gobyday = true;
-
- if(is_array($days))
- {
- $this->byday = array();
- foreach($days as $day)
- {
- $len = strlen($day);
-
- $as = '+';
-
- // 0 mean no occurence is set
- $occ = 0;
-
- if($len == 3)
- {
- $occ = substr($day, 0, 1);
- }
- if($len == 4)
- {
- $as = substr($day, 0, 1);
- $occ = substr($day, 1, 1);
- }
-
- if($as == '-')
- {
- $occ = '-' . $occ;
- }
- else
- {
- $occ = '+' . $occ;
- }
-
- $day = substr($day, -2, 2);
- switch($day)
- {
- case 'SU':
- $this->byday[] = $occ . 'SU';
- break;
- case 'MO':
- $this->byday[] = $occ . 'MO';
- break;
- case 'TU':
- $this->byday[] = $occ . 'TU';
- break;
- case 'WE':
- $this->byday[] = $occ . 'WE';
- break;
- case 'TH':
- $this->byday[] = $occ . 'TH';
- break;
- case 'FR':
- $this->byday[] = $occ . 'FR';
- break;
- case 'SA':
- $this->byday[] = $occ . 'SA';
- break;
- }
- }
- }
-
- return $this;
- }
-
- public function byyearday($days)
- {
- $this->gobyyearday = true;
-
- if(is_array($days))
- {
- $this->byyearday = $days;
- }
-
- return $this;
- }
-
- // this creates a basic list of dates to "try"
- protected function create_suggestions()
- {
- switch($this->frequency)
- {
- case "YEARLY":
- $interval = 'year';
- break;
- case "MONTHLY":
- $interval = 'month';
- break;
- case "WEEKLY":
- $interval = 'week';
- break;
- case "DAILY":
- $interval = 'day';
- break;
- case "HOURLY":
- $interval = 'hour';
- break;
- case "MINUTELY":
- $interval = 'minute';
- break;
- case "SECONDLY":
- $interval = 'second';
- break;
- }
-
- $month_day = $this->try_date->format('j');
- $month = $this->try_date->format('n');
- $year = $this->try_date->format('Y');
-
- $timestamp = $this->try_date->format('H:i:s');
-
- if($this->gobysetpos)
- {
- if($this->try_date == $this->start_date)
- {
- $this->suggestions[] = clone $this->try_date;
- }
- else
- {
- if($this->gobyday)
- {
- foreach($this->bysetpos as $_pos)
- {
- $tmp_array = array();
- $_mdays = range(1, date('t',mktime(0,0,0,$month,1,$year)));
- foreach($_mdays as $_mday)
- {
- $date_time = new DateTime($year . '-' . $month . '-' . $_mday . ' ' . $timestamp);
-
- $occur = ceil($_mday / 7);
-
- $day_of_week = $date_time->format('l');
- $dow_abr = strtoupper(substr($day_of_week, 0, 2));
-
- // set the day of the month + (positive)
- $occur = '+' . $occur . $dow_abr;
- $occur_zero = '+0' . $dow_abr;
-
- // set the day of the month - (negative)
- $total_days = $date_time->format('t') - $date_time->format('j');
- $occur_neg = '-' . ceil(($total_days + 1)/7) . $dow_abr;
-
- $day_from_end_of_month = $date_time->format('t') + 1 - $_mday;
-
- if(in_array($occur, $this->byday) || in_array($occur_zero, $this->byday) || in_array($occur_neg, $this->byday))
- {
- $tmp_array[] = clone $date_time;
- }
- }
-
- if($_pos > 0)
- {
- $this->suggestions[] = clone $tmp_array[$_pos - 1];
- }
- else
- {
- $this->suggestions[] = clone $tmp_array[count($tmp_array) + $_pos];
- }
-
- }
- }
- }
- }
- elseif($this->gobyyearday)
- {
- foreach($this->byyearday as $_day)
- {
- if($_day >= 0)
- {
- $_day--;
-
- $_time = strtotime('+' . $_day . ' days', mktime(0, 0, 0, 1, 1, $year));
- $this->suggestions[] = new Datetime(date('Y-m-d', $_time) . ' ' . $timestamp);
- }
- else
- {
- $year_day_neg = 365 + $_day;
- $leap_year = $this->try_date->format('L');
- if($leap_year == 1)
- {
- $year_day_neg = 366 + $_day;
- }
-
- $_time = strtotime('+' . $year_day_neg . ' days', mktime(0, 0, 0, 1, 1, $year));
- $this->suggestions[] = new Datetime(date('Y-m-d', $_time) . ' ' . $timestamp);
- }
- }
- }
- // special case because for years you need to loop through the months too
- elseif($this->gobyday && $interval == "year")
- {
- foreach($this->bymonth as $_month)
- {
- // this creates an array of days of the month
- $_mdays = range(1, date('t',mktime(0,0,0,$_month,1,$year)));
- foreach($_mdays as $_mday)
- {
- $date_time = new DateTime($year . '-' . $_month . '-' . $_mday . ' ' . $timestamp);
-
- // get the week of the month (1, 2, 3, 4, 5, etc)
- $week = $date_time->format('W');
-
- if($date_time >= $this->start_date && in_array($week, $this->byweekno))
- {
- $this->suggestions[] = clone $date_time;
- }
- }
- }
- }
- elseif($interval == "day")
- {
- $this->suggestions[] = clone $this->try_date;
- }
- elseif($interval == "week")
- {
- $this->suggestions[] = clone $this->try_date;
-
- if($this->gobyday)
- {
- $week_day = $this->try_date->format('w');
-
- $days_in_month = $this->try_date->format('t');
-
- $overflow_count = 1;
- $_day = $month_day;
-
- $run = true;
- while($run)
- {
- $_day++;
- if($_day <= $days_in_month)
- {
- $tmp_date = new DateTime($year . '-' . $month . '-' . $_day . ' ' . $timestamp);
- }
- else
- {
- //$tmp_month = $month+1;
- $tmp_date = new DateTime($year . '-' . $month . '-' . $overflow_count . ' ' . $timestamp);
- $tmp_date->modify('+1 month');
- $overflow_count++;
- }
-
- $week_day = $tmp_date->format('w');
-
- if($this->try_date == $this->start_date)
- {
- if($week_day == $this->wkst)
- {
- $this->try_date = clone $tmp_date;
- $this->try_date->modify('-7 days');
- $run = false;
- }
- }
-
- if($week_day != $this->wkst)
- {
- $this->suggestions[] = clone $tmp_date;
- }
- else
- {
- $run = false;
- }
- }
- }
- }
- elseif($this->gobyday && $interval == "month")
- {
- $_mdays = range(1, date('t',mktime(0,0,0,$month,1,$year)));
- foreach($_mdays as $_mday)
- {
- $date_time = new DateTime($year . '-' . $month . '-' . $_mday . ' ' . $timestamp);
-
- // get the week of the month (1, 2, 3, 4, 5, etc)
- $week = $date_time->format('W');
-
- if($date_time >= $this->start_date && in_array($week, $this->byweekno))
- {
- $this->suggestions[] = clone $date_time;
- }
- }
- }
- elseif($this->gobymonth)
- {
- foreach($this->bymonth as $_month)
- {
- $date_time = new DateTime($year . '-' . $_month . '-' . $month_day . ' ' . $timestamp);
-
- if($date_time >= $this->start_date)
- {
- $this->suggestions[] = clone $date_time;
- }
- }
- }
- else
- {
- $this->suggestions[] = clone $this->try_date;
- }
-
- if($interval == "month")
- {
-
- $this->try_date->modify('first day of next month');
- if((int) date('t', $this->try_date->format('U')) > (int) $this->start_date->format('j')){
- $this->try_date->modify('+' . (int) $this->start_date->format('j') - 1 . ' day');
- }else{
- $this->try_date->modify('+' . (int) date('t', $this->try_date->format('U')) - 1 . ' day');
- }
- }
- else
- {
- $this->try_date->modify($this->interval . ' ' . $interval);
- }
- }
-
- protected function valid_date($date)
- {
- $year = $date->format('Y');
- $month = $date->format('n');
- $day = $date->format('j');
-
- $year_day = $date->format('z') + 1;
-
- $year_day_neg = -366 + $year_day;
- $leap_year = $date->format('L');
- if($leap_year == 1)
- {
- $year_day_neg = -367 + $year_day;
- }
-
- // this is the nth occurence of the date
- $occur = ceil($day / 7);
-
- $week = $date->format('W');
-
- $day_of_week = $date->format('l');
- $dow_abr = strtoupper(substr($day_of_week, 0, 2));
-
- // set the day of the month + (positive)
- $occur = '+' . $occur . $dow_abr;
- $occur_zero = '+0' . $dow_abr;
-
- // set the day of the month - (negative)
- $total_days = $date->format('t') - $date->format('j');
- $occur_neg = '-' . ceil(($total_days + 1)/7) . $dow_abr;
-
- $day_from_end_of_month = $date->format('t') + 1 - $day;
-
- if(in_array($month, $this->bymonth) &&
- (in_array($occur, $this->byday) || in_array($occur_zero, $this->byday) || in_array($occur_neg, $this->byday)) &&
- in_array($week, $this->byweekno) &&
- (in_array($day, $this->bymonthday) || in_array(-$day_from_end_of_month, $this->bymonthday)) &&
- (in_array($year_day, $this->byyearday) || in_array($year_day_neg, $this->byyearday)))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
-
- // return the next valid DateTime object which matches the pattern and follows the rules
- public function next()
- {
- // check the counter is set
- if($this->count !== 0)
- {
- if($this->counter >= $this->count)
- {
- return false;
- }
- }
-
- // create initial set of suggested dates
- if(count($this->suggestions) === 0)
- {
- $this->create_suggestions();
- }
-
- // loop through the suggested dates
- while(count($this->suggestions) > 0)
- {
- // get the first one on the array
- $try_date = array_shift($this->suggestions);
-
- // make sure the date doesn't exceed the max date
- if($try_date > $this->end_date)
- {
- return false;
- }
-
- // make sure it falls within the allowed days
- if($this->valid_date($try_date) === true)
- {
- $this->counter++;
- return $try_date;
- }
- else
- {
- // we might be out of suggested days, so load some more
- if(count($this->suggestions) === 0)
- {
- $this->create_suggestions();
- }
- }
- }
- }
-}