From 04430868b12fc4c8d715a4906a4f043e8f70b117 Mon Sep 17 00:00:00 2001 From: Timur Usenko Date: Tue, 24 Sep 2013 23:04:44 +0400 Subject: [PATCH] v1.2.5.406 --- LICENSE | 24 + data/VERSION | 1 + index.php | 42 + rainloop/v/1.2.5.406/REVISION | 1 + rainloop/v/1.2.5.406/VERSION | 1 + rainloop/v/1.2.5.406/app/.htaccess | 1 + rainloop/v/1.2.5.406/app/domains/disabled | 1 + .../v/1.2.5.406/app/domains/gmail.com.ini | 7 + .../v/1.2.5.406/app/domains/yahoo.com.ini | 7 + rainloop/v/1.2.5.406/app/handle.php | 39 + rainloop/v/1.2.5.406/app/i18n/langs.ini | 3 + rainloop/v/1.2.5.406/app/i18n/moment/bg.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/ca.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/cv.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/da.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/de.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/en-ca.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/en-gb.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/es.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/eu.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/fi.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/fr-ca.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/fr.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/gl.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/hu.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/is.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/it.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/ja.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/jp.js | 6 + rainloop/v/1.2.5.406/app/i18n/moment/ko.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/kr.js | 6 + rainloop/v/1.2.5.406/app/i18n/moment/nb.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/nl.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/pl.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/pt-br.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/pt.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/ru.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/sv.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/tr.js | 5 + rainloop/v/1.2.5.406/app/i18n/moment/zh-cn.js | 4 + rainloop/v/1.2.5.406/app/i18n/moment/zh-tw.js | 4 + .../1.2.5.406/app/libraries/Buzz/Browser.php | 195 + .../libraries/Buzz/Client/AbstractClient.php | 62 + .../libraries/Buzz/Client/AbstractCurl.php | 201 + .../libraries/Buzz/Client/AbstractStream.php | 43 + .../Buzz/Client/BatchClientInterface.php | 11 + .../libraries/Buzz/Client/ClientInterface.php | 17 + .../app/libraries/Buzz/Client/Curl.php | 55 + .../libraries/Buzz/Client/FileGetContents.php | 87 + .../app/libraries/Buzz/Client/MultiCurl.php | 53 + .../Buzz/Exception/ClientException.php | 10 + .../Buzz/Exception/ExceptionInterface.php | 10 + .../Exception/InvalidArgumentException.php | 10 + .../Buzz/Exception/LogicException.php | 10 + .../Buzz/Exception/RuntimeException.php | 7 + .../Buzz/Listener/BasicAuthListener.php | 27 + .../Buzz/Listener/CallbackListener.php | 49 + .../libraries/Buzz/Listener/History/Entry.php | 42 + .../Buzz/Listener/History/Journal.php | 76 + .../Buzz/Listener/HistoryListener.php | 33 + .../libraries/Buzz/Listener/ListenerChain.php | 40 + .../Buzz/Listener/ListenerInterface.php | 12 + .../Buzz/Listener/LoggerListener.php | 36 + .../Buzz/Message/AbstractMessage.php | 154 + .../Buzz/Message/Factory/Factory.php | 26 + .../Buzz/Message/Factory/FactoryInterface.php | 12 + .../Buzz/Message/Form/FormRequest.php | 187 + .../Message/Form/FormRequestInterface.php | 27 + .../Buzz/Message/Form/FormUpload.php | 118 + .../Buzz/Message/Form/FormUploadInterface.php | 13 + .../Buzz/Message/MessageInterface.php | 74 + .../app/libraries/Buzz/Message/Request.php | 174 + .../Buzz/Message/RequestInterface.php | 75 + .../app/libraries/Buzz/Message/Response.php | 193 + .../app/libraries/Buzz/Util/Cookie.php | 216 + .../app/libraries/Buzz/Util/CookieJar.php | 79 + .../1.2.5.406/app/libraries/Buzz/Util/Url.php | 190 + .../KeenIO/Http/Adaptor/AdaptorInterface.php | 19 + .../libraries/KeenIO/Http/Adaptor/Buzz.php | 49 + .../app/libraries/KeenIO/Service/KeenIO.php | 215 + .../app/libraries/MailSo/Base/Collection.php | 183 + .../app/libraries/MailSo/Base/Crypt.php | 180 + .../libraries/MailSo/Base/DateTimeHelper.php | 74 + .../MailSo/Base/Enumerations/Charset.php | 27 + .../MailSo/Base/Enumerations/Encoding.php | 24 + .../MailSo/Base/Exceptions/Exception.php | 24 + .../Exceptions/InvalidArgumentException.php | 10 + .../app/libraries/MailSo/Base/HtmlUtils.php | 666 ++ .../app/libraries/MailSo/Base/Http.php | 583 ++ .../app/libraries/MailSo/Base/LinkFinder.php | 323 + .../app/libraries/MailSo/Base/Loader.php | 112 + .../MailSo/Base/ResourceRegistry.php | 116 + .../MailSo/Base/StreamWrappers/Binary.php | 368 ++ .../MailSo/Base/StreamWrappers/Literal.php | 185 + .../MailSo/Base/StreamWrappers/SubStreams.php | 257 + .../MailSo/Base/StreamWrappers/Test.php | 129 + .../app/libraries/MailSo/Base/Utils.php | 1626 +++++ .../app/libraries/MailSo/Base/Validator.php | 95 + .../libraries/MailSo/Cache/CacheClient.php | 149 + .../MailSo/Cache/DriverInterface.php | 39 + .../libraries/MailSo/Cache/Drivers/APC.php | 76 + .../libraries/MailSo/Cache/Drivers/File.php | 126 + .../MailSo/Cache/Drivers/Memcache.php | 120 + .../libraries/MailSo/Imap/BodyStructure.php | 855 +++ .../MailSo/Imap/Enumerations/FetchType.php | 119 + .../Enumerations/FolderResponseStatus.php | 17 + .../MailSo/Imap/Enumerations/FolderStatus.php | 17 + .../MailSo/Imap/Enumerations/FolderType.php | 21 + .../MailSo/Imap/Enumerations/MessageFlag.php | 18 + .../Imap/Enumerations/ResponseStatus.php | 17 + .../MailSo/Imap/Enumerations/ResponseType.php | 16 + .../MailSo/Imap/Enumerations/StoreAction.php | 25 + .../MailSo/Imap/Exceptions/Exception.php | 10 + .../Exceptions/InvalidResponseException.php | 10 + .../LoginBadCredentialsException.php | 10 + .../Exceptions/LoginBadMethodException.php | 10 + .../MailSo/Imap/Exceptions/LoginException.php | 10 + .../Exceptions/NegativeResponseException.php | 10 + .../Imap/Exceptions/ResponseException.php | 48 + .../Exceptions/ResponseNotFoundException.php | 10 + .../Imap/Exceptions/RuntimeException.php | 10 + .../libraries/MailSo/Imap/FetchResponse.php | 225 + .../app/libraries/MailSo/Imap/Folder.php | 175 + .../MailSo/Imap/FolderInformation.php | 95 + .../app/libraries/MailSo/Imap/ImapClient.php | 2160 +++++++ .../libraries/MailSo/Imap/NamespaceResult.php | 123 + .../app/libraries/MailSo/Imap/Response.php | 67 + .../libraries/MailSo/Imap/SearchBuilder.php | 104 + .../app/libraries/MailSo/Log/Driver.php | 221 + .../libraries/MailSo/Log/Drivers/Callback.php | 74 + .../app/libraries/MailSo/Log/Drivers/File.php | 87 + .../libraries/MailSo/Log/Drivers/Inline.php | 85 + .../MailSo/Log/Enumerations/Type.php | 20 + .../app/libraries/MailSo/Log/Logger.php | 214 + .../app/libraries/MailSo/Mail/Attachment.php | 182 + .../MailSo/Mail/AttachmentCollection.php | 38 + .../MailSo/Mail/Exceptions/Exception.php | 10 + .../MailSo/Mail/Exceptions/NonEmptyFolder.php | 10 + .../Mail/Exceptions/RuntimeException.php | 10 + .../app/libraries/MailSo/Mail/Folder.php | 305 + .../MailSo/Mail/FolderCollection.php | 195 + .../app/libraries/MailSo/Mail/MailClient.php | 1977 ++++++ .../app/libraries/MailSo/Mail/Message.php | 739 +++ .../MailSo/Mail/MessageCollection.php | 108 + .../1.2.5.406/app/libraries/MailSo/MailSo.php | 23 + .../app/libraries/MailSo/Mime/Attachment.php | 124 + .../MailSo/Mime/AttachmentCollection.php | 62 + .../app/libraries/MailSo/Mime/Email.php | 275 + .../libraries/MailSo/Mime/EmailCollection.php | 228 + .../MailSo/Mime/Enumerations/Constants.php | 16 + .../MailSo/Mime/Enumerations/Header.php | 49 + .../Mime/Enumerations/MessagePriority.php | 15 + .../MailSo/Mime/Enumerations/MimeType.php | 27 + .../MailSo/Mime/Enumerations/Parameter.php | 16 + .../MailSo/Mime/Enumerations/Sensitivity.php | 16 + .../app/libraries/MailSo/Mime/Header.php | 299 + .../MailSo/Mime/HeaderCollection.php | 362 ++ .../app/libraries/MailSo/Mime/Message.php | 798 +++ .../app/libraries/MailSo/Mime/Parameter.php | 132 + .../MailSo/Mime/ParameterCollection.php | 197 + .../MailSo/Mime/Parser/ParserEmpty.php | 72 + .../MailSo/Mime/Parser/ParserInterface.php | 57 + .../MailSo/Mime/Parser/ParserMemory.php | 44 + .../app/libraries/MailSo/Mime/Part.php | 618 ++ .../libraries/MailSo/Mime/PartCollection.php | 56 + .../Enumerations/ConnectionSecurityType.php | 60 + .../Net/Exceptions/ConnectionException.php | 10 + .../MailSo/Net/Exceptions/Exception.php | 10 + .../Exceptions/InvalidArgumentException.php | 10 + .../SocketAlreadyConnectedException.php | 10 + .../SocketCanNotConnectToHostException.php | 52 + ...ketConnectionDoesNotAvailableException.php | 10 + .../Net/Exceptions/SocketReadException.php | 10 + .../Exceptions/SocketReadTimeoutException.php | 10 + .../SocketUnreadBufferException.php | 10 + ...etUnsuppoterdSecureConnectionException.php | 10 + .../Net/Exceptions/SocketWriteException.php | 10 + .../app/libraries/MailSo/Net/NetClient.php | 487 ++ .../MailSo/Pop3/Exceptions/Exception.php | 10 + .../LoginBadCredentialsException.php | 10 + .../Exceptions/NegativeResponseException.php | 10 + .../Pop3/Exceptions/ResponseException.php | 48 + .../Pop3/Exceptions/RuntimeException.php | 10 + .../app/libraries/MailSo/Pop3/Pop3Client.php | 365 ++ .../MailSo/Poppassd/Exceptions/Exception.php | 10 + .../LoginBadCredentialsException.php | 10 + .../Exceptions/NegativeResponseException.php | 10 + .../Poppassd/Exceptions/ResponseException.php | 48 + .../Poppassd/Exceptions/RuntimeException.php | 10 + .../MailSo/Poppassd/PoppassdClient.php | 277 + .../MailSo/Sieve/Exceptions/Exception.php | 10 + .../LoginBadCredentialsException.php | 10 + .../Exceptions/LoginBadMethodException.php | 10 + .../Sieve/Exceptions/LoginException.php | 10 + .../Exceptions/NegativeResponseException.php | 10 + .../Sieve/Exceptions/ResponseException.php | 48 + .../Sieve/Exceptions/RuntimeException.php | 10 + .../MailSo/Sieve/ManageSieveClient.php | 629 ++ .../MailSo/Smtp/Exceptions/Exception.php | 10 + .../LoginBadCredentialsException.php | 10 + .../Exceptions/LoginBadMethodException.php | 10 + .../MailSo/Smtp/Exceptions/LoginException.php | 10 + .../Exceptions/NegativeResponseException.php | 10 + .../Smtp/Exceptions/ResponseException.php | 48 + .../Smtp/Exceptions/RuntimeException.php | 10 + .../app/libraries/MailSo/Smtp/SmtpClient.php | 706 ++ .../app/libraries/MailSo/Version.php | 44 + .../app/libraries/PHP-OAuth2/Client.php | 513 ++ .../GrantType/AuthorizationCode.php | 41 + .../GrantType/ClientCredentials.php | 25 + .../PHP-OAuth2/GrantType/IGrantType.php | 15 + .../PHP-OAuth2/GrantType/Password.php | 41 + .../PHP-OAuth2/GrantType/RefreshToken.php | 34 + .../1.2.5.406/app/libraries/PHP-OAuth2/README | 117 + .../app/libraries/PHP-OAuth2/composer.json | 19 + .../app/libraries/RainLoop/Account.php | 197 + .../app/libraries/RainLoop/Actions.php | 5099 +++++++++++++++ .../RainLoop/Config/AbstractConfig.php | 198 + .../libraries/RainLoop/Config/Application.php | 209 + .../app/libraries/RainLoop/Config/Plugin.php | 59 + .../app/libraries/RainLoop/Domain.php | 336 + .../RainLoop/Enumerations/CustomThemeType.php | 9 + .../Enumerations/PluginPropertyType.php | 13 + .../RainLoop/Enumerations/SignMeType.php | 10 + .../RainLoop/Enumerations/TimeFormat.php | 9 + .../RainLoop/Exceptions/AuthException.php | 9 + .../RainLoop/Exceptions/ClientException.php | 15 + .../RainLoop/Exceptions/Exception.php | 5 + .../Exceptions/InvalidArgumentException.php | 9 + .../RainLoop/Exceptions/RuntimeException.php | 9 + .../app/libraries/RainLoop/Notifications.php | 90 + .../RainLoop/Plugins/AbstractPlugin.php | 317 + .../libraries/RainLoop/Plugins/Manager.php | 642 ++ .../libraries/RainLoop/Plugins/Property.php | 178 + .../RainLoop/Providers/AbstractProvider.php | 14 + .../RainLoop/Providers/ChangePassword.php | 74 + .../ChangePasswordInterface.php | 22 + .../libraries/RainLoop/Providers/Contacts.php | 120 + .../Providers/Contacts/Classes/Contact.php | 111 + .../Providers/Contacts/Classes/Db.php | 38 + .../Providers/Contacts/ContactsInterface.php | 68 + .../Providers/Contacts/DefaultContacts.php | 600 ++ .../libraries/RainLoop/Providers/Domain.php | 153 + .../Providers/Domain/DefaultDomain.php | 172 + .../Providers/Domain/DomainAdminInterface.php | 52 + .../Providers/Domain/DomainInterface.php | 7 + .../Domain/DomainSimpleInterface.php | 13 + .../libraries/RainLoop/Providers/Login.php | 62 + .../RainLoop/Providers/Login/DefaultLogin.php | 18 + .../Providers/Login/LoginInterface.php | 15 + .../libraries/RainLoop/Providers/Settings.php | 52 + .../Providers/Settings/DefaultSettings.php | 59 + .../Providers/Settings/SettingsInterface.php | 21 + .../libraries/RainLoop/Providers/Storage.php | 195 + .../Providers/Storage/DefaultStorage.php | 290 + .../Storage/Enumerations/StorageType.php | 11 + .../Enumerations/UploadClientError.php | 16 + .../Storage/Enumerations/UploadError.php | 13 + .../Providers/Storage/StorageInterface.php | 109 + .../RainLoop/Providers/Suggestions.php | 40 + .../Suggestions/SuggestionsInterface.php | 14 + .../app/libraries/RainLoop/Service.php | 231 + .../app/libraries/RainLoop/ServiceActions.php | 887 +++ .../app/libraries/RainLoop/Settings.php | 64 + .../app/libraries/RainLoop/Social.php | 894 +++ .../app/libraries/RainLoop/Utils.php | 392 ++ .../app/libraries/facebook/base_facebook.php | 1442 +++++ .../app/libraries/facebook/facebook.php | 119 + .../libraries/facebook/fb_ca_chain_bundle.crt | 3920 ++++++++++++ .../v/1.2.5.406/app/libraries/lessphp/LICENSE | 660 ++ .../1.2.5.406/app/libraries/lessphp/README.md | 96 + .../1.2.5.406/app/libraries/lessphp/ctype.php | 32 + .../app/libraries/lessphp/lessc.inc.php | 3473 ++++++++++ .../app/libraries/pclzip/gnu-lgpl.txt | 504 ++ .../app/libraries/pclzip/pclzip.lib.php | 5693 +++++++++++++++++ .../1.2.5.406/app/libraries/pclzip/readme.txt | 421 ++ .../1.2.5.406/app/libraries/tmhOAuth/LICENSE | 202 + .../app/libraries/tmhOAuth/README.md | 211 + .../app/libraries/tmhOAuth/cacert.pem | 3376 ++++++++++ .../app/libraries/tmhOAuth/tmhOAuth.php | 724 +++ .../app/libraries/tmhOAuth/tmhUtilities.php | 280 + .../v/1.2.5.406/app/templates/BadBrowser.html | 67 + rainloop/v/1.2.5.406/app/templates/Error.html | 53 + rainloop/v/1.2.5.406/app/templates/Index.html | 66 + .../templates/Themes/custom-values-dark.less | 56 + .../templates/Themes/custom-values-light.less | 55 + .../app/templates/Themes/template.less | 148 + .../app/templates/Themes/values.less | 59 + .../templates/Views/AdminDomainListItem.html | 20 + .../app/templates/Views/AdminDomains.html | 31 + .../app/templates/Views/AdminGeneral.html | 56 + .../app/templates/Views/AdminLicensing.html | 60 + .../app/templates/Views/AdminLogin.html | 35 + .../app/templates/Views/AdminMenu.html | 17 + .../app/templates/Views/AdminPackages.html | 46 + .../Views/AdminPackagesListItem.html | 19 + .../templates/Views/AdminPackagesTable.html | 9 + .../app/templates/Views/AdminPane.html | 21 + .../templates/Views/AdminPluginListItem.html | 15 + .../templates/Views/AdminPluginProperty.html | 28 + .../app/templates/Views/AdminPlugins.html | 48 + .../app/templates/Views/AdminSecurity.html | 51 + .../app/templates/Views/AdminSocial.html | 117 + .../templates/Views/ComposeAttachment.html | 9 + .../Views/ComposeAttachmentInProcess.html | 14 + .../1.2.5.406/app/templates/Views/Login.html | 89 + .../app/templates/Views/MailFolderList.html | 17 + .../templates/Views/MailFolderListItem.html | 7 + .../Views/MailFolderListSystemItem.html | 5 + .../app/templates/Views/MailMessageList.html | 161 + .../templates/Views/MailMessageListItem.html | 44 + .../MailMessageListItemNoPreviewPane.html | 45 + .../app/templates/Views/MailMessageView.html | 190 + .../app/templates/Views/PopupsActivate.html | 62 + .../app/templates/Views/PopupsAddAccount.html | 48 + .../templates/Views/PopupsAdvancedSearch.html | 86 + .../app/templates/Views/PopupsCompose.html | 113 + .../app/templates/Views/PopupsContacts.html | 101 + .../app/templates/Views/PopupsDomain.html | 94 + .../templates/Views/PopupsFolderClear.html | 34 + .../templates/Views/PopupsFolderCreate.html | 40 + .../templates/Views/PopupsFolderSystem.html | 53 + .../app/templates/Views/PopupsPlugin.html | 37 + .../Views/PopupsWindowSimpleMessage.html | 56 + .../app/templates/Views/SettingsAccounts.html | 38 + .../Views/SettingsChangePassword.html | 32 + .../app/templates/Views/SettingsCustom.html | 3 + .../templates/Views/SettingsFolderItem.html | 25 + .../app/templates/Views/SettingsFolders.html | 35 + .../app/templates/Views/SettingsGeneral.html | 106 + .../app/templates/Views/SettingsMenu.html | 18 + .../app/templates/Views/SettingsPane.html | 16 + .../app/templates/Views/SettingsPersonal.html | 33 + .../app/templates/Views/SettingsSocial.html | 101 + .../app/templates/Views/SettingsThemes.html | 59 + .../app/templates/Views/SystemDropDown.html | 63 + rainloop/v/1.2.5.406/check.php | 46 + rainloop/v/1.2.5.406/index.php | 157 + rainloop/v/1.2.5.406/langs/en.ini | 374 ++ rainloop/v/1.2.5.406/langs/ru.ini | 374 ++ .../v/1.2.5.406/static/browsers/chrome.gif | Bin 0 -> 3803 bytes .../v/1.2.5.406/static/browsers/firefox.gif | Bin 0 -> 4202 bytes .../v/1.2.5.406/static/browsers/opera.gif | Bin 0 -> 3508 bytes .../v/1.2.5.406/static/browsers/safari.gif | Bin 0 -> 4876 bytes rainloop/v/1.2.5.406/static/css/app.css | 1 + .../static/css/fonts/icomoon.dev.svg | 308 + .../v/1.2.5.406/static/css/fonts/icomoon.eot | Bin 0 -> 13980 bytes .../v/1.2.5.406/static/css/fonts/icomoon.svg | 308 + .../v/1.2.5.406/static/css/fonts/icomoon.ttf | Bin 0 -> 13816 bytes .../v/1.2.5.406/static/css/fonts/icomoon.woff | Bin 0 -> 19584 bytes .../v/1.2.5.406/static/css/images/editor.png | Bin 0 -> 8395 bytes .../static/css/images/empty-contact.png | Bin 0 -> 1881 bytes .../v/1.2.5.406/static/css/images/grey.png | Bin 0 -> 109 bytes .../css/images/icom-message-notification.png | Bin 0 -> 244 bytes .../static/css/images/loader-black.gif | Bin 0 -> 404 bytes .../static/css/images/loader-white.gif | Bin 0 -> 404 bytes .../v/1.2.5.406/static/css/images/sync.gif | Bin 0 -> 847 bytes .../v/1.2.5.406/static/css/images/sync.png | Bin 0 -> 356 bytes .../v/1.2.5.406/static/css/images/white.png | Bin 0 -> 110 bytes .../1.2.5.406/static/css/select2-spinner.gif | Bin 0 -> 1849 bytes rainloop/v/1.2.5.406/static/css/select2.png | Bin 0 -> 613 bytes rainloop/v/1.2.5.406/static/css/select2x2.png | Bin 0 -> 845 bytes rainloop/v/1.2.5.406/static/favicon.ico | Bin 0 -> 1150 bytes rainloop/v/1.2.5.406/static/favicon.png | Bin 0 -> 1707 bytes rainloop/v/1.2.5.406/static/js/admin.min.js | 143 + rainloop/v/1.2.5.406/static/js/app.min.js | 369 ++ rainloop/v/1.2.5.406/static/js/jquery.js | 2 + rainloop/v/1.2.5.406/static/js/libs.js | 1299 ++++ .../v/1.2.5.406/static/services/amazon.png | Bin 0 -> 18032 bytes .../v/1.2.5.406/static/services/apple.jpg | Bin 0 -> 807 bytes .../v/1.2.5.406/static/services/asana.png | Bin 0 -> 995 bytes .../1.2.5.406/static/services/battle.net.png | Bin 0 -> 3194 bytes rainloop/v/1.2.5.406/static/services/cnet.jpg | Bin 0 -> 16847 bytes rainloop/v/1.2.5.406/static/services/ea.png | Bin 0 -> 6157 bytes rainloop/v/1.2.5.406/static/services/ebay.jpg | Bin 0 -> 10360 bytes .../v/1.2.5.406/static/services/facebook.png | Bin 0 -> 10088 bytes .../v/1.2.5.406/static/services/github.png | Bin 0 -> 1884 bytes .../1.2.5.406/static/services/google-plus.png | Bin 0 -> 2952 bytes .../v/1.2.5.406/static/services/google.png | Bin 0 -> 5949 bytes .../v/1.2.5.406/static/services/icloud.jpg | Bin 0 -> 2111 bytes .../v/1.2.5.406/static/services/microsoft.jpg | Bin 0 -> 2721 bytes .../v/1.2.5.406/static/services/myspace.png | Bin 0 -> 7553 bytes .../v/1.2.5.406/static/services/onlive.png | Bin 0 -> 5000 bytes .../v/1.2.5.406/static/services/paypal.jpg | Bin 0 -> 2494 bytes .../v/1.2.5.406/static/services/skype.png | Bin 0 -> 3435 bytes .../v/1.2.5.406/static/services/steam.png | Bin 0 -> 2697 bytes rainloop/v/1.2.5.406/static/services/ted.png | Bin 0 -> 1248 bytes .../v/1.2.5.406/static/services/twitter.jpg | Bin 0 -> 1361 bytes .../v/1.2.5.406/static/services/youtube.gif | Bin 0 -> 2219 bytes .../v/1.2.5.406/static/sounds/new-mail.mp3 | Bin 0 -> 15288 bytes .../v/1.2.5.406/static/sounds/new-mail.ogg | Bin 0 -> 15090 bytes .../1.2.5.406/themes/A/images/background.jpg | Bin 0 -> 75508 bytes .../v/1.2.5.406/themes/A/images/preview.png | Bin 0 -> 5569 bytes rainloop/v/1.2.5.406/themes/A/styles.less | 52 + .../1.2.5.406/themes/Clear/images/preview.png | Bin 0 -> 961 bytes rainloop/v/1.2.5.406/themes/Clear/styles.less | 0 rainloop/v/1.2.5.406/themes/Custom/ext.less | 4 + .../themes/Custom/images/preview.png | Bin 0 -> 719 bytes .../themes/Default/images/background.jpg | Bin 0 -> 4988 bytes .../themes/Default/images/background.png | Bin 0 -> 37162 bytes .../themes/Default/images/preview.png | Bin 0 -> 5804 bytes .../v/1.2.5.406/themes/Default/styles.less | 52 + .../themes/Linen/images/background.jpg | Bin 0 -> 7258 bytes .../themes/Linen/images/background.png | Bin 0 -> 15597 bytes .../1.2.5.406/themes/Linen/images/preview.png | Bin 0 -> 3142 bytes rainloop/v/1.2.5.406/themes/Linen/styles.less | 51 + .../themes/Love/images/background.jpg | Bin 0 -> 84413 bytes .../1.2.5.406/themes/Love/images/preview.png | Bin 0 -> 6458 bytes rainloop/v/1.2.5.406/themes/Love/styles.less | 52 + .../themes/Snow/images/background.jpg | Bin 0 -> 115505 bytes .../1.2.5.406/themes/Snow/images/preview.png | Bin 0 -> 5660 bytes rainloop/v/1.2.5.406/themes/Snow/styles.less | 52 + .../themes/Squares/images/background.jpg | Bin 0 -> 33347 bytes .../themes/Squares/images/background.png | Bin 0 -> 58585 bytes .../themes/Squares/images/preview.png | Bin 0 -> 6293 bytes .../v/1.2.5.406/themes/Squares/styles.less | 51 + .../themes/SquaresDark/images/background.jpg | Bin 0 -> 19418 bytes .../themes/SquaresDark/images/background.png | Bin 0 -> 33147 bytes .../themes/SquaresDark/images/preview.png | Bin 0 -> 4767 bytes .../1.2.5.406/themes/SquaresDark/styles.less | 52 + .../themes/Stripes/images/background.jpg | Bin 0 -> 58007 bytes .../themes/Stripes/images/preview.png | Bin 0 -> 3586 bytes .../v/1.2.5.406/themes/Stripes/styles.less | 51 + .../themes/Wood/images/background.jpg | Bin 0 -> 39327 bytes .../themes/Wood/images/background.png | Bin 0 -> 150200 bytes .../1.2.5.406/themes/Wood/images/preview.png | Bin 0 -> 11171 bytes rainloop/v/1.2.5.406/themes/Wood/styles.less | 51 + .../1.2.5.406/themes/Xv/images/background.jpg | Bin 0 -> 8556 bytes .../1.2.5.406/themes/Xv/images/background.png | Bin 0 -> 37310 bytes .../v/1.2.5.406/themes/Xv/images/preview.png | Bin 0 -> 6221 bytes rainloop/v/1.2.5.406/themes/Xv/styles.less | 51 + 431 files changed, 64715 insertions(+) create mode 100644 LICENSE create mode 100644 data/VERSION create mode 100644 index.php create mode 100644 rainloop/v/1.2.5.406/REVISION create mode 100644 rainloop/v/1.2.5.406/VERSION create mode 100644 rainloop/v/1.2.5.406/app/.htaccess create mode 100644 rainloop/v/1.2.5.406/app/domains/disabled create mode 100644 rainloop/v/1.2.5.406/app/domains/gmail.com.ini create mode 100644 rainloop/v/1.2.5.406/app/domains/yahoo.com.ini create mode 100644 rainloop/v/1.2.5.406/app/handle.php create mode 100644 rainloop/v/1.2.5.406/app/i18n/langs.ini create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/bg.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/ca.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/cv.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/da.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/de.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/en-ca.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/en-gb.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/es.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/eu.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/fi.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/fr-ca.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/fr.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/gl.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/hu.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/is.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/it.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/ja.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/jp.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/ko.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/kr.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/nb.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/nl.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/pl.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/pt-br.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/pt.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/ru.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/sv.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/tr.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/zh-cn.js create mode 100644 rainloop/v/1.2.5.406/app/i18n/moment/zh-tw.js create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Browser.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Client/AbstractClient.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Client/AbstractCurl.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Client/AbstractStream.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Client/BatchClientInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Client/ClientInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Client/Curl.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Client/FileGetContents.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Client/MultiCurl.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Exception/ClientException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Exception/ExceptionInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Exception/InvalidArgumentException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Exception/LogicException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Exception/RuntimeException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/BasicAuthListener.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/CallbackListener.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/History/Entry.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/History/Journal.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/HistoryListener.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/ListenerChain.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/ListenerInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/LoggerListener.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Message/AbstractMessage.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Factory/Factory.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Factory/FactoryInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Form/FormRequest.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Form/FormRequestInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Form/FormUpload.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Form/FormUploadInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Message/MessageInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Request.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Message/RequestInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Response.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Util/Cookie.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Util/CookieJar.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/Buzz/Util/Url.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/KeenIO/Http/Adaptor/AdaptorInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/KeenIO/Http/Adaptor/Buzz.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/KeenIO/Service/KeenIO.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Collection.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Crypt.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/DateTimeHelper.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Enumerations/Charset.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Enumerations/Encoding.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Exceptions/Exception.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Exceptions/InvalidArgumentException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/HtmlUtils.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Http.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/LinkFinder.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Loader.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/ResourceRegistry.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/StreamWrappers/Binary.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/StreamWrappers/Literal.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/StreamWrappers/SubStreams.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/StreamWrappers/Test.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Utils.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Validator.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/CacheClient.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/DriverInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/Drivers/APC.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/Drivers/File.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/Drivers/Memcache.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/BodyStructure.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Enumerations/FetchType.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Enumerations/FolderResponseStatus.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Enumerations/FolderStatus.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Enumerations/FolderType.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Enumerations/MessageFlag.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Enumerations/ResponseStatus.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Enumerations/ResponseType.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Enumerations/StoreAction.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Exceptions/Exception.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Exceptions/InvalidResponseException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Exceptions/LoginBadCredentialsException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Exceptions/LoginBadMethodException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Exceptions/LoginException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Exceptions/NegativeResponseException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Exceptions/ResponseException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Exceptions/ResponseNotFoundException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Exceptions/RuntimeException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/FetchResponse.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Folder.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/FolderInformation.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/ImapClient.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/NamespaceResult.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Response.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/SearchBuilder.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Driver.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Drivers/Callback.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Drivers/File.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Drivers/Inline.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Enumerations/Type.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Logger.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Attachment.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/AttachmentCollection.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Exceptions/Exception.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Exceptions/NonEmptyFolder.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Exceptions/RuntimeException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Folder.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/FolderCollection.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/MailClient.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Message.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/MessageCollection.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/MailSo.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Attachment.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/AttachmentCollection.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Email.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/EmailCollection.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Enumerations/Constants.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Enumerations/Header.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Enumerations/MessagePriority.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Enumerations/MimeType.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Enumerations/Parameter.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Enumerations/Sensitivity.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Header.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/HeaderCollection.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Message.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Parameter.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/ParameterCollection.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Parser/ParserEmpty.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Parser/ParserInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Parser/ParserMemory.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Part.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/PartCollection.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Enumerations/ConnectionSecurityType.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Exceptions/ConnectionException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Exceptions/Exception.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Exceptions/InvalidArgumentException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Exceptions/SocketAlreadyConnectedException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Exceptions/SocketCanNotConnectToHostException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Exceptions/SocketConnectionDoesNotAvailableException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Exceptions/SocketReadException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Exceptions/SocketReadTimeoutException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Exceptions/SocketUnreadBufferException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Exceptions/SocketUnsuppoterdSecureConnectionException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Exceptions/SocketWriteException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Net/NetClient.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Pop3/Exceptions/Exception.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Pop3/Exceptions/LoginBadCredentialsException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Pop3/Exceptions/NegativeResponseException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Pop3/Exceptions/ResponseException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Pop3/Exceptions/RuntimeException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Pop3/Pop3Client.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Poppassd/Exceptions/Exception.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Poppassd/Exceptions/LoginBadCredentialsException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Poppassd/Exceptions/NegativeResponseException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Poppassd/Exceptions/ResponseException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Poppassd/Exceptions/RuntimeException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Poppassd/PoppassdClient.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Sieve/Exceptions/Exception.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Sieve/Exceptions/LoginBadCredentialsException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Sieve/Exceptions/LoginBadMethodException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Sieve/Exceptions/LoginException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Sieve/Exceptions/NegativeResponseException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Sieve/Exceptions/ResponseException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Sieve/Exceptions/RuntimeException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Sieve/ManageSieveClient.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Smtp/Exceptions/Exception.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Smtp/Exceptions/LoginBadCredentialsException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Smtp/Exceptions/LoginBadMethodException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Smtp/Exceptions/LoginException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Smtp/Exceptions/NegativeResponseException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Smtp/Exceptions/ResponseException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Smtp/Exceptions/RuntimeException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Smtp/SmtpClient.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/MailSo/Version.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/Client.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/GrantType/AuthorizationCode.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/GrantType/ClientCredentials.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/GrantType/IGrantType.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/GrantType/Password.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/GrantType/RefreshToken.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/README create mode 100644 rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/composer.json create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Account.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Actions.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Config/AbstractConfig.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Config/Application.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Config/Plugin.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Domain.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Enumerations/CustomThemeType.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Enumerations/PluginPropertyType.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Enumerations/SignMeType.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Enumerations/TimeFormat.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Exceptions/AuthException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Exceptions/ClientException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Exceptions/Exception.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Exceptions/InvalidArgumentException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Exceptions/RuntimeException.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Notifications.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Plugins/AbstractPlugin.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Plugins/Manager.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Plugins/Property.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/AbstractProvider.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/ChangePassword.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/ChangePassword/ChangePasswordInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Contacts.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Contacts/Classes/Contact.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Contacts/Classes/Db.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Contacts/ContactsInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Contacts/DefaultContacts.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Domain.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Domain/DefaultDomain.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Domain/DomainAdminInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Domain/DomainInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Domain/DomainSimpleInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Login.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Login/DefaultLogin.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Login/LoginInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Settings.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Settings/SettingsInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Storage.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Storage/DefaultStorage.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Storage/Enumerations/UploadClientError.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Storage/Enumerations/UploadError.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Storage/StorageInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Suggestions.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Suggestions/SuggestionsInterface.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Service.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/ServiceActions.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Settings.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Social.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/RainLoop/Utils.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/facebook/base_facebook.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/facebook/facebook.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/facebook/fb_ca_chain_bundle.crt create mode 100644 rainloop/v/1.2.5.406/app/libraries/lessphp/LICENSE create mode 100644 rainloop/v/1.2.5.406/app/libraries/lessphp/README.md create mode 100644 rainloop/v/1.2.5.406/app/libraries/lessphp/ctype.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/lessphp/lessc.inc.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/pclzip/gnu-lgpl.txt create mode 100644 rainloop/v/1.2.5.406/app/libraries/pclzip/pclzip.lib.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/pclzip/readme.txt create mode 100644 rainloop/v/1.2.5.406/app/libraries/tmhOAuth/LICENSE create mode 100644 rainloop/v/1.2.5.406/app/libraries/tmhOAuth/README.md create mode 100644 rainloop/v/1.2.5.406/app/libraries/tmhOAuth/cacert.pem create mode 100644 rainloop/v/1.2.5.406/app/libraries/tmhOAuth/tmhOAuth.php create mode 100644 rainloop/v/1.2.5.406/app/libraries/tmhOAuth/tmhUtilities.php create mode 100644 rainloop/v/1.2.5.406/app/templates/BadBrowser.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Error.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Index.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Themes/custom-values-dark.less create mode 100644 rainloop/v/1.2.5.406/app/templates/Themes/custom-values-light.less create mode 100644 rainloop/v/1.2.5.406/app/templates/Themes/template.less create mode 100644 rainloop/v/1.2.5.406/app/templates/Themes/values.less create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminDomainListItem.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminDomains.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminGeneral.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminLicensing.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminLogin.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminMenu.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminPackages.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminPackagesListItem.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminPackagesTable.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminPane.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminPluginListItem.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminPluginProperty.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminPlugins.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminSecurity.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/AdminSocial.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/ComposeAttachment.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/ComposeAttachmentInProcess.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/Login.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/MailFolderList.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/MailFolderListItem.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/MailFolderListSystemItem.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/MailMessageList.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/MailMessageListItem.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/MailMessageListItemNoPreviewPane.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/MailMessageView.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/PopupsActivate.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/PopupsAddAccount.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/PopupsAdvancedSearch.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/PopupsCompose.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/PopupsContacts.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/PopupsDomain.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/PopupsFolderClear.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/PopupsFolderCreate.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/PopupsFolderSystem.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/PopupsPlugin.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/PopupsWindowSimpleMessage.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/SettingsAccounts.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/SettingsChangePassword.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/SettingsCustom.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/SettingsFolderItem.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/SettingsFolders.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/SettingsGeneral.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/SettingsMenu.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/SettingsPane.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/SettingsPersonal.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/SettingsSocial.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/SettingsThemes.html create mode 100644 rainloop/v/1.2.5.406/app/templates/Views/SystemDropDown.html create mode 100644 rainloop/v/1.2.5.406/check.php create mode 100644 rainloop/v/1.2.5.406/index.php create mode 100644 rainloop/v/1.2.5.406/langs/en.ini create mode 100644 rainloop/v/1.2.5.406/langs/ru.ini create mode 100644 rainloop/v/1.2.5.406/static/browsers/chrome.gif create mode 100644 rainloop/v/1.2.5.406/static/browsers/firefox.gif create mode 100644 rainloop/v/1.2.5.406/static/browsers/opera.gif create mode 100644 rainloop/v/1.2.5.406/static/browsers/safari.gif create mode 100644 rainloop/v/1.2.5.406/static/css/app.css create mode 100644 rainloop/v/1.2.5.406/static/css/fonts/icomoon.dev.svg create mode 100644 rainloop/v/1.2.5.406/static/css/fonts/icomoon.eot create mode 100644 rainloop/v/1.2.5.406/static/css/fonts/icomoon.svg create mode 100644 rainloop/v/1.2.5.406/static/css/fonts/icomoon.ttf create mode 100644 rainloop/v/1.2.5.406/static/css/fonts/icomoon.woff create mode 100644 rainloop/v/1.2.5.406/static/css/images/editor.png create mode 100644 rainloop/v/1.2.5.406/static/css/images/empty-contact.png create mode 100644 rainloop/v/1.2.5.406/static/css/images/grey.png create mode 100644 rainloop/v/1.2.5.406/static/css/images/icom-message-notification.png create mode 100644 rainloop/v/1.2.5.406/static/css/images/loader-black.gif create mode 100644 rainloop/v/1.2.5.406/static/css/images/loader-white.gif create mode 100644 rainloop/v/1.2.5.406/static/css/images/sync.gif create mode 100644 rainloop/v/1.2.5.406/static/css/images/sync.png create mode 100644 rainloop/v/1.2.5.406/static/css/images/white.png create mode 100644 rainloop/v/1.2.5.406/static/css/select2-spinner.gif create mode 100644 rainloop/v/1.2.5.406/static/css/select2.png create mode 100644 rainloop/v/1.2.5.406/static/css/select2x2.png create mode 100644 rainloop/v/1.2.5.406/static/favicon.ico create mode 100644 rainloop/v/1.2.5.406/static/favicon.png create mode 100644 rainloop/v/1.2.5.406/static/js/admin.min.js create mode 100644 rainloop/v/1.2.5.406/static/js/app.min.js create mode 100644 rainloop/v/1.2.5.406/static/js/jquery.js create mode 100644 rainloop/v/1.2.5.406/static/js/libs.js create mode 100644 rainloop/v/1.2.5.406/static/services/amazon.png create mode 100644 rainloop/v/1.2.5.406/static/services/apple.jpg create mode 100644 rainloop/v/1.2.5.406/static/services/asana.png create mode 100644 rainloop/v/1.2.5.406/static/services/battle.net.png create mode 100644 rainloop/v/1.2.5.406/static/services/cnet.jpg create mode 100644 rainloop/v/1.2.5.406/static/services/ea.png create mode 100644 rainloop/v/1.2.5.406/static/services/ebay.jpg create mode 100644 rainloop/v/1.2.5.406/static/services/facebook.png create mode 100644 rainloop/v/1.2.5.406/static/services/github.png create mode 100644 rainloop/v/1.2.5.406/static/services/google-plus.png create mode 100644 rainloop/v/1.2.5.406/static/services/google.png create mode 100644 rainloop/v/1.2.5.406/static/services/icloud.jpg create mode 100644 rainloop/v/1.2.5.406/static/services/microsoft.jpg create mode 100644 rainloop/v/1.2.5.406/static/services/myspace.png create mode 100644 rainloop/v/1.2.5.406/static/services/onlive.png create mode 100644 rainloop/v/1.2.5.406/static/services/paypal.jpg create mode 100644 rainloop/v/1.2.5.406/static/services/skype.png create mode 100644 rainloop/v/1.2.5.406/static/services/steam.png create mode 100644 rainloop/v/1.2.5.406/static/services/ted.png create mode 100644 rainloop/v/1.2.5.406/static/services/twitter.jpg create mode 100644 rainloop/v/1.2.5.406/static/services/youtube.gif create mode 100644 rainloop/v/1.2.5.406/static/sounds/new-mail.mp3 create mode 100644 rainloop/v/1.2.5.406/static/sounds/new-mail.ogg create mode 100644 rainloop/v/1.2.5.406/themes/A/images/background.jpg create mode 100644 rainloop/v/1.2.5.406/themes/A/images/preview.png create mode 100644 rainloop/v/1.2.5.406/themes/A/styles.less create mode 100644 rainloop/v/1.2.5.406/themes/Clear/images/preview.png create mode 100644 rainloop/v/1.2.5.406/themes/Clear/styles.less create mode 100644 rainloop/v/1.2.5.406/themes/Custom/ext.less create mode 100644 rainloop/v/1.2.5.406/themes/Custom/images/preview.png create mode 100644 rainloop/v/1.2.5.406/themes/Default/images/background.jpg create mode 100644 rainloop/v/1.2.5.406/themes/Default/images/background.png create mode 100644 rainloop/v/1.2.5.406/themes/Default/images/preview.png create mode 100644 rainloop/v/1.2.5.406/themes/Default/styles.less create mode 100644 rainloop/v/1.2.5.406/themes/Linen/images/background.jpg create mode 100644 rainloop/v/1.2.5.406/themes/Linen/images/background.png create mode 100644 rainloop/v/1.2.5.406/themes/Linen/images/preview.png create mode 100644 rainloop/v/1.2.5.406/themes/Linen/styles.less create mode 100644 rainloop/v/1.2.5.406/themes/Love/images/background.jpg create mode 100644 rainloop/v/1.2.5.406/themes/Love/images/preview.png create mode 100644 rainloop/v/1.2.5.406/themes/Love/styles.less create mode 100644 rainloop/v/1.2.5.406/themes/Snow/images/background.jpg create mode 100644 rainloop/v/1.2.5.406/themes/Snow/images/preview.png create mode 100644 rainloop/v/1.2.5.406/themes/Snow/styles.less create mode 100644 rainloop/v/1.2.5.406/themes/Squares/images/background.jpg create mode 100644 rainloop/v/1.2.5.406/themes/Squares/images/background.png create mode 100644 rainloop/v/1.2.5.406/themes/Squares/images/preview.png create mode 100644 rainloop/v/1.2.5.406/themes/Squares/styles.less create mode 100644 rainloop/v/1.2.5.406/themes/SquaresDark/images/background.jpg create mode 100644 rainloop/v/1.2.5.406/themes/SquaresDark/images/background.png create mode 100644 rainloop/v/1.2.5.406/themes/SquaresDark/images/preview.png create mode 100644 rainloop/v/1.2.5.406/themes/SquaresDark/styles.less create mode 100644 rainloop/v/1.2.5.406/themes/Stripes/images/background.jpg create mode 100644 rainloop/v/1.2.5.406/themes/Stripes/images/preview.png create mode 100644 rainloop/v/1.2.5.406/themes/Stripes/styles.less create mode 100644 rainloop/v/1.2.5.406/themes/Wood/images/background.jpg create mode 100644 rainloop/v/1.2.5.406/themes/Wood/images/background.png create mode 100644 rainloop/v/1.2.5.406/themes/Wood/images/preview.png create mode 100644 rainloop/v/1.2.5.406/themes/Wood/styles.less create mode 100644 rainloop/v/1.2.5.406/themes/Xv/images/background.jpg create mode 100644 rainloop/v/1.2.5.406/themes/Xv/images/background.png create mode 100644 rainloop/v/1.2.5.406/themes/Xv/images/preview.png create mode 100644 rainloop/v/1.2.5.406/themes/Xv/styles.less diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..14d401048 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Creative Commons — Attribution-NonCommercial 3.0 Unported — CC BY-NC 3.0 +(http://creativecommons.org/licenses/by-nc/3.0/) + +You are free: + +to Share — to copy, distribute and transmit the work +to Remix — to adapt the work + + +Under the following conditions: + +Attribution — You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work). +Noncommercial — You may not use this work for commercial purposes. + + +With the understanding that: + +Waiver — Any of the above conditions can be waived if you get permission from the copyright holder. +Public Domain — Where the work or any of its elements is in the public domain under applicable law, that status is in no way affected by the license. +Other Rights — In no way are any of the following rights affected by the license: +Your fair dealing or fair use rights, or other applicable copyright exceptions and limitations; +The author's moral rights; +Rights other persons may have either in the work itself or in how the work is used, such as publicity or privacy rights. +Notice — For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to this web page. \ No newline at end of file diff --git a/data/VERSION b/data/VERSION new file mode 100644 index 000000000..37757662f --- /dev/null +++ b/data/VERSION @@ -0,0 +1 @@ +1.2.5.406 \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 000000000..7771ae0b2 --- /dev/null +++ b/index.php @@ -0,0 +1,42 @@ +Handle(); + } + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/langs.ini b/rainloop/v/1.2.5.406/app/i18n/langs.ini new file mode 100644 index 000000000..99b6d3332 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/langs.ini @@ -0,0 +1,3 @@ +[LANGS_NAMES] +LANG_EN = "English" +LANG_RU = "Русский (Russian)" diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/bg.js b/rainloop/v/1.2.5.406/app/i18n/moment/bg.js new file mode 100644 index 000000000..94beac475 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/bg.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : bulgarian (bg) +// author : Krasen Borisov : https://github.com/kraz +(function(){var a={months:"януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),monthsShort:"янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"),weekdays:"неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"),weekdaysShort:"нед_пон_вто_сря_чет_пет_съб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"h:mm",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Днес в] LT",nextDay:"[Утре в] LT",nextWeek:"dddd [в] LT",lastDay:"[Вчера в] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[В изминалата] dddd [в] LT";case 1:case 2:case 4:case 5:return"[В изминалия] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"след %s",past:"преди %s",s:"няколко секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дни",M:"месец",MM:"%d месеца",y:"година",yy:"%d години"},ordinal:function(a){return"."}};typeof module!="undefined"&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("bg",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/ca.js b/rainloop/v/1.2.5.406/app/i18n/moment/ca.js new file mode 100644 index 000000000..3c9b56600 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/ca.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : catalan (ca) +// author : Juan G. Hurtado : https://github.com/juanghurtado +(function(){var a={months:"Gener_Febrer_Març_Abril_Maig_Juny_Juliol_Agost_Setembre_Octubre_Novembre_Desembre".split("_"),monthsShort:"Gen._Febr._Mar._Abr._Mai._Jun._Jul._Ag._Set._Oct._Nov._Des.".split("_"),weekdays:"Diumenge_Dilluns_Dimarts_Dimecres_Dijous_Divendres_Dissabte".split("_"),weekdaysShort:"Dg._Dl._Dt._Dc._Dj._Dv._Ds.".split("_"),weekdaysMin:"Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[avui a "+(this.hours()!==1?"les":"la")+"] LT"},nextDay:function(){return"[demà a "+(this.hours()!==1?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(this.hours()!==1?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(this.hours()!==1?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(this.hours()!==1?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fa %s",s:"uns segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("ca",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/cv.js b/rainloop/v/1.2.5.406/app/i18n/moment/cv.js new file mode 100644 index 000000000..92c1c88ec --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/cv.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : chuvash (cv) +// author : Anatoly Mironov : https://github.com/mirontoli +(function(){var a={months:"кăрлач_нарăс_пуш_ака_май_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав".split("_"),monthsShort:"кăр_нар_пуш_ака_май_çĕр_утă_çур_ав_юпа_чӳк_раш".split("_"),weekdays:"вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун".split("_"),weekdaysShort:"выр_тун_ытл_юн_кĕç_эрн_шăм".split("_"),weekdaysMin:"вр_тн_ыт_юн_кç_эр_шм".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"YYYY çулхи MMMM уйăхĕн D-мĕшĕ",LLL:"YYYY çулхи MMMM уйăхĕн D-мĕшĕ, LT",LLLL:"dddd, YYYY çулхи MMMM уйăхĕн D-мĕшĕ, LT"},calendar:{sameDay:"[Паян] LT [сехетре]",nextDay:"[Ыран] LT [сехетре]",lastDay:"[Ĕнер] LT [сехетре]",nextWeek:"[Çитес] dddd LT [сехетре]",lastWeek:"[Иртнĕ] dddd LT [сехетре]",sameElse:"L"},relativeTime:{future:"%sран",past:"%s каялла",s:"пĕр-ик çеккунт",m:"пĕр минут",mm:"%d минут",h:"пĕр сехет",hh:"%d сехет",d:"пĕр кун",dd:"%d кун",M:"пĕр уйăх",MM:"%d уйăх",y:"пĕр çул",yy:"%d çул"},ordinal:function(a){return"-мĕш"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("cv",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/da.js b/rainloop/v/1.2.5.406/app/i18n/moment/da.js new file mode 100644 index 000000000..9a6391ffe --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/da.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : danish (da) +// author : Ulrik Nielsen : https://github.com/mrbase +(function(){var a={months:"Januar_Februar_Marts_April_Maj_Juni_Juli_August_September_Oktober_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Maj_Jun_Jul_Aug_Sep_Okt_Nov_Dec".split("_"),weekdays:"Søndag_Mandag_Tirsdag_Onsdag_Torsdag_Fredag_Lørdag".split("_"),weekdaysShort:"Søn_Man_Tir_Ons_Tor_Fre_Lør".split("_"),weekdaysMin:"Sø_Ma_Ti_On_To_Fr_Lø".split("_"),longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd D. MMMM, YYYY h:mm A"},calendar:{sameDay:"[I dag kl.] LT",nextDay:"[I morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[I går kl.] LT",lastWeek:"[sidste] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"få sekunder",m:"minut",mm:"%d minutter",h:"time",hh:"%d timer",d:"dag",dd:"%d dage",M:"månede",MM:"%d måneder",y:"år",yy:"%d år"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("da",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/de.js b/rainloop/v/1.2.5.406/app/i18n/moment/de.js new file mode 100644 index 000000000..524da560a --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/de.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : german (de) +// author : lluchs : https://github.com/lluchs +(function(){var a={months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),longDateFormat:{LT:"H:mm U\\hr",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[Heute um] LT",sameElse:"L",nextDay:"[Morgen um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gestern um] LT",lastWeek:"[letzten] dddd [um] LT"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:"einer Minute",mm:"%d Minuten",h:"einer Stunde",hh:"%d Stunden",d:"einem Tag",dd:"%d Tagen",M:"einem Monat",MM:"%d Monaten",y:"einem Jahr",yy:"%d Jahren"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("de",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/en-ca.js b/rainloop/v/1.2.5.406/app/i18n/moment/en-ca.js new file mode 100644 index 000000000..b9b32479e --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/en-ca.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : canadian english (en-ca) +// author : Jonathan Abourbih : https://github.com/jonbca +(function(){var a={months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"YYYY-MM-DD",LL:"D MMMM, YYYY",LLL:"D MMMM, YYYY LT",LLLL:"dddd, D MMMM, YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("en-ca",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/en-gb.js b/rainloop/v/1.2.5.406/app/i18n/moment/en-gb.js new file mode 100644 index 000000000..f86fa4391 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/en-gb.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : great britain english (en-gb) +// author : Chris Gedrim : https://github.com/chrisgedrim +(function(){var a={months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("en-gb",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/es.js b/rainloop/v/1.2.5.406/app/i18n/moment/es.js new file mode 100644 index 000000000..53ac4d29a --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/es.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : spanish (es) +// author : Julio Napurí : https://github.com/julionc +(function(){var a={months:"Enero_Febrero_Marzo_Abril_Mayo_Junio_Julio_Agosto_Septiembre_Octubre_Noviembre_Diciembre".split("_"),monthsShort:"Ene._Feb._Mar._Abr._May._Jun._Jul._Ago._Sep._Oct._Nov._Dic.".split("_"),weekdays:"Domingo_Lunes_Martes_Miércoles_Jueves_Viernes_Sábado".split("_"),weekdaysShort:"Dom._Lun._Mar._Mié._Jue._Vie._Sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mi_Ju_Vi_Sá".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[hoy a la"+(this.hours()!==1?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(this.hours()!==1?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(this.hours()!==1?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(this.hours()!==1?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(this.hours()!==1?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("es",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/eu.js b/rainloop/v/1.2.5.406/app/i18n/moment/eu.js new file mode 100644 index 000000000..453d51228 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/eu.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : euskara (eu) +// author : Eneko Illarramendi : https://github.com/eillarra +(function(){var a={months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"YYYYko MMMMren D[a]",LLL:"YYYYko MMMMren D[a] LT",LLLL:"dddd, YYYYko MMMMren D[a] LT"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("eu",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/fi.js b/rainloop/v/1.2.5.406/app/i18n/moment/fi.js new file mode 100644 index 000000000..97c1b22bf --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/fi.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : finnish (fi) +// author : Tarmo Aidantausta : https://github.com/bleadof +(function(){function c(a,b,c,e){var f="";switch(c){case"s":return e?"muutaman sekunnin":"muutama sekunti";case"m":return e?"minuutin":"minuutti";case"mm":f=e?"minuutin":"minuuttia";break;case"h":return e?"tunnin":"tunti";case"hh":f=e?"tunnin":"tuntia";break;case"d":return e?"päivän":"päivä";case"dd":f=e?"päivän":"päivää";break;case"M":return e?"kuukauden":"kuukausi";case"MM":f=e?"kuukauden":"kuukautta";break;case"y":return e?"vuoden":"vuosi";case"yy":f=e?"vuoden":"vuotta"}return f=d(a,e)+" "+f,f}function d(c,d){return c<10?d?b[c]:a[c]:c}var a=["nolla","yksi","kaksi","kolme","neljä","viisi","kuusi","seitsemän","kahdeksan","yhdeksän"],b=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",a[7],a[8],a[9]],e={months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tam_hel_maa_huh_tou_kes_hei_elo_syy_lok_mar_jou".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",L:"DD.MM.YYYY",LL:"Do MMMMt\\a YYYY",LLL:"Do MMMMt\\a YYYY, klo LT",LLLL:"dddd, Do MMMMt\\a YYYY, klo LT"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=e),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("fi",e)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/fr-ca.js b/rainloop/v/1.2.5.406/app/i18n/moment/fr-ca.js new file mode 100644 index 000000000..3ab7da2a9 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/fr-ca.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : canadian french (fr-ca) +// author : Jonathan Abourbih : https://github.com/jonbca +(function(){var a={months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"une année",yy:"%d années"},ordinal:function(a){return a===1?"er":"ème"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("fr-ca",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/fr.js b/rainloop/v/1.2.5.406/app/i18n/moment/fr.js new file mode 100644 index 000000000..53589d966 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/fr.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : french (fr) +// author : John Fischer : https://github.com/jfroffice +(function(){var a={months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"une année",yy:"%d années"},ordinal:function(a){return a===1?"er":"ème"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("fr",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/gl.js b/rainloop/v/1.2.5.406/app/i18n/moment/gl.js new file mode 100644 index 000000000..9e6d6fde4 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/gl.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : galician (gl) +// author : Juan G. Hurtado : https://github.com/juanghurtado +(function(){var a={months:"Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Octubro_Novembro_Decembro".split("_"),monthsShort:"Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"),weekdays:"Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"),weekdaysShort:"Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[hoxe "+(this.hours()!==1?"ás":"a")+"] LT"},nextDay:function(){return"[mañá "+(this.hours()!==1?"ás":"a")+"] LT"},nextWeek:function(){return"dddd ["+(this.hours()!==1?"ás":"a")+"] LT"},lastDay:function(){return"[onte "+(this.hours()!==1?"á":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(this.hours()!==1?"ás":"a")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fai %s",s:"uns segundo",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("gl",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/hu.js b/rainloop/v/1.2.5.406/app/i18n/moment/hu.js new file mode 100644 index 000000000..1101c17f3 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/hu.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : hungarian (hu) +// author : Adam Brunner : https://github.com/adambrunner +(function(){function a(a,b,c,d){var e=a;switch(c){case"s":return d||b?"néhány másodperc":"néhány másodperce";case"m":e="egy";case"mm":return e+(d||b?" perc":" perce");case"h":e="egy";case"hh":return e+(d||b?" óra":" órája");case"d":e="egy";case"dd":return e+(d||b?" nap":" napja");case"M":e="egy";case"MM":return e+(d||b?" hónap":" hónapja");case"y":e="egy";case"yy":return e+(d||b?" év":" éve");default:}return""}function b(a){var b="";switch(this.day()){case 0:b="vasárnap";break;case 1:b="hétfőn";break;case 2:b="kedden";break;case 3:b="szerdán";break;case 4:b="csütörtökön";break;case 5:b="pénteken";break;case 6:b="szombaton"}return(a?"":"múlt ")+"["+b+"] LT[-kor]"}var c={months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),weekdays:"vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D., LT",LLLL:"YYYY. MMMM D., dddd LT"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return b.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return b.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("hu",c)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/is.js b/rainloop/v/1.2.5.406/app/i18n/moment/is.js new file mode 100644 index 000000000..9da042689 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/is.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : icelandic (is) +// author : Hinrik Örn Sigurðsson : https://github.com/hinrik +(function(){var a=function(a){return a%100==11?!0:a%10==1?!1:!0},b=function(b,c,d,e){var f=b+" ";switch(d){case"s":return c||e?"nokkrar sekúndur":"nokkrum sekúndum";case"m":return c?"mínúta":"mínútu";case"mm":return a(b)?f+(c||e?"mínútur":"mínútum"):c?f+"mínúta":f+"mínútu";case"hh":return a(b)?f+(c||e?"klukkustundir":"klukkustundum"):f+"klukkustund";case"d":return c?"dagur":e?"dag":"degi";case"dd":return a(b)?c?f+"dagar":f+(e?"daga":"dögum"):c?f+"dagur":f+(e?"dag":"degi");case"M":return c?"mánuður":e?"mánuð":"mánuði";case"MM":return a(b)?c?f+"mánuðir":f+(e?"mánuði":"mánuðum"):c?f+"mánuður":f+(e?"mánuð":"mánuði");case"y":return c||e?"ár":"ári";case"yy":return a(b)?f+(c||e?"ár":"árum"):f+(c||e?"ár":"ári")}},c={months:"janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),monthsShort:"jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),weekdays:"sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),weekdaysShort:"sun_mán_þri_mið_fim_fös_lau".split("_"),weekdaysMin:"Su_Má_Þr_Mi_Fi_Fö_La".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY kl. LT",LLLL:"dddd, D. MMMM YYYY kl. LT"},calendar:{sameDay:"[í dag kl.] LT",nextDay:"[á morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[í gær kl.] LT",lastWeek:"[síðasta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s síðan",s:b,m:b,mm:b,h:"klukkustund",hh:b,d:b,dd:b,M:b,MM:b,y:b,yy:b},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("is",c)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/it.js b/rainloop/v/1.2.5.406/app/i18n/moment/it.js new file mode 100644 index 000000000..3773f38dd --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/it.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : italian (it) +// author : Lorenzo : https://github.com/aliem +(function(){var a={months:"Gennaio_Febbraio_Marzo_Aprile_Maggio_Giugno_Luglio_Agosto_Settebre_Ottobre_Novembre_Dicembre".split("_"),monthsShort:"Gen_Feb_Mar_Apr_Mag_Giu_Lug_Ago_Set_Ott_Nov_Dic".split("_"),weekdays:"Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),weekdaysShort:"Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),weekdaysMin:"D_L_Ma_Me_G_V_S".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:"[lo scorso] dddd [alle] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s fa",s:"secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},ordinal:function(){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("it",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/ja.js b/rainloop/v/1.2.5.406/app/i18n/moment/ja.js new file mode 100644 index 000000000..c4f01ab5d --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/ja.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : japanese (ja) +// author : LI Long : https://github.com/baryon +(function(){var a={months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日LT",LLLL:"YYYY年M月D日LT dddd"},meridiem:function(a,b,c){return a<12?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("ja",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/jp.js b/rainloop/v/1.2.5.406/app/i18n/moment/jp.js new file mode 100644 index 000000000..dbf237ab3 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/jp.js @@ -0,0 +1,6 @@ +// moment.js language configuration +// language : japanese (jp) +// author : LI Long : https://github.com/baryon +// This language config was incorrectly named 'jp' instead of 'ja'. +// In version 2.0.0, this will be deprecated and you should use 'ja' instead. +(function(){var a={months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日LT",LLLL:"YYYY年M月D日LT dddd"},meridiem:function(a,b,c){return a<12?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("jp",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/ko.js b/rainloop/v/1.2.5.406/app/i18n/moment/ko.js new file mode 100644 index 000000000..f54a5aebf --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/ko.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : korean (ko) +// author : Kyungwook, Park : https://github.com/kyungw00k +(function(){var a={months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h시 mm분",L:"YYYY.MM.DD",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 LT",LLLL:"YYYY년 MMMM D일 dddd LT"},meridiem:function(a,b,c){return a<12?"오전":"오후"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇초",ss:"%d초",m:"일분",mm:"%d분",h:"한시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한달",MM:"%d달",y:"일년",yy:"%d년"},ordinal:function(a){return"일"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("ko",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/kr.js b/rainloop/v/1.2.5.406/app/i18n/moment/kr.js new file mode 100644 index 000000000..d2ac35fac --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/kr.js @@ -0,0 +1,6 @@ +// moment.js language configuration +// language : korean (kr) +// author : Kyungwook, Park : https://github.com/kyungw00k +// This language config was incorrectly named 'kr' instead of 'ko'. +// In version 2.0.0, this will be deprecated and you should use 'ko' instead. +(function(){var a={months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h시 mm분",L:"YYYY.MM.DD",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 LT",LLLL:"YYYY년 MMMM D일 dddd LT"},meridiem:function(a,b,c){return a<12?"오전":"오후"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇초",ss:"%d초",m:"일분",mm:"%d분",h:"한시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한달",MM:"%d달",y:"일년",yy:"%d년"},ordinal:function(a){return"일"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("kr",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/nb.js b/rainloop/v/1.2.5.406/app/i18n/moment/nb.js new file mode 100644 index 000000000..d476a3361 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/nb.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : norwegian bokmål (nb) +// author : Espen Hovlandsdal : https://github.com/rexxars +(function(){var a={months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[I dag klokken] LT",nextDay:"[I morgen klokken] LT",nextWeek:"dddd [klokken] LT",lastDay:"[I går klokken] LT",lastWeek:"[Forrige] dddd [klokken] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"for %s siden",s:"noen sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en måned",MM:"%d måneder",y:"ett år",yy:"%d år"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("nb",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/nl.js b/rainloop/v/1.2.5.406/app/i18n/moment/nl.js new file mode 100644 index 000000000..a9084b735 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/nl.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : dutch (nl) +// author : Joris Röling : https://github.com/jjupiter +(function(){var a="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),b="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),c={months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(c,d){return/-MMM-/.test(d)?b[c.month()]:a[c.month()]},weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Vandaag om] LT",nextDay:"[Morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[Gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},ordinal:function(a){return a===1||a===8||a>=20?"ste":"de"}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("nl",c)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/pl.js b/rainloop/v/1.2.5.406/app/i18n/moment/pl.js new file mode 100644 index 000000000..aeab20881 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/pl.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : polish (pl) +// author : Rafal Hirsz : https://github.com/evoL +(function(){var a=function(a){return a%10<5&&a%10>1&&~~(a/10)!==1},b=function(b,c,d){var e=b+" ";switch(d){case"m":return c?"minuta":"minutę";case"mm":return e+(a(b)?"minuty":"minut");case"h":return c?"godzina":"godzinę";case"hh":return e+(a(b)?"godziny":"godzin");case"MM":return e+(a(b)?"miesiące":"miesięcy");case"yy":return e+(a(b)?"lata":"lat")}},c={months:"styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"nie_pon_wt_śr_czw_pt_sb".split("_"),weekdaysMin:"N_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:"[W] dddd [o] LT",lastDay:"[Wczoraj o] LT",lastWeek:"[W zeszły/łą] dddd [o] LT",sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",m:b,mm:b,h:b,hh:b,d:"1 dzień",dd:"%d dni",M:"miesiąc",MM:b,y:"rok",yy:b},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("pl",c)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/pt-br.js b/rainloop/v/1.2.5.406/app/i18n/moment/pt-br.js new file mode 100644 index 000000000..fcba6852b --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/pt-br.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : brazilian portuguese (pt-br) +// author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira +(function(){var a={months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D \\de MMMM \\de YYYY",LLL:"D \\de MMMM \\de YYYY LT",LLLL:"dddd, D \\de MMMM \\de YYYY LT"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return this.day()===0||this.day()===6?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("pt-br",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/pt.js b/rainloop/v/1.2.5.406/app/i18n/moment/pt.js new file mode 100644 index 000000000..7b9f4c9ae --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/pt.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : portuguese (pt) +// author : Jefferson : https://github.com/jalex79 +(function(){var a={months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D \\de MMMM \\de YYYY",LLL:"D \\de MMMM \\de YYYY LT",LLLL:"dddd, D \\de MMMM \\de YYYY LT"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return this.day()===0||this.day()===6?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("pt",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/ru.js b/rainloop/v/1.2.5.406/app/i18n/moment/ru.js new file mode 100644 index 000000000..66bf4147d --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/ru.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : russian (ru) +// author : Viktorminator : https://github.com/Viktorminator +(function(){var a=[function(a){return a%10===1&&a%100!==11},function(a){return a%10>=2&&a%10<=4&&a%10%1===0&&(a%100<12||a%100>14)},function(a){return a%10===0||a%10>=5&&a%10<=9&&a%10%1===0||a%100>=11&&a%100<=14&&a%100%1===0},function(a){return!0}],b=function(b,c){var d=b.split("_"),e=Math.min(a.length,d.length),f=-1;while(++f=100?100:null;return a[c]||a[d]||a[e]}};typeof module!="undefined"&&module.exports&&(module.exports=b),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("tr",b)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/zh-cn.js b/rainloop/v/1.2.5.406/app/i18n/moment/zh-cn.js new file mode 100644 index 000000000..9f435f62b --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/zh-cn.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : chinese +// author : suupic : https://github.com/suupic +(function(){var a={months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah点mm",L:"YYYY年MMMD日",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日LT",LLLL:"YYYY年MMMD日ddddLT"},meridiem:function(a,b,c){return a<9?"早上":a<11&&b<30?"上午":a<13&&b<30?"中午":a<18?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},relativeTime:{future:"%s内",past:"%s前",s:"几秒",m:"1分钟",mm:"%d分钟",h:"1小时",hh:"%d小时",d:"1天",dd:"%d天",M:"1个月",MM:"%d个月",y:"1年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("zh-cn",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/i18n/moment/zh-tw.js b/rainloop/v/1.2.5.406/app/i18n/moment/zh-tw.js new file mode 100644 index 000000000..915bdba07 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/i18n/moment/zh-tw.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : traditional chinese (zh-tw) +// author : Ben : https://github.com/ben-lin +(function(){var a={months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah點mm",L:"YYYY年MMMD日",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日LT",LLLL:"YYYY年MMMD日ddddLT"},meridiem:function(a,b,c){return a<9?"早上":a<11&&b<30?"上午":a<13&&b<30?"中午":a<18?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},relativeTime:{future:"%s內",past:"%s前",s:"幾秒",m:"一分鐘",mm:"%d分鐘",h:"一小時",hh:"%d小時",d:"一天",dd:"%d天",M:"一個月",MM:"%d個月",y:"一年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("zh-tw",a)})(); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Browser.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Browser.php new file mode 100644 index 000000000..dbc47ec89 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Browser.php @@ -0,0 +1,195 @@ +client = $client ?: new FileGetContents(); + $this->factory = $factory ?: new Factory(); + } + + public function get($url, $headers = array()) + { + return $this->call($url, RequestInterface::METHOD_GET, $headers); + } + + public function post($url, $headers = array(), $content = '') + { + return $this->call($url, RequestInterface::METHOD_POST, $headers, $content); + } + + public function head($url, $headers = array()) + { + return $this->call($url, RequestInterface::METHOD_HEAD, $headers); + } + + public function patch($url, $headers = array(), $content = '') + { + return $this->call($url, RequestInterface::METHOD_PATCH, $headers, $content); + } + + public function put($url, $headers = array(), $content = '') + { + return $this->call($url, RequestInterface::METHOD_PUT, $headers, $content); + } + + public function delete($url, $headers = array(), $content = '') + { + return $this->call($url, RequestInterface::METHOD_DELETE, $headers, $content); + } + + /** + * Sends a request. + * + * @param string $url The URL to call + * @param string $method The request method to use + * @param array $headers An array of request headers + * @param string $content The request content + * + * @return MessageInterface The response object + */ + public function call($url, $method, $headers = array(), $content = '') + { + $request = $this->factory->createRequest($method); + + if (!$url instanceof Url) { + $url = new Url($url); + } + + $url->applyToRequest($request); + + $request->addHeaders($headers); + $request->setContent($content); + + return $this->send($request); + } + + /** + * Sends a form request. + * + * @param string $url The URL to submit to + * @param array $fields An array of fields + * @param string $method The request method to use + * @param array $headers An array of request headers + * + * @return MessageInterface The response object + */ + public function submit($url, array $fields, $method = RequestInterface::METHOD_POST, $headers = array()) + { + $request = $this->factory->createFormRequest(); + + if (!$url instanceof Url) { + $url = new Url($url); + } + + $url->applyToRequest($request); + + $request->addHeaders($headers); + $request->setMethod($method); + $request->setFields($fields); + + return $this->send($request); + } + + /** + * Sends a request. + * + * @param RequestInterface $request A request object + * @param MessageInterface $response A response object + * + * @return MessageInterface The response + */ + public function send(RequestInterface $request, MessageInterface $response = null) + { + if (null === $response) { + $response = $this->factory->createResponse(); + } + + if ($this->listener) { + $this->listener->preSend($request); + } + + $this->client->send($request, $response); + + $this->lastRequest = $request; + $this->lastResponse = $response; + + if ($this->listener) { + $this->listener->postSend($request, $response); + } + + return $response; + } + + public function getLastRequest() + { + return $this->lastRequest; + } + + public function getLastResponse() + { + return $this->lastResponse; + } + + public function setClient(ClientInterface $client) + { + $this->client = $client; + } + + public function getClient() + { + return $this->client; + } + + public function setMessageFactory(FactoryInterface $factory) + { + $this->factory = $factory; + } + + public function getMessageFactory() + { + return $this->factory; + } + + public function setListener(ListenerInterface $listener) + { + $this->listener = $listener; + } + + public function getListener() + { + return $this->listener; + } + + public function addListener(ListenerInterface $listener) + { + if (!$this->listener) { + $this->listener = $listener; + } elseif ($this->listener instanceof ListenerChain) { + $this->listener->addListener($listener); + } else { + $this->listener = new ListenerChain(array( + $this->listener, + $listener, + )); + } + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/AbstractClient.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/AbstractClient.php new file mode 100644 index 000000000..566406252 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/AbstractClient.php @@ -0,0 +1,62 @@ +ignoreErrors = $ignoreErrors; + } + + public function getIgnoreErrors() + { + return $this->ignoreErrors; + } + + public function setMaxRedirects($maxRedirects) + { + $this->maxRedirects = $maxRedirects; + } + + public function getMaxRedirects() + { + return $this->maxRedirects; + } + + public function setTimeout($timeout) + { + $this->timeout = $timeout; + } + + public function getTimeout() + { + return $this->timeout; + } + + public function setVerifyPeer($verifyPeer) + { + $this->verifyPeer = $verifyPeer; + } + + public function getVerifyPeer() + { + return $this->verifyPeer; + } + + public function setProxy($proxy) + { + $this->proxy = $proxy; + } + + public function getProxy() + { + return $this->proxy; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/AbstractCurl.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/AbstractCurl.php new file mode 100644 index 000000000..4d73be127 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/AbstractCurl.php @@ -0,0 +1,201 @@ +options = array( + CURLOPT_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS, + CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS, + ); + } + } + + /** + * Creates a new cURL resource. + * + * @see curl_init() + * + * @return resource A new cURL resource + */ + protected static function createCurlHandle() + { + if (false === $curl = curl_init()) { + throw new ClientException('Unable to create a new cURL handle'); + } + + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_HEADER, true); + + return $curl; + } + + /** + * Populates a response object. + * + * @param resource $curl A cURL resource + * @param string $raw The raw response string + * @param MessageInterface $response The response object + */ + protected static function populateResponse($curl, $raw, MessageInterface $response) + { + $pos = curl_getinfo($curl, CURLINFO_HEADER_SIZE); + + $response->setHeaders(static::getLastHeaders(rtrim(substr($raw, 0, $pos)))); + $response->setContent(substr($raw, $pos)); + } + + /** + * Sets options on a cURL resource based on a request. + */ + private static function setOptionsFromRequest($curl, RequestInterface $request) + { + $options = array( + CURLOPT_CUSTOMREQUEST => $request->getMethod(), + CURLOPT_URL => $request->getHost().$request->getResource(), + CURLOPT_HTTPHEADER => $request->getHeaders(), + ); + + switch ($request->getMethod()) { + case RequestInterface::METHOD_HEAD: + $options[CURLOPT_NOBODY] = true; + break; + + case RequestInterface::METHOD_GET: + $options[CURLOPT_HTTPGET] = true; + break; + + case RequestInterface::METHOD_POST: + case RequestInterface::METHOD_PUT: + case RequestInterface::METHOD_DELETE: + case RequestInterface::METHOD_PATCH: + $options[CURLOPT_POSTFIELDS] = $fields = static::getPostFields($request); + + // remove the content-type header + if (is_array($fields)) { + $options[CURLOPT_HTTPHEADER] = array_filter($options[CURLOPT_HTTPHEADER], function($header) { + return 0 !== stripos($header, 'Content-Type: '); + }); + } + + break; + } + + curl_setopt_array($curl, $options); + } + + /** + * Returns a value for the CURLOPT_POSTFIELDS option. + * + * @return string|array A post fields value + */ + private static function getPostFields(RequestInterface $request) + { + if (!$request instanceof FormRequestInterface) { + return $request->getContent(); + } + + $fields = $request->getFields(); + $multipart = false; + + foreach ($fields as $name => $value) { + if ($value instanceof FormUploadInterface) { + $multipart = true; + + if ($file = $value->getFile()) { + // replace value with upload string + $fields[$name] = '@'.$file; + + if ($contentType = $value->getContentType()) { + $fields[$name] .= ';type='.$contentType; + } + } else { + return $request->getContent(); + } + } + } + + return $multipart ? $fields : http_build_query($fields); + } + + /** + * A helper for getting the last set of headers. + * + * @param string $raw A string of many header chunks + * + * @return array An array of header lines + */ + private static function getLastHeaders($raw) + { + $headers = array(); + foreach (preg_split('/(\\r?\\n)/', $raw) as $header) { + if ($header) { + $headers[] = $header; + } else { + $headers = array(); + } + } + + return $headers; + } + + /** + * Stashes a cURL option to be set on send, when the resource is created. + * + * If the supplied value it set to null the option will be removed. + * + * @param integer $option The option + * @param mixed $value The value + * + * @see curl_setopt() + */ + public function setOption($option, $value) + { + if (null === $value) { + unset($this->options[$option]); + } else { + $this->options[$option] = $value; + } + } + + /** + * Prepares a cURL resource to send a request. + */ + protected function prepare($curl, RequestInterface $request, array $options = array()) + { + static::setOptionsFromRequest($curl, $request); + + // apply settings from client + if ($this->getTimeout() < 1) { + curl_setopt($curl, CURLOPT_TIMEOUT_MS, $this->getTimeout() * 1000); + } else { + curl_setopt($curl, CURLOPT_TIMEOUT, $this->getTimeout()); + } + + if ($this->proxy) { + curl_setopt($curl, CURLOPT_PROXY, $this->proxy); + } + + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 0 < $this->getMaxRedirects()); + curl_setopt($curl, CURLOPT_MAXREDIRS, $this->getMaxRedirects()); + curl_setopt($curl, CURLOPT_FAILONERROR, !$this->getIgnoreErrors()); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->getVerifyPeer()); + + // apply additional options + curl_setopt_array($curl, $options + $this->options); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/AbstractStream.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/AbstractStream.php new file mode 100644 index 000000000..ddb393c5f --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/AbstractStream.php @@ -0,0 +1,43 @@ + array( + // values from the request + 'method' => $request->getMethod(), + 'header' => implode("\r\n", $request->getHeaders()), + 'content' => $request->getContent(), + 'protocol_version' => $request->getProtocolVersion(), + + // values from the current client + 'ignore_errors' => $this->getIgnoreErrors(), + 'max_redirects' => $this->getMaxRedirects(), + 'timeout' => $this->getTimeout(), + ), + 'ssl' => array( + 'verify_peer' => $this->getVerifyPeer(), + ), + ); + + if ($this->proxy) { + $options['http']['proxy'] = $this->proxy; + $options['http']['request_fulluri'] = true; + } + + return $options; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/BatchClientInterface.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/BatchClientInterface.php new file mode 100644 index 000000000..ea1783d64 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/BatchClientInterface.php @@ -0,0 +1,11 @@ +lastCurl)) { + curl_close($this->lastCurl); + } + + $this->lastCurl = static::createCurlHandle(); + $this->prepare($this->lastCurl, $request, $options); + + $data = curl_exec($this->lastCurl); + + if (false === $data) { + $errorMsg = curl_error($this->lastCurl); + $errorNo = curl_errno($this->lastCurl); + + throw new ClientException($errorMsg, $errorNo); + } + + static::populateResponse($this->lastCurl, $data, $response); + } + + /** + * Introspects the last cURL request. + * + * @see curl_getinfo() + */ + public function getInfo($opt = 0) + { + if (!is_resource($this->lastCurl)) { + throw new LogicException('There is no cURL resource'); + } + + return curl_getinfo($this->lastCurl, $opt); + } + + public function __destruct() + { + if (is_resource($this->lastCurl)) { + curl_close($this->lastCurl); + } + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/FileGetContents.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/FileGetContents.php new file mode 100644 index 000000000..44130008f --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/FileGetContents.php @@ -0,0 +1,87 @@ +setCookieJar($cookieJar); + } + } + + /** + * @param CookieJar $cookieJar + */ + public function setCookieJar(CookieJar $cookieJar) + { + $this->cookieJar = $cookieJar; + } + + /** + * @return CookieJar + */ + public function getCookieJar() + { + return $this->cookieJar; + } + + /** + * @see ClientInterface + * + * @throws ClientException If file_get_contents() fires an error + */ + public function send(RequestInterface $request, MessageInterface $response) + { + if ($cookieJar = $this->getCookieJar()) { + $cookieJar->clearExpiredCookies(); + $cookieJar->addCookieHeaders($request); + } + + $context = stream_context_create($this->getStreamContextArray($request)); + $url = $request->getHost().$request->getResource(); + + $level = error_reporting(0); + $content = file_get_contents($url, 0, $context); + error_reporting($level); + if (false === $content) { + $error = error_get_last(); + throw new ClientException($error['message']); + } + + $response->setHeaders($this->filterHeaders((array) $http_response_header)); + $response->setContent($content); + + if ($cookieJar) { + $cookieJar->processSetCookieHeaders($request, $response); + } + } + + private function filterHeaders(array $headers) + { + $filtered = array(); + foreach ($headers as $header) { + if (0 === stripos($header, 'http/')) { + $filtered = array(); + } + + $filtered[] = $header; + } + + return $filtered; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/MultiCurl.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/MultiCurl.php new file mode 100644 index 000000000..a70617227 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Client/MultiCurl.php @@ -0,0 +1,53 @@ +queue[] = array($request, $response, $options); + } + + public function flush() + { + if (false === $curlm = curl_multi_init()) { + throw new ClientException('Unable to create a new cURL multi handle'); + } + + // prepare a cURL handle for each entry in the queue + foreach ($this->queue as $i => &$queue) { + list($request, $response, $options) = $queue; + $curl = $queue[] = static::createCurlHandle(); + $this->prepare($curl, $request, $options); + curl_multi_add_handle($curlm, $curl); + } + + $active = null; + do { + $mrc = curl_multi_exec($curlm, $active); + } while (CURLM_CALL_MULTI_PERFORM == $mrc); + + while ($active && CURLM_OK == $mrc) { + if (-1 != curl_multi_select($curlm)) { + do { + $mrc = curl_multi_exec($curlm, $active); + } while (CURLM_CALL_MULTI_PERFORM == $mrc); + } + } + + // populate the responses + while (list($request, $response, $options, $curl) = array_shift($this->queue)) { + static::populateResponse($curl, curl_multi_getcontent($curl), $response); + curl_multi_remove_handle($curlm, $curl); + } + + curl_multi_close($curlm); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Exception/ClientException.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Exception/ClientException.php new file mode 100644 index 000000000..187157ee8 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Exception/ClientException.php @@ -0,0 +1,10 @@ +username = $username; + $this->password = $password; + } + + public function preSend(RequestInterface $request) + { + $request->addHeader('Authorization: Basic '.base64_encode($this->username.':'.$this->password)); + } + + public function postSend(RequestInterface $request, MessageInterface $response) + { + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/CallbackListener.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/CallbackListener.php new file mode 100644 index 000000000..77f7fa831 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/CallbackListener.php @@ -0,0 +1,49 @@ +callable = $callable; + } + + public function preSend(RequestInterface $request) + { + call_user_func($this->callable, $request); + } + + public function postSend(RequestInterface $request, MessageInterface $response) + { + call_user_func($this->callable, $request, $response); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/History/Entry.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/History/Entry.php new file mode 100644 index 000000000..d7d21066a --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/History/Entry.php @@ -0,0 +1,42 @@ +request = $request; + $this->response = $response; + $this->duration = $duration; + } + + public function getRequest() + { + return $this->request; + } + + public function getResponse() + { + return $this->response; + } + + public function getDuration() + { + return $this->duration; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/History/Journal.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/History/Journal.php new file mode 100644 index 000000000..3e6e700d2 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/History/Journal.php @@ -0,0 +1,76 @@ +addEntry(new Entry($request, $response, $duration)); + } + + public function addEntry(Entry $entry) + { + array_push($this->entries, $entry); + $this->entries = array_slice($this->entries, $this->getLimit() * -1); + end($this->entries); + } + + public function getEntries() + { + return $this->entries; + } + + public function getLast() + { + return end($this->entries); + } + + public function getLastRequest() + { + return $this->getLast()->getRequest(); + } + + public function getLastResponse() + { + return $this->getLast()->getResponse(); + } + + public function clear() + { + $this->entries = array(); + } + + public function count() + { + return count($this->entries); + } + + public function setLimit($limit) + { + $this->limit = $limit; + } + + public function getLimit() + { + return $this->limit; + } + + public function getIterator() + { + return new \ArrayIterator(array_reverse($this->entries)); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/HistoryListener.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/HistoryListener.php new file mode 100644 index 000000000..cd1e6276a --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/HistoryListener.php @@ -0,0 +1,33 @@ +journal = $journal; + } + + public function getJournal() + { + return $this->journal; + } + + public function preSend(RequestInterface $request) + { + $this->startTime = microtime(true); + } + + public function postSend(RequestInterface $request, MessageInterface $response) + { + $this->journal->record($request, $response, microtime(true) - $this->startTime); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/ListenerChain.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/ListenerChain.php new file mode 100644 index 000000000..85024a633 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/ListenerChain.php @@ -0,0 +1,40 @@ +listeners = $listeners; + } + + public function addListener(ListenerInterface $listener) + { + $this->listeners[] = $listener; + } + + public function getListeners() + { + return $this->listeners; + } + + public function preSend(RequestInterface $request) + { + foreach ($this->listeners as $listener) { + $listener->preSend($request); + } + } + + public function postSend(RequestInterface $request, MessageInterface $response) + { + foreach ($this->listeners as $listener) { + $listener->postSend($request, $response); + } + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/ListenerInterface.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/ListenerInterface.php new file mode 100644 index 000000000..6b0815c1c --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Listener/ListenerInterface.php @@ -0,0 +1,12 @@ +logger = $logger; + $this->prefix = $prefix; + } + + public function preSend(RequestInterface $request) + { + $this->startTime = microtime(true); + } + + public function postSend(RequestInterface $request, MessageInterface $response) + { + $seconds = microtime(true) - $this->startTime; + + call_user_func($this->logger, sprintf('%sSent "%s %s%s" in %dms', $this->prefix, $request->getMethod(), $request->getHost(), $request->getResource(), round($seconds * 1000))); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/AbstractMessage.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/AbstractMessage.php new file mode 100644 index 000000000..b4f292c99 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/AbstractMessage.php @@ -0,0 +1,154 @@ +getHeaders() as $header) { + if (0 === stripos($header, $needle)) { + $values[] = trim(substr($header, strlen($needle))); + } + } + + if (false === $glue) { + return $values; + } else { + return count($values) ? implode($glue, $values) : null; + } + } + + /** + * Returns a header's attributes. + * + * @param string $name A header name + * + * @return array An associative array of attributes + */ + public function getHeaderAttributes($name) + { + $attributes = array(); + foreach ($this->getHeader($name, false) as $header) { + if (false !== strpos($header, ';')) { + // remove header value + list(, $header) = explode(';', $header, 2); + + // loop through attribute key=value pairs + foreach (array_map('trim', explode(';', trim($header))) as $pair) { + list($key, $value) = explode('=', $pair); + $attributes[$key] = $value; + } + } + } + + return $attributes; + } + + /** + * Returns the value of a particular header attribute. + * + * @param string $header A header name + * @param string $attribute An attribute name + * + * @return string|null The value of the attribute or null if it isn't set + */ + public function getHeaderAttribute($header, $attribute) + { + $attributes = $this->getHeaderAttributes($header); + + if (isset($attributes[$attribute])) { + return $attributes[$attribute]; + } + } + + /** + * Returns the current message as a DOMDocument. + * + * @return \DOMDocument + */ + public function toDomDocument() + { + $revert = libxml_use_internal_errors(true); + + $document = new \DOMDocument('1.0', $this->getHeaderAttribute('Content-Type', 'charset') ?: 'UTF-8'); + if (0 === strpos($this->getHeader('Content-Type'), 'text/xml')) { + $document->loadXML($this->getContent()); + } else { + $document->loadHTML($this->getContent()); + } + + libxml_use_internal_errors($revert); + + return $document; + } + + public function setHeaders(array $headers) + { + $this->headers = $this->flattenHeaders($headers); + } + + public function addHeader($header) + { + $this->headers[] = $header; + } + + public function addHeaders(array $headers) + { + $this->headers = array_merge($this->headers, $this->flattenHeaders($headers)); + } + + public function getHeaders() + { + return $this->headers; + } + + public function setContent($content) + { + $this->content = $content; + } + + public function getContent() + { + return $this->content; + } + + public function __toString() + { + $string = implode("\r\n", $this->getHeaders())."\r\n"; + + if ($content = $this->getContent()) { + $string .= "\r\n$content\r\n"; + } + + return $string; + } + + protected function flattenHeaders(array $headers) + { + $flattened = array(); + foreach ($headers as $key => $header) { + if (is_int($key)) { + $flattened[] = $header; + } else { + $flattened[] = $key.': '.$header; + } + } + + return $flattened; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Factory/Factory.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Factory/Factory.php new file mode 100644 index 000000000..d601dad33 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Factory/Factory.php @@ -0,0 +1,26 @@ +setField('user[name]', 'Kris Wallsmith'); + * $request->setField('user[image]', new FormUpload('/path/to/image.jpg')); + * + * @author Marc Weistroff + * @author Kris Wallsmith + */ +class FormRequest extends Request implements FormRequestInterface +{ + private $fields = array(); + private $boundary; + + /** + * Constructor. + * + * Defaults to POST rather than GET. + */ + public function __construct($method = self::METHOD_POST, $resource = '/', $host = null) + { + parent::__construct($method, $resource, $host); + } + + /** + * Sets the value of a form field. + * + * If the value is an array it will be flattened and one field value will + * be added for each leaf. + */ + public function setField($name, $value) + { + if (is_array($value)) { + $this->addFields(array($name => $value)); + + return; + } + + if ('[]' == substr($name, -2)) { + $this->fields[substr($name, 0, -2)][] = $value; + } else { + $this->fields[$name] = $value; + } + } + + public function addFields(array $fields) + { + foreach ($this->flattenArray($fields) as $name => $value) { + $this->setField($name, $value); + } + } + + public function setFields(array $fields) + { + $this->fields = array(); + $this->addFields($fields); + } + + public function getFields() + { + return $this->fields; + } + + public function getResource() + { + $resource = parent::getResource(); + + if (!$this->isSafe() || !$this->fields) { + return $resource; + } + + // append the query string + $resource .= false === strpos($resource, '?') ? '?' : '&'; + $resource .= http_build_query($this->fields); + + return $resource; + } + + public function setContent($content) + { + throw new \BadMethodCallException('It is not permitted to set the content.'); + } + + public function getHeaders() + { + $headers = parent::getHeaders(); + + if ($this->isSafe()) { + return $headers; + } + + if ($this->isMultipart()) { + $headers[] = 'Content-Type: multipart/form-data; boundary='.$this->getBoundary(); + } else { + $headers[] = 'Content-Type: application/x-www-form-urlencoded'; + } + + return $headers; + } + + public function getContent() + { + if ($this->isSafe()) { + return; + } + + if (!$this->isMultipart()) { + return http_build_query($this->fields); + } + + $content = ''; + + foreach ($this->fields as $name => $values) { + $content .= '--'.$this->getBoundary()."\r\n"; + if ($values instanceof FormUploadInterface) { + if (!$values->getFilename()) { + throw new LogicException(sprintf('Form upload at "%s" does not include a filename.', $name)); + } + + $values->setName($name); + $content .= (string) $values; + } else { + foreach (is_array($values) ? $values : array($values) as $value) { + $content .= "Content-Disposition: form-data; name=\"$name\"\r\n"; + $content .= "\r\n"; + $content .= $value."\r\n"; + } + } + } + + $content .= '--'.$this->getBoundary().'--'; + + return $content; + } + + // private + + private function flattenArray(array $values, $prefix = '', $format = '%s') + { + $flat = array(); + + foreach ($values as $name => $value) { + $flatName = $prefix.sprintf($format, $name); + + if (is_array($value)) { + $flat += $this->flattenArray($value, $flatName, '[%s]'); + } else { + $flat[$flatName] = $value; + } + } + + return $flat; + } + + private function isSafe() + { + return in_array($this->getMethod(), array(self::METHOD_GET, self::METHOD_HEAD)); + } + + private function isMultipart() + { + foreach ($this->fields as $name => $value) { + if (is_object($value) && $value instanceof FormUploadInterface) { + return true; + } + } + + return false; + } + + private function getBoundary() + { + if (!$this->boundary) { + $this->boundary = sha1(rand(11111, 99999).time().uniqid()); + } + + return $this->boundary; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Form/FormRequestInterface.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Form/FormRequestInterface.php new file mode 100644 index 000000000..ed2bd4900 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Form/FormRequestInterface.php @@ -0,0 +1,27 @@ + + */ +interface FormRequestInterface extends RequestInterface +{ + /** + * Returns an array of field names and values. + * + * @return array A array of names and values + */ + public function getFields(); + + /** + * Sets the form fields for the current request. + * + * @param array $fields An array of field names and values + */ + public function setFields(array $fields); +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Form/FormUpload.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Form/FormUpload.php new file mode 100644 index 000000000..22b932b9d --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Form/FormUpload.php @@ -0,0 +1,118 @@ +loadContent($file); + } + + $this->contentType = $contentType; + } + + public function getName() + { + return $this->name; + } + + public function setName($name) + { + $this->name = $name; + } + + public function getFilename() + { + if ($this->filename) { + return $this->filename; + } elseif ($this->file) { + return basename($this->file); + } + } + + public function setFilename($filename) + { + $this->filename = $filename; + } + + public function getContentType() + { + return $this->contentType ?: $this->detectContentType() ?: 'application/octet-stream'; + } + + public function setContentType($contentType) + { + $this->contentType = $contentType; + } + + /** + * Prepends Content-Disposition and Content-Type headers. + */ + public function getHeaders() + { + $headers = array('Content-Disposition: form-data'); + + if ($name = $this->getName()) { + $headers[0] .= sprintf('; name="%s"', $name); + } + + if ($filename = $this->getFilename()) { + $headers[0] .= sprintf('; filename="%s"', $filename); + } + + if ($contentType = $this->getContentType()) { + $headers[] = 'Content-Type: '.$contentType; + } + + return array_merge($headers, parent::getHeaders()); + } + + /** + * Loads the content from a file. + */ + public function loadContent($file) + { + $this->file = $file; + + parent::setContent(null); + } + + public function setContent($content) + { + parent::setContent($content); + + $this->file = null; + } + + public function getFile() + { + return $this->file; + } + + public function getContent() + { + return $this->file ? file_get_contents($this->file) : parent::getContent(); + } + + // private + + private function detectContentType() + { + if (!class_exists('finfo', false)) { + return false; + } + + $finfo = new \finfo(FILEINFO_MIME_TYPE); + + return $this->file ? $finfo->file($this->file) : $finfo->buffer(parent::getContent()); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Form/FormUploadInterface.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Form/FormUploadInterface.php new file mode 100644 index 000000000..4d6066cc4 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Form/FormUploadInterface.php @@ -0,0 +1,13 @@ + + */ +interface MessageInterface +{ + /** + * Returns a header value. + * + * @param string $name A header name + * @param string|boolean $glue Glue for implode, or false to return an array + * + * @return string|array|null The header value(s) + */ + public function getHeader($name, $glue = "\r\n"); + + /** + * Returns an array of header lines. + * + * @return array An array of header lines (integer indexes, e.g. ["Header: value"]) + */ + public function getHeaders(); + + /** + * Sets all headers on the current message. + * + * Headers can be complete ["Header: value"] pairs or an associative array ["Header" => "value"] + * + * @param array $headers An array of header lines + */ + public function setHeaders(array $headers); + + /** + * Adds a header to this message. + * + * @param string $header A header line + */ + public function addHeader($header); + + /** + * Adds a set of headers to this message. + * + * Headers can be complete ["Header: value"] pairs or an associative array ["Header" => "value"] + * + * @param array $headers Headers + */ + public function addHeaders(array $headers); + + /** + * Returns the content of the message. + * + * @return string The message content + */ + public function getContent(); + + /** + * Sets the content of the message. + * + * @param string $content The message content + */ + public function setContent($content); + + /** + * Returns the message document. + * + * @return string The message + */ + public function __toString(); +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Request.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Request.php new file mode 100644 index 000000000..07f6591eb --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Request.php @@ -0,0 +1,174 @@ +method = strtoupper($method); + $this->resource = $resource; + $this->host = $host; + } + + public function setHeaders(array $headers) + { + parent::setHeaders(array()); + + foreach ($this->flattenHeaders($headers) as $header) { + $this->addHeader($header); + } + } + + public function addHeader($header) + { + if (0 === stripos(substr($header, -8), 'HTTP/1.') && 3 == count($parts = explode(' ', $header))) { + list($method, $resource, $protocolVersion) = $parts; + + $this->setMethod($method); + $this->setResource($resource); + $this->setProtocolVersion((float) substr($protocolVersion, 5)); + } else { + parent::addHeader($header); + } + } + + public function setMethod($method) + { + $this->method = strtoupper($method); + } + + public function getMethod() + { + return $this->method; + } + + public function setResource($resource) + { + $this->resource = $resource; + } + + public function getResource() + { + return $this->resource; + } + + public function setHost($host) + { + $this->host = $host; + } + + public function getHost() + { + return $this->host; + } + + public function setProtocolVersion($protocolVersion) + { + $this->protocolVersion = $protocolVersion; + } + + public function getProtocolVersion() + { + return $this->protocolVersion; + } + + /** + * A convenience method for getting the full URL of the current request. + * + * @return string + */ + public function getUrl() + { + return $this->getHost().$this->getResource(); + } + + /** + * A convenience method for populating the current request from a URL. + * + * @param Url|string $url An URL + */ + public function fromUrl($url) + { + if (!$url instanceof Url) { + $url = new Url($url); + } + + $url->applyToRequest($this); + } + + /** + * Returns true if the current request is secure. + * + * @return boolean + */ + public function isSecure() + { + return 'https' == parse_url($this->getHost(), PHP_URL_SCHEME); + } + + /** + * Merges cookie headers on the way out. + */ + public function getHeaders() + { + return $this->mergeCookieHeaders(parent::getHeaders()); + } + + /** + * Returns a string representation of the current request. + * + * @return string + */ + public function __toString() + { + $string = sprintf("%s %s HTTP/%.1f\r\n", $this->getMethod(), $this->getResource(), $this->getProtocolVersion()); + + if ($host = $this->getHost()) { + $string .= 'Host: '.$host."\r\n"; + } + + if ($parent = trim(parent::__toString())) { + $string .= $parent."\r\n"; + } + + return $string; + } + + // private + + private function mergeCookieHeaders(array $headers) + { + $cookieHeader = null; + $needle = 'Cookie:'; + + foreach ($headers as $i => $header) { + if (0 !== stripos($header, $needle)) { + continue; + } + + if (null === $cookieHeader) { + $cookieHeader = $i; + } else { + $headers[$cookieHeader] .= '; '.trim(substr($header, strlen($needle))); + unset($headers[$i]); + } + } + + return array_values($headers); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/RequestInterface.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/RequestInterface.php new file mode 100644 index 000000000..883c8e4d7 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/RequestInterface.php @@ -0,0 +1,75 @@ + + */ +interface RequestInterface extends MessageInterface +{ + const METHOD_OPTIONS = 'OPTIONS'; + const METHOD_GET = 'GET'; + const METHOD_HEAD = 'HEAD'; + const METHOD_POST = 'POST'; + const METHOD_PUT = 'PUT'; + const METHOD_DELETE = 'DELETE'; + const METHOD_PATCH = 'PATCH'; + + /** + * Returns the HTTP method of the current request. + * + * @return string An HTTP method + */ + public function getMethod(); + + /** + * Sets the HTTP method of the current request. + * + * @param string $method The request method + */ + public function setMethod($method); + + /** + * Returns the resource portion of the request line. + * + * @return string The resource requested + */ + public function getResource(); + + /** + * Sets the resource for the current request. + * + * @param string $resource The resource being requested + */ + public function setResource($resource); + + /** + * Returns the protocol version of the current request. + * + * @return float The protocol version + */ + public function getProtocolVersion(); + + /** + * Returns the value of the host header. + * + * @return string|null The host + */ + public function getHost(); + + /** + * Sets the host for the current request. + * + * @param string $host The host + */ + public function setHost($host); + + /** + * Checks if the current request is secure. + * + * @return Boolean True if the request is secure + */ + public function isSecure(); +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Response.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Response.php new file mode 100644 index 000000000..7f4b5f9d0 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Message/Response.php @@ -0,0 +1,193 @@ +protocolVersion) { + $this->parseStatusLine(); + } + + return $this->protocolVersion ?: null; + } + + /** + * Returns the status code of the current response. + * + * @return integer + */ + public function getStatusCode() + { + if (null === $this->statusCode) { + $this->parseStatusLine(); + } + + return $this->statusCode ?: null; + } + + /** + * Returns the reason phrase for the current response. + * + * @return string + */ + public function getReasonPhrase() + { + if (null === $this->reasonPhrase) { + $this->parseStatusLine(); + } + + return $this->reasonPhrase ?: null; + } + + public function setHeaders(array $headers) + { + parent::setHeaders($headers); + + $this->resetStatusLine(); + } + + public function addHeader($header) + { + parent::addHeader($header); + + $this->resetStatusLine(); + } + + public function addHeaders(array $headers) + { + parent::addHeaders($headers); + + $this->resetStatusLine(); + } + + /** + * Is response invalid? + * + * @return Boolean + */ + public function isInvalid() + { + return $this->getStatusCode() < 100 || $this->getStatusCode() >= 600; + } + + /** + * Is response informative? + * + * @return Boolean + */ + public function isInformational() + { + return $this->getStatusCode() >= 100 && $this->getStatusCode() < 200; + } + + /** + * Is response successful? + * + * @return Boolean + */ + public function isSuccessful() + { + return $this->getStatusCode() >= 200 && $this->getStatusCode() < 300; + } + + /** + * Is the response a redirect? + * + * @return Boolean + */ + public function isRedirection() + { + return $this->getStatusCode() >= 300 && $this->getStatusCode() < 400; + } + + /** + * Is there a client error? + * + * @return Boolean + */ + public function isClientError() + { + return $this->getStatusCode() >= 400 && $this->getStatusCode() < 500; + } + + /** + * Was there a server side error? + * + * @return Boolean + */ + public function isServerError() + { + return $this->getStatusCode() >= 500 && $this->getStatusCode() < 600; + } + + /** + * Is the response OK? + * + * @return Boolean + */ + public function isOk() + { + return 200 === $this->getStatusCode(); + } + + /** + * Is the reponse forbidden? + * + * @return Boolean + */ + public function isForbidden() + { + return 403 === $this->getStatusCode(); + } + + /** + * Is the response a not found error? + * + * @return Boolean + */ + public function isNotFound() + { + return 404 === $this->getStatusCode(); + } + + /** + * Is the response empty? + * + * @return Boolean + */ + public function isEmpty() + { + return in_array($this->getStatusCode(), array(201, 204, 304)); + } + + // private + + private function parseStatusLine() + { + $headers = $this->getHeaders(); + + if (isset($headers[0]) && 3 == count($parts = explode(' ', $headers[0], 3))) { + $this->protocolVersion = (float) $parts[0]; + $this->statusCode = (integer) $parts[1]; + $this->reasonPhrase = $parts[2]; + } else { + $this->protocolVersion = $this->statusCode = $this->reasonPhrase = false; + } + } + + private function resetStatusLine() + { + $this->protocolVersion = $this->statusCode = $this->reasonPhrase = null; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Util/Cookie.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Util/Cookie.php new file mode 100644 index 000000000..21d7c12a7 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Util/Cookie.php @@ -0,0 +1,216 @@ +createdAt = time(); + } + + /** + * Returns true if the current cookie matches the supplied request. + * + * @return boolean + */ + public function matchesRequest(RequestInterface $request) + { + // domain + if (!$this->matchesDomain(parse_url($request->getHost(), PHP_URL_HOST))) { + return false; + } + + // path + if (!$this->matchesPath($request->getResource())) { + return false; + } + + // secure + if ($this->hasAttribute(static::ATTR_SECURE) && !$request->isSecure()) { + return false; + } + + return true; + } + + /** + * Returns true of the current cookie has expired. + * + * Checks the max-age and expires attributes. + * + * @return boolean Whether the current cookie has expired + */ + public function isExpired() + { + $maxAge = $this->getAttribute(static::ATTR_MAX_AGE); + if ($maxAge && time() - $this->getCreatedAt() > $maxAge) { + return true; + } + + $expires = $this->getAttribute(static::ATTR_EXPIRES); + if ($expires && strtotime($expires) < time()) { + return true; + } + + return false; + } + + /** + * Returns true if the current cookie matches the supplied domain. + * + * @param string $domain A domain hostname + * + * @return boolean + */ + public function matchesDomain($domain) + { + $cookieDomain = $this->getAttribute(static::ATTR_DOMAIN); + + if (0 === strpos($cookieDomain, '.')) { + $pattern = '/\b'.preg_quote(substr($cookieDomain, 1), '/').'$/i'; + + return (boolean) preg_match($pattern, $domain); + } else { + return 0 == strcasecmp($cookieDomain, $domain); + } + } + + /** + * Returns true if the current cookie matches the supplied path. + * + * @param string $path A path + * + * @return boolean + */ + public function matchesPath($path) + { + $needle = $this->getAttribute(static::ATTR_PATH); + + return null === $needle || 0 === strpos($path, $needle); + } + + /** + * Populates the current cookie with data from the supplied Set-Cookie header. + * + * @param string $header A Set-Cookie header + * @param string $issuingDomain The domain that issued the header + */ + public function fromSetCookieHeader($header, $issuingDomain) + { + list($this->name, $header) = explode('=', $header, 2); + if (false === strpos($header, ';')) { + $this->value = $header; + $header = null; + } else { + list($this->value, $header) = explode(';', $header, 2); + } + + $this->clearAttributes(); + foreach (array_map('trim', explode(';', trim($header))) as $pair) { + if (false === strpos($pair, '=')) { + $name = $pair; + $value = null; + } else { + list($name, $value) = explode('=', $pair); + } + + $this->setAttribute($name, $value); + } + + if (!$this->getAttribute(static::ATTR_DOMAIN)) { + $this->setAttribute(static::ATTR_DOMAIN, $issuingDomain); + } + } + + /** + * Formats a Cookie header for the current cookie. + * + * @return string An HTTP request Cookie header + */ + public function toCookieHeader() + { + return 'Cookie: '.$this->getName().'='.$this->getValue(); + } + + public function setName($name) + { + $this->name = $name; + } + + public function getName() + { + return $this->name; + } + + public function setValue($value) + { + $this->value = $value; + } + + public function getValue() + { + return $this->value; + } + + public function setAttributes(array $attributes) + { + // attributes are case insensitive + $this->attributes = array_change_key_case($attributes); + } + + public function setAttribute($name, $value) + { + $this->attributes[strtolower($name)] = $value; + } + + public function getAttributes() + { + return $this->attributes; + } + + public function getAttribute($name) + { + $name = strtolower($name); + + if (isset($this->attributes[$name])) { + return $this->attributes[$name]; + } + } + + public function hasAttribute($name) + { + return array_key_exists($name, $this->attributes); + } + + public function clearAttributes() + { + $this->setAttributes(array()); + } + + public function setCreatedAt($createdAt) + { + $this->createdAt = $createdAt; + } + + public function getCreatedAt() + { + return $this->createdAt; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Util/CookieJar.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Util/CookieJar.php new file mode 100644 index 000000000..4b6889b19 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Util/CookieJar.php @@ -0,0 +1,79 @@ +cookies = array(); + foreach ($cookies as $cookie) { + $this->addCookie($cookie); + } + } + + public function getCookies() + { + return $this->cookies; + } + + /** + * Adds a cookie to the current cookie jar. + * + * @param Cookie $cookie A cookie object + */ + public function addCookie(Cookie $cookie) + { + $this->cookies[] = $cookie; + } + + /** + * Adds Cookie headers to the supplied request. + * + * @param RequestInterface $request A request object + */ + public function addCookieHeaders(RequestInterface $request) + { + foreach ($this->cookies as $cookie) { + if ($cookie->matchesRequest($request)) { + $request->addHeader($cookie->toCookieHeader()); + } + } + } + + /** + * Processes Set-Cookie headers from a request/response pair. + * + * @param RequestInterface $request A request object + * @param MessageInterface $response A response object + */ + public function processSetCookieHeaders(RequestInterface $request, MessageInterface $response) + { + foreach ($response->getHeader('Set-Cookie', false) as $header) { + $cookie = new Cookie(); + $cookie->fromSetCookieHeader($header, parse_url($request->getHost(), PHP_URL_HOST)); + + $this->addCookie($cookie); + } + } + + /** + * Removes expired cookies. + */ + public function clearExpiredCookies() + { + foreach ($this->cookies as $i => $cookie) { + if ($cookie->isExpired()) { + unset($this->cookies[$i]); + } + } + + // reset array keys + $this->cookies = array_values($this->cookies); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/Buzz/Util/Url.php b/rainloop/v/1.2.5.406/app/libraries/Buzz/Util/Url.php new file mode 100644 index 000000000..e9be3c28b --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/Buzz/Util/Url.php @@ -0,0 +1,190 @@ + 80, + 'https' => 443, + ); + + private $url; + private $components; + + /** + * Constructor. + * + * @param string $url The URL + * + * @throws InvalidArgumentException If the URL is invalid + */ + public function __construct($url) + { + $components = parse_url($url); + + if (false === $components) { + throw new InvalidArgumentException(sprintf('The URL "%s" is invalid.', $url)); + } + + // support scheme-less URLs + if (!isset($components['host']) && isset($components['path'])) { + $pos = strpos($components['path'], '/'); + if (false === $pos) { + $components['host'] = $components['path']; + unset($components['path']); + } elseif (0 !== $pos) { + list($host, $path) = explode('/', $components['path'], 2); + $components['host'] = $host; + $components['path'] = '/'.$path; + } + } + + // default port + if (isset($components['scheme']) && !isset($components['port']) && isset(self::$defaultPorts[$components['scheme']])) { + $components['port'] = self::$defaultPorts[$components['scheme']]; + } + + $this->url = $url; + $this->components = $components; + } + + public function getScheme() + { + return $this->parseUrl('scheme'); + } + + public function getHostname() + { + return $this->parseUrl('host'); + } + + public function getPort() + { + return $this->parseUrl('port'); + } + + public function getUser() + { + return $this->parseUrl('user'); + } + + public function getPassword() + { + return $this->parseUrl('pass'); + } + + public function getPath() + { + return $this->parseUrl('path'); + } + + public function getQueryString() + { + return $this->parseUrl('query'); + } + + public function getFragment() + { + return $this->parseUrl('fragment'); + } + + /** + * Returns a host string that combines scheme, hostname and port. + * + * @return string A host value for an HTTP message + */ + public function getHost() + { + if ($hostname = $this->parseUrl('host')) { + $host = $scheme = $this->parseUrl('scheme', 'http'); + $host .= '://'; + $host .= $hostname; + + $port = $this->parseUrl('port'); + if ($port && (!isset(self::$defaultPorts[$scheme]) || self::$defaultPorts[$scheme] != $port)) { + $host .= ':'.$port; + } + + return $host; + } + } + + /** + * Returns a resource string that combines path and query string. + * + * @return string A resource value for an HTTP message + */ + public function getResource() + { + $resource = $this->parseUrl('path', '/'); + + if ($query = $this->parseUrl('query')) { + $resource .= '?'.$query; + } + + return $resource; + } + + /** + * Returns a formatted URL. + */ + public function format($pattern) + { + static $map = array( + 's' => 'getScheme', + 'u' => 'getUser', + 'a' => 'getPassword', + 'h' => 'getHostname', + 'o' => 'getPort', + 'p' => 'getPath', + 'q' => 'getQueryString', + 'f' => 'getFragment', + 'H' => 'getHost', + 'R' => 'getResource', + ); + + $url = ''; + + $parts = str_split($pattern); + while ($part = current($parts)) { + if (isset($map[$part])) { + $method = $map[$part]; + $url .= $this->$method(); + } elseif ('\\' == $part) { + $url .= next($parts); + } elseif (!ctype_alpha($part)) { + $url .= $part; + } else { + throw new InvalidArgumentException(sprintf('The format character "%s" is invalid.', $part)); + } + + next($parts); + } + + return $url; + } + + /** + * Applies the current URL to the supplied request. + */ + public function applyToRequest(RequestInterface $request) + { + $request->setResource($this->getResource()); + $request->setHost($this->getHost()); + } + + private function parseUrl($component = null, $default = null) + { + if (null === $component) { + return $this->components; + } elseif (isset($this->components[$component])) { + return $this->components[$component]; + } else { + return $default; + } + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/KeenIO/Http/Adaptor/AdaptorInterface.php b/rainloop/v/1.2.5.406/app/libraries/KeenIO/Http/Adaptor/AdaptorInterface.php new file mode 100644 index 000000000..e530fc6ed --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/KeenIO/Http/Adaptor/AdaptorInterface.php @@ -0,0 +1,19 @@ +apiKey = $apiKey; + $this->browser = new Browser(new Curl()); + $this->browser->getClient()->setVerifyPeer(false); + } + + /** + * post to the KeenIO API + * + * @param $url + * @param array $parameters + * @return mixed + */ + public function doPost($url, array $parameters) + { + $headers = array( +// 'Authorization' => $this->apiKey, + 'Content-Type' => 'application/json' + ); + + $content = json_encode($parameters); + + $response = $this->browser->post($url, $headers, $content); + + return $response->getContent(); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/KeenIO/Service/KeenIO.php b/rainloop/v/1.2.5.406/app/libraries/KeenIO/Service/KeenIO.php new file mode 100644 index 000000000..06bccebef --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/KeenIO/Service/KeenIO.php @@ -0,0 +1,215 @@ +doPost($url, $parameters); + $json = json_decode($response); + + return $json->created; + } + + /** + * get a scoped key for an array of filters + * + * @param $filters + * @return string + */ + public static function getScopedKey($filters) + { + self::validateConfiguration(); + + $filterArray = array('filters' => $filters); + $filterJson = self::padString(json_encode($filterArray)); + + $ivLength = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); + $iv = mcrypt_create_iv($ivLength); + + $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, self::getApiKey(), $filterJson, MCRYPT_MODE_CBC, $iv); + + $ivHex = bin2hex($iv); + $encryptedHex = bin2hex($encrypted); + + $scopedKey = $ivHex . $encryptedHex; + + return $scopedKey; + } + + /** + * decrypt a scoped key (primarily used for testing) + * + * @param $scopedKey + * @return mixed + */ + public static function decryptScopedKey($scopedKey) + { + $ivLength = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC) * 2; + $ivHex = substr($scopedKey, 0, $ivLength); + + $encryptedHex = substr($scopedKey, $ivLength); + + $resultPadded = mcrypt_decrypt( + MCRYPT_RIJNDAEL_128, + self::getApiKey(), + pack('H*', $encryptedHex), + MCRYPT_MODE_CBC, + pack('H*', $ivHex) + ); + + $result = self::unpadString($resultPadded); + + $filterArray = json_decode($result, true); + + return $filterArray['filters']; + } + + + /** + * implement PKCS7 padding + * + * @param $string + * @param int $blockSize + * @return string + */ + protected static function padString($string, $blockSize = 32) + { + $paddingSize = $blockSize - (strlen($string) % $blockSize); + $string .= str_repeat(chr($paddingSize), $paddingSize); + + return $string; + } + + /** + * remove padding for a PKCS7-padded string + * + * @param $string + * @return string + */ + protected static function unpadString($string) + { + $len = strlen($string); + $pad = ord($string[$len - 1]); + + return substr($string, 0, $len - $pad); + } + + + protected static function validateConfiguration() + { + // Validate configuration + if (!self::getProjectId()) { + throw new \Exception('Keen IO has not been configured'); + } +// if (!self::getProjectId() or !self::getApiKey()) { +// throw new \Exception('Keen IO has not been configured'); +// } + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Collection.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Collection.php new file mode 100644 index 000000000..2ddac3c4e --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Collection.php @@ -0,0 +1,183 @@ +aItems = array(); + } + + /** + * @param mixed $mItem + * @param bool $bToTop = false + * @return self + */ + public function Add($mItem, $bToTop = false) + { + if ($bToTop) + { + \array_unshift($this->aItems, $mItem); + } + else + { + \array_push($this->aItems, $mItem); + } + + return $this; + } + + /** + * @param array $aItems + * @return self + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function AddArray($aItems) + { + if (!\is_array($aItems)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + foreach ($aItems as $mItem) + { + $this->Add($mItem); + } + + return $this; + } + + /** + * @return self + */ + public function Clear() + { + $this->aItems = array(); + + return $this; + } + + /** + * @return array + */ + public function CloneAsArray() + { + return $this->aItems; + } + + /** + * @return int + */ + public function Count() + { + return \count($this->aItems); + } + + /** + * @return array + */ + public function &GetAsArray() + { + return $this->aItems; + } + + /** + * @param mixed $mCallback + */ + public function MapList($mCallback) + { + $aResult = array(); + if (\is_callable($mCallback)) + { + foreach ($this->aItems as $oItem) + { + $aResult[] = \call_user_func($mCallback, $oItem); + } + } + + return $aResult; + } + + /** + * @param mixed $mCallback + * @return array + */ + public function FilterList($mCallback) + { + $aResult = array(); + if (\is_callable($mCallback)) + { + foreach ($this->aItems as $oItem) + { + if (\call_user_func($mCallback, $oItem)) + { + $aResult[] = $oItem; + } + } + } + + return $aResult; + } + + /** + * @param mixed $mCallback + * @return void + */ + public function ForeachList($mCallback) + { + if (\is_callable($mCallback)) + { + foreach ($this->aItems as $oItem) + { + \call_user_func($mCallback, $oItem); + } + } + } + + /** + * @return mixed | null + * @return mixed + */ + public function &GetByIndex($iIndex) + { + $mResult = null; + if (\key_exists($iIndex, $this->aItems)) + { + $mResult = $this->aItems[$iIndex]; + } + + return $mResult; + } + + /** + * @param array $aItems + * @return self + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function SetAsArray($aItems) + { + if (!\is_array($aItems)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->aItems = $aItems; + + return $this; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Crypt.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Crypt.php new file mode 100644 index 000000000..e78175ab9 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Crypt.php @@ -0,0 +1,180 @@ +> 2 & 3; + for ($iPIndex = 0; $iPIndex < $iN; $iPIndex++) + { + $iY = $aV[$iPIndex + 1]; + $iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) + + (($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ)); + $iZ = $aV[$iPIndex] = self::int32($aV[$iPIndex] + $iMx); + } + $iY = $aV[0]; + $iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) + + (($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ)); + $iZ = $aV[$iN] = self::int32($aV[$iN] + $iMx); + } + + return self::long2str($aV, false); + } + + /** + * @param string $sEncriptedString + * @param string $sKey + * + * @return string + */ + public static function XxteaDecrypt($sEncriptedString, $sKey) + { + if (0 === \strlen($sEncriptedString)) + { + return ''; + } + + $aV = self::str2long($sEncriptedString, false); + $aK = self::str2long($sKey, false); + + if (\count($aK) < 4) + { + for ($iIndex = \count($aK); $iIndex < 4; $iIndex++) + { + $aK[$iIndex] = 0; + } + } + + $iN = \count($aV) - 1; + + $iZ = $aV[$iN]; + $iY = $aV[0]; + $iDelta = 0x9E3779B9; + $iQ = \floor(6 + 52 / ($iN + 1)); + $iSum = self::int32($iQ * $iDelta); + while ($iSum != 0) + { + $iE = $iSum >> 2 & 3; + for ($iPIndex = $iN; $iPIndex > 0; $iPIndex--) + { + $iZ = $aV[$iPIndex - 1]; + $iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) + + (($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ)); + $iY = $aV[$iPIndex] = self::int32($aV[$iPIndex] - $iMx); + } + $iZ = $aV[$iN]; + $iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) + + (($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ)); + $iY = $aV[0] = self::int32($aV[0] - $iMx); + $iSum = self::int32($iSum - $iDelta); + } + + return self::long2str($aV, true); + } + + /** + * @param array $aV + * @param array $aW + * + * @return string + */ + private static function long2str($aV, $aW) + { + $iLen = \count($aV); + $iN = ($iLen - 1) << 2; + if ($aW) + { + $iM = $aV[$iLen - 1]; + if (($iM < $iN - 3) || ($iM > $iN)) + { + return false; + } + $iN = $iM; + } + $aS = array(); + for ($iIndex = 0; $iIndex < $iLen; $iIndex++) + { + $aS[$iIndex] = \pack('V', $aV[$iIndex]); + } + if ($aW) + { + return \substr(\join('', $aS), 0, $iN); + } + else + { + return \join('', $aS); + } + } + + /** + * @param string $sS + * @param string $sW + * + * @return array + */ + private static function str2long($sS, $sW) + { + $aV = \unpack('V*', $sS . \str_repeat("\0", (4 - \strlen($sS) % 4) & 3)); + $aV = \array_values($aV); + if ($sW) + { + $aV[\count($aV)] = \strlen($sS); + } + return $aV; + } + + /** + * @param int $iN + * + * @return int + */ + private static function int32($iN) + { + while ($iN >= 2147483648) + { + $iN -= 4294967296; + } + while ($iN <= -2147483649) + { + $iN += 4294967296; + } + return (int) $iN; + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/DateTimeHelper.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/DateTimeHelper.php new file mode 100644 index 000000000..c21ce78e0 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/DateTimeHelper.php @@ -0,0 +1,74 @@ +getTimestamp() : 0; + } + + /** + * Parse date string formated as "10-Jan-2012 01:58:17 -0800" + * IMAP INTERNALDATE Format + * + * @param string $sDateTime + * + * @return int + */ + public static function ParseInternalDateString($sDateTime) + { + $oDateTime = \DateTime::createFromFormat('d-M-Y H:i:s O', \trim($sDateTime), \MailSo\Base\DateTimeHelper::GetUtcTimeZoneObject()); + return $oDateTime ? $oDateTime->getTimestamp() : 0; + } + + /** + * Parse date string formated as "2011-06-14 23:59:59 +0400" + * + * @param string $sDateTime + * + * @return int + */ + public static function ParseDateStringType1($sDateTime) + { + $oDateTime = \DateTime::createFromFormat('Y-m-d H:i:s O', \trim($sDateTime), \MailSo\Base\DateTimeHelper::GetUtcTimeZoneObject()); + return $oDateTime ? $oDateTime->getTimestamp() : 0; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Enumerations/Charset.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Enumerations/Charset.php new file mode 100644 index 000000000..3ebaa7870 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Enumerations/Charset.php @@ -0,0 +1,27 @@ +getFile()).' ~ '.$this->getLine().')' : $sMessage; + + parent::__construct($sMessage, $iCode, $oPrevious); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Exceptions/InvalidArgumentException.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Exceptions/InvalidArgumentException.php new file mode 100644 index 000000000..4c3695663 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Exceptions/InvalidArgumentException.php @@ -0,0 +1,10 @@ +loadHTML('<'.'?xml version="1.0" encoding="utf-8"?'.'>'. + ''.$sText.''); + + return $oDom; + } + + /** + * @param string $sHtml + * + * @return string + */ + public static function ClearBodyAndHtmlTag($sHtml) + { + $sHtml = \preg_replace('/]*)>/im', '', $sHtml); + $sHtml = \preg_replace('/<\/body>/im', '', $sHtml); + $sHtml = \preg_replace('/]*)>/im', '', $sHtml); + $sHtml = \preg_replace('/<\/html>/im', '', $sHtml); + return $sHtml; + } + + /** + * @param string $sHtml + * + * @return string + */ + public static function ClearTags($sHtml) + { + $aRemoveTags = array( + 'head', 'link', 'base', 'meta', 'title', 'style', 'script', 'bgsound', + 'object', 'embed', 'applet', 'mocha', 'iframe', 'frame', 'frameset' + ); + + $aToRemove = array( + '/]*>/msi', + '/<\?xml [^>]*\?>/msi' + ); + + foreach ($aRemoveTags as $sTag) + { + $aToRemove[] = '\'<'.$sTag.'[^>]*>.*?\'msi'; + $aToRemove[] = '\'<'.$sTag.'[^>]*>\'msi'; + $aToRemove[] = '\']*>\'msi'; + } + + return \preg_replace($aToRemove, '', $sHtml); + } + + /** + * @param string $sHtml + * + * @return string + */ + public static function ClearOn($sHtml) + { + $aToReplace = array( + '/on(Blur)/si', + '/on(Change)/si', + '/on(Click)/si', + '/on(DblClick)/si', + '/on(Error)/si', + '/on(Focus)/si', + '/on(KeyDown)/si', + '/on(KeyPress)/si', + '/on(KeyUp)/si', + '/on(Load)/si', + '/on(MouseDown)/si', + '/on(MouseEnter)/si', + '/on(MouseLeave)/si', + '/on(MouseMove)/si', + '/on(MouseOut)/si', + '/on(MouseOver)/si', + '/on(MouseUp)/si', + '/on(Move)/si', + '/on(Resize)/si', + '/on(ResizeEnd)/si', + '/on(ResizeStart)/si', + '/on(Scroll)/si', + '/on(Select)/si', + '/on(Submit)/si', + '/on(Unload)/si' + ); + + return \preg_replace($aToReplace, 'оn\\1', $sHtml); + } + + /** + * + * @param string $sStyle + * @param \DOMElement $oElement + * @param bool $bHasExternals + * @param array $aFoundCIDs + * + * @return string + */ + public static function ClearStyle($sStyle, $oElement, &$bHasExternals, &$aFoundCIDs) + { + $sStyle = \trim($sStyle); + $aOutStyles = array(); + $aStyles = \explode(';', $sStyle); + + $aMatch = array(); + foreach ($aStyles as $sStyleItem) + { + $aStyleValue = \explode(':', $sStyleItem, 2); + $sName = \trim(\strtolower($aStyleValue[0])); + $sValue = isset($aStyleValue[1]) ? \trim($aStyleValue[1]) : ''; + + if ('position' === $sName && 'fixed' === \strtolower($sValue)) + { + $sValue = 'absolute'; + } + + if (0 === \strlen($sName) || 0 === \strlen($sValue)) + { + continue; + } + + $sStyleItem = $sName.': '.$sValue; + $aStyleValue = array($sName, $sValue); + + /*if (\in_array($sName, array('position', 'left', 'right', 'top', 'bottom', 'behavior', 'cursor'))) + { + // skip + } + else */if (\in_array($sName, array('behavior', 'cursor')) || + ('display' === $sName && 'none' === \strtolower($sValue)) || + \preg_match('/expression/i', $sValue) || + ('text-indent' === $sName && '-' === \substr(trim($sValue), 0, 1)) + ) + { + // skip + } + else if (\in_array($sName, array('background-image', 'background', 'list-style-image', 'content')) + && \preg_match('/url[\s]?\(([^)]+)\)/im', $sValue, $aMatch) && !empty($aMatch[1])) + { + $sFullUrl = \trim($aMatch[0], '"\' '); + $sUrl = \trim($aMatch[1], '"\' '); + $sStyleValue = \trim(\preg_replace('/[\s]+/', ' ', \str_replace($sFullUrl, '', $sValue))); + $sStyleItem = empty($sStyleValue) ? '' : $sName.': '.$sStyleValue; + + if ('cid:' === \strtolower(\substr($sUrl, 0, 4))) + { + if ($oElement) + { + $oElement->setAttribute('data-x-style-cid-name', + 'background' === $sName ? 'background-image' : $sName); + + $oElement->setAttribute('data-x-style-cid', \substr($sUrl, 4)); + + $aFoundCIDs[] = \substr($sUrl, 4); + } + } + else + { + if ($oElement) + { + if (\preg_match('/http[s]?:\/\//i', $sUrl)) + { + $bHasExternals = true; + if (\in_array($sName, array('background-image', 'list-style-image', 'content'))) + { + $sStyleItem = ''; + } + + $sTemp = ''; + if ($oElement->hasAttribute('data-x-style-url')) + { + $sTemp = \trim($oElement->getAttribute('data-x-style-url')); + } + + $sTemp = empty($sTemp) ? '' : (';' === \substr($sTemp, -1) ? $sTemp.' ' : $sTemp.'; '); + + $oElement->setAttribute('data-x-style-url', \trim($sTemp. + ('background' === $sName ? 'background-image' : $sName).': '.$sFullUrl, ' ;')); + } + else if ('data:image/' !== \strtolower(\substr(\trim($sUrl), 0, 11))) + { + $oElement->setAttribute('data-x-broken-style-src', $sFullUrl); + } + } + } + + if (!empty($sStyleItem)) + { + $aOutStyles[] = $sStyleItem; + } + } + else if ('height' === $sName) + { +// $aOutStyles[] = 'min-'.ltrim($sStyleItem); + $aOutStyles[] = $sStyleItem; + } + else + { + $aOutStyles[] = $sStyleItem; + } + } + + return \implode(';', $aOutStyles); + } + + /** + * @param string $sHtml + * @param bool $bHasExternals + * @param array $aFoundCIDs + * + * @return string + */ + public static function ClearHtml($sHtml, &$bHasExternals = false, &$aFoundCIDs = array()) + { + $sHtml = null === $sHtml ? '' : (string) $sHtml; + $sHtml = \trim($sHtml); + if (0 === \strlen($sHtml)) + { + return ''; + } + + $bHasExternals = false; + + $sHtml = \MailSo\Base\HtmlUtils::ClearTags($sHtml); + $sHtml = \MailSo\Base\HtmlUtils::ClearOn($sHtml); + $sHtml = \MailSo\Base\HtmlUtils::ClearBodyAndHtmlTag($sHtml); + + // Dom Part + $oDom = \MailSo\Base\HtmlUtils::GetDomFromText($sHtml); + unset($sHtml); + + if ($oDom) + { + $aNodes = $oDom->getElementsByTagName('*'); + foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement) + { + $sTagNameLower = \strtolower($oElement->tagName); + + if ('iframe' === $sTagNameLower || 'frame' === $sTagNameLower) + { + $oElement->setAttribute('src', 'javascript:false'); + } + + if (\in_array($sTagNameLower, array('a', 'form', 'area'))) + { + $oElement->setAttribute('target', '_blank'); + } + + if (\in_array($sTagNameLower, array('a', 'form', 'area', 'input', 'button', 'textarea'))) + { + $oElement->setAttribute('tabindex', '-1'); + } + +// if ('blockquote' === $sTagNameLower) +// { +// $oElement->removeAttribute('style'); +// } + + @$oElement->removeAttribute('id'); + @$oElement->removeAttribute('class'); + @$oElement->removeAttribute('contenteditable'); + @$oElement->removeAttribute('designmode'); + @$oElement->removeAttribute('data-bind'); + + if ($oElement->hasAttribute('src')) + { + $sSrc = \trim($oElement->getAttribute('src')); + $oElement->removeAttribute('src'); + + if ('cid:' === \strtolower(\substr($sSrc, 0, 4))) + { + $oElement->setAttribute('data-x-src-cid', \substr($sSrc, 4)); + $aFoundCIDs[] = \substr($sSrc, 4); + } + else + { + if (\preg_match('/http[s]?:\/\//i', $sSrc)) + { + $oElement->setAttribute('data-x-src', $sSrc); + $bHasExternals = true; + } + else if ('data:image/' === \strtolower(\substr(\trim($sSrc), 0, 11))) + { + $oElement->setAttribute('src', $sSrc); + } + else + { + $oElement->setAttribute('data-x-broken-src', $sSrc); + } + } + } + + $sBackground = $oElement->hasAttribute('background') + ? \trim($oElement->getAttribute('background')) : ''; + $sBackgroundColor = $oElement->hasAttribute('bgcolor') + ? \trim($oElement->getAttribute('bgcolor')) : ''; + + if (!empty($sBackground) || !empty($sBackgroundColor)) + { + $aStyles = array(); + $sStyles = $oElement->hasAttribute('style') + ? $oElement->getAttribute('style') : ''; + + if (!empty($sBackground)) + { + $aStyles[] = 'background-image: url(\''.$sBackground.'\')'; + $oElement->removeAttribute('background'); + } + + if (!empty($sBackgroundColor)) + { + $aStyles[] = 'background-color: '.$sBackgroundColor; + $oElement->removeAttribute('bgcolor'); + } + + $oElement->setAttribute('style', (empty($sStyles) ? '' : $sStyles.'; ').\implode('; ', $aStyles)); + } + + if ($oElement->hasAttribute('style')) + { + $oElement->setAttribute('style', + \MailSo\Base\HtmlUtils::ClearStyle($oElement->getAttribute('style'), $oElement, $bHasExternals, $aFoundCIDs)); + } + } + + $sResult = $oDom->saveHTML(); + } + + unset($oDom); + + $sResult = \MailSo\Base\HtmlUtils::ClearTags($sResult); + $sResult = \MailSo\Base\HtmlUtils::ClearBodyAndHtmlTag($sResult); + + return \trim($sResult); + } + + /** + * @param string $sHtml + * @param array $aFoundCids = array() + * + * @return string + */ + public static function BuildHtml($sHtml, &$aFoundCids = array()) + { + $oDom = \MailSo\Base\HtmlUtils::GetDomFromText($sHtml); + unset($sHtml); + + $aNodes = $oDom->getElementsByTagName('*'); + foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement) + { + if ($oElement->hasAttribute('data-x-src-cid')) + { + $sCid = $oElement->getAttribute('data-x-src-cid'); + $oElement->removeAttribute('data-x-src-cid'); + + if (!empty($sCid)) + { + $aFoundCids[] = $sCid; + + @$oElement->removeAttribute('src'); + $oElement->setAttribute('src', 'cid:'.$sCid); + } + } + + if ($oElement->hasAttribute('data-x-broken-src')) + { + $oElement->setAttribute('src', $oElement->getAttribute('data-x-broken-src')); + $oElement->removeAttribute('data-x-broken-src'); + } + + if ($oElement->hasAttribute('data-x-src')) + { + $oElement->setAttribute('src', $oElement->getAttribute('data-x-src')); + $oElement->removeAttribute('data-x-src'); + } + + if ($oElement->hasAttribute('data-x-href')) + { + $oElement->setAttribute('href', $oElement->getAttribute('data-x-href')); + $oElement->removeAttribute('data-x-href'); + } + + if ($oElement->hasAttribute('data-x-style-cid-name') && $oElement->hasAttribute('data-x-style-cid')) + { + $sCidName = $oElement->getAttribute('data-x-style-cid-name'); + $sCid = $oElement->getAttribute('data-x-style-cid'); + + $oElement->removeAttribute('data-x-style-cid-name'); + $oElement->removeAttribute('data-x-style-cid'); + if (!empty($sCidName) && !empty($sCid) && \in_array($sCidName, + array('background-image', 'background', 'list-style-image', 'content'))) + { + $sStyles = ''; + if ($oElement->hasAttribute('style')) + { + $sStyles = \trim(\trim($oElement->getAttribute('style')), ';'); + } + + $sBack = $sCidName.': url(cid:'.$sCid.')'; + $sStyles = \preg_replace('/'.\preg_quote($sCidName, '/').':\s?[^;]+/i', $sBack, $sStyles); + if (false === \strpos($sStyles, $sBack)) + { + $sStyles .= empty($sStyles) ? '': '; '; + $sStyles .= $sBack; + } + + $oElement->setAttribute('style', $sStyles); + $aFoundCids[] = $sCid; + } + } + + if ($oElement->hasAttribute('data-x-style-url')) + { + $sAddStyles = $oElement->getAttribute('data-x-style-url'); + $oElement->removeAttribute('data-x-style-url'); + + if (!empty($sAddStyles)) + { + $sStyles = ''; + if ($oElement->hasAttribute('style')) + { + $sStyles = \trim(\trim($oElement->getAttribute('style')), ';'); + } + + $oElement->setAttribute('style', (empty($sStyles) ? '' : $sStyles.'; ').$sAddStyles); + } + } + } + + $sResult = $oDom->saveHTML(); + unset($oDom); + + $sResult = \MailSo\Base\HtmlUtils::ClearTags($sResult); + $sResult = \MailSo\Base\HtmlUtils::ClearBodyAndHtmlTag($sResult); + + return ''. + ''.\trim($sResult).''; + } + + /** + * @param string $sText + * @param bool $bLinksWithTargetBlank = true + * + * @return string + */ + public static function ConvertPlainToHtml($sText, $bLinksWithTargetBlank = true) + { + $sText = \trim($sText); + if (0 === \strlen($sText)) + { + return ''; + } + + $sText = \MailSo\Base\LinkFinder::NewInstance() + ->Text($sText) + ->UseDefaultWrappers($bLinksWithTargetBlank) +// ->CompileText(true, false); + ->CompileText(true, true); + + $sText = \str_replace("\r", '', $sText); + + $aText = \explode("\n", $sText); + unset($sText); + + $bIn = false; + $bDo = true; + do + { + $bDo = false; + $aNextText = array(); + foreach ($aText as $sTextLine) + { + $bStart = 0 === \strpos(\ltrim($sTextLine), '>'); + if ($bStart && !$bIn) + { + $bDo = true; + $bIn = true; + $aNextText[] = '
'; + $aNextText[] = \substr(\ltrim($sTextLine), 4); + } + else if (!$bStart && $bIn) + { + $bIn = false; + $aNextText[] = '
'; + $aNextText[] = $sTextLine; + } + else if ($bStart && $bIn) + { + $aNextText[] = \substr(\ltrim($sTextLine), 4); + } + else + { + $aNextText[] = $sTextLine; + } + } + + if ($bIn) + { + $bIn = false; + $aNextText[] = ''; + } + + $aText = $aNextText; + } + while ($bDo); + + $sText = \join("\n", $aText); + unset($aText); + + $sText = \preg_replace('/[\n][ ]+/', "\n", $sText); +// $sText = \preg_replace('/[\s]+([\s])/', '\\1', $sText); + + $sText = \preg_replace('/
[\s]+/i', '
', $sText); + $sText = \preg_replace('/[\s]+<\/blockquote>/i', '
', $sText); + + $sText = \preg_replace('/<\/blockquote>([\n]{0,2})
/i', '\\1', $sText); + $sText = \preg_replace('/[\n]{3,}/', "\n\n", $sText); + + $sText = \strtr($sText, array( + "\n" => "
", + "\t" => '   ', + ' ' => '  ' + )); + + return $sText; + } + + /** + * @param string $sText + * + * @return string + */ + public static function ConvertHtmlToPlain($sText) + { + $sText = trim(stripslashes($sText)); + $sText = preg_replace('/[\s]+/', ' ', $sText); + $sText = preg_replace(array( + "/\r/", + "/[\n\t]+/", + '/]*>.*?<\/script>/i', + '/]*>.*?<\/style>/i', + '/]*>.*?<\/title>/i', + '/]*>(.+?)<\/h[123]>/i', + '/]*>(.+?)<\/h[456]>/i', + '/]*>/i', + '/]*>/i', + '/]*>(.+?)<\/b>/i', + '/]*>(.+?)<\/i>/i', + '/(]*>|<\/ul>)/i', + '/(]*>|<\/ol>)/i', + '/]*>/i', + '/]*href="([^"]+)"[^>]*>(.+?)<\/a>/i', + '/]*>/i', + '/(]*>|<\/table>)/i', + '/(]*>|<\/tr>)/i', + '/]*>(.+?)<\/td>/i', + '/]*>(.+?)<\/th>/i', + '/ /i', + '/"/i', + '/>/i', + '/</i', + '/&/i', + '/©/i', + '/™/i', + '/“/', + '/”/', + '/–/', + '/’/', + '/&/', + '/©/', + '/™/', + '/—/', + '/“/', + '/”/', + '/•/', + '/®/i', + '/•/i', + '/&[&;]+;/i', + '/'/', + '/ /' + ), array( + '', + ' ', + '', + '', + '', + "\n\n\\1\n\n", + "\n\n\\1\n\n", + "\n\n\t", + "\n", + '\\1', + '\\1', + "\n\n", + "\n\n", + "\n\t* ", + '\\2 (\\1)', + "\n------------------------------------\n", + "\n", + "\n", + "\t\\1\n", + "\t\\1\n", + ' ', + '"', + '>', + '<', + '&', + '(c)', + '(tm)', + '"', + '"', + '-', + "'", + '&', + '(c)', + '(tm)', + '--', + '"', + '"', + '*', + '(R)', + '*', + '', + '\'', + '' + ), $sText); + + $sText = str_ireplace('
',"\n
", $sText); + $sText = strip_tags($sText, ''); + $sText = preg_replace("/\n\\s+\n/", "\n", $sText); + $sText = preg_replace("/[\n]{3,}/", "\n\n", $sText); + + return trim($sText); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Http.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Http.php new file mode 100644 index 000000000..ed4375f2a --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Http.php @@ -0,0 +1,583 @@ +bIsMagicQuotesOn = (bool) @\ini_get('magic_quotes_gpc'); + } + + /** + * @return \MailSo\Base\Http + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @staticvar \MailSo\Base\Http $oInstance; + * + * @return \MailSo\Base\Http + */ + public static function SingletonInstance() + { + static $oInstance = null; + if (null === $oInstance) + { + $oInstance = self::NewInstance(); + } + + return $oInstance; + } + + /** + * @param string $sKey + * + * @return bool + */ + public function HasQuery($sKey) + { + return isset($_GET[$sKey]); + } + + /** + * @param string $sKey + * @param mixed $mDefault = null + * @param bool $bClearPercZeroZero = true + * + * @return mixed + */ + public function GetQuery($sKey, $mDefault = null, $bClearPercZeroZero = true) + { + return isset($_GET[$sKey]) ? \MailSo\Base\Utils::StripSlashesValue($_GET[$sKey], $bClearPercZeroZero) : $mDefault; + } + + /** + * @return array|null + */ + public function GetQueryAsArray() + { + return isset($_GET) && \is_array($_GET) ? \MailSo\Base\Utils::StripSlashesValue($_GET, true) : null; + } + + /** + * @param string $sKey + * + * @return bool + */ + public function HasPost($sKey) + { + return isset($_POST[$sKey]); + } + + /** + * @param string $sKey + * @param mixed $mDefault = null + * @param bool $bClearPercZeroZero = false + * + * @return mixed + */ + public function GetPost($sKey, $mDefault = null, $bClearPercZeroZero = false) + { + return isset($_POST[$sKey]) ? \MailSo\Base\Utils::StripSlashesValue($_POST[$sKey], $bClearPercZeroZero) : $mDefault; + } + + /** + * @return array|null + */ + public function GetPostAsArray() + { + return isset($_POST) && \is_array($_POST) ? \MailSo\Base\Utils::StripSlashesValue($_POST, false) : null; + } + + /** + * @param string $sKey + * + * @return bool + */ + public function HasRequest($sKey) + { + return isset($_REQUEST[$sKey]); + } + + /** + * @param string $sKey + * @param mixed $mDefault = null + * + * @return mixed + */ + public function GetRequest($sKey, $mDefault = null) + { + return isset($_REQUEST[$sKey]) ? \MailSo\Base\Utils::StripSlashesValue($_REQUEST[$sKey]) : $mDefault; + } + + /** + * @param string $sKey + * + * @return bool + */ + public function HasServer($sKey) + { + return isset($_SERVER[$sKey]); + } + + /** + * @param string $sKey + * @param mixed $mDefault = null + * + * @return mixed + */ + public function GetServer($sKey, $mDefault = null) + { + return isset($_SERVER[$sKey]) ? $_SERVER[$sKey] : $mDefault; + } + + /** + * @param string $sKey + * + * @return bool + */ + public function HasEnv($sKey) + { + return isset($_ENV[$sKey]); + } + + /** + * @param string $sKey + * @param mixed $mDefault = null + * + * @return mixed + */ + public function GetEnv($sKey, $mDefault = null) + { + return isset($_ENV[$sKey]) ? $_ENV[$sKey] : $mDefault; + } + + /** + * @return string + */ + public function ServerProtocol() + { + return $this->GetServer('SERVER_PROTOCOL', 'HTTP/1.0'); + } + + /** + * @return string + */ + public function GetMethod() + { + return $this->GetServer('REQUEST_METHOD', ''); + } + + /** + * @return bool + */ + public function IsPost() + { + return ('POST' === $this->GetMethod()); + } + + /** + * @return bool + */ + public function IsGet() + { + return ('GET' === $this->GetMethod()); + } + + /** + * @return string + */ + public function GetQueryString() + { + return $this->GetServer('QUERY_STRING', ''); + } + + /** + * @return bool + */ + public function CheckLocalhost($sServer) + { + return \in_array(\strtolower(\trim($sServer)), array( + 'localhost', '127.0.0.1', '::1', '::1/128', '0:0:0:0:0:0:0:1' + )); + } + + /** + * @return bool + */ + public function IsLocalhost() + { + return $this->CheckLocalhost($this->GetServer('REMOTE_ADDR', '')); + } + + /** + * @return string + */ + public function GetRawBody() + { + static $sRawBody = null; + if (null === $sRawBody) + { + $sBody = @\file_get_contents('php://input'); + $sRawBody = (false !== $sBody) ? $sBody : ''; + } + return $sRawBody; + } + + /** + * @param string $sHeader + * + * @return string + */ + public function GetHeader($sHeader) + { + $sResultHeader = ''; + $sServerKey = 'HTTP_'.\strtoupper(\str_replace('-', '_', $sHeader)); + $sResultHeader = $this->GetServer($sServerKey, ''); + + if (0 === \strlen($sResultHeader) && + \MailSo\Base\Utils::FunctionExistsAndEnabled('apache_request_headers')) + { + $sHeaders = \apache_request_headers(); + if (isset($sHeaders[$sHeader])) + { + $sResultHeader = $sHeaders[$sHeader]; + } + } + + return $sResultHeader; + } + + /** + * @return string + */ + public function GetScheme() + { + return ('on' === \strtolower($this->GetServer('HTTPS'))) ? 'https' : 'http'; + } + + /** + * @return bool + */ + public function IsSecure() + { + return ('https' === $this->GetScheme()); + } + + /** + * @param bool $bWithRemoteUserData = false + * @param bool $bRemoveWWW = true + * + * @return string + */ + public function GetHost($bWithRemoteUserData = false, $bRemoveWWW = true) + { + $sHost = $this->GetServer('HTTP_HOST', ''); + if (0 === \strlen($sHost)) + { + $sScheme = $this->GetScheme(); + $sName = $this->GetServer('SERVER_NAME'); + $iPort = (int) $this->GetServer('SERVER_PORT'); + + $sHost = (('http' === $sScheme && 80 === $iPort) || ('https' === $sScheme && 443 === $iPort)) + ? $sName : $sName.':'.$iPort; + } + + if ($bRemoveWWW) + { + $sHost = 'www.' === \substr(\strtolower($sHost), 0, 4) ? \substr($sHost, 0, 4) : $sHost; + } + + if ($bWithRemoteUserData) + { + $sUser = \trim($this->HasServer('REMOTE_USER') ? $this->GetServer('REMOTE_USER', '') : ''); + $sHost = (0 < \strlen($sUser) ? $sUser.'@' : '').$sHost; + } + + return $sHost; + } + + /** + * @param bool $bCheckProxy = true + * + * @return string + */ + public function GetClientIp($bCheckProxy = true) + { + $sIp = ''; + if ($bCheckProxy && null !== $this->GetServer('HTTP_CLIENT_IP', null)) + { + $sIp = $this->GetServer('HTTP_CLIENT_IP', ''); + } + else if ($bCheckProxy && null !== $this->GetServer('HTTP_X_FORWARDED_FOR', null)) + { + $sIp = $this->GetServer('HTTP_X_FORWARDED_FOR', ''); + } + else + { + $sIp = $this->GetServer('REMOTE_ADDR', ''); + } + + return $sIp; + } + + /** + * @param string $sUrl + * @param array $aPost = array() + * @param string $sCustomUserAgent = 'MaiSo Http User Agent (v1)' + * @param int $iCode = 0 + * @param \MailSo\Log\Logger $oLogger = null + * + * @return string|bool + */ + public function SendPostRequest($sUrl, $aPost = array(), $sCustomUserAgent = 'MaiSo Http User Agent (v1)', &$iCode = 0, $oLogger = null) + { + $aOptions = array( + CURLOPT_URL => $sUrl, + CURLOPT_HEADER => false, + CURLOPT_FAILONERROR => true, + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => $aPost, + CURLOPT_TIMEOUT => 20 + ); + + if (0 < \strlen($sCustomUserAgent)) + { + $aOptions[CURLOPT_USERAGENT] = $sCustomUserAgent; + } + + $oCurl = \curl_init(); + \curl_setopt_array($oCurl, $aOptions); + + if ($oLogger) + { + $oLogger->Write('cURL: Send post request: '.$sUrl); + } + + $mResult = \curl_exec($oCurl); + + $iCode = (int) \curl_getinfo($oCurl, CURLINFO_HTTP_CODE); + $sContentType = (string) \curl_getinfo($oCurl, CURLINFO_CONTENT_TYPE); + + if ($oLogger) + { + $oLogger->Write('cURL: Post request result: (Status: '.$iCode.', ContentType: '.$sContentType.')'); + if (false === $mResult || 200 !== $iCode) + { + $oLogger->Write('cURL: Error: '.\curl_error($oCurl), \MailSo\Log\Enumerations\Type::WARNING); + } + } + + if (\is_resource($oCurl)) + { + \curl_close($oCurl); + } + + return $mResult; + } + + /** + * @param string $sUrl + * @param resource $rFile + * @param string $sCustomUserAgent = 'MaiSo Http User Agent (v1)' + * @param string $sContentType = '' + * @param int $iCode = 0 + * @param \MailSo\Log\Logger $oLogger = null + * + * @return bool + */ + public function SaveUrlToFile($sUrl, $rFile, $sCustomUserAgent = 'MaiSo Http User Agent (v1)', &$sContentType = '', &$iCode = 0, $oLogger = null) + { + if (!is_resource($rFile)) + { + if ($oLogger) + { + $oLogger->Write('cURL: input resource invalid.', \MailSo\Log\Enumerations\Type::WARNING); + } + + return false; + } + + $aOptions = array( + CURLOPT_URL => $sUrl, + CURLOPT_HEADER => false, + CURLOPT_FAILONERROR => true, + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_FILE => $rFile, + CURLOPT_TIMEOUT => 10 + ); + + if (0 < \strlen($sCustomUserAgent)) + { + $aOptions[CURLOPT_USERAGENT] = $sCustomUserAgent; + } + + $oCurl = \curl_init(); + \curl_setopt_array($oCurl, $aOptions); + + if ($oLogger) + { + $oLogger->Write('cURL: Send request: '.$sUrl); + } + + $bResult = \curl_exec($oCurl); + + $iCode = (int) \curl_getinfo($oCurl, CURLINFO_HTTP_CODE); + $sContentType = (string) \curl_getinfo($oCurl, CURLINFO_CONTENT_TYPE); + + if ($oLogger) + { + $oLogger->Write('cURL: Request result: '.($bResult ? 'true' : 'false').' (Status: '.$iCode.', ContentType: '.$sContentType.')'); + if (!$bResult || 200 !== $iCode) + { + $oLogger->Write('cURL: Error: '.\curl_error($oCurl), \MailSo\Log\Enumerations\Type::WARNING); + } + } + + if (\is_resource($oCurl)) + { + \curl_close($oCurl); + } + + return $bResult; + } + + /** + * @param string $sUrl + * @param string $sCustomUserAgent = 'MaiSo Http User Agent (v1)' + * @param string $sContentType = '' + * @param int $iCode = 0 + * @param \MailSo\Log\Logger $oLogger = null + * + * @return string|bool + */ + public function GetUrlAsString($sUrl, $sCustomUserAgent = 'MaiSo Http User Agent (v1)', &$sContentType = '', &$iCode = 0, $oLogger = null) + { + $rMemFile = \MailSo\Base\ResourceRegistry::CreateMemoryResource(); + if ($this->SaveUrlToFile($sUrl, $rMemFile, $sCustomUserAgent, $sContentType, $iCode, $oLogger) && \is_resource($rMemFile)) + { + \rewind($rMemFile); + return \stream_get_contents($rMemFile); + } + + return false; + } + + /** + * @param int $iExpireTime + * @param bool $bSetCacheHeader = true + * @param string $sEtag = '' + * + * @return bool + */ + public function ServerNotModifiedCache($iExpireTime, $bSetCacheHeader = true, $sEtag = '') + { + $bResult = false; + if (0 < $iExpireTime) + { + $iUtcTimeStamp = \time(); + $sIfModifiedSince = $this->GetHeader('If-Modified-Since', ''); + if (0 === \strlen($sIfModifiedSince)) + { + if ($bSetCacheHeader) + { + \header('Cache-Control: public', true); + \header('Pragma: public', true); + \header('Last-Modified: '.\gmdate('D, d M Y H:i:s', $iUtcTimeStamp - $iExpireTime).' UTC', true); + \header('Expires: '.\gmdate('D, j M Y H:i:s', $iUtcTimeStamp + $iExpireTime).' UTC', true); + + if (0 < strlen($sEtag)) + { + \header('Etag: '.$sEtag, true); + } + } + } + else + { + $this->StatusHeader(304); + $bResult = true; + } + } + + return $bResult; + } + + /** + * @param int $iStatus + * + * @return void + */ + public function StatusHeader($iStatus, $sCustomStatusText = '') + { + switch ($iStatus) + { + default: + \header('Status: '.$iStatus, true, $iStatus); + break; + case 304: + \header($this->ServerProtocol().' 304 '.(0 === \strlen($sCustomStatusText) ? 'Not Modified' : $sCustomStatusText), true, $iStatus); + break; + case 200: + \header($this->ServerProtocol().' 200 '.(0 === \strlen($sCustomStatusText) ? 'OK' : $sCustomStatusText), true, $iStatus); + break; + case 401: + \header($this->ServerProtocol().' 401 '.(0 === \strlen($sCustomStatusText) ? 'Please sign in' : $sCustomStatusText), true, $iStatus); + break; + case 404: + \header($this->ServerProtocol().' 404 '.(0 === \strlen($sCustomStatusText) ? 'Not Found' : $sCustomStatusText), true, $iStatus); + break; + } + } + + /** + * @return string + */ + public function GetPath() + { + $sUrl = \ltrim(\substr($this->GetServer('SCRIPT_NAME', ''), 0, \strrpos($this->GetServer('SCRIPT_NAME', ''), '/')), '/'); + return '' === $sUrl ? '/' : '/'.$sUrl.'/'; + } + + /** + * @return string + */ + public function GetUrl() + { + return '/'.$this->GetServer('REQUEST_URI', ''); + } + + /** + * @return string + */ + public function GetFullUrl() + { + return $this->GetScheme().'://'.$this->GetHost(true, false).$this->GetPath(); + } + + /** + * @return string + */ + public function GetFullUrlWithQuery() + { + return $this->GetScheme().'://'.$this->GetHost(true, false).$this->GetUrl(); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/LinkFinder.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/LinkFinder.php new file mode 100644 index 000000000..2b54620b9 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/LinkFinder.php @@ -0,0 +1,323 @@ +iHtmlSpecialCharsFlags = (\defined('ENT_QUOTES') && \defined('ENT_SUBSTITUTE') && \defined('ENT_HTML401')) + ? ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 : ENT_QUOTES; + + if (\defined('ENT_IGNORE')) + { + $this->iHtmlSpecialCharsFlags |= ENT_IGNORE; + } + + $this->Clear(); + } + + /** + * @return \MailSo\Base\LinkFinder + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @return \MailSo\Base\LinkFinder + */ + public function Clear() + { + $this->aPrepearPlainStringUrls = array(); + $this->fLinkWrapper = null; + $this->fMailWrapper = null; + $this->sText = ''; + + return $this; + } + + /** + * @param string $sText + * + * @return \MailSo\Base\LinkFinder + */ + public function Text($sText) + { + $this->sText = $sText; + + return $this; + } + + /** + * @param mixed $fLinkWrapper + * + * @return \MailSo\Base\LinkFinder + */ + public function LinkWrapper($fLinkWrapper) + { + $this->fLinkWrapper = $fLinkWrapper; + + return $this; + } + + /** + * @param mixed $fMailWrapper + * + * @return \MailSo\Base\LinkFinder + */ + public function MailWrapper($fMailWrapper) + { + $this->fMailWrapper = $fMailWrapper; + + return $this; + } + + /** + * @param bool $bAddTargetBlank = false + * + * @return \MailSo\Base\LinkFinder + */ + public function UseDefaultWrappers($bAddTargetBlank = false) + { + $this->fLinkWrapper = function ($sLink, $bShortLink = false) use ($bAddTargetBlank) { + + if ($bShortLink && \in_array(\strtolower($sLink), array('asp.net', 'vb.net', 'mailbee.net'))) + { + return $sLink; + } + + $sNameLink = $sLink; + if (!\preg_match('/^[a-z]{3,5}\:\/\//i', \ltrim($sLink))) + { + $sLink = 'http://'.\ltrim($sLink); + } + + return ''.$sNameLink.''; + }; + + $this->fMailWrapper = function ($sEmail) use ($bAddTargetBlank) { + return ''.$sEmail.''; + }; + + return $this; + } + + /** + * @param bool $bUseHtmlSpecialChars = true + * @param bool $bFindShortLinks = true + * + * @return string + */ + public function CompileText($bUseHtmlSpecialChars = true, $bFindShortLinks = true) + { + $sText = $this->sText; + + $this->aPrepearPlainStringUrls = array(); + if (null !== $this->fLinkWrapper && \is_callable($this->fLinkWrapper)) + { + $sText = $this->findLinks($sText, $this->fLinkWrapper); + } + + if (null !== $this->fMailWrapper && \is_callable($this->fMailWrapper)) + { + $sText = $this->findMails($sText, $this->fMailWrapper); + } + + if ($bFindShortLinks && null !== $this->fLinkWrapper && \is_callable($this->fLinkWrapper)) + { + $sText = $this->findShortLinks($sText, $this->fLinkWrapper); + } + + if ($bUseHtmlSpecialChars) + { + $sText = @\htmlentities($sText, $this->iHtmlSpecialCharsFlags, 'UTF-8'); + } + + if (0 < \count($this->aPrepearPlainStringUrls)) + { + for ($iIndex = 0, $iLen = \count($this->aPrepearPlainStringUrls); $iIndex < $iLen; $iIndex++) + { + $sText = \str_replace(\MailSo\Base\LinkFinder::OPEN_LINK.$iIndex. + \MailSo\Base\LinkFinder::CLOSE_LINK, $this->aPrepearPlainStringUrls[$iIndex], $sText); + } + + $this->aPrepearPlainStringUrls = array(); + } + + return $sText; + } + + /** + * @param string $sText + * @param mixed $fWrapper + * + * @return string + */ + private function findLinks($sText, $fWrapper) + { + $sPattern = '/([\W]|^)((?:https?:\/\/)|(?:svn:\/\/)|(?:git:\/\/)|(?:s?ftps?:\/\/)|(?:www\.))'. + '((\S+?)(\\/)?)((?:>)?|[^\w\=\\/;\(\)\[\]]*?)(?=<|\s|$)/imu'; + + $aPrepearPlainStringUrls = $this->aPrepearPlainStringUrls; + $sText = \preg_replace_callback($sPattern, function ($aMatch) use ($fWrapper, &$aPrepearPlainStringUrls) { + + if (\is_array($aMatch) && 6 < \count($aMatch)) + { + while (\in_array($sChar = \substr($aMatch[3], -1), array(']', ')'))) + { + if (\substr_count($aMatch[3], ']' === $sChar ? '[': '(') - \substr_count($aMatch[3], $sChar) < 0) + { + $aMatch[3] = \substr($aMatch[3], 0, -1); + $aMatch[6] = (']' === $sChar ? ']': ')').$aMatch[6]; + } + else + { + break; + } + } + + $sLinkWithWrap = \call_user_func($fWrapper, $aMatch[2].$aMatch[3]); + if (\is_string($sLinkWithWrap) && 0 < \strlen($sLinkWithWrap)) + { + $aPrepearPlainStringUrls[] = \stripslashes($sLinkWithWrap); + return $aMatch[1]. + \MailSo\Base\LinkFinder::OPEN_LINK. + (\count($aPrepearPlainStringUrls) - 1). + \MailSo\Base\LinkFinder::CLOSE_LINK. + $aMatch[6]; + } + + return $aMatch[0]; + } + + return ''; + + }, $sText); + + if (0 < \count($aPrepearPlainStringUrls)) + { + $this->aPrepearPlainStringUrls = $aPrepearPlainStringUrls; + } + + return $sText; + } + + /** + * @param string $sText + * @param mixed $fWrapper + * + * @return string + */ + private function findShortLinks($sText, $fWrapper) + { + $sPattern = '/([a-z0-9-\.]+\.(?:com|org|net|ru))([^a-z0-9-\.])/i'; + + $aPrepearPlainStringUrls = $this->aPrepearPlainStringUrls; + $sText = \preg_replace_callback($sPattern, function ($aMatch) use ($fWrapper, &$aPrepearPlainStringUrls) { + + if (\is_array($aMatch) && 2 < \count($aMatch) && isset($aMatch[1]) && 0 < \strlen($aMatch[1])) + { + $sLinkWithWrap = \call_user_func_array($fWrapper, array($aMatch[1], true)); + if (\is_string($sLinkWithWrap)) + { + $aPrepearPlainStringUrls[] = \stripslashes($sLinkWithWrap); + return \MailSo\Base\LinkFinder::OPEN_LINK. + (\count($aPrepearPlainStringUrls) - 1). + \MailSo\Base\LinkFinder::CLOSE_LINK. + $aMatch[2]; + } + + return $aMatch[0]; + } + + return ''; + + }, $sText); + + if (0 < \count($aPrepearPlainStringUrls)) + { + $this->aPrepearPlainStringUrls = $aPrepearPlainStringUrls; + } + + return $sText; + } + + /** + * @param string $sText + * @param mixed $fWrapper + * + * @return string + */ + private function findMails($sText, $fWrapper) + { + $sPattern = '/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/'; + + $aPrepearPlainStringUrls = $this->aPrepearPlainStringUrls; + $sText = \preg_replace_callback($sPattern, function ($aMatch) use ($fWrapper, &$aPrepearPlainStringUrls) { + + if (\is_array($aMatch) && isset($aMatch[1])) + { + $sMailWithWrap = \call_user_func($fWrapper, $aMatch[1]); + if (\is_string($sMailWithWrap) && 0 < \strlen($sMailWithWrap)) + { + $aPrepearPlainStringUrls[] = \stripslashes($sMailWithWrap); + return \MailSo\Base\LinkFinder::OPEN_LINK. + (\count($aPrepearPlainStringUrls) - 1). + \MailSo\Base\LinkFinder::CLOSE_LINK; + } + + return $aMatch[1]; + } + + return ''; + + }, $sText); + + if (0 < \count($aPrepearPlainStringUrls)) + { + $this->aPrepearPlainStringUrls = $aPrepearPlainStringUrls; + } + + return $sText; + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Loader.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Loader.php new file mode 100644 index 000000000..4b1408539 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Loader.php @@ -0,0 +1,112 @@ + array( + 'phpversion' => \phpversion(), + 'ssl' => (int) \function_exists('openssl_open'), + 'iconv' => (int) \function_exists('iconv') + )); + + if (\MailSo\Base\Utils::FunctionExistsAndEnabled('memory_get_usage') && + \MailSo\Base\Utils::FunctionExistsAndEnabled('memory_get_peak_usage')) + { + $aResult['php']['memory_get_usage'] = + Utils::FormatFileSize(\memory_get_usage(true), 2); + $aResult['php']['memory_get_peak_usage'] = + Utils::FormatFileSize(\memory_get_peak_usage(true), 2); + } + + self::SetStatistic('TimeDelta', \microtime(true) - self::GetStatistic('Inited')); + + $aResult['statistic'] = self::$aSetStatistic; + $aResult['counts'] = self::$aIncStatistic; + } + + return $aResult; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/ResourceRegistry.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/ResourceRegistry.php new file mode 100644 index 000000000..751d0c564 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/ResourceRegistry.php @@ -0,0 +1,116 @@ + \MailSo\Mime\Enumerations\Constants::LINE_LENGTH, + 'line-break-chars' => \MailSo\Mime\Enumerations\Constants::CRLF + )); + + return \is_resource($rFilter) ? $rStream : false; + } + + self::$aStreams[$sHashName] = + array($rStream, $sUtilsDecodeOrEncodeFunctionName, $sFromEncoding, $sToEncoding); + + \MailSo\Base\Loader::IncStatistic('CreateStream/Binary'); + + return \fopen(self::STREAM_NAME.'://'.$sHashName, 'rb'); + } + + /** + * @param string $sPath + * + * @return bool + */ + public function stream_open($sPath) + { + $this->iPos = 0; + $this->sBuffer = ''; + $this->sReadEndBuffer = ''; + $this->rStream = false; + $this->sFromEncoding = null; + $this->sToEncoding = null; + $this->sFunctionName = null; + + $bResult = false; + $aPath = parse_url($sPath); + + if (isset($aPath['host']) && isset($aPath['scheme']) && + 0 < strlen($aPath['host']) && 0 < strlen($aPath['scheme']) && + self::STREAM_NAME === $aPath['scheme']) + { + $sHashName = $aPath['host']; + if (isset(self::$aStreams[$sHashName]) && + is_array(self::$aStreams[$sHashName]) && + 4 === count(self::$aStreams[$sHashName])) + { + $this->rStream = self::$aStreams[$sHashName][0]; + $this->sFunctionName = self::$aStreams[$sHashName][1]; + $this->sFromEncoding = self::$aStreams[$sHashName][2]; + $this->sToEncoding = self::$aStreams[$sHashName][3]; + } + + $bResult = is_resource($this->rStream); + } + + return $bResult; + } + + /** + * @param int $iCount + * + * @return string + */ + public function stream_read($iCount) + { + $sReturn = ''; + $sFunctionName = $this->sFunctionName; + + if ($iCount > 0) + { + if ($iCount < strlen($this->sBuffer)) + { + $sReturn = substr($this->sBuffer, 0, $iCount); + $this->sBuffer = substr($this->sBuffer, $iCount); + } + else + { + $sReturn = $this->sBuffer; + while ($iCount > 0) + { + if (feof($this->rStream)) + { + if (0 === strlen($this->sBuffer.$sReturn)) + { + return false; + } + + if (0 < strlen($this->sReadEndBuffer)) + { + $sReturn .= self::$sFunctionName($this->sReadEndBuffer, + $this->sReadEndBuffer, $this->sFromEncoding, $this->sToEncoding); + + $iDecodeLen = strlen($sReturn); + } + + $iCount = 0; + $this->sBuffer = ''; + } + else + { + $sReadResult = fread($this->rStream, 8192); + if (false === $sReadResult) + { + return false; + } + + $sReturn .= self::$sFunctionName($this->sReadEndBuffer.$sReadResult, + $this->sReadEndBuffer, $this->sFromEncoding, $this->sToEncoding); + + $iDecodeLen = strlen($sReturn); + if ($iCount < $iDecodeLen) + { + $this->sBuffer = substr($sReturn, $iCount); + $sReturn = substr($sReturn, 0, $iCount); + $iCount = 0; + } + else + { + $iCount -= $iDecodeLen; + } + } + } + } + + $this->iPos += strlen($sReturn); + return $sReturn; + } + + return false; + } + + /** + * @return int + */ + public function stream_write() + { + return 0; + } + + /** + * @return int + */ + public function stream_tell() + { + return $this->iPos; + } + + /** + * @return bool + */ + public function stream_eof() + { + return 0 === strlen($this->sBuffer) && feof($this->rStream); + } + + /** + * + * @return array + */ + public function stream_stat() + { + return array( + 'dev' => 2, + 'ino' => 0, + 'mode' => 33206, + 'nlink' => 1, + 'uid' => 0, + 'gid' => 0, + 'rdev' => 2, + 'size' => 0, + 'atime' => 1061067181, + 'mtime' => 1056136526, + 'ctime' => 1056136526, + 'blksize' => -1, + 'blocks' => -1 + ); + } + + /** + * @return bool + */ + public function stream_seek() + { + return false; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/StreamWrappers/Literal.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/StreamWrappers/Literal.php new file mode 100644 index 000000000..f2167d5a6 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/StreamWrappers/Literal.php @@ -0,0 +1,185 @@ +iPos = 0; + $this->iSize = 0; + $this->rStream = false; + + $bResult = false; + $aPath = parse_url($sPath); + + if (isset($aPath['host']) && isset($aPath['scheme']) && + 0 < strlen($aPath['host']) && 0 < strlen($aPath['scheme']) && + self::STREAM_NAME === $aPath['scheme']) + { + $sHashName = $aPath['host']; + if (isset(self::$aStreams[$sHashName]) && + is_array(self::$aStreams[$sHashName]) && + 2 === count(self::$aStreams[$sHashName])) + { + $this->rStream = self::$aStreams[$sHashName][0]; + $this->iSize = self::$aStreams[$sHashName][1]; + } + + $bResult = is_resource($this->rStream); + } + + return $bResult; + } + + /** + * @param int $iCount + * + * @return string + */ + public function stream_read($iCount) + { + $sResult = false; + if ($this->iSize < $this->iPos + $iCount) + { + $iCount = $this->iSize - $this->iPos; + } + + if ($iCount > 0) + { + $sReadResult = ''; + $iRead = $iCount; + while (0 < $iRead) + { + $sAddRead = @fread($this->rStream, $iRead); + if (false === $sAddRead) + { + $sReadResult = false; + break; + } + + $sReadResult .= $sAddRead; + $iRead -= strlen($sAddRead); + $this->iPos += strlen($sAddRead); + } + + if (false !== $sReadResult) + { + $sResult = $sReadResult; + } + } + + return $sResult; + } + + /** + * @return int + */ + public function stream_write() + { + return 0; + } + + /** + * @return int + */ + public function stream_tell() + { + return $this->iPos; + } + + /** + * @return bool + */ + public function stream_eof() + { + return $this->iPos >= $this->iSize; + } + + /** + * @return array + */ + public function stream_stat() + { + return array( + 'dev' => 2, + 'ino' => 0, + 'mode' => 33206, + 'nlink' => 1, + 'uid' => 0, + 'gid' => 0, + 'rdev' => 2, + 'size' => $this->iSize, + 'atime' => 1061067181, + 'mtime' => 1056136526, + 'ctime' => 1056136526, + 'blksize' => -1, + 'blocks' => -1 + ); + } + + /** + * @return bool + */ + public function stream_seek() + { + return false; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/StreamWrappers/SubStreams.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/StreamWrappers/SubStreams.php new file mode 100644 index 000000000..a8dcae1e5 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/StreamWrappers/SubStreams.php @@ -0,0 +1,257 @@ +aSubStreams[$this->iIndex])); + { + return $this->aSubStreams[$this->iIndex]; + } + return $nNull; + } + + /** + * @param string $sPath + * + * @return bool + */ + public function stream_open($sPath) + { + $this->aSubStreams = array(); + + $bResult = false; + $aPath = parse_url($sPath); + + if (isset($aPath['host']) && isset($aPath['scheme']) && + 0 < strlen($aPath['host']) && 0 < strlen($aPath['scheme']) && + self::STREAM_NAME === $aPath['scheme']) + { + $sHashName = $aPath['host']; + if (isset(self::$aStreams[$sHashName]) && + is_array(self::$aStreams[$sHashName]) && + 0 < count(self::$aStreams[$sHashName])) + { + $this->iIndex = 0; + $this->iPos = 0; + $this->bIsEnd = false; + $this->sBuffer = ''; + $this->aSubStreams = self::$aStreams[$sHashName]; + } + + $bResult = 0 < count($this->aSubStreams); + } + + return $bResult; + } + + /** + * @param int $iCount + * + * @return string + */ + public function stream_read($iCount) + { + $sReturn = ''; + $mCurrentPart = null; + if ($iCount > 0) + { + if ($iCount < strlen($this->sBuffer)) + { + $sReturn = substr($this->sBuffer, 0, $iCount); + $this->sBuffer = substr($this->sBuffer, $iCount); + } + else + { + $sReturn = $this->sBuffer; + while ($iCount > 0) + { + $mCurrentPart =& $this->getPart(); + if (null === $mCurrentPart) + { + $this->bIsEnd = true; + $this->sBuffer = ''; + $iCount = 0; + break; + } + + if (is_resource($mCurrentPart)) + { + if (!feof($mCurrentPart)) + { + $sReadResult = fread($mCurrentPart, 8192); + if (false === $sReadResult) + { + return false; + } + + $sReturn .= $sReadResult; + + $iLen = strlen($sReturn); + if ($iCount < $iLen) + { + $this->sBuffer = substr($sReturn, $iCount); + $sReturn = substr($sReturn, 0, $iCount); + $iCount = 0; + } + else + { + $iCount -= $iLen; + } + } + else + { + $this->iIndex++; + } + } + else if (is_string($mCurrentPart)) + { + $sReadResult = substr($mCurrentPart, 0, $iCount); + + $sReturn .= $sReadResult; + + $iLen = strlen($sReadResult); + if ($iCount < $iLen) + { + $this->sBuffer = substr($sReturn, $iCount); + $sReturn = substr($sReturn, 0, $iCount); + $iCount = 0; + } + else + { + $iCount -= $iLen; + } + + $this->iIndex++; + } + } + } + + $this->iPos += strlen($sReturn); + return $sReturn; + } + + return false; + } + + /** + * @return int + */ + public function stream_write() + { + return 0; + } + + /** + * @return int + */ + public function stream_tell() + { + return $this->iPos; + } + + /** + * @return bool + */ + public function stream_eof() + { + return $this->bIsEnd; + } + + /** + * @return array + */ + public function stream_stat() + { + return array( + 'dev' => 2, + 'ino' => 0, + 'mode' => 33206, + 'nlink' => 1, + 'uid' => 0, + 'gid' => 0, + 'rdev' => 2, + 'size' => 0, + 'atime' => 1061067181, + 'mtime' => 1056136526, + 'ctime' => 1056136526, + 'blksize' => -1, + 'blocks' => -1 + ); + } + + /** + * @return bool + */ + public function stream_seek() + { + return false; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/StreamWrappers/Test.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/StreamWrappers/Test.php new file mode 100644 index 000000000..080766529 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/StreamWrappers/Test.php @@ -0,0 +1,129 @@ +rReadSream = self::$aStreams[$sHashName]; + $bResult = true; + } + } + + return $bResult; + } + + /** + * @param int $iCount + * + * @return string + */ + public function stream_read($iCount) + { + return fread($this->rReadSream, $iCount); + } + + /** + * @param string $sInputString + * + * @return int + */ + public function stream_write($sInputString) + { + return strlen($sInputString); + } + + /** + * @return int + */ + public function stream_tell() + { + return ftell($this->rReadSream); + } + + /** + * @return bool + */ + public function stream_eof() + { + return feof($this->rReadSream); + } + + /** + * @return array + */ + public function stream_stat() + { + return fstat($this->rReadSream); + } + + /** + * @return bool + */ + public function stream_seek() + { + return false; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Utils.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Utils.php new file mode 100644 index 000000000..38c563643 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Utils.php @@ -0,0 +1,1626 @@ + 1024 && isset($aSizes[$iIndex + 1]); $iIndex++) + { + $iSize /= 1024; + } + return \round($iSize, $iRound).$aSizes[$iIndex]; + } + + /** + * @param string $sEncodedValue + * @param string $sEncodeingType + * + * @return string + */ + public static function DecodeEncodingValue($sEncodedValue, $sEncodeingType) + { + $sResult = $sEncodedValue; + switch (\strtolower($sEncodeingType)) + { + case 'q': + case 'quoted_printable': + case 'quoted-printable': + $sResult = \quoted_printable_decode($sResult); + break; + case 'b': + case 'base64': + $sResult = \MailSo\Base\Utils::Base64Decode($sResult); + break; + } + return $sResult; + } + + /** + * @param string $sEncodedValue + * @param string $sIncomingCharset = '' + * @param string $sForcedIncomingCharset = '' + * + * @return string + */ + public static function DecodeHeaderValue($sEncodedValue, $sIncomingCharset = '', $sForcedIncomingCharset = '') + { + $sValue = $sEncodedValue; + if (0 < \strlen($sIncomingCharset)) + { + $sValue = \MailSo\Base\Utils::ConvertEncoding($sValue, $sIncomingCharset, + \MailSo\Base\Enumerations\Charset::UTF_8); + } + + $sValue = \preg_replace('/\?=[\n\r\t\s]{1,5}=\?/m', '?==?', $sValue); + $sValue = \preg_replace('/[\r\n\t]+/m', ' ', $sValue); + + $aEncodeArray = array(''); + $aMatch = array(); + \preg_match_all('/=\?[^\?]+\?[q|b|Q|B]\?[^\?]*(\?=)/', $sValue, $aMatch); + + if (isset($aMatch[0]) && \is_array($aMatch[0])) + { + for ($iIndex = 0, $iLen = \count($aMatch[0]); $iIndex < $iLen; $iIndex++) + { + if (isset($aMatch[0][$iIndex])) + { + $iPos = @\strpos($aMatch[0][$iIndex], '*'); + if (false !== $iPos) + { + $aMatch[0][$iIndex][0] = \substr($aMatch[0][$iIndex][0], 0, $iPos); + } + } + } + + $aEncodeArray = $aMatch[0]; + } + + $aParts = array(); + + $sMainCharset = ''; + $bOneCharset = true; + + for ($iIndex = 0, $iLen = \count($aEncodeArray); $iIndex < $iLen; $iIndex++) + { + $aTempArr = array('', $aEncodeArray[$iIndex]); + if ('=?' === \substr(\trim($aTempArr[1]), 0, 2)) + { + $iPos = \strpos($aTempArr[1], '?', 2); + $aTempArr[0] = \substr($aTempArr[1], 2, $iPos - 2); + $sEncType = \strtoupper($aTempArr[1]{$iPos + 1}); + switch ($sEncType) + { + case 'Q': + $sHeaderValuePart = \str_replace('_', ' ', $aTempArr[1]); + $aTempArr[1] = \quoted_printable_decode(\substr( + $sHeaderValuePart, $iPos + 3, \strlen($sHeaderValuePart) - $iPos - 5)); + break; + case 'B': + $sHeaderValuePart = $aTempArr[1]; + $aTempArr[1] = \MailSo\Base\Utils::Base64Decode(\substr( + $sHeaderValuePart, $iPos + 3, \strlen($sHeaderValuePart) - $iPos - 5)); + break; + } + } + + if (0 < \strlen($aTempArr[0])) + { + $sCharset = 0 === \strlen($sForcedIncomingCharset) ? $aTempArr[0] : $sForcedIncomingCharset; + + if ('' === $sMainCharset) + { + $sMainCharset = $sCharset; + } + else if ($sMainCharset !== $sCharset) + { + $bOneCharset = false; + } + } + + $aParts[] = array( + $aEncodeArray[$iIndex], + $aTempArr[1], + $sCharset + ); + + unset($aTempArr); + } + + for ($iIndex = 0, $iLen = \count($aParts); $iIndex < $iLen; $iIndex++) + { + if ($bOneCharset) + { + $sValue = \str_replace($aParts[$iIndex][0], $aParts[$iIndex][1], $sValue); + } + else + { + $sValue = \str_replace($aParts[$iIndex][0], + \MailSo\Base\Utils::ConvertEncoding($aParts[$iIndex][1], $aParts[$iIndex][2], \MailSo\Base\Enumerations\Charset::UTF_8), + $sValue); + } + } + + if ($bOneCharset && 0 < \strlen($sMainCharset)) + { + $sValue = \MailSo\Base\Utils::ConvertEncoding($sValue, $sMainCharset, \MailSo\Base\Enumerations\Charset::UTF_8); + } + + return $sValue; + } + + /** + * @param string $sEncodeType + * @param string $sValue + * + * @return string + */ + public static function EncodeUnencodedValue($sEncodeType, $sValue) + { + $sValue = \trim($sValue); + if (0 < \strlen($sValue) && !\MailSo\Base\Utils::IsAscii($sValue)) + { + switch (\strtoupper($sEncodeType)) + { + case 'B': + $sValue = '=?'.\strtolower(\MailSo\Base\Enumerations\Charset::UTF_8). + '?B?'.\base64_encode($sValue).'?='; + break; + + case 'Q': + $sValue = '=?'.\strtolower(\MailSo\Base\Enumerations\Charset::UTF_8). + '?Q?'.\str_replace(array('?', ' ', '_'), array('=3F', '_', '=5F'), + \quoted_printable_encode($sValue)).'?='; + break; + } + } + + return $sValue; + } + + /** + * @unused + * + * @param string $sEncodeType + * @param string $sEncodeCharset + * @param string $sValue + * @param string $sHeaderName = '' + * + * @return string + */ + public static function EncodeHeaderValue($sEncodeType, $sEncodeCharset, $sValue, $sHeaderName = '') + { + $sValue = \trim($sValue); + +// return \mb_encode_mimeheader($sValue, +// \MailSo\Base\Enumerations\Charset::UTF_8, 'Q', +// \MailSo\Mime\Enumerations\Constants::CRLF); + +// $splitWords = true; +// if ($splitWords) { +// $words = \array_map(function($word) use ($sEncodeCharset) { +// $header = \iconv_mime_encode('Header', $word, array( +// 'scheme' => 'Q', +// 'line-length' => 78, +// 'output-charset' => $sEncodeCharset, +// )); +// return \str_replace('Header: ', '', $header); +// }, \explode(' ', $sValue)); +// return \implode("\r\n ", $words); +// } +// +// $header = \iconv_mime_encode('Header', $sValue, array( +// 'scheme' => 'Q', +// 'line-length' => 998, +// 'output-charset' => $sEncodeCharset, +// )); +// return \str_replace('Header: ', '', $header); +// +// $aPreferences = array( +// 'input-charset' => \MailSo\Base\Enumerations\Charset::UTF_8, +// 'output-charset' => $sEncodeCharset, +// 'line-length' => \MailSo\Mime\Enumerations\Constants::LINE_LENGTH, +// 'line-break-chars' => \MailSo\Mime\Enumerations\Constants::CRLF +// ); +// +// if (\in_array(\strtoupper($sEncodeType), array('B', 'Q'))) +// { +// $aPreferences['scheme'] = \strtoupper($sEncodeType); +// } +// +// $sHeaderName = 0 === \strlen($sHeaderName) ? 'X-Header' : $sHeaderName; +// $sValue = \iconv_mime_encode($sHeaderName, $sValue, $aPreferences); +// return \trim(substr($sValue, \strlen($sHeaderName) + 1)); + + if (0 < \strlen($sValue) && !\MailSo\Base\Utils::IsAscii($sValue)) + { + switch (\strtoupper($sEncodeType)) + { + case 'B': + $sValue = '=?'.\strtolower($sEncodeCharset).'?B?'.\base64_encode($sValue).'?='; + break; + + case 'Q': + $sValue = '=?'.\strtolower($sEncodeCharset).'?Q?'.\str_replace( + array('?', ' ', '_'), array('=3F', '_', '=5F'), + \quoted_printable_encode($sValue)).'?='; + break; + } + } + + return \trim($sValue); + } + + /** + * @param string $sEmail + * + * @return string + */ + public static function GetAccountNameFromEmail($sEmail) + { + $sResult = ''; + if (0 < \strlen($sEmail)) + { + $iPos = \strpos($sEmail, '@'); + $sResult = (false === $iPos) ? $sEmail : \substr($sEmail, 0, $iPos); + } + + return $sResult; + } + + /** + * @param string $sEmail + * + * @return string + */ + public static function GetDomainFromEmail($sEmail) + { + $sResult = ''; + if (0 < \strlen($sEmail)) + { + $iPos = \strpos($sEmail, '@'); + if (false !== $iPos && 0 < $iPos) + { + $sResult = \substr($sEmail, $iPos + 1); + } + } + + return $sResult; + } + + /** + * @param string $sFileName + * + * @return string + */ + public static function GetFileExtension($sFileName) + { + $iLast = \strrpos($sFileName, '.'); + return false === $iLast ? '' : \substr($sFileName, $iLast + 1); + } + + /** + * @param string $sFileName + * + * @return string + */ + public static function MimeContentType($sFileName) + { + $sResult = 'application/octet-stream'; + + $aMimeTypes = array( + + 'eml' => 'message/rfc822', + 'mime' => 'message/rfc822', + 'txt' => 'text/plain', + 'text' => 'text/plain', + 'def' => 'text/plain', + 'list' => 'text/plain', + 'in' => 'text/plain', + 'ini' => 'text/plain', + 'log' => 'text/plain', + 'sql' => 'text/plain', + 'cfg' => 'text/plain', + 'conf' => 'text/plain', + 'rtx' => 'text/richtext', + 'vcard' => 'text/vcard', + 'vcf' => 'text/vcard', + 'htm' => 'text/html', + 'html' => 'text/html', + 'csv' => 'text/csv', + 'ics' => 'text/calendar', + 'ifb' => 'text/calendar', + 'xml' => 'text/xml', + 'json' => 'application/json', + 'swf' => 'application/x-shockwave-flash', + 'hlp' => 'application/winhlp', + 'wgt' => 'application/widget', + 'chm' => 'application/vnd.ms-htmlhelp', + 'p10' => 'application/pkcs10', + 'p7c' => 'application/pkcs7-mime', + 'p7m' => 'application/pkcs7-mime', + 'p7s' => 'application/pkcs7-signature', + 'ttf' => 'application/x-ttf', + 'torrent' => 'application/x-bittorrent', + + // scripts + 'js' => 'application/javascript', + 'pl' => 'text/perl', + 'css' => 'text/css', + 'asp' => 'text/asp', + 'php' => 'application/x-httpd-php', + 'php3' => 'application/x-httpd-php', + 'php4' => 'application/x-httpd-php', + 'php5' => 'application/x-httpd-php', + 'phtml' => 'application/x-httpd-php', + + // images + 'png' => 'image/png', + 'jpg' => 'image/jpeg', + 'jpeg' => 'image/jpeg', + 'jpe' => 'image/jpeg', + 'jfif' => 'image/jpeg', + 'gif' => 'image/gif', + 'bmp' => 'image/bmp', + 'cgm' => 'image/cgm', + 'ief' => 'image/ief', + 'ico' => 'image/x-icon', + 'tif' => 'image/tiff', + 'tiff' => 'image/tiff', + 'svg' => 'image/svg+xml', + 'svgz' => 'image/svg+xml', + 'djv' => 'image/vnd.djvu', + 'djvu' => 'image/vnd.djvu', + 'webp' => 'image/webp', + + // archives + 'zip' => 'application/zip', + '7z' => 'application/x-7z-compressed', + 'rar' => 'application/x-rar-compressed', + 'exe' => 'application/x-msdownload', + 'dll' => 'application/x-msdownload', + 'scr' => 'application/x-msdownload', + 'com' => 'application/x-msdownload', + 'bat' => 'application/x-msdownload', + 'msi' => 'application/x-msdownload', + 'cab' => 'application/vnd.ms-cab-compressed', + 'gz' => 'application/x-gzip', + 'tgz' => 'application/x-gzip', + 'bz' => 'application/x-bzip', + 'bz2' => 'application/x-bzip2', + 'deb' => 'application/x-debian-package', + + // fonts + 'psf' => 'application/x-font-linux-psf', + 'otf' => 'application/x-font-otf', + 'pcf' => 'application/x-font-pcf', + 'snf' => 'application/x-font-snf', + 'ttf' => 'application/x-font-ttf', + 'ttc' => 'application/x-font-ttf', + + // audio + 'mp3' => 'audio/mpeg', + 'amr' => 'audio/amr', + 'aac' => 'audio/x-aac', + 'aif' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'wav' => 'audio/x-wav', + 'wma' => 'audio/x-ms-wma', + 'wax' => 'audio/x-ms-wax', + 'midi' => 'audio/midi', + 'mp4a' => 'audio/mp4', + 'ogg' => 'audio/ogg', + 'weba' => 'audio/webm', + 'ra' => 'audio/x-pn-realaudio', + 'ram' => 'audio/x-pn-realaudio', + 'rmp' => 'audio/x-pn-realaudio-plugin', + 'm3u' => 'audio/x-mpegurl', + + // video + 'flv' => 'video/x-flv', + 'qt' => 'video/quicktime', + 'mov' => 'video/quicktime', + 'wmv' => 'video/windows-media', + 'avi' => 'video/x-msvideo', + 'mpg' => 'video/mpeg', + 'mpeg' => 'video/mpeg', + 'mpe' => 'video/mpeg', + 'm1v' => 'video/mpeg', + 'm2v' => 'video/mpeg', + '3gp' => 'video/3gpp', + '3g2' => 'video/3gpp2', + 'h261' => 'video/h261', + 'h263' => 'video/h263', + 'h264' => 'video/h264', + 'jpgv' => 'video/jpgv', + 'mp4v' => 'video/mp4', + 'mpg4' => 'video/mp4', + 'ogv' => 'video/ogg', + 'webm' => 'video/webm', + 'm4v' => 'video/x-m4v', + 'asf' => 'video/x-ms-asf', + 'asx' => 'video/x-ms-asf', + 'wm' => 'video/x-ms-wm', + 'wmv' => 'video/x-ms-wmv', + 'wmx' => 'video/x-ms-wmx', + 'wvx' => 'video/x-ms-wvx', + 'movie' => 'video/x-sgi-movie', + + // adobe + 'pdf' => 'application/pdf', + 'psd' => 'image/vnd.adobe.photoshop', + 'ai' => 'application/postscript', + 'eps' => 'application/postscript', + 'ps' => 'application/postscript', + + // ms office + 'doc' => 'application/msword', + 'dot' => 'application/msword', + 'rtf' => 'application/rtf', + 'xls' => 'application/vnd.ms-excel', + 'ppt' => 'application/vnd.ms-powerpoint', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + + // open office + 'odt' => 'application/vnd.oasis.opendocument.text', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet' + + ); + + $sExt = \strtolower(\MailSo\Base\Utils::GetFileExtension($sFileName)); + if (0 < \strlen($sExt) && isset($aMimeTypes[$sExt])) + { + $sResult = $aMimeTypes[$sExt]; + } + + return $sResult; + } + + /** + * @staticvar bool $bValidateAction + * + * @param int &$iTimer + * @param int $iTimeToReset = 15 + * @param int $iTimeToAdd = 30 + * + * @return bool + */ + public static function ResetTimeLimit(&$iTimer, $iTimeToReset = 15, $iTimeToAdd = 30) + { + static $bValidateAction = null; + if (null === $bValidateAction) + { + $bValidateAction = !((bool) @\ini_get('safe_mode')) && + \MailSo\Base\Utils::FunctionExistsAndEnabled('set_time_limit'); + } + + if ($bValidateAction) + { + $iTime = \time(); + if ($iTimeToReset < $iTime - $iTimer) + { + $iTimer = $iTime; + \set_time_limit($iTimeToAdd); + } + } + + return $bValidateAction; + } + + /** + * @param string $sText + * + * @return string + */ + public static function InlineRebuildStringToJsString($sText) + { + static $aJsonReplaces = array( + array('\\', "\n", "\t", "\r", '\b', "\f", '"'), + array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\"') + ); + + return \str_replace('', '<\/script>', + \str_replace($aJsonReplaces[0], $aJsonReplaces[1], $sText)); + } + + /** + * @param mixed $mInput + * + * @return string + */ + public static function Php2js($mInput) + { + return \json_encode($mInput, defined('JSON_UNESCAPED_UNICODE') ? JSON_UNESCAPED_UNICODE : 0); + + if (\is_null($mInput)) + { + return 'null'; + } + else if ($mInput === false) + { + return 'false'; + } + else if ($mInput === true) + { + return 'true'; + } + else if (\is_scalar($mInput)) + { + if (\is_float($mInput)) + { + $mInput = \str_replace(',', '.', \strval($mInput)); + } + + return '"'.\MailSo\Base\Utils::InlineRebuildStringToJsString($mInput).'"'; + } + + $bIsList = true; + for ($iIndex = 0, \reset($mInput), $iLen = \count($mInput); $iIndex < $iLen; $iIndex++, \next($mInput)) + { + if (\key($mInput) !== $iIndex) + { + $bIsList = false; + break; + } + } + + $aResult = array(); + if ($bIsList) + { + foreach ($mInput as $mValue) + { + $aResult[] = \MailSo\Base\Utils::Php2js($mValue); + } + return '['.\join(',', $aResult).']'; + } + else + { + foreach ($mInput as $sKey => $mValue) + { + $aResult[] = \MailSo\Base\Utils::Php2js($sKey).':'.\MailSo\Base\Utils::Php2js($mValue); + } + return '{'.\join(',', $aResult).'}'; + } + } + + /** + * @param string $sFileName + * + * @return string + */ + public static function ClearFileName($sFileName) + { + return \preg_replace('/[\s]+/', ' ', + \str_replace(array('"', '/', '\\', '*', '?', '<', '>', '|', ':'), ' ', $sFileName)); + } + + /** + * @param string $sDir + * + * @return bool + */ + public static function RecRmDir($sDir) + { + if (@is_dir($sDir)) + { + $aObjects = scandir($sDir); + foreach ($aObjects as $sObject) + { + if ('.' !== $sObject && '..' !== $sObject) + { + if ('dir' === filetype($sDir.'/'.$sObject)) + { + self::RecRmDir($sDir.'/'.$sObject); + } + else + { + @unlink($sDir.'/'.$sObject); + } + } + } + + return @rmdir($sDir); + } + + return false; + } + + /** + * @param string $sSource + * @param string $sDestination + */ + public static function CopyDir($sSource, $sDestination) + { + if (\is_dir($sSource)) + { + if (!\is_dir($sDestination)) + { + \mkdir($sDestination); + } + + $oDirectory = \dir($sSource); + if ($oDirectory) + { + while (false !== ($sRead = $oDirectory->read())) + { + if ('.' === $sRead || '..' === $sRead) + { + continue; + } + + $sPathDir = $sSource.'/'.$sRead; + if (\is_dir($sPathDir)) + { + \MailSo\Base\Utils::CopyDir($sPathDir, $sDestination.'/'.$sRead); + continue; + } + + \copy($sPathDir, $sDestination.'/'.$sRead); + } + + $oDirectory->close(); + } + } + } + + /** + * @param string $sTempPath + * @param int $iTime2Kill + * @param int $iNow + * + * @return bool + */ + public static function RecTimeDirRemove($sTempPath, $iTime2Kill, $iNow) + { + $iFileCount = 0; + + $sTempPath = rtrim($sTempPath, '\\/'); + if (@\is_dir($sTempPath)) + { + $rDirH = @\opendir($sTempPath); + if ($rDirH) + { + $bRemoveAllDirs = true; + while (($sFile = @\readdir($rDirH)) !== false) + { + if ('.' !== $sFile && '..' !== $sFile) + { + if (@\is_dir($sTempPath.'/'.$sFile)) + { + if (!\MailSo\Base\Utils::RecTimeDirRemove($sTempPath.'/'.$sFile, $iTime2Kill, $iNow)) + { + $bRemoveAllDirs = false; + } + } + else + { + $iFileCount++; + } + } + } + + @\closedir($rDirH); + } + + if ($iFileCount > 0) + { + if (\MailSo\Base\Utils::TimeFilesRemove($sTempPath, $iTime2Kill, $iNow)) + { + return @\rmdir($sTempPath); + } + } + else + { + return $bRemoveAllDirs ? @\rmdir($sTempPath) : false; + } + + return false; + } + + return true; + } + + /** + * @param string $sTempPath + * @param int $iTime2Kill + * @param int $iNow + */ + public static function TimeFilesRemove($sTempPath, $iTime2Kill, $iNow) + { + $bResult = true; + + $sTempPath = rtrim($sTempPath, '\\/'); + if (@\is_dir($sTempPath)) + { + $rDirH = @\opendir($sTempPath); + if ($rDirH) + { + while (($sFile = @\readdir($rDirH)) !== false) + { + if ($sFile !== '.' && $sFile !== '..') + { + if ($iNow - \filemtime($sTempPath.'/'.$sFile) > $iTime2Kill) + { + @\unlink($sTempPath.'/'.$sFile); + } + else + { + $bResult = false; + } + } + } + + @\closedir($rDirH); + } + } + + return $bResult; + } + + /** + * @param string $sUtfString + * @param int $iLength + * + * @return string + */ + public static function Utf8Truncate($sUtfString, $iLength) + { + if (\strlen($sUtfString) <= $iLength) + { + return $sUtfString; + } + + while ($iLength >= 0) + { + if ((\ord($sUtfString[$iLength]) < 0x80) || (\ord($sUtfString[$iLength]) >= 0xC0)) + { + return \substr($sUtfString, 0, $iLength); + } + + $iLength--; + } + + return ''; + } + + /** + * @param string $sUtfString + * @param string $sReplaceOn = '' + * + * @return string + */ + public static function Utf8Clear($sUtfString, $sReplaceOn = '') + { + $sUtfString = @\iconv('UTF-8', 'UTF-8//IGNORE', $sUtfString); + + $sUtfString = \preg_replace( + '/[\x00-\x08\x10\x0B\x0C\x0E-\x1F\x7F]'. + '|[\x00-\x7F][\x80-\xBF]+'. + '|([\xC0\xC1]|[\xF0-\xFF])[\x80-\xBF]*'. + '|[\xC2-\xDF]((?![\x80-\xBF])|[\x80-\xBF]{2,})'. + '|[\xE0-\xEF](([\x80-\xBF](?![\x80-\xBF]))|(?![\x80-\xBF]{2})|[\x80-\xBF]{3,})/S', + $sReplaceOn, $sUtfString); + + $sUtfString = \preg_replace( + '/\xE0[\x80-\x9F][\x80-\xBF]'. + '|\xEF\xBF\xBF'. + '|\xED[\xA0-\xBF][\x80-\xBF]/S', $sReplaceOn, $sUtfString); + + $sUtfString = \preg_replace('/\xEF\xBF\xBD/', '?', $sUtfString); + + return $sUtfString; + } + + /** + * @param string $sString + * + * @return bool + */ + public static function IsRTL($sUtfString) + { + // \x{0591}-\x{05F4} - Hebrew + // \x{FB1D}-\x{FB40} - Hebrew ? + // \x{0621}-\x{064A} - Arabic + return 0 < (int) preg_match('/[\x{0591}-\x{05F4}\x{FB1D}-\x{FB40}\x{0621}-\x{064A}]/u', $sUtfString); + } + + /** + * @param string $sString + * + * @return string + */ + public static function Base64Decode($sString) + { + $sResultString = \base64_decode($sString, true); + if (false === $sResultString) + { + $sString = \str_replace(array(' ', "\r", "\n", "\t"), '', $sString); + $sString = \preg_replace('/[^a-zA-Z0-9=+\/](.*)$/', '', $sString); + + if (false !== \strpos(\trim(\trim($sString), '='), '=')) + { + $sString = \preg_replace('/=([^=])/', '= $1', $sString); + $aStrings = \explode(' ', $sString); + foreach ($aStrings as $iIndex => $sParts) + { + $aStrings[$iIndex] = \base64_decode($sParts); + } + + $sResultString = \implode('', $aStrings); + } + else + { + $sResultString = \base64_decode($sString); + } + } + + return $sResultString; + } + + /** + * @param string $sValue + * + * @return string + */ + public static function UrlSafeBase64Encode($sValue) + { + return \str_replace(array('+', '/', '='), array('-', '_', '.'), \base64_encode($sValue)); + } + + /** + * @param string $sValue + * + * @return string + */ + public static function UrlSafeBase64Decode($sValue) + { + $sData = \str_replace(array('-', '_', '.'), array('+', '/', '='), $sValue); + $sMode = \strlen($sData) % 4; + if ($sMode) + { + $sData .= \substr('====', $sMode); + } + + return \MailSo\Base\Utils::Base64Decode($sData); + } + + /** + * + * @param resource $fResource + * @param int $iBufferLen = 8192 + * + * @return bool + */ + public static function FpassthruWithTimeLimitReset($fResource, $iBufferLen = 8192) + { + $iTimer = 0; + $bResult = false; + if (\is_resource($fResource)) + { + while (!\feof($fResource)) + { + $sBuffer = @\fread($fResource, $iBufferLen); + if (false !== $sBuffer) + { + echo $sBuffer; + \MailSo\Base\Utils::ResetTimeLimit($iTimer); + continue; + } + + break; + } + + $bResult = true; + } + + return $bResult; + } + + /** + * @param resource $rRead + * @param array $aWrite + * @param int $iBufferLen = 8192 + * @param bool $bResetTimeLimit = true + * @param bool $bFixCrLf = false + * + * @return int|bool + */ + public static function MultipleStreamWriter($rRead, $aWrite, $iBufferLen = 8192, $bResetTimeLimit = true, $bFixCrLf = false) + { + $iTimer = 0; + $mResult = false; + if ($rRead && \is_array($aWrite) && 0 < \count($aWrite)) + { + $mResult = 0; + while (!\feof($rRead)) + { + $sBuffer = \fread($rRead, $iBufferLen); + if (false === $sBuffer) + { + $mResult = false; + break; + } + + if (0 === $iBufferLen || '' === $sBuffer) + { + break; + } + + if ($bFixCrLf) + { + $sBuffer = \str_replace("\n", "\r\n", \str_replace("\r", '', $sBuffer)); + } + + $mResult += \strlen($sBuffer); + + foreach ($aWrite as $rWriteStream) + { + $mWriteResult = \fwrite($rWriteStream, $sBuffer); + if (false === $mWriteResult) + { + $mResult = false; + break 2; + } + } + + if ($bResetTimeLimit) + { + \MailSo\Base\Utils::ResetTimeLimit($iTimer); + } + } + } + + return $mResult; + } + + /** + * @param string $sUtfModifiedString + * + * @return string + */ + public static function ModifiedToPlainUtf7($sUtfModifiedString) + { + $sUtf = ''; + $bBase = false; + + for ($iIndex = 0, $iLen = \strlen($sUtfModifiedString); $iIndex < $iLen; $iIndex++) + { + if ('&' === $sUtfModifiedString[$iIndex]) + { + if (isset($sUtfModifiedString[$iIndex+1]) && '-' === $sUtfModifiedString[$iIndex + 1]) + { + $sUtf .= '&'; + $iIndex++; + } + else + { + $sUtf .= '+'; + $bBase = true; + } + } + else if ($sUtfModifiedString[$iIndex] == '-' && $bBase) + { + $bBase = false; + } + else + { + if ($bBase && ',' === $sUtfModifiedString[$iIndex]) + { + $sUtf .= '/'; + } + else if (!$bBase && '+' === $sUtfModifiedString[$iIndex]) + { + $sUtf .= '+-'; + } + else + { + $sUtf .= $sUtfModifiedString[$iIndex]; + } + } + } + + return $sUtf; + } + + /** + * @param string $sStr + * + * @return string|bool + */ + public static function Utf7ModifiedToUtf8($sStr) + { + $aArray = array(-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,62, 63,-1,-1,-1,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9, + 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, + 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1); + + $sResult = ''; + $bError = false; + $iLen = \strlen($sStr); + + for ($iIndex = 0; $iLen > 0; $iIndex++, $iLen--) + { + $sChar = $sStr{$iIndex}; + if ($sChar == '&') + { + $iIndex++; + $iLen--; + + $sChar = isset($sStr{$iIndex}) ? $sStr{$iIndex} : null; + if ($sChar === null) + { + break; + } + + if ($iLen && $sChar == '-') + { + $sResult .= '&'; + continue; + } + + $iCh = 0; + $iK = 10; + for (; $iLen > 0; $iIndex++, $iLen--) + { + $sChar = $sStr{$iIndex}; + + $iB = $aArray[\ord($sChar)]; + if ((\ord($sChar) & 0x80) || $iB == -1) + { + break; + } + + if ($iK > 0) + { + $iCh |= $iB << $iK; + $iK -= 6; + } + else + { + $iCh |= $iB >> (-$iK); + if ($iCh < 0x80) + { + if (0x20 <= $iCh && $iCh < 0x7f) + { + return $bError; + } + + $sResult .= \chr($iCh); + } + else if ($iCh < 0x800) + { + $sResult .= \chr(0xc0 | ($iCh >> 6)); + $sResult .= \chr(0x80 | ($iCh & 0x3f)); + } + else + { + $sResult .= \chr(0xe0 | ($iCh >> 12)); + $sResult .= \chr(0x80 | (($iCh >> 6) & 0x3f)); + $sResult .= \chr(0x80 | ($iCh & 0x3f)); + } + + $iCh = ($iB << (16 + $iK)) & 0xffff; + $iK += 10; + } + } + + if (($iCh || $iK < 6) || + (!$iLen || $sChar != '-') || + ($iLen > 2 && '&' === $sStr{$iIndex+1} && '-' !== $sStr{$iIndex+2})) + { + return $bError; + } + } + else if (\ord($sChar) < 0x20 || \ord($sChar) >= 0x7f) + { + return $bError; + } + else + { + $sResult .= $sChar; + } + } + + return $sResult; + } + + /** + * @param string $sStr + * + * @return string|bool + */ + public static function Utf8ToUtf7Modified($sStr) + { + $sArray = array('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S', + 'T','U','V','W','X','Y','Z', 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o', + 'p','q','r','s','t','u','v','w','x','y','z', '0','1','2','3','4','5','6','7','8','9','+',','); + + $sLen = \strlen($sStr); + $bIsB = false; + $iIndex = $iN = 0; + $sReturn = ''; + $bError = false; + $iCh = $iB = $iK = 0; + + while ($sLen) + { + $iC = \ord($sStr{$iIndex}); + if ($iC < 0x80) + { + $iCh = $iC; + $iN = 0; + } + else if ($iC < 0xc2) + { + return $bError; + } + else if ($iC < 0xe0) + { + $iCh = $iC & 0x1f; + $iN = 1; + } + else if ($iC < 0xf0) + { + $iCh = $iC & 0x0f; + $iN = 2; + } + else if ($iC < 0xf8) + { + $iCh = $iC & 0x07; + $iN = 3; + } + else if ($iC < 0xfc) + { + $iCh = $iC & 0x03; + $iN = 4; + } + else if ($iC < 0xfe) + { + $iCh = $iC & 0x01; + $iN = 5; + } + else + { + return $bError; + } + + $iIndex++; + $sLen--; + + if ($iN > $sLen) + { + return $bError; + } + + for ($iJ = 0; $iJ < $iN; $iJ++) + { + $iO = \ord($sStr{$iIndex+$iJ}); + if (($iO & 0xc0) != 0x80) + { + return $bError; + } + + $iCh = ($iCh << 6) | ($iO & 0x3f); + } + + if ($iN > 1 && !($iCh >> ($iN * 5 + 1))) + { + return $bError; + } + + $iIndex += $iN; + $sLen -= $iN; + + if ($iCh < 0x20 || $iCh >= 0x7f) + { + if (!$bIsB) + { + $sReturn .= '&'; + $bIsB = true; + $iB = 0; + $iK = 10; + } + + if ($iCh & ~0xffff) + { + $iCh = 0xfffe; + } + + $sReturn .= $sArray[($iB | $iCh >> $iK)]; + $iK -= 6; + for (; $iK >= 0; $iK -= 6) + { + $sReturn .= $sArray[(($iCh >> $iK) & 0x3f)]; + } + + $iB = ($iCh << (-$iK)) & 0x3f; + $iK += 16; + } + else + { + if ($bIsB) + { + if ($iK > 10) + { + $sReturn .= $sArray[$iB]; + } + $sReturn .= '-'; + $bIsB = false; + } + + $sReturn .= \chr($iCh); + if ('&' === \chr($iCh)) + { + $sReturn .= '-'; + } + } + } + + if ($bIsB) + { + if ($iK > 10) + { + $sReturn .= $sArray[$iB]; + } + + $sReturn .= '-'; + } + + return $sReturn; + } + + /** + * @param string $sFunctionName + * + * @return bool + */ + public static function FunctionExistsAndEnabled($sFunctionName) + { + static $aCache = null; + if (empty($sFunctionName) || !\function_exists($sFunctionName) || !\is_callable($sFunctionName)) + { + return false; + } + + if (null === $aCache) + { + $sDisableFunctions = @\ini_get('disable_functions'); + $sDisableFunctions = \is_string($sDisableFunctions) && 0 < \strlen($sDisableFunctions) ? $sDisableFunctions : ''; + + $aCache = \explode(',', $sDisableFunctions); + $aCache = is_array($aCache) && 0 < count($aCache) ? $aCache : array(); + + if (\extension_loaded('suhosin')) + { + $sSuhosin = @\ini_get('suhosin.executor.func.blacklist'); + $sSuhosin = \is_string($sSuhosin) && 0 < \strlen($sSuhosin) ? $sSuhosin : ''; + + $aSuhosinCache = \explode(',', $sSuhosin); + $aSuhosinCache = is_array($aSuhosinCache) && 0 < count($aSuhosinCache) ? $aSuhosinCache : array(); + + if (0 < \count($aSuhosinCache)) + { + $aCache = array_merge($aCache, $aSuhosinCache); + $aCache = array_unique($aCache); + } + } + } + + return !\in_array($sFunctionName, $aCache); + } + + /** + * @param string $mValue + * + * @return string + */ + public static function ClearNullBite($mValue) + { + return \str_replace('%00', '', $mValue); + } + + /** + * @param mixed $mValue + * @param bool $bClearNullBite = false + * + * @return mixed + */ + public static function StripSlashesValue($mValue, $bClearNullBite = false) + { + static $bIsMagicQuotesOn = null; + if (null === $bIsMagicQuotesOn) + { + $bIsMagicQuotesOn = (bool) @\ini_get('magic_quotes_gpc'); + } + + if (!$bIsMagicQuotesOn) + { + return $bClearNullBite && \is_string($mValue) ? \MailSo\Base\Utils::ClearNullBite($mValue) : $mValue; + } + + $sType = \gettype($mValue); + if ('string' === $sType) + { + return \stripslashes($bClearNullBite ? \MailSo\Base\Utils::ClearNullBite($mValue) : $mValue); + } + else if ('array' === $sType) + { + $aReturnValue = array(); + $mValueKeys = \array_keys($mValue); + foreach ($mValueKeys as $sKey) + { + $aReturnValue[$sKey] = \MailSo\Base\Utils::StripSlashesValue($mValue[$sKey], $bClearNullBite); + } + + return $aReturnValue; + } + + return $mValue; + } + + /** + * @param string $sStr + * + * @return string + */ + public static function CharsetDetect($sStr) + { + $mResult = ''; + if (!\MailSo\Base\Utils::IsAscii($sStr)) + { + $mResult = \MailSo\Base\Utils::FunctionExistsAndEnabled('mb_detect_encoding') ? + @\mb_detect_encoding($sStr, 'auto', true) : false; + + if (false === $mResult && \MailSo\Base\Utils::IsIconvSupported()) + { + foreach (array('utf-8', 'iso-8859-1', 'windows-1251') as $sCharsetItem) + { + $sSample = @\iconv($sCharsetItem, $sCharsetItem.'//IGNORE', $sStr); + if (\md5($sSample) === \md5($sStr)) + { + $mResult = $sCharsetItem; + break; + } + } + } + } + + return !empty($mResult) && \is_string($mResult) ? $mResult : ''; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Validator.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Validator.php new file mode 100644 index 000000000..22a7e7938 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Base/Validator.php @@ -0,0 +1,95 @@ += $iMin; + } + + if ($bResult && null !== $iMax) + { + $bResult = $iNumber <= $iMax; + } + } + + return $bResult; + } + + /** + * @param int $iPort + * + * @return bool + */ + public static function PortInt($iPort) + { + return self::RangeInt($iPort, 0, 65535); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/CacheClient.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/CacheClient.php new file mode 100644 index 000000000..2e086f3a2 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/CacheClient.php @@ -0,0 +1,149 @@ +oDriver = null; + $this->sCacheIndex = ''; + } + + /** + * @return \MailSo\Cache\CacheClient + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @param string $sKey + * @param string $sValue + * + * @return bool + */ + public function Set($sKey, $sValue) + { + return $this->oDriver ? $this->oDriver->Set($sKey.$this->sCacheIndex, $sValue) : false; + } + + /** + * @param string $sKey + * + * @return bool + */ + public function SetTimer($sKey) + { + return $this->Set($sKey.'/TIMER', time()); + } + + /** + * @param string $sKey + * + * @return string + */ + public function Get($sKey) + { + $sValue = ''; + + if ($this->oDriver) + { + $sValue = $this->oDriver->Get($sKey.$this->sCacheIndex); + } + + return $sValue; + } + + /** + * @param string $sKey + * + * @return int + */ + public function GetTimer($sKey) + { + $iTimer = 0; + $sValue = $this->Get($sKey.'/TIMER'); + if (0 < strlen($sValue) && is_numeric($sValue)) + { + $iTimer = (int) $sValue; + } + + return $iTimer; + } + + /** + * @param string $sKey + * + * @return \MailSo\Cache\CacheClient + */ + public function Delete($sKey) + { + if ($this->oDriver) + { + $this->oDriver->Delete($sKey.$this->sCacheIndex); + } + + return $this; + } + + /** + * @param \MailSo\Cache\DriverInterface $oDriver + * + * @return \MailSo\Cache\CacheClient + */ + public function SetDriver(\MailSo\Cache\DriverInterface $oDriver) + { + $this->oDriver = $oDriver; + + return $this; + } + + /** + * @param int $iTimeToClearInHours = 24 + * + * @return bool + */ + public function GC($iTimeToClearInHours = 24) + { + return $this->oDriver ? $this->oDriver->GC($iTimeToClearInHours) : false; + } + + /** + * @return bool + */ + public function IsInited() + { + return $this->oDriver instanceof \MailSo\Cache\DriverInterface; + } + + /** + * @param string $sCacheIndex + * + * @return \MailSo\Cache\CacheClient + */ + public function SetCacheIndex($sCacheIndex) + { + $this->sCacheIndex = 0 < \strlen($sCacheIndex) ? "\x0".$sCacheIndex : ''; + + return $this; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/DriverInterface.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/DriverInterface.php new file mode 100644 index 000000000..ce80133f0 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/DriverInterface.php @@ -0,0 +1,39 @@ +generateCachedKey($sKey), $sValue); + } + + /** + * @param string $sKey + * + * @return string + */ + public function Get($sKey) + { + $sValue = \apc_fetch($this->generateCachedKey($sKey)); + return \is_string($sValue) ? $sValue : ''; + } + + /** + * @param string $sKey + * + * @return void + */ + public function Delete($sKey) + { + \apc_delete($this->generateCachedKey($sKey)); + } + + /** + * @param int $iTimeToClearInHours = 24 + * + * @return bool + */ + public function GC($iTimeToClearInHours = 24) + { + if (0 === $iTimeToClearInHours) + { + return \apc_clear_cache('user'); + } + + return false; + } + + /** + * @param string $sKey + * + * @return string + */ + private function generateCachedKey($sKey) + { + return \sha1($sKey); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/Drivers/File.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/Drivers/File.php new file mode 100644 index 000000000..2c36e80f0 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/Drivers/File.php @@ -0,0 +1,126 @@ +sCacheFolder = $sCacheFolder; + $this->sCacheFolder = rtrim(trim($this->sCacheFolder), '\\/').'/'; + if (!\is_dir($this->sCacheFolder)) + { + @\mkdir($this->sCacheFolder, 0777); + } + } + + /** + * @param string $sCacheFolder + * + * @return \MailSo\Cache\Drivers\File + */ + public static function NewInstance($sCacheFolder) + { + return new self($sCacheFolder); + } + + /** + * @param string $sKey + * @param string $sValue + * + * @return bool + */ + public function Set($sKey, $sValue) + { + return false !== \file_put_contents($sPath = $this->generateCachedFileName($sKey, true), $sValue); + } + + /** + * @param string $sKey + * + * @return string + */ + public function Get($sKey) + { + $sValue = ''; + $sPath = $this->generateCachedFileName($sKey); + if (\file_exists($sPath)) + { + $sValue = \file_get_contents($sPath); + } + + return \is_string($sValue) ? $sValue : ''; + } + + /** + * @param string $sKey + * + * @return void + */ + public function Delete($sKey) + { + $sPath = $this->generateCachedFileName($sKey); + if (\file_exists($sPath)) + { + \unlink($sPath); + } + } + + /** + * @param int $iTimeToClearInHours = 24 + * + * @return bool + */ + public function GC($iTimeToClearInHours = 24) + { + if (0 < $iTimeToClearInHours) + { + \MailSo\Base\Utils::RecTimeDirRemove($this->sCacheFolder, 60 * 60 * $iTimeToClearInHours, \time()); + return true; + } + + return false; + } + + /** + * @param string $sKey + * @param bool $bMkDir = false + * + * @return string + */ + private function generateCachedFileName($sKey, $bMkDir = false) + { + $sFilePath = ''; + if (3 < \strlen($sKey)) + { + $sKeyPath = \sha1($sKey); + $sKeyPath = \substr($sKeyPath, 0, 2).'/'.\substr($sKeyPath, 2, 2).'/'.$sKeyPath; + + $sFilePath = $this->sCacheFolder.'/'.$sKeyPath; + if ($bMkDir && !\is_dir(\dirname($sFilePath))) + { + if (!\mkdir(\dirname($sFilePath), 0777, true)) + { + $sFilePath = ''; + } + } + } + + return $sFilePath; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/Drivers/Memcache.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/Drivers/Memcache.php new file mode 100644 index 000000000..e8f32e5c4 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Cache/Drivers/Memcache.php @@ -0,0 +1,120 @@ +sHost = $sHost; + $this->iPost = $iPost; + $this->iExpire = 0 < $iExpire ? $iExpire : 43200; + + $this->oMem = new \Memcache(); + if (!$this->oMem->connect($this->sHost, $this->iPost)) + { + $this->oMem = null; + } + } + + /** + * @param string $sHost = '127.0.0.1' + * @param int $iPost = 11211 + * + * @return \MailSo\Cache\Drivers\APC + */ + public static function NewInstance($sHost = '127.0.0.1', $iPost = 11211) + { + return new self($sHost, $iPost); + } + + /** + * @param string $sKey + * @param string $sValue + * + * @return bool + */ + public function Set($sKey, $sValue) + { + return $this->oMem ? $this->oMem->set($this->generateCachedKey($sKey), $sValue, 0, $this->iExpire) : false; + } + + /** + * @param string $sKey + * + * @return string + */ + public function Get($sKey) + { + $sValue = $this->oMem ? $this->oMem->get($this->generateCachedKey($sKey)) : ''; + return \is_string($sValue) ? $sValue : ''; + } + + /** + * @param string $sKey + * + * @return void + */ + public function Delete($sKey) + { + if ($this->oMem) + { + $this->oMem->delete($this->generateCachedKey($sKey)); + } + } + + /** + * @param int $iTimeToClearInHours = 24 + * + * @return bool + */ + public function GC($iTimeToClearInHours = 24) + { + if (0 === $iTimeToClearInHours && $this->oMem) + { + return $this->oMem->flush(); + } + + return false; + } + + /** + * @param string $sKey + * + * @return string + */ + private function generateCachedKey($sKey) + { + return \sha1($sKey); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/BodyStructure.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/BodyStructure.php new file mode 100644 index 000000000..de30db5be --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/BodyStructure.php @@ -0,0 +1,855 @@ +sContentType = $sContentType; + $this->sCharset = $sCharset; + $this->aBodyParams = $aBodyParams; + $this->sContentID = $sContentID; + $this->sDescription = $sDescription; + $this->sMailEncodingName = $sMailEncodingName; + $this->sDisposition = $sDisposition; + $this->aDispositionParams = $aDispositionParams; + $this->sFileName = $sFileName; + $this->sLanguage = $sLanguage; + $this->sLocation = $sLocation; + $this->iSize = $iSize; + $this->iTextLineCount = $iTextLineCount; + $this->sPartID = $sPartID; + $this->aSubParts = $aSubParts; + } + + /** + * return string + */ + public function MailEncodingName() + { + return $this->sMailEncodingName; + } + + /** + * return string + */ + public function PartID() + { + return (string) $this->sPartID; + } + + /** + * return string + */ + public function FileName() + { + return $this->sFileName; + } + + /** + * return string + */ + public function ContentType() + { + return $this->sContentType; + } + + /** + * return int + */ + public function Size() + { + return (int) $this->iSize; + } + + /** + * return int + */ + public function EstimatedSize() + { + $fCoefficient = 1; + switch (strtolower($this->MailEncodingName())) + { + case 'base64': + $fCoefficient = 0.75; + break; + case 'quoted-printable': + $fCoefficient = 0.44; + break; + } + + return (int) ($this->Size() * $fCoefficient); + } + + /** + * return string + */ + public function Charset() + { + return $this->sCharset; + } + + + /** + * return string + */ + public function ContentID() + { + return (null === $this->sContentID) ? '' : $this->sContentID; + } + + /** + * return bool + */ + public function IsInline() + { + return (null === $this->sDisposition) ? false : ('inline' === strtolower($this->sDisposition)); + } + + /** + * @return array|null + */ + public function SearchPlainParts() + { + $aReturn = array(); + $aParts = $this->SearchByContentType('text/plain'); + foreach ($aParts as $oPart) + { + if (!$oPart->isAttachBodyPart()) + { + $aReturn[] = $oPart; + } + } + return $aReturn; + } + + /** + * @return array|null + */ + public function SearchHtmlParts() + { + $aReturn = array(); + $aParts = $this->SearchByContentType('text/html'); + + foreach ($aParts as $oPart) + { + if (!$oPart->isAttachBodyPart()) + { + $aReturn[] = $oPart; + } + } + + return $aReturn; + } + + /** + * @return array|null + */ + public function SearchHtmlOrPlainParts() + { + $mResult = $this->SearchHtmlParts(); + if (null === $mResult || (is_array($mResult) && 0 === count($mResult))) + { + $mResult = $this->SearchPlainParts(); + } + + return $mResult; + } + + /** + * @return string + */ + public function SearchCharset() + { + $sResult = ''; + + $mHtmlParts = $this->SearchHtmlParts(); + $mPlainParts = $this->SearchPlainParts(); + $mParts = array(); + if (is_array($mHtmlParts) && 0 < count($mHtmlParts)) + { + $mParts = array_merge($mParts, $mHtmlParts); + } + + if (is_array($mPlainParts) && 0 < count($mPlainParts)) + { + $mParts = array_merge($mParts, $mPlainParts); + } + + foreach ($mParts as $oPart) + { + $sResult = $oPart ? $oPart->Charset() : ''; + if (!empty($sResult)) + { + break; + } + } + + if (0 === strlen($sResult)) + { + $aParts = $this->SearchAttachmentsParts(); + foreach ($aParts as $oPart) + { + if (0 === strlen($sResult)) + { + $sResult = $oPart ? $oPart->Charset() : ''; + } + else + { + break; + } + } + } + + return $sResult; + } + + /** + * @return bool + */ + protected function isAttachBodyPart() + { + $bResult = ( + (null !== $this->sDisposition && 'attachment' === strtolower($this->sDisposition)) + ); + + if (!$bResult && null !== $this->sContentType) + { + $sContentType = strtolower($this->sContentType); + $bResult = false === strpos($sContentType, 'multipart/') && + 'text/html' !== $sContentType && 'text/plain' !== $sContentType; + } + + return $bResult; + } + + /** + * @return array + */ + public function SearchAttachmentsParts() + { + $aReturn = array(); + if ($this->isAttachBodyPart()) + { + $aReturn[] = $this; + } + + if (is_array($this->aSubParts) && 0 < count($this->aSubParts)) + { + foreach ($this->aSubParts as /* @var $oSubPart \MailSo\Imap\BodyStructure */ &$oSubPart) + { + $aReturn = array_merge($aReturn, $oSubPart->SearchAttachmentsParts()); + unset($oSubPart); + } + } + + return $aReturn; + } + + /** + * @param string $sContentType + * + * @return array + */ + public function SearchByContentType($sContentType) + { + $aReturn = array(); + if (strtolower($sContentType) === $this->sContentType) + { + $aReturn[] = $this; + } + + if (is_array($this->aSubParts) && 0 < count($this->aSubParts)) + { + foreach ($this->aSubParts as /* @var $oSubPart \MailSo\Imap\BodyStructure */ &$oSubPart) + { + $aReturn = array_merge($aReturn, $oSubPart->SearchByContentType($sContentType)); + } + } + + return $aReturn; + } + + /** + * @param string $sMimeIndex + * + * @return \MailSo\Imap\BodyStructure + */ + public function GetPartByMimeIndex($sMimeIndex) + { + $oPart = null; + if (0 < strlen($sMimeIndex)) + { + if ($sMimeIndex === $this->sPartID) + { + $oPart = $this; + } + + if (null === $oPart && is_array($this->aSubParts) && 0 < count($this->aSubParts)) + { + foreach ($this->aSubParts as /* @var $oSubPart \MailSo\Imap\BodyStructure */ &$oSubPart) + { + $oPart = $oSubPart->GetPartByMimeIndex($sMimeIndex); + if (null !== $oPart) + { + break; + } + } + } + } + + return $oPart; + } + + /** + * @param array $aParams + * @param string $sParamName + * @param string $sCharset = \MailSo\Base\Enumerations\Charset::UTF_8 + * + * @return string + */ + private static function decodeAttrParamenter($aParams, $sParamName, $sCharset = \MailSo\Base\Enumerations\Charset::UTF_8) + { + $sResult = ''; + if (isset($aParams[$sParamName])) + { + $sResult = \MailSo\Base\Utils::DecodeHeaderValue($aParams[$sParamName], $sCharset); + } + else if (isset($aParams[$sParamName.'*'])) + { + $aValueParts = explode('\'\'', $aParams[$sParamName.'*'], 2); + if (is_array($aValueParts) && 2 === count($aValueParts)) + { + $sCharset = isset($aValueParts[0]) ? $aValueParts[0] : \MailSo\Base\Enumerations\Charset::UTF_8; + + $sResult = \MailSo\Base\Utils::ConvertEncoding( + urldecode($aValueParts[1]), $sCharset, \MailSo\Base\Enumerations\Charset::UTF_8); + } + else + { + $sResult = urldecode($aParams[$sParamName.'*']); + } + } + else if (isset($aParams[$sParamName.'*0*'])) + { + $sCharset = ''; + $aFileNames = array(); + foreach ($aParams as $sName => $sValue) + { + $aMatches = array(); + if ($sParamName.'*0*' === $sName) + { + if (0 === strlen($sCharset)) + { + $aValueParts = explode('\'\'', $sValue, 2); + if (is_array($aValueParts) && 2 === count($aValueParts) && 0 < strlen($aValueParts[0])) + { + $sCharset = $aValueParts[0]; + $sValue = $aValueParts[1]; + } + } + + $aFileNames[0] = $sValue; + } + else if ($sParamName.'*0*' !== $sName && preg_match('/^'.preg_quote($sParamName, '/').'\*([0-9]+)\*$/i', $sName, $aMatches) && 0 < strlen($aMatches[1])) + { + $aFileNames[(int) $aMatches[1]] = $sValue; + } + } + + if (0 < count($aFileNames)) + { + ksort($aFileNames, SORT_NUMERIC); + $sResult = implode(array_values($aFileNames)); + $sResult = urldecode($sResult); + + if (0 < strlen($sCharset)) + { + $sResult = \MailSo\Base\Utils::ConvertEncoding($sResult, + $sCharset, \MailSo\Base\Enumerations\Charset::UTF_8); + } + } + } + + return $sResult; + } + + /** + * @param array $aBodyStructure + * @param string $sPartID = '' + * + * @return \MailSo\Imap\BodyStructure + */ + public static function NewInstance(array $aBodyStructure, $sPartID = '') + { + if (!is_array($aBodyStructure) || 2 > count($aBodyStructure)) + { + return null; + } + else + { + $sBodyMainType = null; + if (is_string($aBodyStructure[0]) && 'NIL' !== $aBodyStructure[0]) + { + $sBodyMainType = $aBodyStructure[0]; + } + + $sBodySubType = null; + $sContentType = ''; + $aSubParts = null; + $aBodyParams = array(); + $sName = null; + $sCharset = null; + $sContentID = null; + $sDescription = null; + $sMailEncodingName = null; + $iSize = 0; + $iTextLineCount = 0; // valid for rfc822/message and text parts + $iExtraItemPos = 0; // list index of items which have no well-established position (such as 0, 1, 5, etc). + + if (null === $sBodyMainType) + { + // Process multipart body structure + if (!is_array($aBodyStructure[0])) + { + return null; + } + else + { + $sBodyMainType = 'multipart'; + $sSubPartIDPrefix = ''; + if (0 === strlen($sPartID) || '.' === $sPartID[strlen($sPartID) - 1]) + { + // This multi-part is root part of message. + $sSubPartIDPrefix = $sPartID; + $sPartID .= 'TEXT'; + } + else if (0 < strlen($sPartID)) + { + // This multi-part is a part of another multi-part. + $sSubPartIDPrefix = $sPartID.'.'; + } + + $aSubParts = array(); + $iIndex = 1; + + while ($iExtraItemPos < count($aBodyStructure) && is_array($aBodyStructure[$iExtraItemPos])) + { + $oPart = self::NewInstance($aBodyStructure[$iExtraItemPos], $sSubPartIDPrefix.$iIndex); + if (null === $oPart) + { + return null; + } + else + { + // For multipart, we have no charset info in the part itself. Thus, + // obtain charset from nested parts. + if ($sCharset == null) + { + $sCharset = $oPart->Charset(); + } + + $aSubParts[] = $oPart; + $iExtraItemPos++; + $iIndex++; + } + } + } + + if ($iExtraItemPos < count($aBodyStructure)) + { + if (!is_string($aBodyStructure[$iExtraItemPos]) || 'NIL' === $aBodyStructure[$iExtraItemPos]) + { + return null; + } + + $sBodySubType = strtolower($aBodyStructure[$iExtraItemPos]); + $iExtraItemPos++; + } + + if ($iExtraItemPos < count($aBodyStructure)) + { + $sBodyParamList = $aBodyStructure[$iExtraItemPos]; + if (is_array($sBodyParamList)) + { + $aBodyParams = self::getKeyValueListFromArrayList($sBodyParamList); + } + } + $iExtraItemPos++; + } + else + { + // Process simple (singlepart) body structure + if (7 > count($aBodyStructure)) + { + return null; + } + + $sBodyMainType = strtolower($sBodyMainType); + if (!is_string($aBodyStructure[1]) || 'NIL' === $aBodyStructure[1]) + { + return null; + } + + $sBodySubType = strtolower($aBodyStructure[1]); + + $aBodyParamList = $aBodyStructure[2]; + if (is_array($aBodyParamList)) + { + $aBodyParams = self::getKeyValueListFromArrayList($aBodyParamList); + if (isset($aBodyParams['charset'])) + { + $sCharset = $aBodyParams['charset']; + } + + if (is_array($aBodyParams)) + { + $sName = self::decodeAttrParamenter($aBodyParams, 'name', $sContentType); + } + } + + if (null !== $aBodyStructure[3] && 'NIL' !== $aBodyStructure[3]) + { + if (!is_string($aBodyStructure[3])) + { + return null; + } + + $sContentID = $aBodyStructure[3]; + } + + if (null !== $aBodyStructure[4] && 'NIL' !== $aBodyStructure[4]) + { + if (!is_string($aBodyStructure[4])) + { + return null; + } + + $sDescription = $aBodyStructure[4]; + } + + if (null !== $aBodyStructure[5] && 'NIL' !== $aBodyStructure[5]) + { + if (!is_string($aBodyStructure[5])) + { + return null; + } + $sMailEncodingName = $aBodyStructure[5]; + } + + if (is_numeric($aBodyStructure[6])) + { + $iSize = (int) $aBodyStructure[6]; + } + else + { + $iSize = -1; + } + + if (0 === strlen($sPartID) || '.' === $sPartID[strlen($sPartID) - 1]) + { + // This is the only sub-part of the message (otherwise, it would be + // one of sub-parts of a multi-part, and partID would already be fully set up). + $sPartID .= '1'; + } + + $iExtraItemPos = 7; + if ('text' === $sBodyMainType) + { + if ($iExtraItemPos < count($aBodyStructure)) + { + if (is_numeric($aBodyStructure[$iExtraItemPos])) + { + $iTextLineCount = (int) $aBodyStructure[$iExtraItemPos]; + } + else + { + $iTextLineCount = -1; + } + } + else + { + $iTextLineCount = -1; + } + $iExtraItemPos++; + } + else if ('message' === $sBodyMainType && 'rfc822' === $sBodySubType) + { + if ($iExtraItemPos + 2 < count($aBodyStructure)) + { + if (is_numeric($aBodyStructure[$iExtraItemPos + 2])) + { + $iTextLineCount = (int) $aBodyStructure[$iExtraItemPos + 2]; + } + else + { + $iTextLineCount = -1; + } + } + else + { + $iTextLineCount = -1; + } + + $iExtraItemPos += 3; + } + + $iExtraItemPos++; // skip MD5 digest of the body because most mail servers leave it NIL anyway + } + + $sContentType = $sBodyMainType.'/'.$sBodySubType; + + $sDisposition = null; + $aDispositionParams = null; + $sFileName = null; + + if ($iExtraItemPos < count($aBodyStructure)) + { + $aDispList = $aBodyStructure[$iExtraItemPos]; + if (is_array($aDispList) && 1 < count($aDispList)) + { + if (null !== $aDispList[0]) + { + if (is_string($aDispList[0]) && 'NIL' !== $aDispList[0]) + { + $sDisposition = $aDispList[0]; + } + else + { + return null; + } + } + } + + $aDispParamList = $aDispList[1]; + if (is_array($aDispParamList)) + { + $aDispositionParams = self::getKeyValueListFromArrayList($aDispParamList); + if (is_array($aDispositionParams)) + { + $sFileName = self::decodeAttrParamenter($aDispositionParams, 'filename', $sCharset); + } + } + } + $iExtraItemPos++; + + $sLanguage = null; + if ($iExtraItemPos < count($aBodyStructure)) + { + if (null !== $aBodyStructure[$iExtraItemPos] && 'NIL' !== $aBodyStructure[$iExtraItemPos]) + { + if (is_array($aBodyStructure[$iExtraItemPos])) + { + $sLanguage = implode(',', $aBodyStructure[$iExtraItemPos]); + } + else if (is_string($aBodyStructure[$iExtraItemPos])) + { + $sLanguage = $aBodyStructure[$iExtraItemPos]; + } + } + $iExtraItemPos++; + } + + $sLocation = null; + if ($iExtraItemPos < count($aBodyStructure)) + { + if (null !== $aBodyStructure[$iExtraItemPos] && 'NIL' !== $aBodyStructure[$iExtraItemPos]) + { + if (is_string($aBodyStructure[$iExtraItemPos])) + { + $sLocation = $aBodyStructure[$iExtraItemPos]; + } + } + $iExtraItemPos++; + } + + return new self( + $sContentType, + $sCharset, + $aBodyParams, + $sContentID, + $sDescription, + $sMailEncodingName, + $sDisposition, + $aDispositionParams, + \MailSo\Base\Utils::Utf8Clear( + null === $sFileName || 0 === strlen($sFileName) ? $sName : $sFileName), + $sLanguage, + $sLocation, + $iSize, + $iTextLineCount, + $sPartID, + $aSubParts + ); + } + } + + /** + * @param array $aBodyStructure + * @param string $sPartID + * + * @return \MailSo\Imap\BodyStructure|null + */ + public static function NewInstanceFromRfc822SubPart(array $aBodyStructure, $sSubPartID) + { + $oBody = null; + $aBodySubStructure = self::findPartByIndexInArray($aBodyStructure, $sSubPartID); + if ($aBodySubStructure && is_array($aBodySubStructure) && isset($aBodySubStructure[8])) + { + $oBody = self::NewInstance($aBodySubStructure[8], $sSubPartID); + } + + return $oBody; + } + + /** + * @param array $aList + * @param string $sPartID + * + * @return array|null + */ + private static function findPartByIndexInArray(array $aList, $sPartID) + { + $bFind = false; + $aPath = explode('.', ''.$sPartID); + $aCurrentPart = $aList; + foreach ($aPath as $iPos => $iNum) + { + $iIndex = intval($iNum) - 1; + if (0 <= $iIndex && 0 < $iPos ? isset($aCurrentPart[8][$iIndex]) : isset($aCurrentPart[$iIndex])) + { + $aCurrentPart = 0 < $iPos ? $aCurrentPart[8][$iIndex] : $aCurrentPart[$iIndex]; + $bFind = true; + } + } + + return $bFind ? $aCurrentPart : null; + } + + /** + * Returns dict with key="charset" and value="US-ASCII" for array ("CHARSET" "US-ASCII"). + * Keys are lowercased (StringDictionary itself does this), values are not altered. + * + * @param array $aList + * + * @return array + */ + private static function getKeyValueListFromArrayList(array $aList) + { + $aDict = null; + if (0 === count($aList) % 2) + { + $aDict = array(); + for ($iIndex = 0, $iLen = count($aList); $iIndex < $iLen; $iIndex += 2) + { + if (is_string($aList[$iIndex]) && isset($aList[$iIndex + 1]) && is_string($aList[$iIndex + 1])) + { + $aDict[strtolower($aList[$iIndex])] = $aList[$iIndex + 1]; + } + } + } + + return $aDict; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Enumerations/FetchType.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Enumerations/FetchType.php new file mode 100644 index 000000000..cb5accdb8 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Enumerations/FetchType.php @@ -0,0 +1,119 @@ +aResponses = $aResponses; + } + } + + /** + * @return array + */ + public function GetResponses() + { + return $this->aResponses; + } + + /** + * @return \MailSo\Imap\Response | null + */ + public function GetLastResponse() + { + return 0 < count($this->aResponses) ? $this->aResponses[count($this->aResponses) - 1] : null; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Exceptions/ResponseNotFoundException.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Exceptions/ResponseNotFoundException.php new file mode 100644 index 000000000..c5ec6706e --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Exceptions/ResponseNotFoundException.php @@ -0,0 +1,10 @@ +oImapResponse =& $oImapResponse; + $this->aEnvelopeCache = null; + } + + /** + * @param \MailSo\Imap\Response &$oImapResponse + * @return \MailSo\Imap\FetchResponse + */ + public static function NewInstance(&$oImapResponse) + { + return new self($oImapResponse); + } + + /** + * @param bool $bForce = false + * + * @return array|null + */ + public function GetEnvelope($bForce = false) + { + if (null === $this->aEnvelopeCache || $bForce) + { + $this->aEnvelopeCache = $this->GetFetchValue(Enumerations\FetchType::ENVELOPE); + } + return $this->aEnvelopeCache; + } + + /** + * @param int $iIndex + * @param mixed $mNullResult = null + * + * @return mixed + */ + public function GetFetchEnvelopeValue($iIndex, $mNullResult) + { + return self::findEnvelopeIndex($this->GetEnvelope(), $iIndex, $mNullResult); + } + + /** + * @param int $iIndex + * @param string $sParentCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1 + * + * @return \MailSo\Mime\EmailCollection|null + */ + public function GetFetchEnvelopeEmailCollection($iIndex, $sParentCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1) + { + $oResult = null; + $aEmails = $this->GetFetchEnvelopeValue($iIndex, null); + if (is_array($aEmails) && 0 < count($aEmails)) + { + $oResult = \MailSo\Mime\EmailCollection::NewInstance(); + foreach ($aEmails as $aEmailItem) + { + if (is_array($aEmailItem) && 4 === count($aEmailItem)) + { + $sDisplayName = \MailSo\Base\Utils::DecodeHeaderValue( + self::findEnvelopeIndex($aEmailItem, 0, ''), $sParentCharset); + + $sRemark = \MailSo\Base\Utils::DecodeHeaderValue( + self::findEnvelopeIndex($aEmailItem, 1, ''), $sParentCharset); + + $sLocalPart = self::findEnvelopeIndex($aEmailItem, 2, ''); + $sDomainPart = self::findEnvelopeIndex($aEmailItem, 3, ''); + + if (0 < strlen($sLocalPart) && 0 < strlen($sDomainPart)) + { + $oResult->Add( + \MailSo\Mime\Email::NewInstance( + $sLocalPart.'@'.$sDomainPart, $sDisplayName, $sRemark) + ); + } + } + } + } + + return $oResult; + } + + /** + * @param string $sRfc822SubMimeIndex = '' + * + * @return \MailSo\Imap\BodyStructure|null + */ + public function GetFetchBodyStructure($sRfc822SubMimeIndex = '') + { + $oBodyStructure = null; + $aBodyStructureArray = $this->GetFetchValue(Enumerations\FetchType::BODYSTRUCTURE); + + if (is_array($aBodyStructureArray)) + { + if (0 < strlen($sRfc822SubMimeIndex)) + { + $oBodyStructure = BodyStructure::NewInstanceFromRfc822SubPart($aBodyStructureArray, $sRfc822SubMimeIndex); + } + else + { + $oBodyStructure = BodyStructure::NewInstance($aBodyStructureArray); + } + } + + return $oBodyStructure; + } + + /** + * @param string $sFetchItemName + * + * @return mixed + */ + public function &GetFetchValue($sFetchItemName) + { + $mReturn = null; + $bNextIsValue = false; + + if (Enumerations\FetchType::INDEX === $sFetchItemName) + { + $mReturn =& $this->oImapResponse->ResponseList[1]; + } + else + { + foreach ($this->oImapResponse->ResponseList[3] as &$mItem) + { + if ($bNextIsValue) + { + $mReturn =& $mItem; + break; + } + + if ($sFetchItemName === $mItem) + { + $bNextIsValue = true; + } + } + } + + return $mReturn; + } + + /** + * @param string $sRfc822SubMimeIndex = '' + * + * @return string + */ + public function GetHeaderFieldsValue($sRfc822SubMimeIndex = '') + { + $sReturn = ''; + $bNextIsValue = false; + + $sRfc822SubMimeIndex = 0 < \strlen($sRfc822SubMimeIndex) ? ''.$sRfc822SubMimeIndex.'.' : ''; + + if (isset($this->oImapResponse->ResponseList[3]) && \is_array($this->oImapResponse->ResponseList[3])) + { + foreach ($this->oImapResponse->ResponseList[3] as &$mItem) + { + if ($bNextIsValue) + { + $sReturn = (string) $mItem; + break; + } + + if (\is_string($mItem) && ( + $mItem === 'BODY['.$sRfc822SubMimeIndex.'HEADER]' || + 0 === \strpos($mItem, 'BODY['.$sRfc822SubMimeIndex.'HEADER.FIELDS') || + $mItem === 'BODY['.$sRfc822SubMimeIndex.'MIME]')) + { + $bNextIsValue = true; + } + } + } + + return $sReturn; + } + + /** + * @param \MailSo\Imap\Response $oImapResponse + * + * @return bool + */ + public static function IsValidFetchImapResponse($oImapResponse) + { + return ($oImapResponse && true !== $oImapResponse->IsStatusResponse + && \MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType + && 3 < count($oImapResponse->ResponseList) && 'FETCH' === $oImapResponse->ResponseList[2] + && is_array($oImapResponse->ResponseList[3])); + } + + /** + * @param array $aEnvelope + * @param int $iIndex + * @param mixed $mNullResult = null + * + * @return mixed + */ + private static function findEnvelopeIndex($aEnvelope, $iIndex, $mNullResult) + { + return (isset($aEnvelope[$iIndex]) && 'NIL' !== $aEnvelope[$iIndex] && '' !== $aEnvelope[$iIndex]) + ? $aEnvelope[$iIndex] : $mNullResult; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Folder.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Folder.php new file mode 100644 index 000000000..369422c91 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Folder.php @@ -0,0 +1,175 @@ +sNameRaw = ''; + $this->sFullNameRaw = ''; + $this->sDelimiter = ''; + $this->aFlags = array(); + $this->aExtended = array(); + + $sDelimiter = 'NIL' === \strtoupper($sDelimiter) ? '' : $sDelimiter; + + if (!\is_array($aFlags) || + !\is_string($sDelimiter) || 1 < \strlen($sDelimiter) || + !\is_string($sFullNameRaw) || 0 === \strlen($sFullNameRaw)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->sFullNameRaw = $sFullNameRaw; + $this->sDelimiter = $sDelimiter; + $this->aFlags = $aFlags; + $this->aFlagsLowerCase = \array_map('strtolower', $this->aFlags); + + $this->sFullNameRaw = 'INBOX'.$this->sDelimiter === \substr(\strtoupper($this->sFullNameRaw), 0, 5 + \strlen($this->sDelimiter)) ? + 'INBOX'.\substr($this->sFullNameRaw, 5) : $this->sFullNameRaw; + + if ($this->IsInbox()) + { + $this->sFullNameRaw = 'INBOX'; + } + + $this->sNameRaw = $this->sFullNameRaw; + if (0 < \strlen($this->sDelimiter)) + { + $aNames = \explode($this->sDelimiter, $this->sFullNameRaw); + $this->sNameRaw = \end($aNames); + } + } + + /** + * @param string $sFullNameRaw + * @param string $sDelimiter = '/' + * @param array $aFlags = array() + * + * @return \MailSo\Imap\Folder + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public static function NewInstance($sFullNameRaw, $sDelimiter = '/', $aFlags = array()) + { + return new self($sFullNameRaw, $sDelimiter, $aFlags); + } + + /** + * @return string + */ + public function NameRaw() + { + return $this->sNameRaw; + } + + /** + * @return string + */ + public function FullNameRaw() + { + return $this->sFullNameRaw; + } + + /** + * @return string | null + */ + public function Delimiter() + { + return $this->sDelimiter; + } + + /** + * @return array + */ + public function Flags() + { + return $this->aFlags; + } + + /** + * @return array + */ + public function FlagsLowerCase() + { + return $this->aFlagsLowerCase; + } + + /** + * @return bool + */ + public function IsSelectable() + { + return !\in_array('\noselect', $this->aFlagsLowerCase); + } + + /** + * @return bool + */ + public function IsInbox() + { + return 'INBOX' === \strtoupper($this->sFullNameRaw) || \in_array('\inbox', $this->aFlagsLowerCase); + } + + /** + * @param string $sName + * @param mixed $mData + */ + public function SetExtended($sName, $mData) + { + $this->aExtended[$sName] = $mData; + } + + /** + * @param string $sName + * @return mixed + */ + public function GetExtended($sName) + { + return isset($this->aExtended[$sName]) ? $this->aExtended[$sName] : null; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/FolderInformation.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/FolderInformation.php new file mode 100644 index 000000000..05dd4cc4b --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/FolderInformation.php @@ -0,0 +1,95 @@ +FolderName = $sFolderName; + $this->IsWritable = $bIsWritable; + $this->Exists = null; + $this->Recent = null; + $this->Flags = array(); + $this->PermanentFlags = array(); + + $this->Unread = null; + $this->Uidnext = null; + } + + /** + * @param string $sFolderName + * @param bool $bIsWritable + * + * @return \MailSo\Imap\FolderInformation + */ + public static function NewInstance($sFolderName, $bIsWritable) + { + return new self($sFolderName, $bIsWritable); + } + + /** + * @param string $sFlag + * + * @return bool + */ + public function IsFlagSupported($sFlag) + { + return in_array('\\*', $this->PermanentFlags) || in_array($sFlag, $this->PermanentFlags); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/ImapClient.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/ImapClient.php new file mode 100644 index 000000000..66e9136d6 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/ImapClient.php @@ -0,0 +1,2160 @@ +iTagCount = 0; + $this->aCapabilityItems = null; + $this->oCurrentFolderInfo = null; + $this->aFetchCallbacks = null; + $this->iResponseBufParsedPos = 0; + + $this->aLastResponse = array(); + $this->bNeedNext = true; + $this->aPartialResponses = array(); + + $this->aTagTimeouts = array(); + + $this->bIsLoggined = false; + $this->bIsSelected = false; + $this->sLogginedUser = ''; + + @\ini_set('xdebug.max_nesting_level', 500); + } + + /** + * @return \MailSo\Imap\ImapClient + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @return string + */ + public function GetLogginedUser() + { + return $this->sLogginedUser; + } + + /** + * @param string $sServerName + * @param int $iPort = 143 + * @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function Connect($sServerName, $iPort = 143, + $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT) + { + $this->aTagTimeouts['*'] = microtime(true); + + parent::Connect($sServerName, $iPort, $iSecurityType); + + $this->parseResponseWithValidation('*', true); + + if (\MailSo\Net\Enumerations\ConnectionSecurityType::UseStartTLS( + $this->IsSupported('STARTTLS'), $this->iSecurityType)) + { + $this->SendRequestWithCheck('STARTTLS'); + if (!@stream_socket_enable_crypto($this->rConnect, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) + { + $this->writeLogException( + new \MailSo\Imap\Exceptions\RuntimeException('Cannot enable STARTTLS'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $this->aCapabilityItems = null; + } + else if (\MailSo\Net\Enumerations\ConnectionSecurityType::STARTTLS === $this->iSecurityType) + { + $this->writeLogException( + new \MailSo\Net\Exceptions\SocketUnsuppoterdSecureConnectionException('STARTTLS is not supported'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + return $this; + } + + /** + * @param string $sLogin + * @param string $sPassword + * @param string $sProxyAuthUser = '' + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function Login($sLogin, $sPassword, $sProxyAuthUser = '') + { + if (!\MailSo\Base\Validator::NotEmptyString($sLogin, true) || + !\MailSo\Base\Validator::NotEmptyString($sPassword, true)) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $sLogin = trim($sLogin); + $sPassword = $sPassword; + + $this->sLogginedUser = $sLogin; + + try + { + $this->SendRequestWithCheck('LOGIN', + array( + $this->EscapeString($sLogin), + $this->EscapeString($sPassword) + )); + + if (0 < \strlen($sProxyAuthUser)) + { + $this->SendRequestWithCheck('PROXYAUTH', array($this->EscapeString($sProxyAuthUser))); + } + } + catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException) + { + $this->writeLogException( + new \MailSo\Imap\Exceptions\LoginBadCredentialsException( + $oException->GetResponses(), '', 0, $oException), + \MailSo\Log\Enumerations\Type::NOTICE, true); + } + + $this->bIsLoggined = true; + $this->aCapabilityItems = null; + + return $this; + } + + /** + * @param string $sXOAuth2Token + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function LoginWithXOauth2($sXOAuth2Token) + { + if (!\MailSo\Base\Validator::NotEmptyString($sXOAuth2Token, true)) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + if (!$this->IsSupported('AUTH=XOAUTH2')) + { + $this->writeLogException( + new \MailSo\Imap\Exceptions\LoginBadMethodException(), + \MailSo\Log\Enumerations\Type::NOTICE, true); + } + + try + { + $this->SendRequestWithCheck('AUTHENTICATE', array('XOAUTH2', trim($sXOAuth2Token))); + } + catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException) + { + $this->writeLogException( + new \MailSo\Imap\Exceptions\LoginBadCredentialsException( + $oException->GetResponses(), '', 0, $oException), + \MailSo\Log\Enumerations\Type::NOTICE, true); + } + + $this->bIsLoggined = true; + $this->aCapabilityItems = null; + + return $this; + } + + /** + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Net\Exceptions\Exception + */ + public function Logout() + { + if ($this->bIsLoggined) + { + $this->bIsLoggined = false; + $this->SendRequestWithCheck('LOGOUT', array()); + } + + return $this; + } + + /** + * @return \MailSo\Imap\ImapClient + */ + public function ForceCloseConnection() + { + $this->Disconnect(); + + return $this; + } + + /** + * @return bool + */ + public function IsLoggined() + { + return $this->IsConnected() && $this->bIsLoggined; + } + + /** + * @return bool + */ + public function IsSelected() + { + return $this->IsLoggined() && $this->bIsSelected; + } + + /** + * @return array|null + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function Capability() + { + $this->SendRequestWithCheck('CAPABILITY', array(), true); + return $this->aCapabilityItems; + } + + /** + * @param string $sExtentionName + * @return bool + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function IsSupported($sExtentionName) + { + $bResult = \MailSo\Base\Validator::NotEmptyString($sExtentionName, true); + if ($bResult && null === $this->aCapabilityItems) + { + $this->aCapabilityItems = $this->Capability(); + } + + return $bResult && is_array($this->aCapabilityItems) && + in_array(strtoupper($sExtentionName), $this->aCapabilityItems); + } + + /** + * @return \MailSo\Imap\NamespaceResult|null + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function GetNamespace() + { + if (!$this->IsSupported('NAMESPACE')) + { + return null; + } + + $oReturn = false; + + $this->SendRequest('NAMESPACE'); + $aResult = $this->parseResponseWithValidation(); + + $oImapResponse = null; + foreach ($aResult as /* @var $oImapResponse \MailSo\Imap\Response */ $oImapResponse) + { + if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType && + 'NAMESPACE' === $oImapResponse->StatusOrIndex) + { + $oReturn = NamespaceResult::NewInstance(); + $oReturn->InitByImapResponse($oImapResponse); + break; + } + } + + if (false === $oReturn) + { + $this->writeLogException( + new \MailSo\Imap\Exceptions\ResponseException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + return $oReturn; + } + + /** + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function Noop() + { + return $this->SendRequestWithCheck('NOOP'); + } + + /** + * @param string $sFolderName + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function FolderCreate($sFolderName) + { + return $this->SendRequestWithCheck('CREATE', + array($this->EscapeString($sFolderName))); + } + + /** + * @param string $sFolderName + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function FolderDelete($sFolderName) + { + return $this->SendRequestWithCheck('DELETE', + array($this->EscapeString($sFolderName))); + } + + /** + * @param string $sFolderName + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function FolderSubscribe($sFolderName) + { + return $this->SendRequestWithCheck('SUBSCRIBE', + array($this->EscapeString($sFolderName))); + } + + /** + * @param string $sFolderName + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function FolderUnSubscribe($sFolderName) + { + return $this->SendRequestWithCheck('UNSUBSCRIBE', + array($this->EscapeString($sFolderName))); + } + + /** + * @param string $sOldFolderName + * @param string $sNewFolderName + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function FolderRename($sOldFolderName, $sNewFolderName) + { + return $this->SendRequestWithCheck('RENAME', array( + $this->EscapeString($sOldFolderName), + $this->EscapeString($sNewFolderName))); + } + + /** + * @param array $aResult + * + * @return array + */ + protected function getStatusFolderInformation($aResult) + { + $aReturn = array(); + + if (is_array($aResult)) + { + $oImapResponse = null; + foreach ($aResult as /* @var $oImapResponse \MailSo\Imap\Response */ $oImapResponse) + { + if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType && + 'STATUS' === $oImapResponse->StatusOrIndex && isset($oImapResponse->ResponseList[3]) && + is_array($oImapResponse->ResponseList[3])) + { + $sName = null; + foreach ($oImapResponse->ResponseList[3] as $sArrayItem) + { + if (null === $sName) + { + $sName = $sArrayItem; + } + else + { + $aReturn[$sName] = $sArrayItem; + $sName = null; + } + } + } + } + } + + return $aReturn; + } + + /** + * @param string $sFolderName + * @param array $aStatusItems + * + * @return array|bool + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function FolderStatus($sFolderName, array $aStatusItems) + { + $aResult = false; + if (count($aStatusItems) > 0) + { + $this->SendRequest('STATUS', + array($this->EscapeString($sFolderName), $aStatusItems)); + + $aResult = $this->getStatusFolderInformation( + $this->parseResponseWithValidation()); + } + + return $aResult; + } + + /** + * @param array $aResult + * @param bool $bIsSubscribeList + * + * @return array + */ + private function getFoldersFromResult(array $aResult, $sStatus, $bUseListStatus = false) + { + $aReturn = array(); + + $oImapResponse = null; + foreach ($aResult as /* @var $oImapResponse \MailSo\Imap\Response */ $oImapResponse) + { + if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType && + $sStatus === $oImapResponse->StatusOrIndex && 5 === count($oImapResponse->ResponseList)) + { + try + { + $oFolder = Folder::NewInstance($oImapResponse->ResponseList[4], + $oImapResponse->ResponseList[3], $oImapResponse->ResponseList[2]); + + $aReturn[] = $oFolder; + } + catch (\MailSo\Base\Exceptions\InvalidArgumentException $oException) + { + $this->writeLogException($oException, \MailSo\Log\Enumerations\Type::WARNING, false); + } + } + } + + if ($bUseListStatus) + { + foreach ($aResult as /* @var $oImapResponse \MailSo\Imap\Response */ $oImapResponse) + { + if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType && + 'STATUS' === $oImapResponse->StatusOrIndex && + isset($oImapResponse->ResponseList[2]) && + isset($oImapResponse->ResponseList[3]) && + is_array($oImapResponse->ResponseList[3])) + { + $sFolderNameRaw = $oImapResponse->ResponseList[2]; + + $oCurrentFolder = null; + foreach ($aReturn as &$oFolder) + { + if ($oFolder && $sFolderNameRaw === $oFolder->FullNameRaw()) + { + $oCurrentFolder =& $oFolder; + break; + } + } + + if (null !== $oCurrentFolder) + { + $sName = null; + $aStatus = array(); + foreach ($oImapResponse->ResponseList[3] as $sArrayItem) + { + if (null === $sName) + { + $sName = $sArrayItem; + } + else + { + $aStatus[$sName] = $sArrayItem; + $sName = null; + } + } + + if (0 < count($aStatus)) + { + $oCurrentFolder->SetExtended('STATUS', $aStatus); + } + } + + unset($oCurrentFolder); + } + } + } + + return $aReturn; + } + + /** + * @param bool $bIsSubscribeList + * @param string $sParentFolderName = '' + * @param string $sListPattern = '*' + * + * @return array + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + private function specificFolderList($bIsSubscribeList, $sParentFolderName = '', $sListPattern = '*', $bUseListStatus = false) + { + $sCmd = 'LSUB'; + if (!$bIsSubscribeList) + { + if ($bUseListStatus) + { + $bUseListStatus = $this->IsSupported('LIST-STATUS'); + } + + $sCmd = (!$bUseListStatus && $this->IsSupported('XLIST') && !$this->IsSupported('LIST-EXTENDED')) ? 'XLIST' : 'LIST'; + } + + $sListPattern = 0 === strlen(trim($sListPattern)) ? '*' : $sListPattern; + + $aParameters = array( + $this->EscapeString($sParentFolderName), + $this->EscapeString($sListPattern) + ); + + if ($bUseListStatus) + { + $aParameters[] = 'RETURN'; + $aParameters[] = array( + 'STATUS', + array( + \MailSo\Imap\Enumerations\FolderStatus::MESSAGES, + \MailSo\Imap\Enumerations\FolderStatus::UNSEEN, + \MailSo\Imap\Enumerations\FolderStatus::UIDNEXT + ) + ); + } + + $this->SendRequest($sCmd, $aParameters); + + return $this->getFoldersFromResult( + $this->parseResponseWithValidation(), $sCmd, $bUseListStatus); + } + + /** + * @param string $sParentFolderName = '' + * @param string $sListPattern = '*' + * + * @return array + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function FolderList($sParentFolderName = '', $sListPattern = '*') + { + return $this->specificFolderList(false, $sParentFolderName, $sListPattern); + } + + /** + * @param string $sParentFolderName = '' + * @param string $sListPattern = '*' + * + * @return array + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function FolderSubscribeList($sParentFolderName = '', $sListPattern = '*') + { + return $this->specificFolderList(true, $sParentFolderName, $sListPattern); + } + + /** + * @param string $sParentFolderName = '' + * @param string $sListPattern = '*' + * + * @return array + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function FolderStatusList($sParentFolderName = '', $sListPattern = '*') + { + return $this->specificFolderList(false, $sParentFolderName, $sListPattern, true); + } + + /** + * @param array $aResult + * @param string $sFolderName + * @param bool $bIsWritable + * + * @return void + */ + protected function initCurrentFolderInformation($aResult, $sFolderName, $bIsWritable) + { + if (is_array($aResult)) + { + $oImapResponse = null; + $oResult = FolderInformation::NewInstance($sFolderName, $bIsWritable); + + foreach ($aResult as /* @var $oImapResponse \MailSo\Imap\Response */ $oImapResponse) + { + if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType) + { + if (count($oImapResponse->ResponseList) > 2 && + 'FLAGS' === $oImapResponse->ResponseList[1] && is_array($oImapResponse->ResponseList[2])) + { + $oResult->Flags = $oImapResponse->ResponseList[2]; + } + + if (is_array($oImapResponse->OptionalResponse) && count($oImapResponse->OptionalResponse) > 1) + { + if ('PERMANENTFLAGS' === $oImapResponse->OptionalResponse[0] && + is_array($oImapResponse->OptionalResponse[1])) + { + $oResult->PermanentFlags = $oImapResponse->OptionalResponse[1]; + } + else if ('UIDVALIDITY' === $oImapResponse->OptionalResponse[0] && + isset($oImapResponse->OptionalResponse[1])) + { + $oResult->Uidvalidity = $oImapResponse->OptionalResponse[1]; + } + else if ('UNSEEN' === $oImapResponse->OptionalResponse[0] && + isset($oImapResponse->OptionalResponse[1]) && + is_numeric($oImapResponse->OptionalResponse[1])) + { + $oResult->Unread = (int) $oImapResponse->OptionalResponse[1]; + } + else if ('UIDNEXT' === $oImapResponse->OptionalResponse[0] && + isset($oImapResponse->OptionalResponse[1])) + { + $oResult->Uidnext = $oImapResponse->OptionalResponse[1]; + } + } + + if (count($oImapResponse->ResponseList) > 2 && + is_string($oImapResponse->ResponseList[2]) && + is_numeric($oImapResponse->ResponseList[1])) + { + switch($oImapResponse->ResponseList[2]) + { + case 'EXISTS': + $oResult->Exists = (int) $oImapResponse->ResponseList[1]; + break; + case 'RECENT': + $oResult->Recent = (int) $oImapResponse->ResponseList[1]; + break; + } + } + } + } + + $this->oCurrentFolderInfo = $oResult; + } + } + + /** + * @param string $sFolderName + * @param bool $bIsWritable + * @param bool $bReSelectSameFolders + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + protected function selectOrExamineFolder($sFolderName, $bIsWritable, $bReSelectSameFolders) + { + if (!$bReSelectSameFolders) + { + if ($this->oCurrentFolderInfo && + $sFolderName === $this->oCurrentFolderInfo->FolderName && + $bIsWritable === $this->oCurrentFolderInfo->IsWritable) + { + return $this; + } + } + + if (!\MailSo\Base\Validator::NotEmptyString($sFolderName, true)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->SendRequest(($bIsWritable) ? 'SELECT' : 'EXAMINE', + array($this->EscapeString($sFolderName))); + + $this->initCurrentFolderInformation( + $this->parseResponseWithValidation(), $sFolderName, $bIsWritable); + + $this->bIsSelected = true; + + return $this; + } + + /** + * @param string $sFolderName + * @param bool $bReSelectSameFolders = false + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function FolderSelect($sFolderName, $bReSelectSameFolders = false) + { + return $this->selectOrExamineFolder($sFolderName, true, $bReSelectSameFolders); + } + + /** + * @param string $sFolderName + * @param bool $bReSelectSameFolders = false + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function FolderExamine($sFolderName, $bReSelectSameFolders = false) + { + return $this->selectOrExamineFolder($sFolderName, false, $bReSelectSameFolders); + } + + /** + * @param array $aInputFetchItems + * @param string $sIndexRange + * @param bool $bIndexIsUid + * + * @return array + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function Fetch(array $aInputFetchItems, $sIndexRange, $bIndexIsUid) + { + $sIndexRange = (string) $sIndexRange; + if (!\MailSo\Base\Validator::NotEmptyString($sIndexRange, true)) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $aFetchItems = \MailSo\Imap\Enumerations\FetchType::ChangeFetchItemsBefourRequest($aInputFetchItems); + foreach ($aFetchItems as $sName => $mItem) + { + if (0 < strlen($sName) && '' !== $mItem) + { + if (null === $this->aFetchCallbacks) + { + $this->aFetchCallbacks = array(); + } + + $this->aFetchCallbacks[$sName] = $mItem; + } + } + + $this->SendRequest((($bIndexIsUid) ? 'UID ' : '').'FETCH', array($sIndexRange, array_keys($aFetchItems))); + $aResult = $this->validateResponse($this->parseResponse()); + $this->aFetchCallbacks = null; + + $aReturn = array(); + $oImapResponse = null; + foreach ($aResult as &$oImapResponse) + { + if (FetchResponse::IsValidFetchImapResponse($oImapResponse)) + { + $aReturn[] = FetchResponse::NewInstance($oImapResponse); + } + } + + return $aReturn; + } + + + /** + * @return array|false + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function Quota() + { + $aReturn = false; + if ($this->IsSupported('QUOTA')) + { + $this->SendRequest('GETQUOTAROOT "INBOX"'); + $aResult = $this->parseResponseWithValidation(); + + $aReturn = array(0, 0); + $oImapResponse = null; + foreach ($aResult as /* @var $oImapResponse \MailSo\Imap\Response */ $oImapResponse) + { + if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType + && 'QUOTA' === $oImapResponse->StatusOrIndex + && is_array($oImapResponse->ResponseList) + && isset($oImapResponse->ResponseList[3]) + && is_array($oImapResponse->ResponseList[3]) + && 2 < count($oImapResponse->ResponseList[3]) + && 'STORAGE' === strtoupper($oImapResponse->ResponseList[3][0]) + && is_numeric($oImapResponse->ResponseList[3][1]) + && is_numeric($oImapResponse->ResponseList[3][2]) + ) + { + $aReturn = array( + (int) $oImapResponse->ResponseList[3][1], + (int) $oImapResponse->ResponseList[3][2] + ); + } + } + } + + return $aReturn; + } + + /** + * @param array $aSortTypes + * @param string $sSearchCriterias + * @param bool $bReturnUid + * + * @return array + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageSimpleSort($aSortTypes, $sSearchCriterias = 'ALL', $bReturnUid = true) + { + $sCommandPrefix = ($bReturnUid) ? 'UID ' : ''; + $sSearchCriterias = !\MailSo\Base\Validator::NotEmptyString($sSearchCriterias, true) || '*' === $sSearchCriterias + ? 'ALL' : $sSearchCriterias; + + if (!is_array($aSortTypes) || 0 === count($aSortTypes)) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + else if (!$this->IsSupported('SORT')) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $aRequest = array(); + $aRequest[] = $aSortTypes; + $aRequest[] = \MailSo\Base\Utils::IsAscii($sSearchCriterias) ? 'US-ASCII' : 'UTF-8'; + $aRequest[] = $sSearchCriterias; + + $sCmd = 'SORT'; + + $this->SendRequest($sCommandPrefix.$sCmd, $aRequest); + $aResult = $this->parseResponseWithValidation(); + + $aReturn = array(); + $oImapResponse = null; + foreach ($aResult as /* @var $oImapResponse \MailSo\Imap\Response */ $oImapResponse) + { + if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType + && $sCmd === $oImapResponse->StatusOrIndex + && is_array($oImapResponse->ResponseList) && 2 < count($oImapResponse->ResponseList)) + { + for ($iIndex = 2, $iLen = count($oImapResponse->ResponseList); $iIndex < $iLen; $iIndex++) + { + $aReturn[] = (int) $oImapResponse->ResponseList[$iIndex]; + } + } + } + + $aReturn = array_reverse($aReturn); + return $aReturn; + } + + /** + * @param string $sSearchCriterias + * @param bool $bReturnUid + * @param string $sCharset = '' + * + * @return array + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageSimpleSearch($sSearchCriterias = 'ALL', $bReturnUid = true, $sCharset = '') + { + $sCommandPrefix = ($bReturnUid) ? 'UID ' : ''; + $sSearchCriterias = 0 === strlen($sSearchCriterias) || '*' === $sSearchCriterias + ? 'ALL' : $sSearchCriterias; + + $aRequest = array(); + if (0 < strlen($sCharset)) + { + $aRequest[] = 'CHARSET'; + $aRequest[] = strtoupper($sCharset); + } + + $aRequest[] = $sSearchCriterias; + + $sCmd = 'SEARCH'; + + $this->SendRequest($sCommandPrefix.$sCmd, $aRequest); + $aResult = $this->parseResponseWithValidation(); + + $aReturn = array(); + $oImapResponse = null; + foreach ($aResult as /* @var $oImapResponse \MailSo\Imap\Response */ $oImapResponse) + { + if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType + && $sCmd === $oImapResponse->StatusOrIndex + && is_array($oImapResponse->ResponseList) && 2 < count($oImapResponse->ResponseList)) + { + for ($iIndex = 2, $iLen = count($oImapResponse->ResponseList); $iIndex < $iLen; $iIndex++) + { + $aReturn[] = (int) $oImapResponse->ResponseList[$iIndex]; + } + } + } + + $aReturn = array_reverse($aReturn); + return $aReturn; + } + + /** + * @param mixed $aValue + * + * @return mixed + */ + private function validateThreadItem($aValue) + { + $mResult = false; + if (is_numeric($aValue)) + { + $mResult = (int) $aValue; + } + else if (is_array($aValue)) + { + if (1 === count($aValue) && is_numeric($aValue[0])) + { + $mResult = (int) $aValue[0]; + } + else + { + $mResult = array(); + foreach ($aValue as $aValueItem) + { + $mResult[] = $this->validateThreadItem($aValueItem); + } + } + } + + return $mResult; + } + + /** + * @param string $sSearchCriterias = 'ALL' + * @param bool $bReturnUid = true + * @param string $sCharset = \MailSo\Base\Enumerations\Charset::UTF_8 + * + * @return array + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageSimpleThread($sSearchCriterias = 'ALL', $bReturnUid = true, $sCharset = \MailSo\Base\Enumerations\Charset::UTF_8) + { + $sCommandPrefix = ($bReturnUid) ? 'UID ' : ''; + $sSearchCriterias = !\MailSo\Base\Validator::NotEmptyString($sSearchCriterias, true) || '*' === $sSearchCriterias + ? 'ALL' : $sSearchCriterias; + + $sThreadType = ''; + switch (true) + { + case $this->IsSupported('THREAD=REFS'): + $sThreadType = 'REFS'; + break; + case $this->IsSupported('THREAD=REFERENCES'): + $sThreadType = 'REFERENCES'; + break; + case $this->IsSupported('THREAD=ORDEREDSUBJECT'): + $sThreadType = 'ORDEREDSUBJECT'; + break; + default: + $this->writeLogException( + new Exceptions\RuntimeException('Thread is not supported'), + \MailSo\Log\Enumerations\Type::ERROR, true); + break; + } + + $aRequest = array(); + $aRequest[] = $sThreadType; + $aRequest[] = strtoupper($sCharset); + $aRequest[] = $sSearchCriterias; + + $sCmd = 'THREAD'; + + $this->SendRequest($sCommandPrefix.$sCmd, $aRequest); + $aResult = $this->parseResponseWithValidation(); + + $aReturn = array(); + $oImapResponse = null; + + foreach ($aResult as /* @var $oImapResponse \MailSo\Imap\Response */ $oImapResponse) + { + if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType + && $sCmd === $oImapResponse->StatusOrIndex + && is_array($oImapResponse->ResponseList) && 2 < count($oImapResponse->ResponseList)) + { + for ($iI = 2, $iC = count($oImapResponse->ResponseList); $iI < $iC; $iI++) + { + $aNewValue = $this->validateThreadItem($oImapResponse->ResponseList[$iI]); + if (false !== $aNewValue) + { + $aReturn[] = $aNewValue; + } + } + } + } + + return $aReturn; + } + + /** + * @param string $sToFolder + * @param string $sIndexRange + * @param bool $bIndexIsUid + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageCopy($sToFolder, $sIndexRange, $bIndexIsUid) + { + if (0 === strlen($sIndexRange)) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $sCommandPrefix = ($bIndexIsUid) ? 'UID ' : ''; + return $this->SendRequestWithCheck($sCommandPrefix.'COPY', + array($sIndexRange, $this->EscapeString($sToFolder))); + } + + /** + * @param string $sToFolder + * @param string $sIndexRange + * @param bool $bIndexIsUid + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageMove($sToFolder, $sIndexRange, $bIndexIsUid) + { + if (0 === strlen($sIndexRange)) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + if (!$this->IsSupported('MOVE')) + { + $this->writeLogException( + new Exceptions\RuntimeException('Move is not supported'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $sCommandPrefix = ($bIndexIsUid) ? 'UID ' : ''; + return $this->SendRequestWithCheck($sCommandPrefix.'MOVE', + array($sIndexRange, $this->EscapeString($sToFolder))); + } + + /** + * @param string $sUidRangeIfSupported + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageExpunge($sUidRangeIfSupported = '', $bForceUidExpunge = false) + { + $sUidRangeIfSupported = trim($sUidRangeIfSupported); + + $sCmd = 'EXPUNGE'; + $aArguments = array(); + + if ($bForceUidExpunge && 0 < strlen($sUidRangeIfSupported) && $this->IsSupported('UIDPLUS')) + { + $sCmd = 'UID '.$sCmd; + $aArguments = array($sUidRangeIfSupported); + } + + return $this->SendRequestWithCheck($sCmd, $aArguments); + } + + /** + * @param string $sIndexRange + * @param bool $bIndexIsUid + * @param array $aInputStoreItems + * @param string $sStoreAction + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageStoreFlag($sIndexRange, $bIndexIsUid, $aInputStoreItems, $sStoreAction) + { + if (!\MailSo\Base\Validator::NotEmptyString($sIndexRange, true) || + !\MailSo\Base\Validator::NotEmptyString($sStoreAction, true) || + 0 === count($aInputStoreItems)) + { + return false; + } + + $sCmd = ($bIndexIsUid) ? 'UID STORE' : 'STORE'; + return $this->SendRequestWithCheck($sCmd, + array($sIndexRange, $sStoreAction, $aInputStoreItems)); + } + + /** + * @param string $sFolderName + * @param resource $rMessageAppendStream + * @param int $iStreamSize + * @param array $aAppendFlags = null + * @param int $iUid = null + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageAppendStream($sFolderName, $rMessageAppendStream, $iStreamSize, $aAppendFlags = null, &$iUid = null) + { + $this->SendRequest('APPEND', + array($this->EscapeString($sFolderName), $aAppendFlags, '{'.$iStreamSize.'}')); + + $this->parseResponseWithValidation('+'); + + $this->writeLog('Write to connection stream', \MailSo\Log\Enumerations\Type::NOTE); + + \MailSo\Base\Utils::MultipleStreamWriter($rMessageAppendStream, array($this->rConnect)); + + $this->sendRaw(''); + $this->parseResponseWithValidation(); + + if (null !== $iUid) + { + $aLastResponse = $this->GetLastResponse(); + if (is_array($aLastResponse) && 0 < count($aLastResponse) && $aLastResponse[count($aLastResponse) - 1]) + { + $oLast = $aLastResponse[count($aLastResponse) - 1]; + if ($oLast && \MailSo\Imap\Enumerations\ResponseType::TAGGED === $oLast->ResponseType && is_array($oLast->OptionalResponse)) + { + if (0 < strlen($oLast->OptionalResponse[0]) && + 0 < strlen($oLast->OptionalResponse[2]) && + 'APPENDUID' === strtoupper($oLast->OptionalResponse[0]) && + is_numeric($oLast->OptionalResponse[2]) + ) + { + $iUid = (int) $oLast->OptionalResponse[2]; + } + } + } + } + + return $this; + } + + /** + * @return \MailSo\Imap\FolderInformation + */ + public function FolderCurrentInformation() + { + return $this->oCurrentFolderInfo; + } + + /** + * @param string $sCommand + * @param array $aParams = array() + * + * @return void + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + */ + public function SendRequest($sCommand, $aParams = array()) + { + if (!\MailSo\Base\Validator::NotEmptyString($sCommand, true) || !is_array($aParams)) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $this->IsConnected(true); + + $sTag = $this->getNewTag(); + + $sCommand = trim($sCommand); + $sRealCommand = $sTag.' '.$sCommand.$this->prepearParamLine($aParams); + + $sFakeCommand = ''; + $aFakeParams = $this->secureRequestParams($sCommand, $aParams); + if (null !== $aFakeParams) + { + $sFakeCommand = $sTag.' '.$sCommand.$this->prepearParamLine($aFakeParams); + } + + $this->aTagTimeouts[$sTag] = microtime(true); + $this->sendRaw($sRealCommand, true, $sFakeCommand); + } + + /** + * @param string $sCommand + * @param array $aParams + * + * @return array|null + */ + private function secureRequestParams($sCommand, $aParams) + { + $aResult = null; + switch ($sCommand) + { + case 'LOGIN': + $aResult = $aParams; + if (is_array($aResult) && 2 === count($aResult)) + { + $aResult[1] = '"*******"'; + } + break; + } + + return $aResult; + } + + /** + * @param string $sCommand + * @param array $aParams = array() + * @param bool $bFindCapa = false + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function SendRequestWithCheck($sCommand, $aParams = array(), $bFindCapa = false) + { + $this->SendRequest($sCommand, $aParams); + $this->parseResponseWithValidation(null, $bFindCapa); + + return $this; + } + + /** + * @return array + */ + public function GetLastResponse() + { + return $this->aLastResponse; + } + + /** + * @param mixed $aResult + * + * @return array + * + * @throws \MailSo\Imap\Exceptions\ResponseNotFoundException + * @throws \MailSo\Imap\Exceptions\InvalidResponseException + * @throws \MailSo\Imap\Exceptions\NegativeResponseException + */ + private function validateResponse($aResult) + { + if (!is_array($aResult) || 0 === $iCnt = count($aResult)) + { + $this->writeLogException( + new Exceptions\ResponseNotFoundException(), + \MailSo\Log\Enumerations\Type::WARNING, true); + } + + if ($aResult[$iCnt - 1]->ResponseType !== \MailSo\Imap\Enumerations\ResponseType::CONTINUATION) + { + if (!$aResult[$iCnt - 1]->IsStatusResponse) + { + $this->writeLogException( + new Exceptions\InvalidResponseException($aResult), + \MailSo\Log\Enumerations\Type::WARNING, true); + } + + if (\MailSo\Imap\Enumerations\ResponseStatus::OK !== $aResult[$iCnt - 1]->StatusOrIndex) + { + $this->writeLogException( + new Exceptions\NegativeResponseException($aResult), + \MailSo\Log\Enumerations\Type::WARNING, true); + } + } + + return $aResult; + } + + /** + * @param string $sEndTag = null + * @param bool $bFindCapa = false + * + * @return array|bool + */ + protected function parseResponse($sEndTag = null, $bFindCapa = false) + { + if (is_resource($this->rConnect)) + { + $oImapResponse = null; + $sEndTag = (null === $sEndTag) ? $this->getCurrentTag() : $sEndTag; + while (true) + { + $oImapResponse = Response::NewInstance(); + + $this->partialParseResponseBranch($oImapResponse); + + if ($oImapResponse) + { + if (\MailSo\Imap\Enumerations\ResponseType::UNKNOWN === $oImapResponse->ResponseType) + { + return false; + } + + if ($bFindCapa) + { +// $this->oLogger->WriteDump($oImapResponse); + $this->initCapabilityImapResponse($oImapResponse); + } + + $this->aPartialResponses[] = $oImapResponse; + if ($sEndTag === $oImapResponse->Tag || \MailSo\Imap\Enumerations\ResponseType::CONTINUATION === $oImapResponse->ResponseType) + { + if (isset($this->aTagTimeouts[$sEndTag])) + { + $this->writeLog((microtime(true) - $this->aTagTimeouts[$sEndTag]).' ('.$sEndTag.')', + \MailSo\Log\Enumerations\Type::TIME); + + unset($this->aTagTimeouts[$sEndTag]); + } + + break; + } + } + else + { + return false; + } + + unset($oImapResponse); + } + } + + $this->iResponseBufParsedPos = 0; + $this->aLastResponse = $this->aPartialResponses; + $this->aPartialResponses = array(); + + return $this->aLastResponse; + } + + /** + * @param string $sEndTag = null + * @param bool $bFindCapa = false + * + * @return array + */ + private function parseResponseWithValidation($sEndTag = null, $bFindCapa = false) + { + return $this->validateResponse($this->parseResponse($sEndTag, $bFindCapa)); + } + + /** + * @param \MailSo\Imap\Response $oImapResponse + * + * @return void + */ + private function initCapabilityImapResponse($oImapResponse) + { + if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType + && is_array($oImapResponse->ResponseList)) + { + $aList = null; + if (isset($oImapResponse->ResponseList[1]) && is_string($oImapResponse->ResponseList[1]) && + 'CAPABILITY' === strtoupper($oImapResponse->ResponseList[1])) + { + $aList = array_slice($oImapResponse->ResponseList, 2); + } + else if ($oImapResponse->OptionalResponse && is_array($oImapResponse->OptionalResponse) && + 1 < count($oImapResponse->OptionalResponse) && is_string($oImapResponse->OptionalResponse[0]) && + 'CAPABILITY' === strtoupper($oImapResponse->OptionalResponse[0])) + { + $aList = array_slice($oImapResponse->OptionalResponse, 1); + } + + if (is_array($aList) && 0 < count($aList)) + { + $this->aCapabilityItems = array_map('strtoupper', $aList); + } + } + } + + /** + * @return array|string + * + * @throws \MailSo\Net\Exceptions\Exception + */ + private function partialParseResponseBranch(&$oImapResponse, $iStackIndex = -1, + $bTreatAsAtom = false, $sParentToken = '') + { + $mNull = null; + + $iStackIndex++; + $iPos = $this->iResponseBufParsedPos; + + $sPreviousAtomUpperCase = null; + $bIsEndOfList = false; + $bIsClosingBracketSquare = false; + $iLiteralLen = 0; + $iBufferEndIndex = 0; + + $rImapLiteralStream = null; + + $bIsGotoDefault = false; + $bIsGotoLiteral = false; + $bIsGotoLiteralEnd = false; + $bIsGotoAtomBracket = false; + $bIsGotoNotAtomBracket = false; + + $bCountOneInited = false; + $bCountTwoInited = false; + + $sAtomBuilder = $bTreatAsAtom ? '' : null; + $aList = array(); + if (null !== $oImapResponse) + { + $aList =& $oImapResponse->ResponseList; + } + + while (!$bIsEndOfList) + { + if ($this->bNeedNext) + { + $iPos = 0; + $this->getNextBuffer(); + $this->iResponseBufParsedPos = $iPos; + $this->bNeedNext = false; + } + + $sChar = null; + if ($bIsGotoDefault) + { + $sChar = 'GOTO_DEFAULT'; + $bIsGotoDefault = false; + } + else if ($bIsGotoLiteral) + { + $bIsGotoLiteral = false; + $bIsGotoLiteralEnd = true; + + if ($this->partialResponseLiteralCallbackCallable( + $sParentToken, null === $sPreviousAtomUpperCase ? '' : strtoupper($sPreviousAtomUpperCase), $this->rConnect, $iLiteralLen)) + { + if (!$bTreatAsAtom) + { + $aList[] = ''; + } + } + else + { + $sLiteral = ''; + $iRead = $iLiteralLen; + while (0 < $iRead) + { + $sAddRead = fread($this->rConnect, $iRead); + if (false === $sAddRead) + { + $sLiteral = false; + break; + } + + $sLiteral .= $sAddRead; + $iRead -= strlen($sAddRead); + } + + if (false !== $sLiteral) + { + $iLiteralSize = strlen($sLiteral); + \MailSo\Base\Loader::IncStatistic('NetRead', $iLiteralSize); + if ($iLiteralLen !== $iLiteralSize) + { + $this->writeLog('Literal stream read warning "read '.$iLiteralSize.' of '. + $iLiteralLen.'" bytes', \MailSo\Log\Enumerations\Type::WARNING); + } + + if (!$bTreatAsAtom) + { + $aList[] = $sLiteral; + } + } + else + { + $this->writeLog('Can\'t read imap stream', \MailSo\Log\Enumerations\Type::NOTE); + } + + unset($sLiteral); + } + + continue; + } + else if ($bIsGotoLiteralEnd) + { + $rImapLiteralStream = null; + $sPreviousAtomUpperCase = null; + $this->bNeedNext = true; + $bIsGotoLiteralEnd = false; + + continue; + } + else if ($bIsGotoAtomBracket) + { + if ($bTreatAsAtom) + { + $sAtomBlock = $this->partialParseResponseBranch($mNull, $iStackIndex, true, + null === $sPreviousAtomUpperCase ? '' : strtoupper($sPreviousAtomUpperCase)); + $sAtomBuilder .= $sAtomBlock; + $iPos = $this->iResponseBufParsedPos; + $sAtomBuilder .= ($bIsClosingBracketSquare) ? ']' : ')'; + } + + $sPreviousAtomUpperCase = null; + $bIsGotoAtomBracket = false; + + continue; + } + else if ($bIsGotoNotAtomBracket) + { + $aSubItems = $this->partialParseResponseBranch($mNull, $iStackIndex, false, + null === $sPreviousAtomUpperCase ? '' : strtoupper($sPreviousAtomUpperCase)); + + $aList[] = $aSubItems; + $iPos = $this->iResponseBufParsedPos; + $sPreviousAtomUpperCase = null; + if (null !== $oImapResponse && $oImapResponse->IsStatusResponse) + { + $oImapResponse->OptionalResponse = $aSubItems; + // Got optional response in status response, the rest of the line is human-readable text. + $bIsGotoDefault = true; + $bIsGotoNotAtomBracket = false; + continue; + } + $bIsGotoNotAtomBracket = false; + + continue; + } + else + { + $iBufferEndIndex = strlen($this->sResponseBuffer) - 3; + $this->bResponseBufferChanged = false; + + if ($iPos > $iBufferEndIndex) + { + break; + } + + $sChar = $this->sResponseBuffer[$iPos]; + } + + switch ($sChar) + { + case ']': + case ')': + $iPos++; + $sPreviousAtomUpperCase = null; + $bIsEndOfList = true; + break; + case ' ': + if ($bTreatAsAtom) + { + $sAtomBuilder .= ' '; + } + $iPos++; + break; + case '[': + $bIsClosingBracketSquare = true; + case '(': + if ($bTreatAsAtom) + { + $sAtomBuilder .= ($bIsClosingBracketSquare) ? '[' : '('; + } + $iPos++; + + $this->iResponseBufParsedPos = $iPos; + if ($bTreatAsAtom) + { + $bIsGotoAtomBracket = true; + } + else + { + $bIsGotoNotAtomBracket = true; + } + break; + case '{': + $bIsLiteralParsed = false; + $mLiteralEndPos = strpos($this->sResponseBuffer, '}', $iPos); + if (false !== $mLiteralEndPos && $mLiteralEndPos > $iPos) + { + $sLiteralLenAsString = substr($this->sResponseBuffer, $iPos + 1, $mLiteralEndPos - $iPos - 1); + if (is_numeric($sLiteralLenAsString)) + { + // Detected literal size + $iLiteralLen = (int) $sLiteralLenAsString; + $bIsLiteralParsed = true; + $iPos = $mLiteralEndPos + 3; + $bIsGotoLiteral = true; + break; + } + } + if (!$bIsLiteralParsed) + { + // On error parsing literal, skip the problem place. + $iPos = $iBufferEndIndex; + } + $sPreviousAtomUpperCase = null; + break; + case '"': + $bIsQuotedParsed = false; + while (true) + { + $iClosingPos = $iPos + 1; + if ($iClosingPos > $iBufferEndIndex) + { + // Closing '=' will not fit even if it immediately follows the opening one. + break; + } + + while (true) + { + $iClosingPos = strpos($this->sResponseBuffer, '"', $iClosingPos); + if (false === $iClosingPos) + { + break; + } + + // $iSlashCount will contain the number of back-slashes before closing quote. + $iSlashCount = 0; + while ('\\' === $this->sResponseBuffer[$iClosingPos - $iSlashCount - 1]) + { + $iSlashCount++; + } + + // Even number of back-slashes denotes encoded slashes. Odd number denotes + // zero or more encoded back-slashes and an encoded quote. + if ($iSlashCount % 2 == 1) + { + $iClosingPos++; + // That was encoded quote - \", not actually the end of quoted string. + continue; + } + else + { + break; + } + } + + if (false === $iClosingPos) + { + break; + } + else + { +// $iSkipClosingPos = 0; + $bIsQuotedParsed = true; + if ($bTreatAsAtom) + { + // Quoted string is copied as-is, including quotes. + $sAtomBuilder .= strtr( + substr($this->sResponseBuffer, $iPos, $iClosingPos - $iPos + 1), + array('\\\\' => '\\', '\\"' => '"') + ); + } + else + { + $aList[] = strtr( + substr($this->sResponseBuffer, $iPos + 1, $iClosingPos - $iPos - 1), + array('\\\\' => '\\', '\\"' => '"') + ); + } + + $iPos = $iClosingPos + 1; + break; + } + } + + if (!$bIsQuotedParsed) + { + // On error parsing literal, skip the problem place. + $iPos = $iBufferEndIndex; + } + + $sPreviousAtomUpperCase = null; + break; + + case 'GOTO_DEFAULT': + default: + // Deal with atoms and human-readable text here. + $iCharBlockStartPos = $iPos; + + if (null !== $oImapResponse && $oImapResponse->IsStatusResponse) + { + // In case of status response, any atom after first two atoms (and possibly 1 optional response) + // means human-readable text till the end of line. Special thing about atoms in human-readble + // text is that they are not atoms actually. They can be zero-length and can contain spaces and + // other delimiters. So we do some kind of special processing for them. Thus, we declare everything + // after known atoms and optional response is human-readable text. + $iPos = $iBufferEndIndex; + + while ($iPos > $iCharBlockStartPos && $this->sResponseBuffer[$iCharBlockStartPos] == ' ') + { + // Remove trailing space in the beginning of the human-readable text. + $iCharBlockStartPos++; + } + } + + $bIsAtomDone = false; + while (!$bIsAtomDone && ($iPos <= $iBufferEndIndex)) + { + $sCharDef = $this->sResponseBuffer[$iPos]; + switch ($sCharDef) + { + case '[': + if (null === $sAtomBuilder) + { + // We create StringBuilder only if required. Two cases possible: + // 1) treatAsString mode (atom is StringBuilder from the very beginning) + // 2) we got '[' as non-first symbol in response data + // We could create StringBuilder any time we encounter an atom in response data + // but it would be the waste of resources (most atoms in response data are simple + // char blocks with no special symbols and thus do not require concatenation). + $sAtomBuilder = ''; + } + + // Append BODY[ from BODY[...] response. + $sAtomBuilder .= substr($this->sResponseBuffer, $iCharBlockStartPos, $iPos - $iCharBlockStartPos + 1); + + $iPos++; + $this->iResponseBufParsedPos = $iPos; + + $sListBlock = $this->partialParseResponseBranch($mNull, $iStackIndex, true, + null === $sPreviousAtomUpperCase ? '' : strtoupper($sPreviousAtomUpperCase)); + + if (null !== $sListBlock) + { + $sAtomBuilder .= $sListBlock.']'; + } + + $iPos = $this->iResponseBufParsedPos; + $iCharBlockStartPos = $iPos; + break; + case ' ': + case ']': + case ')': + $bIsAtomDone = true; + break; + default: + $iPos++; + break; + } + } + + // If pos == charBlockStartPos (zero length) and nothing stored in atomBuilder, this means + // we got no human-readable text in status response. In all other cases, pos > charBlockStartPos + // because real atoms are always not empty. + if ($iPos > $iCharBlockStartPos || null !== $sAtomBuilder) + { + $sLastCharBlock = substr($this->sResponseBuffer, $iCharBlockStartPos, $iPos - $iCharBlockStartPos); + if (null === $sAtomBuilder) + { + // When atomBuilder is null, this also means !treatAsAtom. + $aList[] = $sLastCharBlock; +// $this->writeLog($sLastCharBlock); + $sPreviousAtomUpperCase = $sLastCharBlock; + } + else + { + // This case is never top-level case (when response != null). We get here only + // when parsing internals of BODY[...] literals. + $sAtomBuilder .= $sLastCharBlock; + + if (!$bTreatAsAtom) + { + $aList[] = $sAtomBuilder; + $sPreviousAtomUpperCase = $sAtomBuilder; + $sAtomBuilder = null; + } + } + + if (null !== $oImapResponse) + { +// if (1 === count($aList)) + if (!$bCountOneInited && 1 === count($aList)) +// if (isset($aList[0]) && !isset($aList[1])) // fast 1 === count($aList) + { + $bCountOneInited = true; + + $oImapResponse->Tag = $aList[0]; + if ('+' === $oImapResponse->Tag) + { + $oImapResponse->ResponseType = \MailSo\Imap\Enumerations\ResponseType::CONTINUATION; + } + else if ('*' === $oImapResponse->Tag) + { + $oImapResponse->ResponseType = \MailSo\Imap\Enumerations\ResponseType::UNTAGGED; + } + else if ($this->getCurrentTag() === $oImapResponse->Tag) + { + $oImapResponse->ResponseType = \MailSo\Imap\Enumerations\ResponseType::TAGGED; + } + else + { + $oImapResponse->ResponseType = \MailSo\Imap\Enumerations\ResponseType::UNKNOWN; + } + } +// else if (2 === count($aList)) + else if (!$bCountTwoInited && 2 === count($aList)) +// else if (isset($aList[1]) && !isset($aList[2])) // fast 2 === count($aList) + { + $bCountTwoInited = true; + + $oImapResponse->StatusOrIndex = strtoupper($aList[1]); + + if ($oImapResponse->StatusOrIndex == \MailSo\Imap\Enumerations\ResponseStatus::OK || + $oImapResponse->StatusOrIndex == \MailSo\Imap\Enumerations\ResponseStatus::NO || + $oImapResponse->StatusOrIndex == \MailSo\Imap\Enumerations\ResponseStatus::BAD || + $oImapResponse->StatusOrIndex == \MailSo\Imap\Enumerations\ResponseStatus::BYE || + $oImapResponse->StatusOrIndex == \MailSo\Imap\Enumerations\ResponseStatus::PREAUTH) + { + $oImapResponse->IsStatusResponse = true; + } + } + else if (\MailSo\Imap\Enumerations\ResponseType::CONTINUATION === $oImapResponse->ResponseType) + { + $oImapResponse->HumanReadable = $sLastCharBlock; + } + else if ($oImapResponse->IsStatusResponse) + { + $oImapResponse->HumanReadable = $sLastCharBlock; + } + } + } + } + } + + $this->iResponseBufParsedPos = $iPos; + if (null !== $oImapResponse) + { + $this->bNeedNext = true; + $this->iResponseBufParsedPos = 0; + } + + return $bTreatAsAtom ? $sAtomBuilder : $aList; + } + + /** + * @param string $sParent + * @param string $sLiteralAtomUpperCase + * @param resource $rImapStream + * @param int $iLiteralLen + * + * @return bool + */ + private function partialResponseLiteralCallbackCallable($sParent, $sLiteralAtomUpperCase, $rImapStream, $iLiteralLen) + { + $sLiteralAtomUpperCasePeek = ''; + if (0 === strpos($sLiteralAtomUpperCase, 'BODY')) + { + $sLiteralAtomUpperCasePeek = str_replace('BODY', 'BODY.PEEK', $sLiteralAtomUpperCase); + } + + $sFetchKey = ''; + if (is_array($this->aFetchCallbacks)) + { + if (0 < strlen($sLiteralAtomUpperCasePeek) && isset($this->aFetchCallbacks[$sLiteralAtomUpperCasePeek])) + { + $sFetchKey = $sLiteralAtomUpperCasePeek; + } + else if (0 < strlen($sLiteralAtomUpperCase) && isset($this->aFetchCallbacks[$sLiteralAtomUpperCase])) + { + $sFetchKey = $sLiteralAtomUpperCase; + } + } + + $bResult = false; + if (0 < \strlen($sFetchKey) && '' !== $this->aFetchCallbacks[$sFetchKey] && + \is_callable($this->aFetchCallbacks[$sFetchKey])) + { + $rImapLiteralStream = + \MailSo\Base\StreamWrappers\Literal::CreateStream($rImapStream, $iLiteralLen); + + $bResult = true; + $this->writeLog('Callback for '.$sParent.' / '.$sLiteralAtomUpperCase. + ' - try to read '.$iLiteralLen.' bytes.', \MailSo\Log\Enumerations\Type::NOTE); + + \call_user_func($this->aFetchCallbacks[$sFetchKey], + $sParent, $sLiteralAtomUpperCase, $rImapLiteralStream); + + $iTimer = 0; + $iNotReadLiteralLen = 0; + while (!\feof($rImapLiteralStream)) + { + $sBuf = \fread($rImapLiteralStream, 8192); + if (false !== $sBuf) + { + \MailSo\Base\Utils::ResetTimeLimit($iTimer); + $iNotReadLiteralLen += \strlen($sBuf); + continue; + } + break; + } + + if ($iNotReadLiteralLen > 0) + { + $this->writeLog('Not read literal size '.$iNotReadLiteralLen.' bytes.', + \MailSo\Log\Enumerations\Type::WARNING); + } + + \MailSo\Base\Loader::IncStatistic('NetRead', $iLiteralLen); + + if (\is_resource($rImapLiteralStream)) + { + \fclose($rImapLiteralStream); + } + } + + return $bResult; + } + + /** + * @param array $aParams = null + * + * @return string + */ + private function prepearParamLine($aParams = array()) + { + $sReturn = ''; + if (\is_array($aParams) && 0 < \count($aParams)) + { + foreach ($aParams as $mParamItem) + { + if (\is_array($mParamItem) && 0 < \count($mParamItem)) + { + $sReturn .= ' ('.\trim($this->prepearParamLine($mParamItem)).')'; + } + else if (\is_string($mParamItem)) + { + $sReturn .= ' '.$mParamItem; + } + } + } + return $sReturn; + } + + /** + * @return string + */ + private function getNewTag() + { + $this->iTagCount++; + return $this->getCurrentTag(); + } + + /** + * @return string + */ + private function getCurrentTag() + { + return self::TAG_PREFIX.$this->iTagCount; + } + + /** + * @param string $sStringForEscape + * + * @return string + */ + public function EscapeString($sStringForEscape) + { + return '"'.str_replace(array('\\', '"'), array('\\\\', '\\"'), $sStringForEscape).'"'; + } + + /** + * @return string + */ + protected function getLogName() + { + return 'IMAP'; + } + + /** + * @param \MailSo\Log\Logger $oLogger + * + * @return \MailSo\Imap\ImapClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function SetLogger($oLogger) + { + parent::SetLogger($oLogger); + + return $this; + } + + /** + * @param resource $rConnect + * @param array $aCapabilityItems = array() + * + * @return \MailSo\Imap\ImapClient + */ + public function TestSetValues($rConnect, $aCapabilityItems = array()) + { + $this->rConnect = $rConnect; + $this->aCapabilityItems = $aCapabilityItems; + + return $this; + } + + /** + * @param string $sEndTag = null + * @param string $bFindCapa = false + * + * @return array + */ + public function TestParseResponseWithValidationProxy($sEndTag = null, $bFindCapa = false) + { + return $this->parseResponseWithValidation($sEndTag, $bFindCapa); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/NamespaceResult.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/NamespaceResult.php new file mode 100644 index 000000000..a19970c17 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/NamespaceResult.php @@ -0,0 +1,123 @@ +sPersonal = ''; + $this->sPersonalDelimiter = ''; + $this->sOtherUser = ''; + $this->sOtherUserDelimiter = ''; + $this->sShared = ''; + $this->sSharedDelimiter = ''; + } + + /** + * @return \MailSo\Imap\NamespaceResult + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @param \MailSo\Imap\Response $oImapResponse + * + * @return \MailSo\Imap\NamespaceResult + */ + public function InitByImapResponse($oImapResponse) + { + if ($oImapResponse && $oImapResponse instanceof \MailSo\Imap\Response) + { + if (isset($oImapResponse->ResponseList[2][0]) && + \is_array($oImapResponse->ResponseList[2][0]) && + 2 <= \count($oImapResponse->ResponseList[2][0])) + { + $this->sPersonal = $oImapResponse->ResponseList[2][0][0]; + $this->sPersonalDelimiter = $oImapResponse->ResponseList[2][0][1]; + + $this->sPersonal = 'INBOX'.$this->sPersonalDelimiter === \substr(\strtoupper($this->sPersonal), 0, 6) ? + 'INBOX'.$this->sPersonalDelimiter.\substr($this->sPersonal, 6) : $this->sPersonal; + } + + if (isset($oImapResponse->ResponseList[3][0]) && + \is_array($oImapResponse->ResponseList[3][0]) && + 2 <= \count($oImapResponse->ResponseList[3][0])) + { + $this->sOtherUser = $oImapResponse->ResponseList[3][0][0]; + $this->sOtherUserDelimiter = $oImapResponse->ResponseList[3][0][1]; + + $this->sOtherUser = 'INBOX'.$this->sOtherUserDelimiter === \substr(\strtoupper($this->sOtherUser), 0, 6) ? + 'INBOX'.$this->sOtherUserDelimiter.\substr($this->sOtherUser, 6) : $this->sOtherUser; + } + + if (isset($oImapResponse->ResponseList[4][0]) && + \is_array($oImapResponse->ResponseList[4][0]) && + 2 <= \count($oImapResponse->ResponseList[4][0])) + { + $this->sShared = $oImapResponse->ResponseList[4][0][0]; + $this->sSharedDelimiter = $oImapResponse->ResponseList[4][0][1]; + + $this->sShared = 'INBOX'.$this->sSharedDelimiter === \substr(\strtoupper($this->sShared), 0, 6) ? + 'INBOX'.$this->sSharedDelimiter.\substr($this->sShared, 6) : $this->sShared; + } + } + + return $this; + } + + /** + * @return string + */ + public function GetPersonalNamespace() + { + return $this->sPersonal; + } + + /** + * @return string + */ + public function GetPersonalNamespaceDelimiter() + { + return $this->sPersonalDelimiter; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Response.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Response.php new file mode 100644 index 000000000..a2eb768fd --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/Response.php @@ -0,0 +1,67 @@ +ResponseList = array(); + $this->OptionalResponse = null; + $this->StatusOrIndex = ''; + $this->HumanReadable = ''; + $this->IsStatusResponse = false; + $this->ResponseType = \MailSo\Imap\Enumerations\ResponseType::UNKNOWN; + $this->Tag = ''; + } + + /** + * @return \MailSo\Imap\Response + */ + public static function NewInstance() + { + return new self(); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/SearchBuilder.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/SearchBuilder.php new file mode 100644 index 000000000..775899af2 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Imap/SearchBuilder.php @@ -0,0 +1,104 @@ +Clear(); + } + + /** + * @return \MailSo\Imap\SearchBuilder + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @return \MailSo\Imap\SearchBuilder + */ + public function Clear() + { + $this->aList = array(); + return $this; + } + + /** + * @param string $sName + * @param string $sValue = '' + * + * @return \MailSo\Imap\SearchBuilder + */ + public function AddAnd($sName, $sValue = '') + { + return $this->addCri('AND', $sName, $sValue); + } + + /** + * @param string $sName + * @param string $sValue = '' + * + * @return \MailSo\Imap\SearchBuilder + */ + public function AddOr($sName, $sValue = '') + { + return $this->addCri('OR', $sName, $sValue); + } + + /** + * @return string + */ + public function Complete() + { + $sResult = ''; + foreach ($this->aList as $iIndex => $aItem) + { + $sResult = trim((0 < $iIndex && 'OR' === $aItem[0] ? $aItem[0] : ''). + (0 === strlen($sResult) ? '' : ' ('.$sResult.')').' '.$aItem[1]. + (0 < strlen($aItem[2]) ? ' '.$aItem[2] : '')); + } + + if (0 === strlen($sResult)) + { + $sResult = 'ALL'; + } + + return $sResult; + } + + /** + * @return string + */ + public function __toString() + { + return $this->Complete(); + } + + /** + * @param string $sType + * @param string $sName + * @param string $sValue = '' + * + * @return \MailSo\Imap\SearchBuilder + */ + private function addCri($sType, $sName, $sValue = '') + { + $this->aList[] = array($sType, $sName, $sValue); + return $this; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Driver.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Driver.php new file mode 100644 index 000000000..48ba7f398 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Driver.php @@ -0,0 +1,221 @@ +sDatePattern = 'H:i:s'; + $this->sName = 'INFO'; + $this->bTimePrefix = true; + $this->bTypedPrefix = true; + + $this->bWriteOnErrorOnly = false; + $this->bFlushCache = false; + $this->aCache = array(); + + $this->aPrefixes = array( + \MailSo\Log\Enumerations\Type::INFO => '[DATA]', + \MailSo\Log\Enumerations\Type::SECURE => '[SECURE]', + \MailSo\Log\Enumerations\Type::NOTE => '[NOTE]', + \MailSo\Log\Enumerations\Type::TIME => '[TIME]', + \MailSo\Log\Enumerations\Type::MEMORY => '[MEMORY]', + \MailSo\Log\Enumerations\Type::NOTICE => '[NOTICE]', + \MailSo\Log\Enumerations\Type::WARNING => '[WARNING]', + \MailSo\Log\Enumerations\Type::ERROR => '[ERROR]', + ); + } + + /** + * @return \MailSo\Log\Driver + */ + public function DisableTimePrefix() + { + $this->bTimePrefix = false; + return $this; + } + + /** + * @param bool $bValue + * + * @return \MailSo\Log\Driver + */ + public function WriteOnErrorOnly($bValue) + { + $this->bWriteOnErrorOnly = !!$bValue; + return $this; + } + + /** + * @return \MailSo\Log\Driver + */ + public function DisableTypedPrefix() + { + $this->bTypedPrefix = false; + return $this; + } + + /** + * @param string|array $sDesc + * @return bool + */ + abstract protected function writeImplementation($mDesc); + + /** + * @return bool + */ + protected function writeEmptyLineImplementation() + { + return $this->writeImplementation(''); + } + + /** + * @param string $sTimePrefix + * @param string $sDesc + * @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO + * @param array $sName = '' + * + * @return string + */ + protected function loggerLineImplementation($sTimePrefix, $sDesc, + $iDescType = \MailSo\Log\Enumerations\Type::INFO, $sName = '') + { + return ($this->bTimePrefix ? '['.$sTimePrefix.'] ' : ''). + ($this->bTypedPrefix ? $this->getTypedPrefix($iDescType, $sName) : ''). + $sDesc; + } + + /** + * @return bool + */ + protected function clearImplementation() + { + return true; + } + + /** + * @return string + */ + protected function getTimeWithMicroSec() + { + $aMicroTimeItems = \explode(' ', \microtime()); + return \gmdate($this->sDatePattern, $aMicroTimeItems[1]).'.'. + \str_pad((int) ($aMicroTimeItems[0] * 1000), 3, '0', STR_PAD_LEFT); + } + + /** + * @param int $iDescType + * @param string $sName = '' + * + * @return string + */ + protected function getTypedPrefix($iDescType, $sName = '') + { + $sName = 0 < \strlen($sName) ? $sName : $this->sName; + return isset($this->aPrefixes[$iDescType]) ? $sName.$this->aPrefixes[$iDescType].': ' : ''; + } + + /** + * @final + * @param string $sDesc + * @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO + * @param array $sName = '' + * + * @return bool + */ + final public function Write($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO, $sName = '') + { + if ($this->bWriteOnErrorOnly && !$this->bFlushCache) + { + $this->aCache[] = $this->loggerLineImplementation($this->getTimeWithMicroSec(), $sDesc, $iDescType, $sName); + + if (\in_array($iDescType, array( + \MailSo\Log\Enumerations\Type::NOTICE, + \MailSo\Log\Enumerations\Type::WARNING, + \MailSo\Log\Enumerations\Type::ERROR + ))) + { + $this->bFlushCache = true; + return $this->writeImplementation($this->aCache); + } + + return true; + } + + return $this->writeImplementation( + $this->loggerLineImplementation($this->getTimeWithMicroSec(), $sDesc, $iDescType, $sName)); + } + + /** + * @final + * @return bool + */ + final public function Clear() + { + return $this->clearImplementation(); + } + + /** + * @final + * @return void + */ + final public function WriteEmptyLine() + { + if ($this->bWriteOnErrorOnly && !$this->bFlushCache) + { + $this->aCache[] = ''; + } + else + { + $this->writeEmptyLineImplementation(); + } + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Drivers/Callback.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Drivers/Callback.php new file mode 100644 index 000000000..051bef588 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Drivers/Callback.php @@ -0,0 +1,74 @@ +fWriteCallback = \is_callable($fWriteCallback) ? $fWriteCallback : null; + $this->fClearCallback = \is_callable($fClearCallback) ? $fClearCallback : null; + } + + /** + * @param mixed $fWriteCallback + * @param mixed $fClearCallback = null + * + * @return \MailSo\Log\Drivers\Callback + */ + public static function NewInstance($fWriteCallback, $fClearCallback = null) + { + return new self($fWriteCallback, $fClearCallback); + } + + /** + * @param string|array $sDesc + * + * @return bool + */ + protected function writeImplementation($sDesc) + { + if ($this->fWriteCallback) + { + \call_user_func_array($this->fWriteCallback, array($sDesc)); + } + + return true; + } + + /** + * @return bool + */ + protected function clearImplementation() + { + if ($this->fClearCallback) + { + \call_user_func($this->fClearCallback); + } + + return true; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Drivers/File.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Drivers/File.php new file mode 100644 index 000000000..b4d38497b --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Drivers/File.php @@ -0,0 +1,87 @@ +sLoggerFileName = $sLoggerFileName; + $this->sCrLf = $sCrLf; + } + + /** + * @param string $sLoggerFileName + */ + public function SetLoggerFileName($sLoggerFileName) + { + $this->sLoggerFileName = $sLoggerFileName; + } + + /** + * @param string $sLoggerFileName + * @param string $sCrLf = "\r\n" + * + * @return \MailSo\Log\Drivers\File + */ + public static function NewInstance($sLoggerFileName, $sCrLf = "\r\n") + { + return new self($sLoggerFileName, $sCrLf); + } + + /** + * @param string|array $mDesc + * + * @return bool + */ + protected function writeImplementation($mDesc) + { + return $this->writeToLogFile($mDesc); + } + + /** + * @return bool + */ + protected function clearImplementation() + { + return \unlink($this->sLoggerFileName); + } + + /** + * @param string|array $mDesc + * + * @return bool + */ + private function writeToLogFile($mDesc) + { + if (is_array($mDesc)) + { + $mDesc = \implode($this->sCrLf, $mDesc); + } + + return \error_log($mDesc.$this->sCrLf, 3, $this->sLoggerFileName); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Drivers/Inline.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Drivers/Inline.php new file mode 100644 index 000000000..d68a081a7 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Drivers/Inline.php @@ -0,0 +1,85 @@ +sNewLine = $sNewLine; + $this->bHtmlEncodeSpecialChars = $bHtmlEncodeSpecialChars; + } + + /** + * @param string $sNewLine = "\r\n" + * @param bool $bHtmlEncodeSpecialChars = false + * + * @return \MailSo\Log\Drivers\Inline + */ + public static function NewInstance($sNewLine = "\r\n", $bHtmlEncodeSpecialChars = false) + { + return new self($sNewLine, $bHtmlEncodeSpecialChars); + } + + /** + * @param string $mDesc + * + * @return bool + */ + protected function writeImplementation($mDesc) + { + if (is_array($mDesc)) + { + if ($this->bHtmlEncodeSpecialChars) + { + $mDesc = array_map(function ($sItem) { + $sItem = \htmlspecialchars($mDesc); + }, $mDesc); + } + + $mDesc = \implode($this->sNewLine, $mDesc); + } + else + { + echo ($this->bHtmlEncodeSpecialChars) ? \htmlspecialchars($mDesc).$this->sNewLine : $mDesc.$this->sNewLine; + } + + return true; + } + + /** + * @return bool + */ + protected function clearImplementation() + { + if (\defined('PHP_SAPI') && 'cli' === PHP_SAPI) + { + \system('clear'); + } + + return true; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Enumerations/Type.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Enumerations/Type.php new file mode 100644 index 000000000..f46c7964d --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Log/Enumerations/Type.php @@ -0,0 +1,20 @@ +bUsed = false; + $this->aForbiddenTypes = array(); + $this->aSecretWords = array(); + + \register_shutdown_function(array(&$this, '__loggerShutDown')); + } + + /** + * @return \MailSo\Log\Logger + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @staticvar \MailSo\Log\Logger $oInstance; + * + * @return \MailSo\Log\Logger + */ + public static function SingletonInstance() + { + static $oInstance = null; + if (null === $oInstance) + { + $oInstance = self::NewInstance(); + } + + return $oInstance; + } + + /** + * @return bool + */ + public function IsEnabled() + { + return 0 < $this->Count(); + } + + /** + * @param string $sWord + * @return bool + */ + public function AddSecret($sWord) + { + if (0 < \strlen(\trim($sWord))) + { + $this->aSecretWords[] = $sWord; + $this->aSecretWords = array_unique($this->aSecretWords); + } + } + + /** + * @param int $iDescType + * + * @return \MailSo\Log\Logger + */ + public function AddForbiddenType($iType) + { + $this->aForbiddenTypes[$iType] = true; + + return $this; + } + + /** + * @param int $iDescType + * + * @return \MailSo\Log\Logger + */ + public function RemoveForbiddenType($iType) + { + $this->aForbiddenTypes[$iType] = false; + + return $this; + } + + /** + * @return void + */ + public function __loggerShutDown() + { + if ($this->bUsed) + { + $aStatistic = \MailSo\Base\Loader::Statistic(); +// $this->WriteDump($aStatistic, \MailSo\Log\Enumerations\Type::INFO); + if (\is_array($aStatistic) && isset($aStatistic['php']['memory_get_peak_usage'])) + { + $this->Write('Memory peak usage: '.$aStatistic['php']['memory_get_peak_usage'], + \MailSo\Log\Enumerations\Type::MEMORY); + } + } + } + + /** + * @return bool + */ + public function WriteEmptyLine() + { + $iResult = 1; + + $aLoggers =& $this->GetAsArray(); + foreach ($aLoggers as /* @var $oLogger \MailSo\Log\Driver */ &$oLogger) + { + $iResult &= $oLogger->WriteEmptyLine(); + } + + return (bool) $iResult; + } + + /** + * @param string $sDesc + * @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO + * @param string $sName = '' + * @param bool $bSearchWords = false + * + * @return bool + */ + public function Write($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO, $sName = '', $bSearchWords = false) + { + if (isset($this->aForbiddenTypes[$iDescType]) && true === $this->aForbiddenTypes[$iDescType]) + { + return true; + } + + $this->bUsed = true; + + $oLogger = null; + $aLoggers = array(); + $iResult = 1; + + if ($bSearchWords && 0 < \count($this->aSecretWords)) + { + $sDesc = \str_replace($this->aSecretWords, '*******', $sDesc); + } + + $aLoggers =& $this->GetAsArray(); + foreach ($aLoggers as /* @var $oLogger \MailSo\Log\Driver */ $oLogger) + { + $iResult &= $oLogger->Write($sDesc, $iDescType, $sName); + } + + return (bool) $iResult; + } + + /** + * @param mixed $oValue + * @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO + * @param string $sName = '' + * @param bool $bSearchSecretWords = false + * + * @return bool + */ + public function WriteDump($oValue, $iDescType = \MailSo\Log\Enumerations\Type::INFO, $sName = '', $bSearchSecretWords = false) + { + return $this->Write(\print_r($oValue, true), $iDescType, $sName, $bSearchSecretWords); + } + + /** + * @param \Exception $oException + * @param int $iDescType = \MailSo\Log\Enumerations\Type::NOTICE + * @param string $sName = '' + * @param bool $bSearchSecretWords = true + * + * @return bool + */ + public function WriteException($oException, $iDescType = \MailSo\Log\Enumerations\Type::NOTICE, $sName = '', $bSearchSecretWords = true) + { + if ($oException instanceof \Exception) + { + if (isset($oException->__LOGINNED__)) + { + return true; + } + + $oException->__LOGINNED__ = true; + + return $this->Write((string) $oException, $iDescType, $sName, $bSearchSecretWords); + } + + return false; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Attachment.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Attachment.php new file mode 100644 index 000000000..6602f6cd3 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Attachment.php @@ -0,0 +1,182 @@ +Clear(); + } + + /** + * @return \MailSo\Mail\Attachment + */ + public function Clear() + { + $this->sFolder = ''; + $this->iUid = 0; + $this->oBodyStructure = null; + + return $this; + } + + /** + * @return string + */ + public function Folder() + { + return $this->sFolder; + } + + /** + * @return int + */ + public function Uid() + { + return $this->iUid; + } + + /** + * @return string + */ + public function MimeIndex() + { + return $this->oBodyStructure ? $this->oBodyStructure->PartID() : ''; + } + + /** + * @param bool $bCalculateOnEmpty = false + * + * @return string + */ + public function FileName($bCalculateOnEmpty = false) + { + $sFileName = ''; + if ($this->oBodyStructure) + { + $sFileName = $this->oBodyStructure->FileName(); + if ($bCalculateOnEmpty && 0 === \strlen(trim($sFileName))) + { + $sMimeType = \strtolower(\trim($this->MimeType())); + if ('message/rfc822' === $sMimeType) + { + $sFileName = 'message'.$this->MimeIndex().'.eml'; + } + else if ('text/calendar' === $sMimeType) + { + $sFileName = 'calendar'.$this->MimeIndex().'.ics'; + } + else if (0 < \strlen($sMimeType)) + { + $sFileName = \str_replace('/', $this->MimeIndex().'.', $sMimeType); + } + } + } + + return $sFileName; + } + + /** + * @return string + */ + public function MimeType() + { + return $this->oBodyStructure ? $this->oBodyStructure->ContentType() : ''; + } + + /** + * @return string + */ + public function ContentTransferEncoding() + { + return $this->oBodyStructure ? $this->oBodyStructure->MailEncodingName() : ''; + } + + /** + * @return int + */ + public function EncodedSize() + { + return $this->oBodyStructure ? $this->oBodyStructure->Size() : 0; + } + + /** + * @return int + */ + public function EstimatedSize() + { + return $this->oBodyStructure ? $this->oBodyStructure->EstimatedSize() : 0; + } + + /** + * @return string + */ + public function Cid() + { + return $this->oBodyStructure ? $this->oBodyStructure->ContentID() : ''; + } + + /** + * @return bool + */ + public function IsInline() + { + return $this->oBodyStructure ? $this->oBodyStructure->IsInline() : false; + } + + /** + * @return \MailSo\Mail\Attachment + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @param string $sFolder + * @param int $iUid + * @param \MailSo\Imap\BodyStructure $oBodyStructure + * @return \MailSo\Mail\Attachment + */ + public static function NewBodyStructureInstance($sFolder, $iUid, $oBodyStructure) + { + return self::NewInstance()->InitByBodyStructure($sFolder, $iUid, $oBodyStructure); + } + + /** + * @param string $sFolder + * @param int $iUid + * @param \MailSo\Imap\BodyStructure $oBodyStructure + * @return \MailSo\Mail\Attachment + */ + public function InitByBodyStructure($sFolder, $iUid, $oBodyStructure) + { + $this->sFolder = $sFolder; + $this->iUid = $iUid; + $this->oBodyStructure = $oBodyStructure; + return $this; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/AttachmentCollection.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/AttachmentCollection.php new file mode 100644 index 000000000..44a57062a --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/AttachmentCollection.php @@ -0,0 +1,38 @@ +FilterList(function ($oAttachment) { + return $oAttachment && $oAttachment->IsInline(); + }); + + return \is_array($aList) ? \count($aList) : 0; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Exceptions/Exception.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Exceptions/Exception.php new file mode 100644 index 000000000..de488c51e --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Exceptions/Exception.php @@ -0,0 +1,10 @@ +oImapFolder = $oImapFolder; + $this->oSubFolders = null; + + $aNames = \explode($this->oImapFolder->Delimiter(), $this->oImapFolder->FullNameRaw()); + $this->iNestingLevel = \count($aNames); + + $this->sParentFullNameRaw = ''; + if (1 < $this->iNestingLevel) + { + \array_pop($aNames); + $this->sParentFullNameRaw = \implode($this->oImapFolder->Delimiter(), $aNames); + } + + $this->bSubscribed = $bSubscribed; + $this->bExisten = $bExisten; + } + else + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + } + + /** + * @param \MailSo\Imap\Folder $oImapFolder + * @param bool $bSubscribed = true + * @param bool $bExisten = true + * + * @return \MailSo\Mail\Folder + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public static function NewInstance($oImapFolder, $bSubscribed = true, $bExisten = true) + { + return new self($oImapFolder, $bSubscribed, $bExisten); + } + + /** + * @param string $sFullNameRaw + * @param string $sDelimiter + * + * @return \MailSo\Mail\Folder + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public static function NewNonExistenInstance($sFullNameRaw, $sDelimiter) + { + return self::NewInstance( + \MailSo\Imap\Folder::NewInstance($sFullNameRaw, $sDelimiter, array('\NoSelect')), true, false); + } + + /** + * @return string + */ + public function Name() + { + return \MailSo\Base\Utils::ConvertEncoding($this->NameRaw(), + \MailSo\Base\Enumerations\Charset::UTF_7_IMAP, + \MailSo\Base\Enumerations\Charset::UTF_8); + } + + /** + * @return string + */ + public function FullName() + { + return \MailSo\Base\Utils::ConvertEncoding($this->FullNameRaw(), + \MailSo\Base\Enumerations\Charset::UTF_7_IMAP, + \MailSo\Base\Enumerations\Charset::UTF_8); + } + + /** + * @return string + */ + public function NameRaw() + { + return $this->oImapFolder->NameRaw(); + } + + /** + * @return string + */ + public function FullNameRaw() + { + return $this->oImapFolder->FullNameRaw(); + } + + /** + * @return string + */ + public function ParentFullName() + { + return \MailSo\Base\Utils::ConvertEncoding($this->sParentFullNameRaw, + \MailSo\Base\Enumerations\Charset::UTF_7_IMAP, + \MailSo\Base\Enumerations\Charset::UTF_8); + } + + /** + * @return string + */ + public function ParentFullNameRaw() + { + return $this->sParentFullNameRaw; + } + + /** + * @return string + */ + public function Delimiter() + { + return $this->oImapFolder->Delimiter(); + } + + /** + * @return array + */ + public function Flags() + { + return $this->oImapFolder->Flags(); + } + + /** + * @return array + */ + public function FlagsLowerCase() + { + return $this->oImapFolder->FlagsLowerCase(); + } + + /** + * @param bool $bCreateIfNull = false + * @return \MailSo\Mail\FolderCollection + */ + public function SubFolders($bCreateIfNull = false) + { + if ($bCreateIfNull && !$this->oSubFolders) + { + $this->oSubFolders = FolderCollection::NewInstance(); + } + + return $this->oSubFolders; + } + + /** + * @return bool + */ + public function HasSubFolders() + { + return $this->oSubFolders && 0 < $this->oSubFolders->Count(); + } + + /** + * @return bool + */ + public function HasVisibleSubFolders() + { + $sList = array(); + if ($this->oSubFolders) + { + $sList = $this->oSubFolders->FilterList(function (\MailSo\Mail\Folder $oFolder) { + return $oFolder->IsSubscribed(); + }); + } + + return 0 < \count($sList); + } + + /** + * @return bool + */ + public function IsSubscribed() + { + return $this->bSubscribed; + } + + /** + * @return bool + */ + public function IsExisten() + { + return $this->bExisten; + } + + /** + * @return bool + */ + public function IsSelectable() + { + return $this->IsExisten() && $this->oImapFolder->IsSelectable(); + } + + /** + * @return mixed + */ + public function Status() + { + return $this->oImapFolder->GetExtended('STATUS'); + } + + /** + * @return bool + */ + public function IsInbox() + { + return $this->oImapFolder->IsInbox(); + } + + /** + * @return int + */ + public function GetFolderXListType() + { + $aFlags = $this->oImapFolder->FlagsLowerCase(); + $iXListType = \MailSo\Imap\Enumerations\FolderType::USER; + + if (\is_array($aFlags)) + { + switch (true) + { + case \in_array('\inbox', $aFlags): + $iXListType = \MailSo\Imap\Enumerations\FolderType::INBOX; + break; + case \in_array('\sent', $aFlags): + $iXListType = \MailSo\Imap\Enumerations\FolderType::SENT; + break; + case \in_array('\drafts', $aFlags): + $iXListType = \MailSo\Imap\Enumerations\FolderType::DRAFTS; + break; + case \in_array('\spam', $aFlags): + $iXListType = \MailSo\Imap\Enumerations\FolderType::SPAN; + break; + case \in_array('\bin', $aFlags): + case \in_array('\trash', $aFlags): + $iXListType = \MailSo\Imap\Enumerations\FolderType::TRASH; + break; + case \in_array('\important', $aFlags): + $iXListType = \MailSo\Imap\Enumerations\FolderType::IMPORTANT; + break; + case \in_array('\starred', $aFlags): + $iXListType = \MailSo\Imap\Enumerations\FolderType::STARRED; + break; + case \in_array('\all', $aFlags): + case \in_array('\archive', $aFlags): + case \in_array('\allmail', $aFlags): + $iXListType = \MailSo\Imap\Enumerations\FolderType::ALLMAIL; + break; + } + } + + return $iXListType; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/FolderCollection.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/FolderCollection.php new file mode 100644 index 000000000..5f8ebd271 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/FolderCollection.php @@ -0,0 +1,195 @@ +sNamespace = ''; + + $this->FoldersHash = ''; + } + + /** + * @return \MailSo\Mail\FolderCollection + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @param string $sFullNameRaw + * + * @return \MailSo\Mail\Folder|null + */ + public function &GetByFullNameRaw($sFullNameRaw) + { + $mResult = null; + foreach ($this->aItems as /* @var $oFolder \MailSo\Mail\Folder */ $oFolder) + { + if ($oFolder->FullNameRaw() === $sFullNameRaw) + { + $mResult = $oFolder; + break; + } + } + + return $mResult; + } + + /** + * @return string + */ + public function GetNamespace() + { + return $this->sNamespace; + } + + /** + * @param string $sNamespace + * + * @return \MailSo\Mail\FolderCollection + */ + public function SetNamespace($sNamespace) + { + $this->sNamespace = $sNamespace; + + return $this; + } + + /** + * @param array $aUnsortedMailFolders + * + * @return void + */ + public function InitByUnsortedMailFolderArray($aUnsortedMailFolders) + { + $this->Clear(); + + $aSortedByLenImapFolders = array(); + foreach ($aUnsortedMailFolders as /* @var $oMailFolder \MailSo\Mail\Folder */ &$oMailFolder) + { + $aSortedByLenImapFolders[$oMailFolder->FullNameRaw()] =& $oMailFolder; + unset($oMailFolder); + } + unset($aUnsortedMailFolders); + + $aAddedFolders = array(); + foreach ($aSortedByLenImapFolders as /* @var $oMailFolder \MailSo\Mail\Folder */ $oMailFolder) + { + $sDelimiter = $oMailFolder->Delimiter(); + $aFolderExplode = \explode($sDelimiter, $oMailFolder->FullNameRaw()); + + if (1 < \count($aFolderExplode)) + { + \array_pop($aFolderExplode); + + $sNonExistenFolderFullNameRaw = ''; + foreach ($aFolderExplode as $sFolderExplodeItem) + { + $sNonExistenFolderFullNameRaw .= (0 < \strlen($sNonExistenFolderFullNameRaw)) + ? $sDelimiter.$sFolderExplodeItem : $sFolderExplodeItem; + + if (!isset($aSortedByLenImapFolders[$sNonExistenFolderFullNameRaw])) + { + $aAddedFolders[$sNonExistenFolderFullNameRaw] = + Folder::NewNonExistenInstance($sNonExistenFolderFullNameRaw, $sDelimiter); + } + } + } + } + + $aSortedByLenImapFolders = \array_merge($aSortedByLenImapFolders, $aAddedFolders); + unset($aAddedFolders); + + \uasort($aSortedByLenImapFolders, function ($oFolderA, $oFolderB) { + return \strnatcmp($oFolderA->FullNameRaw(), $oFolderB->FullNameRaw()); + }); + + foreach ($aSortedByLenImapFolders as /* @var $oMailFolder \MailSo\Mail\Folder */ &$oMailFolder) + { + $this->AddWithPositionSearch($oMailFolder); + unset($oMailFolder); + } + + unset($aSortedByLenImapFolders); + } + + /** + * @param \MailSo\Mail\Folder $oMailFolder + * + * @return bool + */ + public function AddWithPositionSearch($oMailFolder) + { + $oItemFolder = null; + $bIsAdded = false; + $aList =& $this->GetAsArray(); + + foreach ($aList as /* @var $oItemFolder \MailSo\Mail\Folder */ $oItemFolder) + { + if ($oMailFolder instanceof \MailSo\Mail\Folder && + 0 === \strpos($oMailFolder->FullNameRaw(), $oItemFolder->FullNameRaw().$oItemFolder->Delimiter())) + { + if ($oItemFolder->SubFolders(true)->AddWithPositionSearch($oMailFolder)) + { + $bIsAdded = true; + } + + break; + } + } + + if (!$bIsAdded && $oMailFolder instanceof \MailSo\Mail\Folder) + { + $bIsAdded = true; + $this->Add($oMailFolder); + } + + return $bIsAdded; + } + + /** + * @param callable $fCallback + * + * @return void + */ + public function SortByCallback($fCallback) + { + if (\is_callable($fCallback)) + { + $aList =& $this->GetAsArray(); + + \usort($aList, $fCallback); + + foreach ($aList as &$oItemFolder) + { + if ($oItemFolder->HasSubFolders()) + { + $oItemFolder->SubFolders()->SortByCallback($fCallback); + } + } + } + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/MailClient.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/MailClient.php new file mode 100644 index 000000000..767c2bc94 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/MailClient.php @@ -0,0 +1,1977 @@ +oLogger = null; + + $this->oImapClient = \MailSo\Imap\ImapClient::NewInstance(); + $this->oImapClient->SetTimeOuts(5, 30); + } + + /** + * @return \MailSo\Mail\MailClient + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @param string $sServerName + * @param int $iPort = 143 + * @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT + * + * @return \MailSo\Mail\MailClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function Connect($sServerName, $iPort = 143, + $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT) + { + $this->oImapClient->Connect($sServerName, $iPort, $iSecurityType); + return $this; + } + + /** + * @param string $sLogin + * @param string $sPassword + * @param string $sProxyAuthUser = '' + * + * @return \MailSo\Mail\MailClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\LoginException + */ + public function Login($sLogin, $sPassword, $sProxyAuthUser = '') + { + $this->oImapClient->Login($sLogin, $sPassword, $sProxyAuthUser); + return $this; + } + + /** + * @param string $sXOAuth2Token + * + * @return \MailSo\Mail\MailClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\LoginException + */ + public function LoginWithXOauth2($sXOAuth2Token) + { + $this->oImapClient->LoginWithXOauth2($sXOAuth2Token); + return $this; + } + + /** + * @return \MailSo\Mail\MailClient + * + * @throws \MailSo\Net\Exceptions\Exception + */ + public function Logout() + { + $this->oImapClient->Logout(); + return $this; + } + + /** + * @return \MailSo\Mail\MailClient + * + * @throws \MailSo\Net\Exceptions\Exception + */ + public function Disconnect() + { + $this->oImapClient->Disconnect(); + return $this; + } + + /** + * @return \MailSo\Mail\MailClient + * + * @throws \MailSo\Net\Exceptions\Exception + */ + public function LogoutAndDisconnect() + { + return $this->Logout()->Disconnect(); + } + + /** + * @return bool + */ + public function IsConnected() + { + return $this->oImapClient->IsConnected(); + } + + /** + * @return bool + */ + public function IsLoggined() + { + return $this->oImapClient->IsLoggined(); + } + + /** + * @return string + */ + private function getEnvelopeOrHeadersRequestString() + { +// return \MailSo\Imap\Enumerations\FetchType::ENVELOPE; + + return \MailSo\Imap\Enumerations\FetchType::BODY_HEADER_PEEK; + + return \MailSo\Imap\Enumerations\FetchType::BuildBodyCustomHeaderRequest(array( + \MailSo\Mime\Enumerations\Header::RETURN_PATH, + \MailSo\Mime\Enumerations\Header::RECEIVED, + \MailSo\Mime\Enumerations\Header::MIME_VERSION, + \MailSo\Mime\Enumerations\Header::MESSAGE_ID, + \MailSo\Mime\Enumerations\Header::FROM_, + \MailSo\Mime\Enumerations\Header::TO_, + \MailSo\Mime\Enumerations\Header::CC, + \MailSo\Mime\Enumerations\Header::BCC, + \MailSo\Mime\Enumerations\Header::SENDER, + \MailSo\Mime\Enumerations\Header::REPLY_TO, + \MailSo\Mime\Enumerations\Header::IN_REPLY_TO, + \MailSo\Mime\Enumerations\Header::DATE, + \MailSo\Mime\Enumerations\Header::SUBJECT, + \MailSo\Mime\Enumerations\Header::X_MSMAIL_PRIORITY, + \MailSo\Mime\Enumerations\Header::IMPORTANCE, + \MailSo\Mime\Enumerations\Header::X_PRIORITY, + \MailSo\Mime\Enumerations\Header::CONTENT_TYPE, + \MailSo\Mime\Enumerations\Header::REFERENCES, + \MailSo\Mime\Enumerations\Header::X_DRAFT_INFO, + ), true); + } + + /** + * @param string $sFolderName + * @param string $sMessageFlag + * @param bool $bSetAction = true + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + * @throws \MailSo\Mail\Exceptions\Exception + */ + public function MessageSetFlagToAll($sFolderName, $sMessageFlag, $bSetAction = true) + { + $this->oImapClient->FolderSelect($sFolderName); + + $oFolderInfo = $this->oImapClient->FolderCurrentInformation(); + if (!$oFolderInfo || !$oFolderInfo->IsFlagSupported($sMessageFlag)) + { + throw new \MailSo\Mail\Exceptions\RuntimeException('Message flag is not supported.'); + } + + if (0 < $oFolderInfo->Exists) + { + $sStoreAction = $bSetAction + ? \MailSo\Imap\Enumerations\StoreAction::ADD_FLAGS_SILENT + : \MailSo\Imap\Enumerations\StoreAction::REMOVE_FLAGS_SILENT + ; + + $this->oImapClient->MessageStoreFlag('1:*', false, array($sMessageFlag), $sStoreAction); + } + } + + /** + * @param string $sFolderName + * @param array $aIndexRange + * @param bool $bIndexIsUid + * @param string $sMessageFlag + * @param bool $bSetAction = true + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + * @throws \MailSo\Mail\Exceptions\Exception + */ + public function MessageSetFlag($sFolderName, $aIndexRange, $bIndexIsUid, $sMessageFlag, $bSetAction = true) + { + $this->oImapClient->FolderSelect($sFolderName); + + $oFolderInfo = $this->oImapClient->FolderCurrentInformation(); + if (!$oFolderInfo || !$oFolderInfo->IsFlagSupported($sMessageFlag)) + { + throw new \MailSo\Mail\Exceptions\RuntimeException('Message flag is not supported.'); + } + + $sStoreAction = $bSetAction + ? \MailSo\Imap\Enumerations\StoreAction::ADD_FLAGS_SILENT + : \MailSo\Imap\Enumerations\StoreAction::REMOVE_FLAGS_SILENT + ; + + $sIndexRange = \implode(',', $aIndexRange); + $this->oImapClient->MessageStoreFlag($sIndexRange, $bIndexIsUid, array($sMessageFlag), $sStoreAction); + } + + /** + * @param string $sFolderName + * @param array $aIndexRange + * @param bool $bIndexIsUid + * @param bool $bSetAction = true + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageSetFlagged($sFolderName, $aIndexRange, $bIndexIsUid, $bSetAction = true) + { + $this->MessageSetFlag($sFolderName, $aIndexRange, $bIndexIsUid, + \MailSo\Imap\Enumerations\MessageFlag::FLAGGED, $bSetAction); + } + + /** + * @param string $sFolderName + * @param bool $bSetAction = true + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageSetSeenToAll($sFolderName, $bSetAction = true) + { + $this->MessageSetFlagToAll($sFolderName, \MailSo\Imap\Enumerations\MessageFlag::SEEN, $bSetAction); + } + + /** + * @param string $sFolderName + * @param array $aIndexRange + * @param bool $bIndexIsUid + * @param bool $bSetAction = true + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageSetSeen($sFolderName, $aIndexRange, $bIndexIsUid, $bSetAction = true) + { + $this->MessageSetFlag($sFolderName, $aIndexRange, $bIndexIsUid, + \MailSo\Imap\Enumerations\MessageFlag::SEEN, $bSetAction); + } + + /** + * @param string $sFolderName + * @param string $sFolderHash + * @param string $sUid + * @param mixed $oCacher = null + * + * @return \MailSo\Mail\Message|false + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageThreadInfo($sFolderName, $sFolderHash, $sUid, $oCacher) + { + $aResult = array( + array(), + array() + ); + + $aThreads = $this->MessageListThreadsMap($sFolderName, $sFolderHash, $oCacher); + if (isset($aThreads[$sUid]) && is_array($aThreads[$sUid])) + { + $aResult[0] = $aThreads[$sUid]; + + $oMessageCollection = MessageCollection::NewInstance(); + $oMessageCollection->FolderName = $sFolderName; + $oMessageCollection->FolderHash = $sFolderHash; + $oMessageCollection->Offset = 0; + $oMessageCollection->Limit = 999; + $oMessageCollection->Search = ''; + + $this->MessageListByRequestIndexOrUids($oMessageCollection, $aThreads[$sUid], true); + +// $oMessageCollection->ForeachList(function (/* @var $oMessage \MailSo\Mail\Message */ $oMessage) use ($aThreads) { +// $oMessage->SetThreads(isset($aThreads[$oMessage->Uid()]) && is_array($aThreads[$oMessage->Uid()]) ? +// $aThreads[$oMessage->Uid()] : null); +// }); + + $aResult[1] = $oMessageCollection; + } + + return $aResult; + } + + /** + * @param string $sFolderName + * @param int $iIndex + * @param bool $bIndexIsUid = true + * @param mixed $oCacher = null + * + * @return \MailSo\Mail\Message|false + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function Message($sFolderName, $iIndex, $bIndexIsUid = true, $oCacher = null) + { + if (!\MailSo\Base\Validator::RangeInt($iIndex, 1)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->oImapClient->FolderExamine($sFolderName); + + $oBodyStructure = null; + $oMessage = false; + $aTextMimeIndexes = array(); + + $aFetchResponse = $this->oImapClient->Fetch(array(\MailSo\Imap\Enumerations\FetchType::BODYSTRUCTURE), $iIndex, $bIndexIsUid); + if (0 < \count($aFetchResponse)) + { + $oBodyStructure = $aFetchResponse[0]->GetFetchBodyStructure(); + $aTextParts = $oBodyStructure ? $oBodyStructure->SearchHtmlOrPlainParts() : null; + if (is_array($aTextParts) && 0 < \count($aTextParts)) + { + foreach ($aTextParts as $oPart) + { + $aTextMimeIndexes[] = $oPart->PartID(); + } + } + } + + $aFetchItems = array( + \MailSo\Imap\Enumerations\FetchType::INDEX, + \MailSo\Imap\Enumerations\FetchType::UID, + \MailSo\Imap\Enumerations\FetchType::RFC822_SIZE, + \MailSo\Imap\Enumerations\FetchType::INTERNALDATE, + \MailSo\Imap\Enumerations\FetchType::FLAGS, + $this->getEnvelopeOrHeadersRequestString() + ); + + if (0 < \count($aTextMimeIndexes)) + { + foreach ($aTextMimeIndexes as $sTextMimeIndex) + { + $aFetchItems[] = \MailSo\Imap\Enumerations\FetchType::BODY_PEEK.'['.$sTextMimeIndex.']'; + } + } + + if (!$oBodyStructure) + { + $aFetchItems[] = \MailSo\Imap\Enumerations\FetchType::BODYSTRUCTURE; + } + + $aFetchResponse = $this->oImapClient->Fetch($aFetchItems, $iIndex, $bIndexIsUid); + if (0 < \count($aFetchResponse)) + { + $oMessage = \MailSo\Mail\Message::NewFetchResponseInstance( + $sFolderName, $aFetchResponse[0], $oBodyStructure); + } + + return $oMessage; + } + + /** + * @param mixed $mCallback + * @param string $sFolderName + * @param int $iIndex + * @param bool $bIndexIsUid = true, + * @param string $sMimeIndex = '' + * + * @return bool + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageMimeStream($mCallback, $sFolderName, $iIndex, $bIndexIsUid = true, $sMimeIndex = '') + { + if (!is_callable($mCallback)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->oImapClient->FolderExamine($sFolderName); + + $sFileName = ''; + $sContentType = ''; + $sMailEncodingName = ''; + + $sMimeIndex = trim($sMimeIndex); + $aFetchResponse = $this->oImapClient->Fetch(array( + 0 === \strlen($sMimeIndex) + ? \MailSo\Imap\Enumerations\FetchType::BODY_HEADER_PEEK + : \MailSo\Imap\Enumerations\FetchType::BODY_PEEK.'['.$sMimeIndex.'.MIME]' + ), $iIndex, $bIndexIsUid); + + if (0 < \count($aFetchResponse)) + { + $sMime = $aFetchResponse[0]->GetFetchValue( + 0 === \strlen($sMimeIndex) + ? \MailSo\Imap\Enumerations\FetchType::BODY_HEADER + : \MailSo\Imap\Enumerations\FetchType::BODY.'['.$sMimeIndex.'.MIME]' + ); + + if (0 < \strlen($sMime)) + { + $oHeaders = \MailSo\Mime\HeaderCollection::NewInstance()->Parse($sMime); + + if (0 < \strlen($sMimeIndex)) + { + $sFileName = $oHeaders->ParameterValue( + \MailSo\Mime\Enumerations\Header::CONTENT_DISPOSITION, + \MailSo\Mime\Enumerations\Parameter::FILENAME); + + if (0 === \strlen($sFileName)) + { + $sFileName = $oHeaders->ParameterValue( + \MailSo\Mime\Enumerations\Header::CONTENT_TYPE, + \MailSo\Mime\Enumerations\Parameter::NAME); + } + + $sMailEncodingName = $oHeaders->ValueByName( + \MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING); + + $sContentType = $oHeaders->ValueByName( + \MailSo\Mime\Enumerations\Header::CONTENT_TYPE); + } + else + { + $sSubject = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::SUBJECT); + + $sFileName = 0 === \strlen($sSubject) ? (string) $iIndex : $sSubject; + $sFileName .= '.eml'; + + $sContentType = 'message/rfc822'; + } + } + } + + $aFetchResponse = $this->oImapClient->Fetch(array( + array(\MailSo\Imap\Enumerations\FetchType::BODY_PEEK.'['.$sMimeIndex.']', + function ($sParent, $sLiteralAtomUpperCase, $rImapLiteralStream) use ($mCallback, $sMimeIndex, $sMailEncodingName, $sContentType, $sFileName) + { + if (0 < \strlen($sLiteralAtomUpperCase)) + { + if (is_resource($rImapLiteralStream) && 'FETCH' === $sParent) + { + $rMessageMimeIndexStream = (0 === \strlen($sMailEncodingName)) + ? $rImapLiteralStream + : \MailSo\Base\StreamWrappers\Binary::CreateStream($rImapLiteralStream, + \MailSo\Base\StreamWrappers\Binary::GetInlineDecodeOrEncodeFunctionName( + $sMailEncodingName, true)); + + \call_user_func($mCallback, $rMessageMimeIndexStream, $sContentType, $sFileName, $sMimeIndex); + } + } + } + )), $iIndex, $bIndexIsUid); + + return ($aFetchResponse && 1 === \count($aFetchResponse)); + } + + /** + * @param string $sFolder + * @param array $aIndexRange + * @param bool $bIndexIsUid + * @param bool $bUseExpunge = true + * + * @return \MailSo\Mail\MailClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageDelete($sFolder, $aIndexRange, $bIndexIsUid, $bUseExpunge = true) + { + if (0 === \strlen($sFolder) || !\is_array($aIndexRange) || 0 === \count($aIndexRange)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->oImapClient->FolderSelect($sFolder); + + $sIndexRange = \implode(',', $aIndexRange); + + $this->oImapClient->MessageStoreFlag($sIndexRange, $bIndexIsUid, + array(\MailSo\Imap\Enumerations\MessageFlag::DELETED), + \MailSo\Imap\Enumerations\StoreAction::ADD_FLAGS_SILENT + ); + + if ($bUseExpunge) + { + $this->oImapClient->MessageExpunge($bIndexIsUid ? $sIndexRange : '', $bIndexIsUid); + } + + return $this; + } + + /** + * @param string $sFromFolder + * @param string $sToFolder + * @param array $aIndexRange + * @param bool $bIndexIsUid + * @param bool $bUseMoveSupported = false + * + * @return \MailSo\Mail\MailClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageMove($sFromFolder, $sToFolder, $aIndexRange, $bIndexIsUid, $bUseMoveSupported = false) + { + if (0 === \strlen($sFromFolder) || 0 === \strlen($sToFolder) || + !\is_array($aIndexRange) || 0 === \count($aIndexRange)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->oImapClient->FolderSelect($sFromFolder); + + if ($bUseMoveSupported && $this->oImapClient->IsSupported('MOVE')) + { + $this->oImapClient->MessageMove($sToFolder, \implode(',', $aIndexRange), $bIndexIsUid); + } + else + { + $this->oImapClient->MessageCopy($sToFolder, \implode(',', $aIndexRange), $bIndexIsUid); + $this->MessageDelete($sFromFolder, $aIndexRange, $bIndexIsUid, true); + } + + return $this; + } + + /** + * @param resource $rMessageStream + * @param int $iMessageStreamSize + * @param string $sFolderToSave + * @param array $aAppendFlags = null + * @param int $iUid = null + * + * @return \MailSo\Mail\MailClient + */ + public function MessageAppendStream($rMessageStream, $iMessageStreamSize, $sFolderToSave, $aAppendFlags = null, &$iUid = null) + { + if (!\is_resource($rMessageStream) || 0 === \strlen($sFolderToSave)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->oImapClient->MessageAppendStream( + $sFolderToSave, $rMessageStream, $iMessageStreamSize, $aAppendFlags, $iUid); + + return $this; + } + + /** + * @param string $sMessageFileName + * @param string $sFolderToSave + * @param array $aAppendFlags = null + * @param int &$iUid = null + * + * @return \MailSo\Mail\MailClient + */ + public function MessageAppendFile($sMessageFileName, $sFolderToSave, $aAppendFlags = null, &$iUid = null) + { + if (!@\is_file($sMessageFileName) || !@\is_readable($sMessageFileName)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $iMessageStreamSize = \filesize($sMessageFileName); + $rMessageStream = \fopen($sMessageFileName, 'rb'); + + $this->MessageAppendStream($rMessageStream, $iMessageStreamSize, $sFolderToSave, $aAppendFlags, $iUid); + + if (\is_resource($rMessageStream)) + { + @fclose($rMessageStream); + } + + return $this; + } + + /** + * @param string $sFolderName + * @param int $iCount + * @param int $iUnseenCount + * @param string $sUidNext + * + * @return void + */ + protected function initFolderValues($sFolderName, &$iCount, &$iUnseenCount, &$sUidNext) + { + $aFolderStatus = $this->oImapClient->FolderStatus($sFolderName, array( + \MailSo\Imap\Enumerations\FolderResponseStatus::MESSAGES, + \MailSo\Imap\Enumerations\FolderResponseStatus::UNSEEN, + \MailSo\Imap\Enumerations\FolderResponseStatus::UIDNEXT + )); + + $iCount = isset($aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::MESSAGES]) + ? (int) $aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::MESSAGES] : 0; + + $iUnseenCount = isset($aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::UNSEEN]) + ? (int) $aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::UNSEEN] : 0; + + $sUidNext = isset($aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::UIDNEXT]) + ? (string) $aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::UIDNEXT] : '0'; + } + + /** + * @param string $sFolder + * @param int $iCount + * @param int $iUnseenCount + * @param string $sUidNext + * + * @return string + */ + public static function GenerateHash($sFolder, $iCount, $iUnseenCount, $sUidNext) + { + $iUnseenCount = 0; + return \md5($sFolder.'-'.$iCount.'-'.$iUnseenCount.'-'.$sUidNext); + } + + /** + * @param string $sFolderName + * @param string $sPrevUidNext + * @param string $sCurrentUidNext + * + * @return array + */ + private function getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sCurrentUidNext) + { + $aNewMessages = array(); + + if (0 < \strlen($sPrevUidNext) && (string) $sPrevUidNext !== (string) $sCurrentUidNext) + { + $this->oImapClient->FolderExamine($sFolderName); + + $aFetchResponse = $this->oImapClient->Fetch(array( + \MailSo\Imap\Enumerations\FetchType::INDEX, + \MailSo\Imap\Enumerations\FetchType::UID, + \MailSo\Imap\Enumerations\FetchType::FLAGS, + \MailSo\Imap\Enumerations\FetchType::BuildBodyCustomHeaderRequest(array( + \MailSo\Mime\Enumerations\Header::FROM_, + \MailSo\Mime\Enumerations\Header::SUBJECT, + \MailSo\Mime\Enumerations\Header::CONTENT_TYPE + )) + ), $sPrevUidNext.':*', true); + + if (\is_array($aFetchResponse) && 0 < \count($aFetchResponse)) + { + foreach ($aFetchResponse as /* @var $oFetchResponse \MailSo\Imap\FetchResponse */ $oFetchResponse) + { + $aFlags = \array_map('strtolower', $oFetchResponse->GetFetchValue( + \MailSo\Imap\Enumerations\FetchType::FLAGS)); + + if (\in_array(\strtolower(\MailSo\Imap\Enumerations\MessageFlag::RECENT), $aFlags) && + !\in_array(\strtolower(\MailSo\Imap\Enumerations\MessageFlag::SEEN), $aFlags)) + { + $sUid = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::UID); + $sHeaders = $oFetchResponse->GetHeaderFieldsValue(); + + $oHeaders = \MailSo\Mime\HeaderCollection::NewInstance()->Parse($sHeaders); + + $sContentTypeCharset = $oHeaders->ParameterValue( + \MailSo\Mime\Enumerations\Header::CONTENT_TYPE, + \MailSo\Mime\Enumerations\Parameter::CHARSET + ); + + $sCharset = ''; + if (0 < \strlen($sContentTypeCharset)) + { + $sCharset = $sContentTypeCharset; + } + + if (0 < \strlen($sCharset)) + { + $oHeaders->SetParentCharset(\MailSo\Base\Enumerations\Charset::ISO_8859_1); + } + + $aNewMessages[] = array( + 'Folder' => $sFolderName, + 'Uid' => $sUid, + 'Subject' => $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::SUBJECT), + 'From' => $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::FROM_) + ); + } + } + } + } + + return $aNewMessages; + } + + /** + * @param string $sFolderName + * @param string $sPrevUidNext = '' + * @param array $aUids = '' + * + * @return string + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function FolderInformation($sFolderName, $sPrevUidNext = '', $aUids = array()) + { + $aFlags = array(); + if (\is_array($aUids) && 0 < \count($aUids)) + { + $this->oImapClient->FolderExamine($sFolderName); + + $aFetchResponse = $this->oImapClient->Fetch(array( + \MailSo\Imap\Enumerations\FetchType::INDEX, + \MailSo\Imap\Enumerations\FetchType::UID, + \MailSo\Imap\Enumerations\FetchType::FLAGS + ), \implode(',', $aUids), true); + + if (\is_array($aFetchResponse) && 0 < \count($aFetchResponse)) + { + foreach ($aFetchResponse as $oFetchResponse) + { + $sUid = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::UID); + $aFlags[(\is_numeric($sUid) ? (int) $sUid : 0)] = + $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::FLAGS); + } + } + } + + $iCount = 0; + $iUnseenCount = 0; + $sUidNext = '0'; + + $this->initFolderValues($sFolderName, $iCount, $iUnseenCount, $sUidNext); + + $aResult = array( + 'Folder' => $sFolderName, + 'Hash' => self::GenerateHash($sFolderName, $iCount, $iUnseenCount, $sUidNext), + 'MessageCount' => $iCount, + 'MessageUnseenCount' => $iUnseenCount, + 'UidNext' => $sUidNext, + 'Flags' => $aFlags, + 'NewMessages' => 'INBOX' === $sFolderName ? $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext) : array() + ); + + return $aResult; + } + + /** + * @param string $sFolderName + * + * @return string + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function FolderHash($sFolderName) + { + $iCount = 0; + $iUnseenCount = 0; + $sUidNext = '0'; + + $this->initFolderValues($sFolderName, $iCount, $iUnseenCount, $sUidNext); + + return self::GenerateHash($sFolderName, $iCount, $iUnseenCount, $sUidNext); + } + + /** + * @param string $sSearch + * + * @return string + */ + private function escapeSearchString($sSearch) + { + return ('ssl://imap.gmail.com' === \strtolower($this->oImapClient->GetConnectedHost())) // gmail + ? '{'.\strlen($sSearch).'+}'."\r\n".$sSearch + : $this->oImapClient->EscapeString($sSearch); + } + + /** + * @param string $sDate + * @param int $iTimeZoneOffset + * + * @return int + */ + private function parseSearchDate($sDate, $iTimeZoneOffset) + { + $iResult = 0; + if (0 < \strlen($sDate)) + { + $oDateTime = \DateTime::createFromFormat('Y.m.d', $sDate, \MailSo\Base\DateTimeHelper::GetUtcTimeZoneObject()); + return $oDateTime ? $oDateTime->getTimestamp() - $iTimeZoneOffset : 0; + } + + return $iResult; + } + + /** + * @param string $sSearch + * + * @return array + */ + private function parseSearchString($sSearch) + { + $aResult = array( + 'OTHER' => '' + ); + + $aCache = array(); + + $sSearch = \trim(\preg_replace('/[\s]+/', ' ', $sSearch)); + $sSearch = \trim(\preg_replace('/(e?mail|from|to|subject|has|date|text|body): /i', '\\1:', $sSearch)); + + $mMatch = array(); + \preg_match_all('/".*?(? $sName) + { + if (isset($mMatch[2][$iIndex]) && 0 < \strlen($mMatch[2][$iIndex])) + { + $sName = \strtoupper($sName); + $sValue = $mMatch[2][$iIndex]; + switch ($sName) + { + case 'TEXT': + case 'BODY': + case 'EMAIL': + case 'MAIL': + case 'FROM': + case 'TO': + case 'SUBJECT': + case 'HAS': + case 'DATE': + if ('MAIL' === $sName) + { + $sName = 'EMAIL'; + } + $aResult[$sName] = $sValue; + break; + } + } + } + } + + $aResult['OTHER'] = $sSearch; + foreach ($aResult as $sName => $sValue) + { + if (isset($aCache[$sValue])) + { + $aResult[$sName] = \trim($aCache[$sValue], '"\' '); + } + } + + return $aResult; + } + + /** + * @param string $sSearch + * @param int $iTimeZoneOffset = 0 + * + * @return \MailSo\Imap\SearchBuilder + */ + private function getSearchBuilder($sSearch, $iTimeZoneOffset = 0) + { + $oSearchBuilder = \MailSo\Imap\SearchBuilder::NewInstance(); + if (0 < \strlen(\trim($sSearch))) + { + $aLines = $this->parseSearchString($sSearch); + + if (1 === \count($aLines) && isset($aLines['OTHER'])) + { + if (true) + { + $sValue = $this->escapeSearchString($aLines['OTHER']); + + $oSearchBuilder->AddOr('FROM', $sValue); + $oSearchBuilder->AddOr('TO', $sValue); + $oSearchBuilder->AddOr('CC', $sValue); + $oSearchBuilder->AddOr('SUBJECT', $sValue); + } + else + { + $oSearchBuilder->AddAnd('TEXT', $this->escapeSearchString($aLines['OTHER'])); + } + } + else + { + if (isset($aLines['EMAIL'])) + { + $sValue = $this->escapeSearchString($aLines['EMAIL']); + + $oSearchBuilder->AddOr('FROM', $sValue); + $oSearchBuilder->AddOr('TO', $sValue); + $oSearchBuilder->AddOr('CC', $sValue); + unset($aLines['EMAIL']); + } + + if (isset($aLines['TO'])) + { + $sValue = $this->escapeSearchString($aLines['TO']); + + $oSearchBuilder->AddAnd('TO', $this->escapeSearchString($aLines['TO'])); + $oSearchBuilder->AddOr('CC', $this->escapeSearchString($aLines['TO'])); + unset($aLines['TO']); + } + + $sMainText = ''; + foreach ($aLines as $sName => $sRawValue) + { + if ('' === \trim($sRawValue)) + { + continue; + } + + $sValue = $this->escapeSearchString($sRawValue); + switch ($sName) + { + case 'FROM': + $oSearchBuilder->AddAnd('FROM', $sValue); + break; + case 'SUBJECT': + $oSearchBuilder->AddAnd('SUBJECT', $sValue); + break; + case 'OTHER': + case 'BODY': + case 'TEXT': + $sMainText .= ' '.$sRawValue; + break; + case 'HAS': + if (false !== \strpos($sRawValue, 'attach')) + { + $oSearchBuilder->AddAnd('HEADER CONTENT-TYPE', '"MULTIPART/MIXED"'); + } +// if (false !== strpos($sRawValue, 'flag')) +// { +// $oSearchBuilder->AddAnd('FLAGGED'); +// } +// if (false !== strpos($sRawValue, 'unseen')) +// { +// $oSearchBuilder->AddAnd('UNSEEN'); +// } + break; + case 'DATE': + $iDateStampFrom = $iDateStampTo = 0; + + $sDate = $sRawValue; + $aDate = \explode('/', $sDate); + + if (\is_array($aDate) && 2 === \count($aDate)) + { + if (0 < \strlen($aDate[0])) + { + $iDateStampFrom = $this->parseSearchDate($aDate[0], $iTimeZoneOffset); + } + + if (0 < \strlen($aDate[1])) + { + $iDateStampTo = $this->parseSearchDate($aDate[1], $iTimeZoneOffset); + $iDateStampTo += 60 * 60 * 24; + } + } + else + { + if (0 < \strlen($sDate)) + { + $iDateStampFrom = $this->parseSearchDate($sDate, $iTimeZoneOffset); + $iDateStampTo = $iDateStampFrom + 60 * 60 * 24; + } + } + + if (0 < $iDateStampFrom) + { + $oSearchBuilder->AddAnd('SINCE', \gmdate('j-M-Y', $iDateStampFrom)); + } + + if (0 < $iDateStampTo) + { + $oSearchBuilder->AddAnd('BEFORE', \gmdate('j-M-Y', $iDateStampTo)); + } + break; + } + } + + if ('' !== trim($sMainText)) + { + $sMainText = trim(trim(preg_replace('/[\s]+/', ' ', $sMainText)), '"'); + $oSearchBuilder->AddAnd('TEXT', $this->escapeSearchString($sMainText)); + } + } + } + + return $oSearchBuilder; + } + + /** + * @param array $aThreads + * @return array + */ + private function threadArrayReverseRec($aThreads) + { + $aThreads = \array_reverse($aThreads); + foreach ($aThreads as &$mItem) + { + if (\is_array($mItem)) + { + $mItem = $this->threadArrayReverseRec($mItem); + } + } + return $aThreads; + } + + /** + * @param array $aThreads + * @return array + */ + private function threadArrayMap($aThreads) + { + $aNew = array(); + foreach ($aThreads as $mItem) + { + if (!\is_array($mItem)) + { + $aNew[] = $mItem; + } + else + { + $mMap = $this->threadArrayMap($mItem); + if (\is_array($mMap) && 0 < \count($mMap)) + { + $aNew = \array_merge($aNew, $mMap); + } + } + } + + \sort($aNew, SORT_NUMERIC); + return $aNew; + } + + /** + * @param array $aThreads + * @param array $aLastCollapsedThreadUids + * @param array $aExpandedThreadsUids = array() + * @param int|null $mLimit = null + * + * @return array + */ + private function compileLineThreadUids($aThreads, &$aLastCollapsedThreadUids, $aExpandedThreadsUids = array(), $mLimit = null) + { + $aResult = array(); + $aLastCollapsedThreadUids = array(); + $aExpandedThreadsUids = is_array($aExpandedThreadsUids) ? $aExpandedThreadsUids : array(); + $bUseLimit = \is_int($mLimit); + + foreach ($aThreads as $iParentUid => $mItem) + { + if (\is_array($mItem)) + { + $aResult[] = $iParentUid; + + $iLocalLimit = $mLimit; + foreach ($mItem as $iIndex => $mSubItem) + { + if (!\is_array($mSubItem)) + { + if (!$bUseLimit || in_array($iParentUid, $aExpandedThreadsUids)) + { + $aResult[] = $mSubItem; + } + else if (0 < $mLimit && 0 < $iLocalLimit--) + { + $aResult[] = $mSubItem; + if (0 === $iLocalLimit && $iIndex + 1 < count($mItem)) + { + $aLastCollapsedThreadUids[] = $mSubItem; + break; + } + } + else if (0 === $mLimit) + { + $aLastCollapsedThreadUids[] = $iParentUid; + break; + } + } + } + } + else + { + $aResult[] = $iParentUid; + } + } + + return $aResult; + } + + /** + * @param array $aThreads + * + * @return array + */ + private function compileThreadArray($aThreads) + { + $aThreads = $this->threadArrayReverseRec($aThreads); + + $aResult = array(); + foreach ($aThreads as $mItem) + { + if (\is_array($mItem)) + { + $aMap = $this->threadArrayMap($mItem); + if (\is_array($aMap)) + { + if (1 < \count($aMap)) + { + $iMax = array_pop($aMap); + \rsort($aMap, SORT_NUMERIC); + $aResult[(int) $iMax] = $aMap; + } + else if (0 < \count($aMap)) + { + $aResult[(int) $aMap[0]] = $aMap[0]; + } + } + } + else + { + $aResult[(int) $mItem] = $mItem; + } + } + + \krsort($aResult, SORT_NUMERIC); + return $aResult; + } + + /** + * @param string $sFolderName + * @param string $sFolderHash + * @param mixed $oCacher + * + * @return array + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageListThreadsMap($sFolderName, $sFolderHash, $oCacher) + { + if ($oCacher && $oCacher->IsInited()) + { + $sSerializedHash = + 'ThreadsMap/'. + $this->oImapClient->GetLogginedUser().'@'. + $this->oImapClient->GetConnectedHost().':'. + $this->oImapClient->GetConnectedPort().'/'. + $sFolderName.'/'.$sFolderHash; + + $sSerializedUids = $oCacher->Get($sSerializedHash); + if (!empty($sSerializedUids)) + { + $aSerializedUids = @\unserialize($sSerializedUids); + if (is_array($aSerializedUids)) + { + return $aSerializedUids; + } + } + } + + $this->oImapClient->FolderExamine($sFolderName); + + $aThreadUids = array(); + try + { + $aThreadUids = $this->oImapClient->MessageSimpleThread(); + } + catch (\MailSo\Imap\Exceptions\RuntimeException $oException) + { + $aThreadUids = array(); + } + + $aResult = $this->compileThreadArray($aThreadUids); + + if ($oCacher && $oCacher->IsInited() && !empty($sSerializedHash)) + { + $oCacher->Set($sSerializedHash, serialize($aResult)); + } + + return $aResult; + } + + /** + * @param \MailSo\Mail\MessageCollection &$oMessageCollection + * @param array $aRequestIndexOrUids + * @param bool $bIndexAsUid + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageListByRequestIndexOrUids(&$oMessageCollection, $aRequestIndexOrUids, $bIndexAsUid) + { + if (\is_array($aRequestIndexOrUids) && 0 < \count($aRequestIndexOrUids)) + { + $aFetchResponse = $this->oImapClient->Fetch(array( + \MailSo\Imap\Enumerations\FetchType::INDEX, + \MailSo\Imap\Enumerations\FetchType::UID, + \MailSo\Imap\Enumerations\FetchType::RFC822_SIZE, + \MailSo\Imap\Enumerations\FetchType::INTERNALDATE, + \MailSo\Imap\Enumerations\FetchType::FLAGS, + \MailSo\Imap\Enumerations\FetchType::BODYSTRUCTURE, + $this->getEnvelopeOrHeadersRequestString() + ), \implode(',', $aRequestIndexOrUids), $bIndexAsUid); + + if (\is_array($aFetchResponse) && 0 < \count($aFetchResponse)) + { + $aFetchIndexArray = array(); + $oFetchResponseItem = null; + foreach ($aFetchResponse as /* @var $oFetchResponseItem \MailSo\Imap\FetchResponse */ &$oFetchResponseItem) + { + $aFetchIndexArray[($bIndexAsUid) + ? $oFetchResponseItem->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::UID) + : $oFetchResponseItem->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::INDEX)] =& $oFetchResponseItem; + + unset($oFetchResponseItem); + } + + foreach ($aRequestIndexOrUids as $iFUid) + { + if (isset($aFetchIndexArray[$iFUid])) + { + $oMessageCollection->Add( + Message::NewFetchResponseInstance( + $oMessageCollection->FolderName, $aFetchIndexArray[$iFUid])); + } + } + } + } + } + + /** + * @param string $sFolderName + * @param int $iOffset = 0 + * @param int $iLimit = 10 + * @param string $sSearch = '' + * @param string $sPrevUidNext = '' + * @param mixed $oCacher = null + * @param string $sCachePrefix = '' + * @param bool $bUseSortIfSupported = false + * @param bool $bUseThreadSortIfSupported = false + * @param array $aExpandedThreadsUids = array() + * + * @return \MailSo\Mail\MessageCollection + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageList($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '', + $oCacher = null, $bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $aExpandedThreadsUids = array()) + { + $sSearch = \trim($sSearch); + if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) || + !\MailSo\Base\Validator::RangeInt($iLimit, 0, 999) || + !is_string($sSearch)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->oImapClient->FolderExamine($sFolderName); + + $oMessageCollection = MessageCollection::NewInstance(); + $oMessageCollection->FolderName = $sFolderName; + $oMessageCollection->Offset = $iOffset; + $oMessageCollection->Limit = $iLimit; + $oMessageCollection->Search = $sSearch; + + $aLastCollapsedThreadUids = array(); + + $aThreads = array(); + $iMessageCount = 0; + $iMessageRealCount = 0; + $iMessageUnseenCount = 0; + $sUidNext = '0'; + $sSerializedHash = ''; + $bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false; + $bUseThreadSortIfSupported = $bUseThreadSortIfSupported ? + ($this->oImapClient->IsSupported('THREAD=REFS') || $this->oImapClient->IsSupported('THREAD=REFERENCES') || $this->oImapClient->IsSupported('THREAD=ORDEREDSUBJECT')) : false; + + if (!$oCacher || !($oCacher instanceof \MailSo\Cache\CacheClient)) + { + $oCacher = null; + } + + $this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); + $iMessageCount = $iMessageRealCount; + + $oMessageCollection->FolderHash = self::GenerateHash($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); + $oMessageCollection->UidNext = $sUidNext; + $oMessageCollection->NewMessages = $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext); + + $bCacher = false; + $bSearch = false; + + if (0 < $iMessageRealCount) + { + $bIndexAsUid = false; + $aIndexOrUids = array(); + + $bSearch = 0 < \strlen($sSearch); + + if ($bSearch || ($bUseSortIfSupported && !$bUseThreadSortIfSupported)) + { + $bIndexAsUid = true; + + $aIndexOrUids = null; + + $sSearchCriterias = $this->getSearchBuilder($sSearch)->Complete(); + + if ($oCacher && $oCacher->IsInited()) + { + $sSerializedHash = + ($bUseSortIfSupported ? 'S': 'N').'/'. + ($bUseThreadSortIfSupported ? 'T': 'N').'/'. + $this->oImapClient->GetLogginedUser().'@'. + $this->oImapClient->GetConnectedHost().':'. + $this->oImapClient->GetConnectedPort().'/'. + $oMessageCollection->FolderName.'/'. + $oMessageCollection->FolderHash.'/'. + $sSearchCriterias; + + $sSerializedUids = $oCacher->Get($sSerializedHash); + if (!empty($sSerializedUids)) + { + $aSerializedUids = @\unserialize($sSerializedUids); + if (\is_array($aSerializedUids)) + { + $aIndexOrUids = $aSerializedUids; + $bCacher = true; + } + } + } + + if (!\is_array($aIndexOrUids)) + { + if ($bUseSortIfSupported && !$bUseThreadSortIfSupported) + { + $aIndexOrUids = $this->oImapClient->MessageSimpleSort(array('ARRIVAL'), $sSearchCriterias, $bIndexAsUid); + } + else + { + if (!\MailSo\Base\Utils::IsAscii($sSearch)) + { + try + { + $aIndexOrUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid, 'UTF-8'); + } + catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException) + { + $oException = null; + $aIndexOrUids = null; + } + } + + if (null === $aIndexOrUids) + { + $aIndexOrUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid); + } + } + } + } + else + { + if ($bUseThreadSortIfSupported && 1 < $iMessageCount) + { + $bIndexAsUid = true; + $aThreads = $this->MessageListThreadsMap( + $oMessageCollection->FolderName, + $oMessageCollection->FolderHash, + $oCacher); + + $aIndexOrUids = $this->compileLineThreadUids($aThreads, $aLastCollapsedThreadUids, $aExpandedThreadsUids, 0); + $iMessageCount = count($aIndexOrUids); + } + else + { + $bIndexAsUid = false; + $aIndexOrUids = array(1); + if (1 < $iMessageCount) + { + $aIndexOrUids = \array_reverse(\range(1, $iMessageCount)); + } + } + } + + if ($bIndexAsUid && !$bCacher && \is_array($aIndexOrUids) && $oCacher && $oCacher->IsInited() && 0 < \strlen($sSerializedHash)) + { + $oCacher->Set($sSerializedHash, \serialize($aIndexOrUids)); + } + + if (\is_array($aIndexOrUids)) + { + $oMessageCollection->MessageCount = $iMessageRealCount; + $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; + $oMessageCollection->MessageResultCount = 0 === \strlen($sSearch) + ? $iMessageCount : \count($aIndexOrUids); + + if (0 < count($aIndexOrUids)) + { + $iOffset = (0 > $iOffset) ? 0 : $iOffset; + $aRequestIndexOrUids = \array_slice($aIndexOrUids, $iOffset, $iLimit); + + $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestIndexOrUids, $bIndexAsUid); + } + } + } + + $aLastCollapsedThreadUidsForPage = array(); + + if (!$bSearch && $bUseThreadSortIfSupported && 0 < \count($aThreads)) + { + $oMessageCollection->ForeachList(function (/* @var $oMessage \MailSo\Mail\Message */ $oMessage) use ( + $aThreads, $aLastCollapsedThreadUids, &$aLastCollapsedThreadUidsForPage) + { + $iUid = $oMessage->Uid(); + if (in_array($iUid, $aLastCollapsedThreadUids)) + { + $aLastCollapsedThreadUidsForPage[] = $iUid; + } + + if (isset($aThreads[$iUid]) && \is_array($aThreads[$iUid]) && 0 < \count($aThreads[$iUid])) + { + $oMessage->SetThreads($aThreads[$iUid]); + $oMessage->SetThreadsLen(\count($aThreads[$iUid])); + } + else if (!isset($aThreads[$iUid])) + { + foreach ($aThreads as $iKeyUid => $mSubItem) + { + if (is_array($mSubItem) && in_array($iUid, $mSubItem)) + { + $oMessage->SetParentThread($iKeyUid); + $oMessage->SetThreadsLen(\count($mSubItem)); + } + } + } + }); + + $oMessageCollection->LastCollapsedThreadUids = $aLastCollapsedThreadUidsForPage; + } + + return $oMessageCollection; + } + + /** + * @param array $aList + * @param int $iUid + * @return array | null + */ + private function findMessageTreadUidsRec($aList, $iUid, $bRoot = false) + { + $mResult = null; + foreach ($aList as $mItem) + { + if (\is_array($mItem)) + { + $mResult = $this->findMessageTreadUidsRec($mItem, $iUid); + if (\is_array($mResult)) + { + break; + } + } + else if ((int) $mItem === (int) $iUid) + { + $mResult = $bRoot ? null : $aList; + break; + } + } + + return $mResult; + } + + /** + * @param array $aThreadUids + * @param int $iUid + * @return array | null + */ + public function GetMessageTreadUids($aThreadUids, $iUid) + { + return $this->findMessageTreadUidsRec($aThreadUids, $iUid, true); + } + + /** + * @return array|false + */ + public function Quota() + { + return $this->oImapClient->Quota(); + } + + /** + * @param string $sFolderName + * @param string $sMessageId + * + * @return int|null + */ + public function FindMessageUidByMessageId($sFolderName, $sMessageId) + { + if (0 === \strlen($sMessageId)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->oImapClient->FolderExamine($sFolderName); + + $sSearchCriterias = \MailSo\Imap\SearchBuilder::NewInstance() + ->AddAnd('HEADER MESSAGE-ID', $sMessageId) + ->Complete(); + + $aUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, true); + + return \is_array($aUids) && 1 === \count($aUids) && \is_numeric($aUids[0]) ? (int) $aUids[0] : null; + } + + /** + * @param string $sParent = '' + * @param string $sListPattern = '*' + * @param bool $bUseListStatus = false + * + * @return \MailSo\Mail\FolderCollection|false + */ + public function Folders($sParent = '', $sListPattern = '*', $bUseListStatus = false) + { + $oFolderCollection = false; + + $aFolders = $this->oImapClient->FolderList($sParent, $sListPattern); + $aSubscribedFolders = $this->oImapClient->FolderSubscribeList($sParent, $sListPattern); + + $mStatusFolders = null; + if ($bUseListStatus) + { + $mStatusFolders = $this->oImapClient->FolderStatusList($sParent, $sListPattern); + } + + $aImapSubscribedFoldersHelper = array(); + if (\is_array($aSubscribedFolders)) + { + foreach ($aSubscribedFolders as /* @var $oImapFolder \MailSo\Imap\Folder */ $oImapFolder) + { + $aImapSubscribedFoldersHelper[] = $oImapFolder->FullNameRaw(); + } + } + + $aMailFoldersHelper = null; + if (\is_array($aFolders)) + { + $aMailFoldersHelper = array(); + + foreach ($aFolders as /* @var $oImapFolder \MailSo\Imap\Folder */ $oImapFolder) + { + $aMailFoldersHelper[] = Folder::NewInstance($oImapFolder, + \in_array($oImapFolder->FullNameRaw(), $aImapSubscribedFoldersHelper) || $oImapFolder->IsInbox() + ); + } + } + + if (\is_array($aMailFoldersHelper)) + { + $oFolderCollection = FolderCollection::NewInstance(); + $oFolderCollection->InitByUnsortedMailFolderArray($aMailFoldersHelper); + } + + if ($oFolderCollection) + { + $oFolderCollection->SortByCallback(function ($oFolderA, $oFolderB) { + $sA = \strtoupper($oFolderA->FullNameRaw()); + $sB = \strtoupper($oFolderB->FullNameRaw()); + switch (true) + { + case 'INBOX' === $sA: + return -1; + case 'INBOX' === $sB: + return 1; + case '[GMAIL]' === $sA: + return -1; + case '[GMAIL]' === $sB: + return 1; + } + + return \strnatcmp($oFolderA->FullName(), $oFolderB->FullName()); + }); + + $oNamespace = $this->oImapClient->GetNamespace(); + if ($oNamespace) + { + $oFolderCollection->SetNamespace($oNamespace->GetPersonalNamespace()); + } + } + + return $oFolderCollection; + } + + /** + * @param string $sFolderName = '' + * + * @return \MailSo\Mail\FolderCollection|false + */ + public function FoldersLevel($sFolderName = '', $sDelimiter = '/') + { + $oFolderCollection = false; + + $sFolderLevel = 0 === \strlen($sFolderName) ? '' : $sFolderName.$sDelimiter; + + $aFolders = $this->oImapClient->FolderList($sFolderLevel, '%'); + $aSubscribedFolders = $this->oImapClient->FolderSubscribeList($sFolderLevel, '%'); + + $aSubFolders = $this->oImapClient->FolderList($sFolderLevel, '%/%'); + $aSubSubscribedFolders = $this->oImapClient->FolderSubscribeList($sFolderLevel, '%/%'); + + $aImapSubscribedFoldersHelper = array(); + if (\is_array($aSubscribedFolders)) + { + foreach ($aSubscribedFolders as /* @var $oImapFolder \MailSo\Imap\Folder */ $oImapFolder) + { + $aImapSubscribedFoldersHelper[] = $oImapFolder->FullNameRaw(); + } + } + if (\is_array($aSubSubscribedFolders)) + { + foreach ($aSubSubscribedFolders as /* @var $oImapFolder \MailSo\Imap\Folder */ $oImapFolder) + { + $aImapSubscribedFoldersHelper[] = $oImapFolder->FullNameRaw(); + } + } + + $aMailFoldersHelper = null; + if (\is_array($aFolders)) + { + $aMailFoldersHelper = array(); + + foreach ($aFolders as /* @var $oImapFolder \MailSo\Imap\Folder */ $oImapFolder) + { + $aMailFoldersHelper[] = Folder::NewInstance($oImapFolder, + in_array($oImapFolder->FullNameRaw(), $aImapSubscribedFoldersHelper) || $oImapFolder->IsInbox() + ); + } + } + + if (\is_array($aMailFoldersHelper) && \is_array($aSubFolders)) + { + foreach ($aSubFolders as /* @var $oImapFolder \MailSo\Imap\Folder */ $oImapFolder) + { + $aMailFoldersHelper[] = Folder::NewInstance($oImapFolder, + \in_array($oImapFolder->FullNameRaw(), $aImapSubscribedFoldersHelper) || $oImapFolder->IsInbox() + ); + } + } + + if (\is_array($aMailFoldersHelper)) + { + $oFolderCollection = FolderCollection::NewInstance(); + $oFolderCollection->InitByUnsortedMailFolderArray($aMailFoldersHelper); + } + + if (0 < \strlen($sFolderLevel) && $oFolderCollection) + { + $oLevelFolder = $oFolderCollection->GetByFullNameRaw($sFolderName); + if ($oLevelFolder && $oLevelFolder->HasSubFolders()) + { + $oFolderCollection = $oLevelFolder->SubFolders(); + } + else + { + $oFolderCollection = false; + } + } + + return $oFolderCollection; + } + + /** + * @param string $sFolderNameInUtf + * @param string $sFolderParentFullNameRaw = '' + * @param bool $bSubscribeOnCreation = true + * + * @return \MailSo\Mail\MailClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function FolderCreate($sFolderNameInUtf, $sFolderParentFullNameRaw = '', $bSubscribeOnCreation = true) + { + if (!\MailSo\Base\Validator::NotEmptyString($sFolderNameInUtf, true) || + !\is_string($sFolderParentFullNameRaw)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $sFolderNameInUtf = trim($sFolderNameInUtf); + + $aFolders = $this->oImapClient->FolderList('', 0 === \strlen(\trim($sFolderParentFullNameRaw)) ? 'INBOX' : $sFolderParentFullNameRaw); + if (!\is_array($aFolders) || !isset($aFolders[0])) + { + // TODO + throw new \MailSo\Mail\Exceptions\RuntimeException( + 0 === \strlen(trim($sFolderParentFullNameRaw)) + ? 'Cannot get folder delimiter' + : 'Cannot create folder in non-existen parent folder'); + } + + $sDelimiter = $aFolders[0]->Delimiter(); + if (0 < \strlen($sDelimiter) && 0 < \strlen(\trim($sFolderParentFullNameRaw))) + { + $sFolderParentFullNameRaw .= $sDelimiter; + } + + $sFullNameRawToCreate = \MailSo\Base\Utils::ConvertEncoding($sFolderNameInUtf, + \MailSo\Base\Enumerations\Charset::UTF_8, + \MailSo\Base\Enumerations\Charset::UTF_7_IMAP); + + if (0 < \strlen($sDelimiter) && false !== \strpos($sFullNameRawToCreate, $sDelimiter)) + { + // TODO + throw new \MailSo\Mail\Exceptions\RuntimeException( + 'New folder name contain delimiter'); + } + + $sFullNameRawToCreate = $sFolderParentFullNameRaw.$sFullNameRawToCreate; + + $this->oImapClient->FolderCreate($sFullNameRawToCreate); + + if ($bSubscribeOnCreation) + { + $this->oImapClient->FolderSubscribe($sFullNameRawToCreate); + } + + return $this; + } + + /** + * @param string $sPrevFolderFullNameRaw + * @param string $sNewTopFolderNameInUtf + * + * @return \MailSo\Mail\MailClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function FolderRename($sPrevFolderFullNameRaw, $sNewTopFolderNameInUtf) + { + if (0 === \strlen($sPrevFolderFullNameRaw) || 0 === \strlen($sNewTopFolderNameInUtf)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $aFolders = $this->oImapClient->FolderList('', $sPrevFolderFullNameRaw); + if (!\is_array($aFolders) || !isset($aFolders[0])) + { + // TODO + throw new \MailSo\Mail\Exceptions\RuntimeException('Cannot rename non-existen folder'); + } + + $sDelimiter = $aFolders[0]->Delimiter(); + $iLast = \strrpos($sPrevFolderFullNameRaw, $sDelimiter); + $sFolderParentFullNameRaw = false === $iLast ? '' : \substr($sPrevFolderFullNameRaw, 0, $iLast + 1); + + $aSubscribeFolders = $this->oImapClient->FolderSubscribeList($sPrevFolderFullNameRaw, '*'); + if (\is_array($aSubscribeFolders) && 0 < count($aSubscribeFolders)) + { + foreach ($aSubscribeFolders as /* @var $oFolder \MailSo\Imap\Folder */ $oFolder) + { + $this->oImapClient->FolderUnSubscribe($oFolder->FullNameRaw()); + } + } + + $sNewFolderFullNameRaw = \MailSo\Base\Utils::ConvertEncoding($sNewTopFolderNameInUtf, + \MailSo\Base\Enumerations\Charset::UTF_8, + \MailSo\Base\Enumerations\Charset::UTF_7_IMAP); + + if (0 < \strlen($sDelimiter) && false !== \strpos($sNewFolderFullNameRaw, $sDelimiter)) + { + // TODO + throw new \MailSo\Mail\Exceptions\RuntimeException( + 'New folder name contain delimiter'); + } + + $sNewFolderFullNameRaw = $sFolderParentFullNameRaw.$sNewFolderFullNameRaw; + + $this->oImapClient->FolderRename($sPrevFolderFullNameRaw, $sNewFolderFullNameRaw); + + if (\is_array($aSubscribeFolders) && 0 < count($aSubscribeFolders)) + { + foreach ($aSubscribeFolders as /* @var $oFolder \MailSo\Imap\Folder */ $oFolder) + { + $sFolderFullNameRawForResubscrine = $oFolder->FullNameRaw(); + if (0 === \strpos($sFolderFullNameRawForResubscrine, $sPrevFolderFullNameRaw)) + { + $sNewFolderFullNameRawForResubscrine = $sNewFolderFullNameRaw. + \substr($sFolderFullNameRawForResubscrine, \strlen($sPrevFolderFullNameRaw)); + + $this->oImapClient->FolderSubscribe($sNewFolderFullNameRawForResubscrine); + } + } + } + + return $this; + } + + /** + * @param string $sFolderFullNameRaw + * @param bool $bUnsubscribeOnDeletion = true + * + * @return \MailSo\Mail\MailClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Mail\Exceptions\RuntimeException + */ + public function FolderDelete($sFolderFullNameRaw, $bUnsubscribeOnDeletion = true) + { + if (0 === \strlen($sFolderFullNameRaw) || 'INBOX' === $sFolderFullNameRaw) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->oImapClient->FolderExamine($sFolderFullNameRaw); + + $aIndexOrUids = $this->oImapClient->MessageSimpleSearch('ALL'); + if (0 < \count($aIndexOrUids)) + { + throw new \MailSo\Mail\Exceptions\NonEmptyFolder(); + } + + $this->oImapClient->FolderExamine('INBOX'); + + if ($bUnsubscribeOnDeletion) + { + $this->oImapClient->FolderUnSubscribe($sFolderFullNameRaw); + } + + $this->oImapClient->FolderDelete($sFolderFullNameRaw); + + return $this; + } + + /** + * @param string $sFolderFullNameRaw + * + * @return \MailSo\Mail\MailClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function FolderClear($sFolderFullNameRaw) + { + $this->oImapClient->FolderSelect($sFolderFullNameRaw); + + $oFolderInformation = $this->oImapClient->FolderCurrentInformation(); + if ($oFolderInformation && 0 < $oFolderInformation->Exists) // STATUS? + { + $this->oImapClient->MessageStoreFlag('1:*', false, + array(\MailSo\Imap\Enumerations\MessageFlag::DELETED), + \MailSo\Imap\Enumerations\StoreAction::ADD_FLAGS_SILENT + ); + + $this->oImapClient->MessageExpunge(); + } + + return $this; + } + + /** + * @param string $sFolderFullNameRaw + * @param bool $bSubscribe + * + * @return \MailSo\Mail\MailClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function FolderSubscribe($sFolderFullNameRaw, $bSubscribe) + { + if (0 === \strlen($sFolderFullNameRaw)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->oImapClient->{($bSubscribe) ? 'FolderSubscribe' : 'FolderUnSubscribe'}($sFolderFullNameRaw); + + return $this; + } + + /** + * @param \MailSo\Log\Logger $oLogger + * + * @return \MailSo\Mail\MailClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function SetLogger($oLogger) + { + if (!($oLogger instanceof \MailSo\Log\Logger)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->oLogger = $oLogger; + $this->oImapClient->SetLogger($this->oLogger); + + return $this; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Message.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Message.php new file mode 100644 index 000000000..18a7d3619 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/Message.php @@ -0,0 +1,739 @@ +Clear(); + } + + /** + * @return \MailSo\Mail\Message + */ + public function Clear() + { + $this->sFolder = ''; + $this->iUid = 0; + $this->sSubject = ''; + $this->sMessageId = ''; + $this->sContentType = ''; + $this->iSize = 0; + $this->iInternalTimeStampInUTC = 0; + $this->iHeaderTimeStampInUTC = 0; + $this->sHeaderDate = ''; + $this->aFlags = array(); + $this->aFlagsLowerCase = array(); + + $this->oFrom = null; + $this->oSender = null; + $this->oReplyTo = null; + $this->oTo = null; + $this->oCc = null; + $this->oBcc = null; + + $this->sPlain = ''; + $this->sHtml = ''; + + $this->oAttachments = null; + $this->aDraftInfo = null; + + $this->sInReplyTo = ''; + $this->sReferences = ''; + + $this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::NOTHING; + $this->iPriority = \MailSo\Mime\Enumerations\MessagePriority::NORMAL; + $this->sReadingConfirmation = ''; + + $this->aThreads = array(); + $this->iThreadsLen = 0; + $this->iParentThread = 0; + + return $this; + } + + /** + * @return \MailSo\Mail\Message + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @return string + */ + public function Plain() + { + return $this->sPlain; + } + + /** + * @return string + */ + public function Html() + { + return $this->sHtml; + } + + /** + * @param string $sHtml + * + * @retun void + */ + public function SetHtml($sHtml) + { + $this->sHtml = $sHtml; + } + + /** + * @return string + */ + public function Folder() + { + return $this->sFolder; + } + + /** + * @return int + */ + public function Uid() + { + return $this->iUid; + } + + /** + * @return string + */ + public function MessageId() + { + return $this->sMessageId; + } + + /** + * @return string + */ + public function Subject() + { + return $this->sSubject; + } + + /** + * @return string + */ + public function ContentType() + { + return $this->sContentType; + } + + /** + * @return int + */ + public function Size() + { + return $this->iSize; + } + + /** + * @return int + */ + public function InternalTimeStampInUTC() + { + return $this->iInternalTimeStampInUTC; + } + + /** + * @return int + */ + public function HeaderTimeStampInUTC() + { + return $this->iHeaderTimeStampInUTC; + } + + /** + * @return string + */ + public function HeaderDate() + { + return $this->sHeaderDate; + } + + /** + * @return array + */ + public function Flags() + { + return $this->aFlags; + } + + /** + * @return array + */ + public function FlagsLowerCase() + { + return $this->aFlagsLowerCase; + } + + /** + * @return \MailSo\Mime\EmailCollection + */ + public function From() + { + return $this->oFrom; + } + + /** + * @return int + */ + public function Sensitivity() + { + return $this->iSensitivity; + } + + /** + * @return int + */ + public function Priority() + { + return $this->iPriority; + } + + /** + * @return \MailSo\Mime\EmailCollection + */ + public function Sender() + { + return $this->oSender; + } + + /** + * @return \MailSo\Mime\EmailCollection + */ + public function ReplyTo() + { + return $this->oReplyTo; + } + + /** + * @return \MailSo\Mime\EmailCollection + */ + public function To() + { + return $this->oTo; + } + + /** + * @return \MailSo\Mime\EmailCollection + */ + public function Cc() + { + return $this->oCc; + } + + /** + * @return \MailSo\Mime\EmailCollection + */ + public function Bcc() + { + return $this->oBcc; + } + + /** + * @return \MailSo\Mail\AttachmentCollection + */ + public function Attachments() + { + return $this->oAttachments; + } + + /** + * @return string + */ + public function InReplyTo() + { + return $this->sInReplyTo; + } + + /** + * @return string + */ + public function References() + { + return $this->sReferences; + } + + /** + * @return string + */ + public function ReadingConfirmation() + { + return $this->sReadingConfirmation; + } + + /** + * @return array | null + */ + public function DraftInfo() + { + return $this->aDraftInfo; + } + + /** + * @return array + */ + public function Threads() + { + return $this->aThreads; + } + + /** + * @param array $aThreads + */ + public function SetThreads($aThreads) + { + $this->aThreads = \is_array($aThreads) ? $aThreads : array(); + } + + /** + * @return int + */ + public function ThreadsLen() + { + return $this->iThreadsLen; + } + + /** + * @param int $iThreadsLen + */ + public function SetThreadsLen($iThreadsLen) + { + $this->iThreadsLen = $iThreadsLen; + } + + /** + * @return int + */ + public function ParentThread() + { + return $this->iParentThread; + } + + /** + * @param int $iParentThread + */ + public function SetParentThread($iParentThread) + { + $this->iParentThread = $iParentThread; + } + + /** + * @param string $sFolder + * @param \MailSo\Imap\FetchResponse $oFetchResponse + * @param \MailSo\Imap\BodyStructure $oBodyStructure = null + * + * @return \MailSo\Mail\Message + */ + public static function NewFetchResponseInstance($sFolder, $oFetchResponse, $oBodyStructure = null) + { + return self::NewInstance()->InitByFetchResponse($sFolder, $oFetchResponse, $oBodyStructure); + } + + /** + * @param string $sFolder + * @param \MailSo\Imap\FetchResponse $oFetchResponse + * @param \MailSo\Imap\BodyStructure $oBodyStructure = null + * + * @return \MailSo\Mail\Message + */ + public function InitByFetchResponse($sFolder, $oFetchResponse, $oBodyStructure = null) + { + if (!$oBodyStructure) + { + $oBodyStructure = $oFetchResponse->GetFetchBodyStructure(); + } + + $aTextParts = $oBodyStructure ? $oBodyStructure->SearchHtmlOrPlainParts() : array(); + + $sUid = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::UID); + $sSize = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::RFC822_SIZE); + $sInternalDate = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::INTERNALDATE); + $aFlags = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::FLAGS); + + $this->sFolder = $sFolder; + $this->iUid = \is_numeric($sUid) ? (int) $sUid : 0; + $this->iSize = \is_numeric($sSize) ? (int) $sSize : 0; + $this->aFlags = \is_array($aFlags) ? $aFlags : array(); + $this->aFlagsLowerCase = \array_map('strtolower', $this->aFlags); + + $this->iInternalTimeStampInUTC = + \MailSo\Base\DateTimeHelper::ParseInternalDateString($sInternalDate); + + $sCharset = $oBodyStructure ? $oBodyStructure->SearchCharset() : ''; + + $sHeaders = $oFetchResponse->GetHeaderFieldsValue(); + if (0 < \strlen($sHeaders)) + { + $oHeaders = \MailSo\Mime\HeaderCollection::NewInstance()->Parse($sHeaders); + + $sContentTypeCharset = $oHeaders->ParameterValue( + \MailSo\Mime\Enumerations\Header::CONTENT_TYPE, + \MailSo\Mime\Enumerations\Parameter::CHARSET + ); + + if (0 < \strlen($sContentTypeCharset)) + { + $sCharset = $sContentTypeCharset; + } + + if (0 < \strlen($sCharset)) + { + $oHeaders->SetParentCharset($sCharset); + } + + $this->sSubject = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::SUBJECT, true); + $this->sMessageId = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::MESSAGE_ID); + $this->sContentType = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE); + + $this->oFrom = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::FROM_, true); + $this->oTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::TO_, true); + $this->oCc = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::CC, true); + $this->oBcc = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::BCC, true); + + $this->oSender = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::SENDER); + $this->oReplyTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::REPLY_TO, true); + + $this->sInReplyTo = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IN_REPLY_TO); + $this->sReferences = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::REFERENCES); + + $sHeaderDate = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DATE); + $this->sHeaderDate = $sHeaderDate; + $this->iHeaderTimeStampInUTC = \MailSo\Base\DateTimeHelper::ParseRFC2822DateString($sHeaderDate); + + // Sensitivity + $this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::NOTHING; + $sSensitivity = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::SENSITIVITY); + switch (\strtolower($sSensitivity)) + { + case 'personal': + $this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::PERSONAL; + break; + case 'private': + $this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::PRIVATE_; + break; + case 'company-confidential': + $this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::CONFIDENTIAL; + break; + } + + // Priority + $this->iPriority = \MailSo\Mime\Enumerations\MessagePriority::NORMAL; + $sPriority = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_MSMAIL_PRIORITY); + if (0 === \strlen($sPriority)) + { + $sPriority = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IMPORTANCE); + } + if (0 === \strlen($sPriority)) + { + $sPriority = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_PRIORITY); + } + if (0 < \strlen($sPriority)) + { + switch (\str_replace(' ', '', \strtolower($sPriority))) + { + case 'high': + case '1(highest)': + case '2(high)': + case '1': + case '2': + $this->iPriority = \MailSo\Mime\Enumerations\MessagePriority::HIGH; + break; + + case 'low': + case '4(low)': + case '5(lowest)': + case '4': + case '5': + $this->iPriority = \MailSo\Mime\Enumerations\MessagePriority::LOW; + break; + } + } + + // ReadingConfirmation + $this->sReadingConfirmation = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DISPOSITION_NOTIFICATION_TO); + if (0 === \strlen($this->sReadingConfirmation)) + { + $this->sReadingConfirmation = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_CONFIRM_READING_TO); + } + + $this->sReadingConfirmation = \trim($this->sReadingConfirmation); + + $sDraftInfo = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_DRAFT_INFO); + if (0 < \strlen($sDraftInfo)) + { + $sType = ''; + $sFolder = ''; + $sUid = ''; + + \MailSo\Mime\ParameterCollection::NewInstance($sDraftInfo) + ->ForeachList(function ($oParameter) use (&$sType, &$sFolder, &$sUid) { + + switch (\strtolower($oParameter->Name())) + { + case 'type': + $sType = $oParameter->Value(); + break; + case 'uid': + $sUid = $oParameter->Value(); + break; + case 'folder': + $sFolder = \base64_decode($oParameter->Value()); + break; + } + }) + ; + + if (0 < \strlen($sType) && 0 < \strlen($sFolder) && 0 < \strlen($sUid)) + { + $this->aDraftInfo = array($sType, $sUid, $sFolder); + } + } + } + else if ($oFetchResponse->GetEnvelope()) + { + if (0 === \strlen($sCharset) && $oBodyStructure) + { + $sCharset = $oBodyStructure->SearchCharset(); + } + + if (0 === \strlen($sCharset)) + { + $sCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1; + } + + // date, subject, from, sender, reply-to, to, cc, bcc, in-reply-to, message-id + $this->sMessageId = $oFetchResponse->GetFetchEnvelopeValue(9, ''); + $this->sSubject = \MailSo\Base\Utils::DecodeHeaderValue($oFetchResponse->GetFetchEnvelopeValue(1, ''), $sCharset); + + $this->oFrom = $oFetchResponse->GetFetchEnvelopeEmailCollection(2, $sCharset); + $this->oSender = $oFetchResponse->GetFetchEnvelopeEmailCollection(3, $sCharset); + $this->oReplyTo = $oFetchResponse->GetFetchEnvelopeEmailCollection(4, $sCharset); + $this->oTo = $oFetchResponse->GetFetchEnvelopeEmailCollection(5, $sCharset); + $this->oCc = $oFetchResponse->GetFetchEnvelopeEmailCollection(6, $sCharset); + $this->oBcc = $oFetchResponse->GetFetchEnvelopeEmailCollection(7, $sCharset); + $this->sInReplyTo = $oFetchResponse->GetFetchEnvelopeValue(8, ''); + } + + if (\is_array($aTextParts) && 0 < \count($aTextParts)) + { + $sHtmlParts = array(); + $sPlainParts = array(); + + foreach ($aTextParts as $oPart) + { + $sText = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::BODY.'['.$oPart->PartID().']'); + if (\is_string($sText) && 0 < \strlen($sText)) + { + $sTextCharset = $oPart->Charset(); + if (empty($sTextCharset)) + { + $sTextCharset = $sCharset; + } + + $sText = \MailSo\Base\Utils::DecodeEncodingValue($sText, $oPart->MailEncodingName()); + $sText = \MailSo\Base\Utils::ConvertEncoding($sText, $sTextCharset, \MailSo\Base\Enumerations\Charset::UTF_8); + $sText = \MailSo\Base\Utils::Utf8Clear($sText); + + if ('text/html' === $oPart->ContentType()) + { + $sHtmlParts[] = $sText; + } + else + { + $sPlainParts[] = $sText; + } + } + } + + if (0 < \count($sHtmlParts)) + { + $this->sHtml = \implode('
', $sHtmlParts); + } + else + { + $this->sPlain = \implode("\n", $sPlainParts); + } + + unset($sHtmlParts, $sPlainParts); + } + + if ($oBodyStructure) + { + $aAttachmentsParts = $oBodyStructure->SearchAttachmentsParts(); + if ($aAttachmentsParts && 0 < count($aAttachmentsParts)) + { + $this->oAttachments = AttachmentCollection::NewInstance(); + foreach ($aAttachmentsParts as /* @var $oAttachmentItem \MailSo\Imap\BodyStructure */ $oAttachmentItem) + { + $this->oAttachments->Add( + \MailSo\Mail\Attachment::NewBodyStructureInstance($this->sFolder, $this->iUid, $oAttachmentItem) + ); + } + } + } + + return $this; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/MessageCollection.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/MessageCollection.php new file mode 100644 index 000000000..ad2b0a023 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mail/MessageCollection.php @@ -0,0 +1,108 @@ +Clear(); + } + + /** + * @return \MailSo\Mail\MessageCollection + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @return \MailSo\Mail\MessageCollection + */ + public function Clear() + { + parent::Clear(); + + $this->FolderHash = ''; + + $this->MessageCount = 0; + $this->MessageUnseenCount = 0; + $this->MessageResultCount = 0; + + $this->FolderName = ''; + $this->Offset = 0; + $this->Limit = 0; + $this->Search = ''; + $this->UidNext = ''; + $this->NewMessages = array(); + + $this->LastCollapsedThreadUids = array(); + + return $this; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/MailSo.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/MailSo.php new file mode 100644 index 000000000..552d943b9 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/MailSo.php @@ -0,0 +1,23 @@ +rResource = $rResource; + $this->sFileName = $sFileName; + $this->iFileSize = $iFileSize; + $this->bIsInline = $bIsInline; + $this->bIsLinked = $bIsLinked; + $this->sCID = $sCID; + } + + /** + * @param resource $rResource + * @param string $sFileName = '' + * @param int $iFileSize = 0 + * @param bool $bIsInline = false + * @param bool $bIsLinked = false + * @param string $sCID = '' + * + * @return \MailSo\Mime\Attachment + */ + public static function NewInstance($rResource, $sFileName = '', $iFileSize = 0, $bIsInline = false, $bIsLinked = false, $sCID = '') + { + return new self($rResource, $sFileName, $iFileSize, $bIsInline, $bIsLinked, $sCID); + } + + /** + * @return resource + */ + public function Resource() + { + return $this->rResource; + } + + /** + * @return string + */ + public function ContentType() + { + return \MailSo\Base\Utils::MimeContentType($this->sFileName); + } + + /** + * @return string + */ + public function CID() + { + return $this->sCID; + } + + /** + * @return string + */ + public function FileName() + { + return $this->sFileName; + } + + /** + * @return int + */ + public function FileSize() + { + return $this->iFileSize; + } + + /** + * @return bool + */ + public function IsInline() + { + return $this->bIsInline; + } + + /** + * @return bool + */ + public function IsLinked() + { + return $this->bIsLinked && 0 < \strlen($this->sCID); + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/AttachmentCollection.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/AttachmentCollection.php new file mode 100644 index 000000000..5139ae4ac --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/AttachmentCollection.php @@ -0,0 +1,62 @@ +FilterList(function ($oItem) { + return $oItem && $oItem->IsLinked(); + }); + } + + /** + * @return array + */ + public function UnlinkedAttachments() + { + return $this->FilterList(function ($oItem) { + return $oItem && !$oItem->IsLinked(); + }); + } + + /** + * @return int + */ + public function SizeOfAttachments() + { + $iResult = 0; + $this->ForeachList(function ($oItem) use (&$iResult) { + if ($oItem) + { + $iResult += $oItem->FileSize(); + } + }); + + return $iResult; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Email.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Email.php new file mode 100644 index 000000000..59c590922 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Email.php @@ -0,0 +1,275 @@ +sEmail = \trim($sEmail); + $this->sDisplayName = \trim($sDisplayName); + $this->sRemark = \trim($sRemark); + } + + /** + * @param string $sEmail + * @param string $sDisplayName = '' + * @param string $sRemark = '' + * + * @return \MailSo\Mime\Email + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public static function NewInstance($sEmail, $sDisplayName = '', $sRemark = '') + { + return new self($sEmail, $sDisplayName, $sRemark); + } + + /** + * @param string $sEmailAddress + * @return \MailSo\Mime\Email + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public static function Parse($sEmailAddress) + { + if (!\MailSo\Base\Validator::NotEmptyString($sEmailAddress, true)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $sName = ''; + $sEmail = ''; + $sComment = ''; + + $bInName = false; + $bInAddress = false; + $bInComment = false; + + $iStartIndex = 0; + $iEndIndex = 0; + $iCurrentIndex = 0; + + while ($iCurrentIndex < \strlen($sEmailAddress)) + { + switch ($sEmailAddress{$iCurrentIndex}) + { +// case '\'': + case '"': +// $sQuoteChar = $sEmailAddress{$iCurrentIndex}; + if ((!$bInName) && (!$bInAddress) && (!$bInComment)) + { + $bInName = true; + $iStartIndex = $iCurrentIndex; + } + else if ((!$bInAddress) && (!$bInComment)) + { + $iEndIndex = $iCurrentIndex; + $sName = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); + $sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); + $iEndIndex = 0; + $iCurrentIndex = 0; + $iStartIndex = 0; + $bInName = false; + } + break; + case '<': + if ((!$bInName) && (!$bInAddress) && (!$bInComment)) + { + if ($iCurrentIndex > 0 && \strlen($sName) == 0) + { + $sName = \substr($sEmailAddress, 0, $iCurrentIndex); + } + + $bInAddress = true; + $iStartIndex = $iCurrentIndex; + } + break; + case '>': + if ($bInAddress) + { + $iEndIndex = $iCurrentIndex; + $sEmail = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); + $sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); + $iEndIndex = 0; + $iCurrentIndex = 0; + $iStartIndex = 0; + $bInAddress = false; + } + break; + case '(': + if ((!$bInName) && (!$bInAddress) && (!$bInComment)) + { + $bInComment = true; + $iStartIndex = $iCurrentIndex; + } + break; + case ')': + if ($bInComment) + { + $iEndIndex = $iCurrentIndex; + $sComment = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); + $sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); + $iEndIndex = 0; + $iCurrentIndex = 0; + $iStartIndex = 0; + $bInComment = false; + } + break; + case '\\': + $iCurrentIndex++; + break; + } + + $iCurrentIndex++; + } + + if (strlen($sEmail) == 0) + { + $aRegs = array(''); + if (\preg_match('/[^@\s]+@\S+/i', $sEmailAddress, $aRegs) && isset($aRegs[0])) + { + $sEmail = $aRegs[0]; + } + else + { + $sName = $sEmailAddress; + } + } + + if ((\strlen($sEmail) > 0) && (\strlen($sName) == 0) && (strlen($sComment) == 0)) + { + $sName = \str_replace($sEmail, '', $sEmailAddress); + } + + $sEmail = \trim(\trim($sEmail), '<>'); + $sName = \trim(\trim($sName), '"'); + $sComment = \trim(\trim($sComment), '()'); + + // Remove backslash + $sName = \preg_replace('/\\\\(.)/s', '$1', $sName); + $sComment = \preg_replace('/\\\\(.)/s', '$1', $sComment); + + return Email::NewInstance($sEmail, $sName, $sComment); + } + + /** + * @return string + */ + public function GetEmail() + { + return $this->sEmail; + } + + /** + * @return string + */ + public function GetDisplayName() + { + return $this->sDisplayName; + } + + /** + * @return string + */ + public function GetRemark() + { + return $this->sRemark; + } + + /** + * @return string + */ + public function GetAccountName() + { + return \MailSo\Base\Utils::GetAccountNameFromEmail($this->sEmail); + } + + /** + * @return string + */ + public function GetDomain() + { + return \MailSo\Base\Utils::GetDomainFromEmail($this->sEmail); + } + + /** + * @return array + */ + public function ToArray() + { + return array($this->sDisplayName, $this->sEmail, $this->sRemark); + } + + /** + * @param bool $bConvertSpecialsName = false + * + * @return string + */ + public function ToString($bConvertSpecialsName = false) + { + $sReturn = ''; + + $sRemark = \str_replace(')', '\)', $this->sRemark); + $sDisplayName = \str_replace('"', '\"', $this->sDisplayName); + + if ($bConvertSpecialsName) + { + $sDisplayName = 0 === \strlen($sDisplayName) ? '' : \MailSo\Base\Utils::EncodeUnencodedValue( + \MailSo\Base\Enumerations\Encoding::BASE64_SHORT, + $sDisplayName); + + $sRemark = 0 === \strlen($sRemark) ? '' : \MailSo\Base\Utils::EncodeUnencodedValue( + \MailSo\Base\Enumerations\Encoding::BASE64_SHORT, + $sRemark); + } + + $sDisplayName = 0 === \strlen($sDisplayName) ? '' : '"'.$sDisplayName.'"'; + $sRemark = 0 === \strlen($sRemark) ? '' : '('.$sRemark.')'; + + if (0 < \strlen($this->sEmail)) + { + $sReturn = $this->sEmail; + + if (0 < \strlen($sDisplayName.$sRemark)) + { + $sReturn = $sDisplayName.' <'.$sReturn.'> '.$sRemark; + } + } + + return \trim($sReturn); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/EmailCollection.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/EmailCollection.php new file mode 100644 index 000000000..0e496c8cd --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/EmailCollection.php @@ -0,0 +1,228 @@ +parseEmailAddresses($sEmailAddresses); + } + } + + /** + * @param string $sEmailAddresses = '' + * + * @return \MailSo\Mime\EmailCollection + */ + public static function NewInstance($sEmailAddresses = '') + { + return new self($sEmailAddresses); + } + + /** + * @param string $sEmailAddresses + * + * @return \MailSo\Mime\EmailCollection + */ + public static function Parse($sEmailAddresses) + { + return self::NewInstance($sEmailAddresses); + } + + /** + * @return array + */ + public function ToArray() + { + $aReturn = $aEmails = array(); + $aEmails =& $this->GetAsArray(); + foreach ($aEmails as /* @var $oEmail \MailSo\Mime\Email */ $oEmail) + { + $aReturn[] = $oEmail->ToArray(); + } + + return $aReturn; + } + + /** + * @param \MailSo\Mime\EmailCollection $oEmails + * + * @return \MailSo\Mime\EmailCollection + */ + public function MergeWithOtherCollection(\MailSo\Mime\EmailCollection $oEmails) + { + $aEmails =& $oEmails->GetAsArray(); + foreach ($aEmails as /* @var $oEmail \MailSo\Mime\Email */ $oEmail) + { + $this->Add($oEmail); + } + + return $this; + } + + /** + * @return \MailSo\Mime\EmailCollection + */ + public function Unique() + { + $aCache = array(); + $aReturn = array(); + + $aEmails =& $this->GetAsArray(); + foreach ($aEmails as /* @var $oEmail \MailSo\Mime\Email */ $oEmail) + { + $sEmail = $oEmail->GetEmail(); + if (!isset($aCache[$sEmail])) + { + $aCache[$sEmail] = true; + $aReturn[] = $oEmail; + } + } + + $this->SetAsArray($aReturn); + + return $this; + } + + /** + * @param bool $bConvertSpecialsName = false + * + * @return string + */ + public function ToString($bConvertSpecialsName = false) + { + $aReturn = $aEmails = array(); + $aEmails =& $this->GetAsArray(); + foreach ($aEmails as /* @var $oEmail \MailSo\Mime\Email */ $oEmail) + { + $aReturn[] = $oEmail->ToString($bConvertSpecialsName); + } + + return \implode(', ', $aReturn); + } + + /** + * @param string $sRawEmails + * + * @return \MailSo\Mime\EmailCollection + */ + private function parseEmailAddresses($sRawEmails) + { + $this->Clear(); + + $sWorkingRecipients = \trim($sRawEmails); + + if (0 === \strlen($sWorkingRecipients)) + { + return $this; + } + + $iEmailStartPos = 0; + $iEmailEndPos = 0; + + $bIsInQuotes = false; + $sChQuote = '"'; + $bIsInAngleBrackets = false; + $bIsInBrackets = false; + + $iCurrentPos = 0; + + $sWorkingRecipientsLen = \strlen($sWorkingRecipients); + + while ($iCurrentPos < $sWorkingRecipientsLen) + { + switch ($sWorkingRecipients{$iCurrentPos}) + { + case '\'': + case '"': + if (!$bIsInQuotes) + { + $sChQuote = $sWorkingRecipients{$iCurrentPos}; + $bIsInQuotes = true; + } + else if ($sChQuote == $sWorkingRecipients{$iCurrentPos}) + { + $bIsInQuotes = false; + } + break; + + case '<': + if (!$bIsInAngleBrackets) + { + $bIsInAngleBrackets = true; + } + break; + + case '>': + if ($bIsInAngleBrackets) + { + $bIsInAngleBrackets = false; + } + break; + + case '(': + if (!$bIsInBrackets) + { + $bIsInBrackets = true; + } + break; + + case ')': + if ($bIsInBrackets) + { + $bIsInBrackets = false; + } + break; + + case ',': + case ';': + if (!$bIsInAngleBrackets && !$bIsInBrackets && !$bIsInQuotes) + { + $iEmailEndPos = $iCurrentPos; + + try + { + $this->Add( + \MailSo\Mime\Email::Parse(\substr($sWorkingRecipients, $iEmailStartPos, $iEmailEndPos - $iEmailStartPos)) + ); + + $iEmailStartPos = $iCurrentPos + 1; + } + catch (\MailSo\Base\Exceptions\InvalidArgumentException $oException) + { + } + } + break; + } + + $iCurrentPos++; + } + + if ($iEmailStartPos < $iCurrentPos) + { + try + { + $this->Add( + \MailSo\Mime\Email::Parse(\substr($sWorkingRecipients, $iEmailStartPos, $iCurrentPos - $iEmailStartPos)) + ); + } + catch (\MailSo\Base\Exceptions\InvalidArgumentException $oException) {} + } + + return $this; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Enumerations/Constants.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Enumerations/Constants.php new file mode 100644 index 000000000..5f58ba30b --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Enumerations/Constants.php @@ -0,0 +1,16 @@ +sParentCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1; + + $this->initInputData($sName, $sValue, $sEncodedValueForReparse); + } + + /** + * @param string $sName + * @param string $sValue + * @param string $sEncodedValueForReparse + * + * @return void + */ + private function initInputData($sName, $sValue, $sEncodedValueForReparse) + { + $this->sName = trim($sName); + $this->sFullValue = trim($sValue); + $this->sEncodedValueForReparse = ''; + + $this->oParameters = null; + if (0 < \strlen($sEncodedValueForReparse) && $this->IsReparsed()) + { + $this->sEncodedValueForReparse = \trim($sEncodedValueForReparse); + } + + if (0 < \strlen($this->sFullValue) && $this->IsParameterized()) + { + $aRawExplode = \explode(';', $this->sFullValue, 2); + if (2 === \count($aRawExplode)) + { + $this->sValue = $aRawExplode[0]; + $this->oParameters = + \MailSo\Mime\ParameterCollection::NewInstance($aRawExplode[1]); + } + else + { + $this->sValue = $this->sFullValue; + } + } + else + { + $this->sValue = $this->sFullValue; + } + } + + /** + * @param string $sName + * @param string $sValue = '' + * @param string $sEncodedValueForReparse = '' + * + * @return \MailSo\Mime\Header + */ + public static function NewInstance($sName, $sValue = '', $sEncodedValueForReparse = '') + { + return new self($sName, $sValue, $sEncodedValueForReparse); + } + + /** + * @param string $sEncodedLines + * @param string $sIncomingCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1 + * + * @return \MailSo\Mime\Header | false + */ + public static function NewInstanceFromEncodedString($sEncodedLines, $sIncomingCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1) + { + $aParts = \explode(':', \str_replace("\r", '', $sEncodedLines), 2); + if (isset($aParts[0]) && isset($aParts[1]) && 0 < \strlen($aParts[0]) && 0 < \strlen($aParts[1])) + { + return self::NewInstance( + \trim($aParts[0]), + \trim(\MailSo\Base\Utils::DecodeHeaderValue(\trim($aParts[1]), $sIncomingCharset)), + \trim($aParts[1]) + ); + } + + return false; + } + + /** + * @return string + */ + public function Name() + { + return $this->sName; + } + + /** + * @return string + */ + public function NameWithDelimitrom() + { + return $this->Name().': '; + } + + /** + * @return string + */ + public function Value() + { + return $this->sValue; + } + + /** + * @return string + */ + public function FullValue() + { + return $this->sFullValue; + } + + /** + * @param string $sParentCharset + * @return \MailSo\Mime\Header + */ + public function SetParentCharset($sParentCharset) + { + if ($this->sParentCharset !== $sParentCharset && $this->IsReparsed() && 0 < \strlen($this->sEncodedValueForReparse)) + { + $this->initInputData( + $this->sName, + \trim(\MailSo\Base\Utils::DecodeHeaderValue($this->sEncodedValueForReparse, $sParentCharset)), + $this->sEncodedValueForReparse); + } + + $this->sParentCharset = $sParentCharset; + + return $this; + } + + /** + * @return \MailSo\Mime\ParameterCollection | null + */ + public function Parameters() + { + return $this->oParameters; + } + + /** + * @param string $sValue + * @return string + */ + private function wordWrapHelper($sValue, $sGlue = "\r\n ") + { + return \trim(substr(wordwrap($this->NameWithDelimitrom().$sValue, + \MailSo\Mime\Enumerations\Constants::LINE_LENGTH, $sGlue + ), \strlen($this->NameWithDelimitrom()))); + } + + /** + * @return string + */ + public function EncodedValue() + { + $sResult = $this->sFullValue; + + if ($this->IsSubject()) + { + if (!\MailSo\Base\Utils::IsAscii($sResult) && \function_exists('iconv_mime_encode')) + { + $aPreferences = array( +// 'scheme' => \MailSo\Base\Enumerations\Encoding::QUOTED_PRINTABLE_SHORT, + 'scheme' => \MailSo\Base\Enumerations\Encoding::BASE64_SHORT, + 'input-charset' => \MailSo\Base\Enumerations\Charset::UTF_8, + 'output-charset' => \MailSo\Base\Enumerations\Charset::UTF_8, + 'line-length' => \MailSo\Mime\Enumerations\Constants::LINE_LENGTH, + 'line-break-chars' => \MailSo\Mime\Enumerations\Constants::CRLF + ); + + return \iconv_mime_encode($this->Name(), $sResult, $aPreferences); + } + } + else if ($this->IsParameterized() && $this->oParameters && 0 < $this->oParameters->Count()) + { + $sResult = $this->sValue.'; '.$this->oParameters->ToString(true); + } + else if ($this->IsEmail()) + { + $oEmailCollection = \MailSo\Mime\EmailCollection::NewInstance($this->sFullValue); + if ($oEmailCollection && 0 < $oEmailCollection->Count()) + { + $sResult = $oEmailCollection->ToString(true); + } + } + + return $this->NameWithDelimitrom().$this->wordWrapHelper($sResult); + } + + /** + * @return bool + */ + public function IsSubject() + { + return \strtolower(\MailSo\Mime\Enumerations\Header::SUBJECT) === \strtolower($this->Name()); + } + + /** + * @return bool + */ + public function IsParameterized() + { + return \in_array(\strtolower($this->sName), array( + \strtolower(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE), + \strtolower(\MailSo\Mime\Enumerations\Header::CONTENT_DISPOSITION) + )); + } + + /** + * @return bool + */ + public function IsEmail() + { + return \in_array(\strtolower($this->sName), array( + \strtolower(\MailSo\Mime\Enumerations\Header::FROM_), + \strtolower(\MailSo\Mime\Enumerations\Header::TO_), + \strtolower(\MailSo\Mime\Enumerations\Header::CC), + \strtolower(\MailSo\Mime\Enumerations\Header::BCC), + \strtolower(\MailSo\Mime\Enumerations\Header::REPLY_TO), + \strtolower(\MailSo\Mime\Enumerations\Header::RETURN_PATH), + \strtolower(\MailSo\Mime\Enumerations\Header::SENDER) + )); + } + + /** + * @return string + */ + public function ValueWithCharsetAutoDetect() + { + $sValue = $this->Value(); + if (!\MailSo\Base\Utils::IsAscii($sValue) && + 0 < \strlen($this->sEncodedValueForReparse) && + !\MailSo\Base\Utils::IsAscii($this->sEncodedValueForReparse)) + { + $sValueCharset = \MailSo\Base\Utils::CharsetDetect($this->sEncodedValueForReparse); + if (0 < \strlen($sValueCharset)) + { + $this->SetParentCharset($sValueCharset); + $sValue = $this->Value(); + } + } + + return $sValue; + } + + /** + * @return bool + */ + public function IsReparsed() + { + return $this->IsEmail() || $this->IsSubject() || $this->IsParameterized(); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/HeaderCollection.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/HeaderCollection.php new file mode 100644 index 000000000..35b8577ca --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/HeaderCollection.php @@ -0,0 +1,362 @@ +sRawHeaders = ''; + $this->sParentCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1; + + if (0 < \strlen($sRawHeaders)) + { + $this->Parse($sRawHeaders, $bStoreRawHeaders); + } + } + + /** + * @param string $sRawHeaders = '' + * @param bool $bStoreRawHeaders = true + * + * @return \MailSo\Mime\HeaderCollection + */ + public static function NewInstance($sRawHeaders = '', $bStoreRawHeaders = true) + { + return new self($sRawHeaders, $bStoreRawHeaders); + } + + /** + * @param string $sName + * @param string $sValue + * @param bool $bToTop = false + * + * @return \MailSo\Mime\HeaderCollection + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function AddByName($sName, $sValue, $bToTop = false) + { + return $this->Add(Header::NewInstance($sName, $sValue), $bToTop); + } + + /** + * @param string $sName + * @param string $sValue + * @param bool $bToTop = false + * + * @return \MailSo\Mime\HeaderCollection + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function SetByName($sName, $sValue, $bToTop = false) + { + return $this->RemoveByName($sName)->Add(Header::NewInstance($sName, $sValue), $bToTop); + } + + /** + * @return \MailSo\Mime\Header | null + */ + public function &GetByIndex($iIndex) + { + $mResult = null; + $mResult =& parent::GetByIndex($iIndex); + return $mResult; + } + + /** + * @param string $sHeaderName + * @param bool $bCharsetAutoDetect = false + * @return string + */ + public function ValueByName($sHeaderName, $bCharsetAutoDetect = false) + { + $oHeader = null; + $oHeader =& $this->GetByName($sHeaderName); + return (null !== $oHeader) ? ($bCharsetAutoDetect ? $oHeader->ValueWithCharsetAutoDetect() : $oHeader->Value()) : ''; + } + + /** + * @param string $sHeaderName + * @param bool $bCharsetAutoDetect = false + * @return array + */ + public function ValuesByName($sHeaderName, $bCharsetAutoDetect = false) + { + $aResult = array(); + $oHeader = null; + + $sHeaderNameLower = \strtolower($sHeaderName); + $aHeaders =& $this->GetAsArray(); + foreach ($aHeaders as /* @var $oHeader \MailSo\Mime\Header */ &$oHeader) + { + if ($sHeaderNameLower === \strtolower($oHeader->Name())) + { + $aResult[] = $bCharsetAutoDetect ? $oHeader->ValueWithCharsetAutoDetect() : $oHeader->Value(); + } + } + + return $aResult; + } + + /** + * @param string $sHeaderName + * + * @return \MailSo\Mime\HeaderCollection + */ + public function RemoveByName($sHeaderName) + { + $aResult = $this->FilterList(function ($oHeader) use ($sHeaderName) { + return $oHeader && \strtolower($oHeader->Name()) !== \strtolower($sHeaderName); + }); + + return $this->SetAsArray($aResult); + } + + /** + * @param string $sHeaderName + * @param bool $bCharsetAutoDetect = false + * @return string + */ + public function GetAsEmailCollection($sHeaderName, $bCharsetAutoDetect = false) + { + $oResult = null; + $sValue = $this->ValueByName($sHeaderName, $bCharsetAutoDetect); + if (0 < \strlen($sValue)) + { + $oResult = \MailSo\Mime\EmailCollection::NewInstance($sValue); + } + + return $oResult && 0 < $oResult->Count() ? $oResult : null; + } + + /** + * @param string $sHeaderName + * @return \MailSo\Mime\ParameterCollection | null + */ + public function ParametersByName($sHeaderName) + { + $oParameters = $oHeader = null; + $oHeader =& $this->GetByName($sHeaderName); + if ($oHeader) + { + $oParameters = $oHeader->Parameters(); + } + + return $oParameters; + } + + /** + * @param string $sHeaderName + * @param string $sParamName + * @return string + */ + public function ParameterValue($sHeaderName, $sParamName) + { + $oParameters = $this->ParametersByName($sHeaderName); + return (null !== $oParameters) ? $oParameters->ParameterValueByName($sParamName) : ''; + } + + /** + * @param string $sHeaderName + * @return \MailSo\Mime\Header | false + */ + public function &GetByName($sHeaderName) + { + $oResult = $oHeader = null; + + $sHeaderNameLower = \strtolower($sHeaderName); + $aHeaders =& $this->GetAsArray(); + foreach ($aHeaders as /* @var $oHeader \MailSo\Mime\Header */ &$oHeader) + { + if ($sHeaderNameLower === \strtolower($oHeader->Name())) + { + $oResult =& $oHeader; + break; + } + } + + return $oResult; + } + + /** + * @param array $aList + * @return \MailSo\Mime\HeaderCollection + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function SetAsArray($aList) + { + parent::SetAsArray($aList); + + return $this; + } + + /** + * @param string $sParentCharset + * @return \MailSo\Mime\HeaderCollection + */ + public function SetParentCharset($sParentCharset) + { + if (0 < \strlen($sParentCharset)) + { + if ($this->sParentCharset !== $sParentCharset) + { + $oHeader = null; + $aHeaders =& $this->GetAsArray(); + + foreach ($aHeaders as /* @var $oHeader \MailSo\Mime\Header */ &$oHeader) + { + $oHeader->SetParentCharset($sParentCharset); + } + + $this->sParentCharset = $sParentCharset; + } + } + + return $this; + } + + /** + * @return void + */ + public function Clear() + { + parent::Clear(); + + $this->sRawHeaders = ''; + } + + /** + * @param string $sRawHeaders + * @param bool $bStoreRawHeaders = false + * @param string $sParentCharset = '' + * + * @return \MailSo\Mime\HeaderCollection + */ + public function Parse($sRawHeaders, $bStoreRawHeaders = false, $sParentCharset = '') + { + $this->Clear(); + + if ($bStoreRawHeaders) + { + $this->sRawHeaders = $sRawHeaders; + } + + if (0 === \strlen($this->sParentCharset)) + { + $this->sParentCharset = $sParentCharset; + } + + $aHeaders = \explode("\n", \str_replace("\r", '', $sRawHeaders)); + + $sName = null; + $sValue = null; + foreach ($aHeaders as $sHeadersValue) + { + if (0 === strlen($sHeadersValue)) + { + continue; + } + + $sFirstChar = \substr($sHeadersValue, 0, 1); + if ($sFirstChar !== ' ' && $sFirstChar !== "\t" && false === \strpos($sHeadersValue, ':')) + { + continue; + } + else if (null !== $sName && ($sFirstChar === ' ' || $sFirstChar === "\t")) + { + $sValue = \is_null($sValue) ? '' : $sValue; + + if ('?=' === \substr(\rtrim($sHeadersValue), -2)) + { + $sHeadersValue = \rtrim($sHeadersValue); + } + + if ('=?' === \substr(\ltrim($sHeadersValue), 0, 2)) + { + $sHeadersValue = \ltrim($sHeadersValue); + } + + if ('=?' === \substr($sHeadersValue, 0, 2)) + { + $sValue .= $sHeadersValue; + } + else + { + $sValue .= "\n".$sHeadersValue; + } + } + else + { + if (null !== $sName) + { + $oHeader = Header::NewInstanceFromEncodedString($sName.': '.$sValue, $this->sParentCharset); + if ($oHeader) + { + $this->Add($oHeader); + } + $sName = null; + $sValue = null; + } + + $aHeaderParts = \explode(':', $sHeadersValue, 2); + $sName = $aHeaderParts[0]; + $sValue = isset($aHeaderParts[1]) ? $aHeaderParts[1] : ''; + + if ('?=' === \substr(\rtrim($sValue), -2)) + { + $sValue = \rtrim($sValue); + } + } + } + + if (null !== $sName) + { + $oHeader = Header::NewInstanceFromEncodedString($sName.': '.$sValue, $this->sParentCharset); + if ($oHeader) + { + $this->Add($oHeader); + } + } + + return $this; + } + + /** + * @return string + */ + public function ToEncodedString() + { + $aResult = array(); + $aHeaders =& $this->GetAsArray(); + foreach ($aHeaders as /* @var $oHeader \MailSo\Mime\Header */ &$oHeader) + { + $aResult[] = $oHeader->EncodedValue(); + } + + return \implode(\MailSo\Mime\Enumerations\Constants::CRLF, $aResult); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Message.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Message.php new file mode 100644 index 000000000..32f03a1ac --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Message.php @@ -0,0 +1,798 @@ +aHeadersValue = array(); + $this->aAlternativeParts = array(); + $this->oAttachmentCollection = AttachmentCollection::NewInstance(); + $this->sMessageId = ''; + $this->sCustomXMailer = ''; + $this->bAddEmptyTextPart = true; + } + + /** + * @return \MailSo\Mime\Message + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @return void + */ + public function DoesNotCreateEmptyTextPart() + { + $this->bAddEmptyTextPart = false; + } + + /** + * @return string + */ + public function MessageId() + { + return $this->sMessageId; + } + + /** + * @param string $sMessageId + * + * @return void + */ + public function SetMessageId($sMessageId) + { + $this->sMessageId = $sMessageId; + } + + /** + * @param string $sHostName = '' + * + * @return void + */ + public function RegenerateMessageId($sHostName = '') + { + $this->SetMessageId($this->generateNewMessageId($sHostName)); + } + + /** + * @return \MailSo\Mime\AttachmentCollection + */ + public function Attachments() + { + return $this->oAttachmentCollection; + } + + /** + * @return \MailSo\Mime\EmailCollection + */ + public function GetTo() + { + $oResult = \MailSo\Mime\EmailCollection::NewInstance(); + + if (isset($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::TO_]) && + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::TO_] instanceof \MailSo\Mime\EmailCollection) + { + $oResult->MergeWithOtherCollection($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::TO_]); + } + + return $oResult->Unique(); + } + + /** + * @return \MailSo\Mime\EmailCollection + */ + public function GetRcpt() + { + $oResult = \MailSo\Mime\EmailCollection::NewInstance(); + + if (isset($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::TO_]) && + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::TO_] instanceof \MailSo\Mime\EmailCollection) + { + $oResult->MergeWithOtherCollection($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::TO_]); + } + + if (isset($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::CC]) && + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::CC] instanceof \MailSo\Mime\EmailCollection) + { + $oResult->MergeWithOtherCollection($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::CC]); + } + + if (isset($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::BCC]) && + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::BCC] instanceof \MailSo\Mime\EmailCollection) + { + $oResult->MergeWithOtherCollection($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::BCC]); + } + + return $oResult->Unique(); + } + + /** + * @param string $sHeader + * @param string $sValue + * + * @return \MailSo\Mime\Message + */ + public function SetCustomHeader($sHeaderName, $sValue) + { + $sHeaderName = \trim($sHeaderName); + if (0 < \strlen($sHeaderName)) + { + $this->aHeadersValue[$sHeaderName] = $sValue; + } + + return $this; + } + + /** + * @param string $sSubject + * + * @return \MailSo\Mime\Message + */ + public function SetSubject($sSubject) + { + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::SUBJECT] = $sSubject; + + return $this; + } + + /** + * @param string $sInReplyTo + * + * @return \MailSo\Mime\Message + */ + public function SetInReplyTo($sInReplyTo) + { + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::IN_REPLY_TO] = $sInReplyTo; + + return $this; + } + + /** + * @param string $sReferences + * + * @return \MailSo\Mime\Message + */ + public function SetReferences($sReferences) + { + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::REFERENCES] = $sReferences; + + return $this; + } + + /** + * @param string $sEmail + * + * @return \MailSo\Mime\Message + */ + public function SetReadConfirmation($sEmail) + { + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::DISPOSITION_NOTIFICATION_TO] = $sEmail; + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::X_CONFIRM_READING_TO] = $sEmail; + + return $this; + } + + /** + * @param int $iValue + * + * @return \MailSo\Mime\Message + */ + public function SetPriority($iValue) + { + $sResult = ''; + switch ($iValue) + { + case \MailSo\Mime\Enumerations\MessagePriority::HIGH: + $sResult = \MailSo\Mime\Enumerations\MessagePriority::HIGH.' (Highest)'; + break; + case \MailSo\Mime\Enumerations\MessagePriority::NORMAL: + $sResult = \MailSo\Mime\Enumerations\MessagePriority::NORMAL.' (Normal)'; + break; + case \MailSo\Mime\Enumerations\MessagePriority::LOW: + $sResult = \MailSo\Mime\Enumerations\MessagePriority::LOW.' (Lowest)'; + break; + } + + if (0 < \strlen($sResult)) + { + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::X_PRIORITY] = $sResult; + } + + return $this; + } + + /** + * @param int $iValue + * + * @return \MailSo\Mime\Message + */ + public function SetSensivity($iValue) + { + $sResult = ''; + switch ($iValue) + { + case \MailSo\Mime\Enumerations\Sensitivity::CONFIDENTIAL: + $sResult = 'Company-Confidential'; + break; + case \MailSo\Mime\Enumerations\Sensitivity::PERSONAL: + $sResult = 'Personal'; + break; + case \MailSo\Mime\Enumerations\Sensitivity::PRIVATE_: + $sResult = 'Private'; + break; + } + + if (0 < \strlen($sResult)) + { + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::SENSITIVITY] = $sResult; + } + + return $this; + } + + /** + * @param string $sXMailer + * + * @return \MailSo\Mime\Message + */ + public function SetXMailer($sXMailer) + { + $this->sCustomXMailer = $sXMailer; + + return $this; + } + + /** + * @param \MailSo\Mime\Email $oEmail + * + * @return \MailSo\Mime\Message + */ + public function SetFrom(\MailSo\Mime\Email $oEmail) + { + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::FROM_] = $oEmail; + + return $this; + } + + /** + * @param \MailSo\Mime\EmailCollection $oEmails + * + * @return \MailSo\Mime\Message + */ + public function SetTo(\MailSo\Mime\EmailCollection $oEmails) + { + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::TO_] = $oEmails; + + return $this; + } + + /** + * @param \MailSo\Mime\EmailCollection $oEmails + * + * @return \MailSo\Mime\Message + */ + public function SetReplyTo(\MailSo\Mime\EmailCollection $oEmails) + { + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::REPLY_TO] = $oEmails; + + return $this; + } + + /** + * @param \MailSo\Mime\EmailCollection $oEmails + * + * @return \MailSo\Mime\Message + */ + public function SetCc(\MailSo\Mime\EmailCollection $oEmails) + { + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::CC] = $oEmails; + + return $this; + } + + /** + * @param \MailSo\Mime\EmailCollection $oEmails + * + * @return \MailSo\Mime\Message + */ + public function SetBcc(\MailSo\Mime\EmailCollection $oEmails) + { + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::BCC] = $oEmails; + + return $this; + } + + /** + * @param \MailSo\Mime\EmailCollection $oEmails + * + * @return \MailSo\Mime\Message + */ + public function SetSender(\MailSo\Mime\EmailCollection $oEmails) + { + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::SENDER] = $oEmails; + + return $this; + } + + /** + * @param string $sType + * @param string $sUid + * @param string $sFolder + * + * @return \MailSo\Mime\Message + */ + public function SetDraftInfo($sType, $sUid, $sFolder) + { + $this->aHeadersValue[\MailSo\Mime\Enumerations\Header::X_DRAFT_INFO] = \MailSo\Mime\ParameterCollection::NewInstance() + ->Add(\MailSo\Mime\Parameter::NewInstance('type', $sType)) + ->Add(\MailSo\Mime\Parameter::NewInstance('uid', $sUid)) + ->Add(\MailSo\Mime\Parameter::NewInstance('folder', base64_encode($sFolder))) + ; + + return $this; + } + + /** + * @param string $sPlain + * + * @return \MailSo\Mime\Message + */ + public function AddPlain($sPlain) + { + return $this->AddAlternative( + \MailSo\Mime\Enumerations\MimeType::TEXT_PLAIN, trim($sPlain), + \MailSo\Base\Enumerations\Encoding::QUOTED_PRINTABLE); + } + /** + * @param string $sHtml + * + * @return \MailSo\Mime\Message + */ + public function AddHtml($sHtml) + { + return $this->AddAlternative( + \MailSo\Mime\Enumerations\MimeType::TEXT_HTML, trim($sHtml), + \MailSo\Base\Enumerations\Encoding::QUOTED_PRINTABLE); + } + + /** + * @param string $sHtmlOrPlainText + * @param bool $bIsHtml = false + * + * @return \MailSo\Mime\Message + */ + public function AddText($sHtmlOrPlainText, $bIsHtml = false) + { + return $bIsHtml ? $this->AddHtml($sHtmlOrPlainText) : $this->AddPlain($sHtmlOrPlainText); + } + + /** + * @param string $sContentType + * @param string | resource $mData + * @param string $sContentTransferEncoding = '' + * + * @return \MailSo\Mime\Message + */ + public function AddAlternative($sContentType, $mData, $sContentTransferEncoding = '') + { + $this->aAlternativeParts[] = array($sContentType, $mData, $sContentTransferEncoding); + + return $this; + } + + /** + * @return string + */ + private function generateNewBoundary() + { + return '----=_Part_'.mt_rand(100, 999).'_'.mt_rand(100000000, 999999999).'.'.time(); + } + + /** + * @param string $sHostName = '' + * + * @return string + */ + private function generateNewMessageId($sHostName = '') + { + if (0 === strlen($sHostName)) + { + $sHostName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'mailso'; + } + + return '<'.md5(mt_rand(100000, 999999).time().$sHostName).'@'.$sHostName.'>'; + } + + /** + * @param \MailSo\Mime\Attachment $oAttachment + * + * @return \MailSo\Mime\Part + */ + private function createNewMessageAttachmentBody($oAttachment) + { + $oAttachmentPart = Part::NewInstance(); + + $sFileName = $oAttachment->FileName(); + $sCID = $oAttachment->CID(); + + $oContentTypeParameters = null; + $oContentDispositionParameters = null; + + if (0 < strlen(trim($sFileName))) + { + $oContentTypeParameters = + ParameterCollection::NewInstance()->Add(Parameter::NewInstance( + \MailSo\Mime\Enumerations\Parameter::NAME, $sFileName)); + + $oContentDispositionParameters = + ParameterCollection::NewInstance()->Add(Parameter::NewInstance( + \MailSo\Mime\Enumerations\Parameter::FILENAME, $sFileName)); + } + + $oAttachmentPart->Headers->Add( + Header::NewInstance(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, + $oAttachment->ContentType().';'. + (($oContentTypeParameters) ? ' '.$oContentTypeParameters->ToString() : '') + ) + ); + + $oAttachmentPart->Headers->Add( + Header::NewInstance(\MailSo\Mime\Enumerations\Header::CONTENT_DISPOSITION, + ($oAttachment->IsInline() ? 'inline' : 'attachment').';'. + (($oContentDispositionParameters) ? ' '.$oContentDispositionParameters->ToString() : '') + ) + ); + + if (0 < strlen($sCID)) + { + $oAttachmentPart->Headers->Add( + Header::NewInstance(\MailSo\Mime\Enumerations\Header::CONTENT_ID, $sCID) + ); + } + + $oAttachmentPart->Body = $oAttachment->Resource(); + + if ('message/rfc822' !== strtolower($oAttachment->ContentType())) + { + $oAttachmentPart->Headers->Add( + Header::NewInstance( + \MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING, + \MailSo\Base\Enumerations\Encoding::BASE64 + ) + ); + + if (is_resource($oAttachmentPart->Body)) + { + $oAttachmentPart->Body = + \MailSo\Base\StreamWrappers\Binary::CreateStream($oAttachmentPart->Body, + \MailSo\Base\StreamWrappers\Binary::GetInlineDecodeOrEncodeFunctionName( + \MailSo\Base\Enumerations\Encoding::BASE64, false)); + } + } + + return $oAttachmentPart; + } + + /** + * @param array $aAlternativeData + * + * @return \MailSo\Mime\Part + */ + private function createNewMessageAlternativePartBody($aAlternativeData) + { + $oAlternativePart = null; + + if (is_array($aAlternativeData) && isset($aAlternativeData[0])) + { + $oAlternativePart = Part::NewInstance(); + + $oAlternativePart->Headers->Add( + Header::NewInstance(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, + $aAlternativeData[0].'; '. + ParameterCollection::NewInstance()->Add( + Parameter::NewInstance( + \MailSo\Mime\Enumerations\Parameter::CHARSET, + \MailSo\Base\Enumerations\Charset::UTF_8) + )->ToString() + ) + ); + + $oAlternativePart->Body = null; + if (isset($aAlternativeData[1])) + { + if (is_resource($aAlternativeData[1])) + { + $oAlternativePart->Body = $aAlternativeData[1]; + } + else if (is_string($aAlternativeData[1]) && 0 < strlen($aAlternativeData[1])) + { + $oAlternativePart->Body = + \MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString($aAlternativeData[1]); + } + } + + if (isset($aAlternativeData[2]) && 0 < strlen($aAlternativeData[2])) + { + $oAlternativePart->Headers->Add( + Header::NewInstance(\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING, + $aAlternativeData[2] + ) + ); + + if (is_resource($oAlternativePart->Body)) + { + $oAlternativePart->Body = + \MailSo\Base\StreamWrappers\Binary::CreateStream($oAlternativePart->Body, + \MailSo\Base\StreamWrappers\Binary::GetInlineDecodeOrEncodeFunctionName( + $aAlternativeData[2], false)); + } + } + + if (!is_resource($oAlternativePart->Body)) + { + $oAlternativePart->Body = + \MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString(''); + } + } + + return $oAlternativePart; + } + + /** + * @param \MailSo\Mime\Part $oPlainPart + * @param \MailSo\Mime\Part $oHtmlPart + * + * @return \MailSo\Mime\Part + */ + private function createNewMessageSimpleOrAlternativeBody() + { + $oResultPart = null; + if (1 < count($this->aAlternativeParts)) + { + $oResultPart = Part::NewInstance(); + + $oResultPart->Headers->Add( + Header::NewInstance(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, + \MailSo\Mime\Enumerations\MimeType::MULTIPART_ALTERNATIVE.'; '. + ParameterCollection::NewInstance()->Add( + Parameter::NewInstance( + \MailSo\Mime\Enumerations\Parameter::BOUNDARY, + $this->generateNewBoundary()) + )->ToString() + ) + ); + + foreach ($this->aAlternativeParts as $aAlternativeData) + { + $oAlternativePart = $this->createNewMessageAlternativePartBody($aAlternativeData); + if ($oAlternativePart) + { + $oResultPart->SubParts->Add($oAlternativePart); + } + + unset($oAlternativePart); + } + + } + else if (1 === count($this->aAlternativeParts)) + { + $oAlternativePart = $this->createNewMessageAlternativePartBody($this->aAlternativeParts[0]); + if ($oAlternativePart) + { + $oResultPart = $oAlternativePart; + } + } + + if (!$oResultPart) + { + if ($this->bAddEmptyTextPart) + { + $oResultPart = $this->createNewMessageAlternativePartBody(array( + \MailSo\Mime\Enumerations\MimeType::TEXT_PLAIN, null + )); + } + else + { + $aAttachments = $this->oAttachmentCollection->CloneAsArray(); + if (1 === count($aAttachments) && isset($aAttachments[0])) + { + $this->oAttachmentCollection->Clear(); + + $oResultPart = $this->createNewMessageAlternativePartBody(array( + $aAttachments[0]->ContentType(), $aAttachments[0]->Resource() + )); + } + } + } + + return $oResultPart; + } + + /** + * @param \MailSo\Mime\Part $oIncPart + * + * @return \MailSo\Mime\Part + */ + private function createNewMessageRelatedBody($oIncPart) + { + $oResultPart = null; + + $aAttachments = $this->oAttachmentCollection->LinkedAttachments(); + if (0 < count($aAttachments)) + { + $oResultPart = Part::NewInstance(); + + $oResultPart->Headers->Add( + Header::NewInstance(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, + \MailSo\Mime\Enumerations\MimeType::MULTIPART_RELATED.'; '. + ParameterCollection::NewInstance()->Add( + Parameter::NewInstance( + \MailSo\Mime\Enumerations\Parameter::BOUNDARY, + $this->generateNewBoundary()) + )->ToString() + ) + ); + + $oResultPart->SubParts->Add($oIncPart); + + foreach ($aAttachments as $oAttachment) + { + $oResultPart->SubParts->Add($this->createNewMessageAttachmentBody($oAttachment)); + } + } + else + { + $oResultPart = $oIncPart; + } + + return $oResultPart; + } + + /** + * @param \MailSo\Mime\Part $oIncPart + * + * @return \MailSo\Mime\Part + */ + private function createNewMessageMixedBody($oIncPart) + { + $oResultPart = null; + + $aAttachments = $this->oAttachmentCollection->UnlinkedAttachments(); + if (0 < count($aAttachments)) + { + $oResultPart = Part::NewInstance(); + + $oResultPart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, + \MailSo\Mime\Enumerations\MimeType::MULTIPART_MIXED.'; '. + ParameterCollection::NewInstance()->Add( + Parameter::NewInstance( + \MailSo\Mime\Enumerations\Parameter::BOUNDARY, + $this->generateNewBoundary()) + )->ToString() + ); + + $oResultPart->SubParts->Add($oIncPart); + + foreach ($aAttachments as $oAttachment) + { + $oResultPart->SubParts->Add($this->createNewMessageAttachmentBody($oAttachment)); + } + } + else + { + $oResultPart = $oIncPart; + } + + return $oResultPart; + } + + /** + * @param \MailSo\Mime\Part $oIncPart + * @param bool $bWithoutBcc = false + * + * @return \MailSo\Mime\Part + */ + private function setDefaultHeaders($oIncPart, $bWithoutBcc = false) + { + $oIncPart->Headers->SetByName(\MailSo\Mime\Enumerations\Header::DATE, \gmdate('r'), true); + if (0 < \strlen($this->sMessageId)) + { + $oIncPart->Headers->SetByName(\MailSo\Mime\Enumerations\Header::MESSAGE_ID, $this->sMessageId, true); + } + + $oIncPart->Headers->SetByName(\MailSo\Mime\Enumerations\Header::X_MAILER, + 0 === \strlen($this->sCustomXMailer) ? \MailSo\Version::XMailer() : $this->sCustomXMailer, true); + + $oIncPart->Headers->SetByName(\MailSo\Mime\Enumerations\Header::MIME_VERSION, '1.0', true); + + foreach ($this->aHeadersValue as $sName => $mValue) + { + if (\is_object($mValue)) + { + if ($mValue instanceof \MailSo\Mime\EmailCollection || $mValue instanceof \MailSo\Mime\Email || + $mValue instanceof \MailSo\Mime\ParameterCollection) + { + $mValue = $mValue->ToString(); + } + } + + if (!($bWithoutBcc && \strtolower(\MailSo\Mime\Enumerations\Header::BCC) === \strtolower($sName))) + { + $oIncPart->Headers->SetByName($sName, (string) $mValue); + } + } + + return $oIncPart; + } + + /** + * @param bool $bWithoutBcc = false + * + * @return \MailSo\Mime\Part + */ + public function ToPart($bWithoutBcc = false) + { + $oPart = $this->createNewMessageSimpleOrAlternativeBody(); + $oPart = $this->createNewMessageRelatedBody($oPart); + $oPart = $this->createNewMessageMixedBody($oPart); + $oPart = $this->setDefaultHeaders($oPart, $bWithoutBcc); + + return $oPart; + } + + /** + * @param bool $bWithoutBcc = false + * + * @return resource + */ + public function ToStream($bWithoutBcc = false) + { + return $this->ToPart($bWithoutBcc)->ToStream(); + } + + /** + * @param bool $bWithoutBcc = false + * + * @return string + */ + public function ToString($bWithoutBcc = false) + { + return \stream_get_contents($this->ToStream($bWithoutBcc)); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Parameter.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Parameter.php new file mode 100644 index 000000000..1f6f28ed2 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Parameter.php @@ -0,0 +1,132 @@ +sName = $sName; + $this->sValue = $sValue; + } + + /** + * @param string $sName + * @param string $sValue = '' + * + * @return \MailSo\Mime\Parameter + */ + public static function NewInstance($sName, $sValue = '') + { + return new self($sName, $sValue); + } + + /** + * @param string $sName + * @param string $sValue = '' + * + * @return \MailSo\Mime\Parameter + */ + public static function CreateFromParameterLine($sRawParam) + { + $oParameter = self::NewInstance(''); + return $oParameter->Parse($sRawParam); + } + + /** + * @return \MailSo\Mime\Parameter + */ + public function Reset() + { + $this->sName = ''; + $this->sValue = ''; + + return $this; + } + + /** + * @return string + */ + public function Name() + { + return $this->sName; + } + + /** + * @return string + */ + public function Value() + { + return $this->sValue; + } + + /** + * @param string $sRawParam + * @param string $sSeparator = '=' + * + * @return \MailSo\Mime\Parameter + */ + public function Parse($sRawParam, $sSeparator = '=') + { + $this->Reset(); + + $aParts = explode($sSeparator, $sRawParam, 2); + + $this->sName = trim(trim($aParts[0]), '"\''); + if (2 === count($aParts)) + { + $this->sValue = trim(trim($aParts[1]), '"\''); + } + + return $this; + } + + /** + * @param bool $bConvertSpecialsName = false + * + * @return string + */ + public function ToString($bConvertSpecialsName = false) + { + $sResult = ''; + if (0 < strlen($this->sName)) + { + $sResult = $this->sName.'='; + if ($bConvertSpecialsName && in_array(strtolower($this->sName), array( + strtolower(\MailSo\Mime\Enumerations\Parameter::NAME), + strtolower(\MailSo\Mime\Enumerations\Parameter::FILENAME) + ))) + { + $sResult .= '"'.\MailSo\Base\Utils::EncodeUnencodedValue( + \MailSo\Base\Enumerations\Encoding::BASE64_SHORT, + $this->sValue).'"'; + } + else + { + $sResult .= '"'.$this->sValue.'"'; + } + } + + return $sResult; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/ParameterCollection.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/ParameterCollection.php new file mode 100644 index 000000000..879648e9d --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/ParameterCollection.php @@ -0,0 +1,197 @@ +Parse($sRawParams); + } + } + + /** + * @param string $sRawParams = '' + * + * @return \MailSo\Mime\ParameterCollection + */ + public static function NewInstance($sRawParams = '') + { + return new self($sRawParams); + } + + /** + * @return \MailSo\Mime\Parameter|null + */ + public function &GetByIndex($iIndex) + { + $mResult = null; + $mResult =& parent::GetByIndex($iIndex); + return $mResult; + } + + /** + * @param array $aList + * + * @return \MailSo\Mime\ParameterCollection + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function SetAsArray($aList) + { + parent::SetAsArray($aList); + + return $this; + } + + /** + * @param string $sName + * + * @return string + */ + public function ParameterValueByName($sName) + { + $sResult = ''; + $sName = trim($sName); + + $aParams =& $this->GetAsArray(); + foreach ($aParams as /* @var $oParam \MailSo\Mime\ParameterCollection */ $oParam) + { + if (strtolower($sName) === strtolower($oParam->Name())) + { + $sResult = $oParam->Value(); + break; + } + } + + return $sResult; + } + + /** + * @param string $sRawParams + * + * @return \MailSo\Mime\ParameterCollection + */ + public function Parse($sRawParams) + { + $this->Clear(); + + $aDataToParse = explode(';', $sRawParams); + + foreach ($aDataToParse as $sParam) + { + $this->Add(Parameter::CreateFromParameterLine($sParam)); + } + + $this->reParseParameters(); + + return $this; + } + + /** + * @param bool $bConvertSpecialsName = false + * + * @return string + */ + public function ToString($bConvertSpecialsName = false) + { + $aResult = array(); + $aParams =& $this->GetAsArray(); + foreach ($aParams as /* @var $oParam \MailSo\Mime\Parameter */ $oParam) + { + $sLine = $oParam->ToString($bConvertSpecialsName); + if (0 < strlen($sLine)) + { + $aResult[] = $sLine; + } + } + + return 0 < count($aResult) ? implode('; ', $aResult) : ''; + } + + /** + * @return void + */ + private function reParseParameters() + { + $aDataToReParse = $this->CloneAsArray(); + $sCharset = \MailSo\Base\Enumerations\Charset::UTF_8; + + $this->Clear(); + + $aPreParams = array(); + foreach ($aDataToReParse as /* @var $oParam \MailSo\Mime\Parameter */ $oParam) + { + $aMatch = array(); + $sParamName = $oParam->Name(); + + if (preg_match('/([^\*]+)\*([\d]{1,2})\*/', $sParamName, $aMatch) && isset($aMatch[1], $aMatch[2]) + && 0 < strlen($aMatch[1]) && is_numeric($aMatch[2])) + { + if (!isset($aPreParams[$aMatch[1]])) + { + $aPreParams[$aMatch[1]] = array(); + } + + $sValue = $oParam->Value(); + $aValueParts = explode('\'\'', $sValue, 2); + if (is_array($aValueParts) && 2 === count($aValueParts) && 0 < strlen($aValueParts[1])) + { + $sCharset = $aValueParts[0]; + $sValue = $aValueParts[1]; + } + + $aPreParams[$aMatch[1]][(int) $aMatch[2]] = $sValue; + } + else if (preg_match('/([^\*]+)\*/', $sParamName, $aMatch) && isset($aMatch[1])) + { + if (!isset($aPreParams[$aMatch[1]])) + { + $aPreParams[$aMatch[1]] = array(); + } + + $sValue = $oParam->Value(); + $aValueParts = explode('\'\'', $sValue, 2); + if (is_array($aValueParts) && 2 === count($aValueParts) && 0 < strlen($aValueParts[1])) + { + $sCharset = $aValueParts[0]; + $sValue = $aValueParts[1]; + } + + $aPreParams[$aMatch[1]][0] = $sValue; + } + else + { + $this->Add($oParam); + } + } + + foreach ($aPreParams as $sName => $aValues) + { + ksort($aValues); + $sResult = implode(array_values($aValues)); + $sResult = urldecode($sResult); + + if (0 < strlen($sCharset)) + { + $sResult = \MailSo\Base\Utils::ConvertEncoding($sResult, + $sCharset, \MailSo\Base\Enumerations\Charset::UTF_8); + } + + $this->Add(Parameter::NewInstance($sName, $sResult)); + } + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Parser/ParserEmpty.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Parser/ParserEmpty.php new file mode 100644 index 000000000..c13b6c8c6 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Parser/ParserEmpty.php @@ -0,0 +1,72 @@ +oCurrentMime = $oPart; + } + + /** + * @param string $sBuffer + * + * @return void + */ + public function WriteBody($sBuffer) + { + if (null === $this->oCurrentMime->Body) + { + $this->oCurrentMime->Body = \MailSo\Base\ResourceRegistry::CreateMemoryResource(); + } + + if (\is_resource($this->oCurrentMime->Body)) + { + \fwrite($this->oCurrentMime->Body, $sBuffer); + } + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Part.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Part.php new file mode 100644 index 000000000..9c8051e17 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/Part.php @@ -0,0 +1,618 @@ +iParseBuffer = \MailSo\Mime\Part::DEFAUL_BUFFER; + $this->Reset(); + } + + /** + * @return \MailSo\Mime\Part + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @return \MailSo\Mime\Part + */ + public function Reset() + { + \MailSo\Base\ResourceRegistry::CloseMemoryResource($this->Body); + $this->Body = null; + + $this->Headers = HeaderCollection::NewInstance(); + $this->SubParts = PartCollection::NewInstance(); + $this->LineParts = array(); + $this->sBoundary = ''; + $this->sParentCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1; + + return $this; + } + + /** + * @return string + */ + public function Boundary() + { + return $this->sBoundary; + } + + /** + * @return string + */ + public function ParentCharset() + { + return (0 < strlen($this->sCharset)) ? $this->sParentCharset : self::$DefaultCharset; + } + + /** + * @param string $sParentCharset + * @return \MailSo\Mime\Part + */ + public function SetParentCharset($sParentCharset) + { + $this->sParentCharset = $sParentCharset; + + return $this; + } + + /** + * @param string $sBoundary + * @return \MailSo\Mime\Part + */ + public function SetBoundary($sBoundary) + { + $this->sBoundary = $sBoundary; + + return $this; + } + + /** + * @param int $iParseBuffer + * @return \MailSo\Mime\Part + */ + public function SetParseBuffer($iParseBuffer) + { + $this->iParseBuffer = $iParseBuffer; + + return $this; + } + + /** + * @return string + */ + public function HeaderCharset() + { + return ($this->Headers) ? trim(strtolower($this->Headers->ParameterValue( + \MailSo\Mime\Enumerations\Header::CONTENT_TYPE, + \MailSo\Mime\Enumerations\Parameter::CHARSET))) : ''; + } + + /** + * @return string + */ + public function HeaderBoundary() + { + return ($this->Headers) ? trim($this->Headers->ParameterValue( + \MailSo\Mime\Enumerations\Header::CONTENT_TYPE, + \MailSo\Mime\Enumerations\Parameter::BOUNDARY)) : ''; + } + + /** + * @return string + */ + public function ContentType() + { + return ($this->Headers) ? + trim(strtolower($this->Headers->ValueByName( + \MailSo\Mime\Enumerations\Header::CONTENT_TYPE))) : ''; + } + + /** + * @return string + */ + public function ContentTransferEncoding() + { + return ($this->Headers) ? + trim(strtolower($this->Headers->ValueByName( + \MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING))) : ''; + } + + /** + * @return string + */ + public function ContentID() + { + return ($this->Headers) ? trim($this->Headers->ValueByName( + \MailSo\Mime\Enumerations\Header::CONTENT_ID)) : ''; + } + + /** + * @return string + */ + public function ContentLocation() + { + return ($this->Headers) ? trim($this->Headers->ValueByName( + \MailSo\Mime\Enumerations\Header::CONTENT_LOCATION)) : ''; + } + + /** + * @return string + */ + public function FileName() + { + $sResult = ''; + if ($this->Headers) + { + $sResult = trim($this->Headers->ParameterValue( + \MailSo\Mime\Enumerations\Header::CONTENT_DISPOSITION, + \MailSo\Mime\Enumerations\Parameter::FILENAME)); + + if (0 === strlen($sResult)) + { + $sResult = trim($this->Headers->ParameterValue( + \MailSo\Mime\Enumerations\Header::CONTENT_TYPE, + \MailSo\Mime\Enumerations\Parameter::NAME)); + } + } + + return $sResult; + } + + /** + * @param string $sFileName + * @return \MailSo\Mime\Part + */ + public function ParseFromFile($sFileName) + { + $rStreamHandle = (@file_exists($sFileName)) ? @fopen($sFileName, 'rb') : false; + if (is_resource($rStreamHandle)) + { + $this->ParseFromStream($rStreamHandle); + + if (is_resource($rStreamHandle)) + { + fclose($rStreamHandle); + } + } + + return $this; + } + + /** + * @param string $sRawMessage + * @return \MailSo\Mime\Part + */ + public function ParseFromString($sRawMessage) + { + $rStreamHandle = (0 < strlen($sRawMessage)) ? + \MailSo\Base\ResourceRegistry::CreateMemoryResource() : false; + + if (is_resource($rStreamHandle)) + { + fwrite($rStreamHandle, $sRawMessage); + unset($sRawMessage); + fseek($rStreamHandle, 0); + + $this->ParseFromStream($rStreamHandle); + + \MailSo\Base\ResourceRegistry::CloseMemoryResource($rStreamHandle); + } + + return $this; + } + + /** + * @param resource $rStreamHandle + * @return \MailSo\Mime\Part + */ + public function ParseFromStream($rStreamHandle) + { + $this->Reset(); + + $oParserClass = new \MailSo\Mime\Parser\ParserMemory(); + + $oMimePart = null; + $bIsOef = false; + $iOffset = 0; + $sBuffer = ''; + $sPrevBuffer = ''; + $aBoundaryStack = array(); + + + $oParserClass->StartParse($this); + + $this->LineParts[] =& $this; + $this->ParseFromStreamRecursion($rStreamHandle, $oParserClass, $iOffset, + $sPrevBuffer, $sBuffer, $aBoundaryStack, $bIsOef); + + $sFirstNotNullCharset = null; + foreach ($this->LineParts as /* @var $oMimePart \MailSo\Mime\Part */ &$oMimePart) + { + $sCharset = $oMimePart->HeaderCharset(); + if (0 < strlen($sCharset)) + { + $sFirstNotNullCharset = $sCharset; + break; + } + } + + $sForceCharset = self::$ForceCharset; + if (0 < strlen($sForceCharset)) + { + foreach ($this->LineParts as /* @var $oMimePart \MailSo\Mime\Part */ &$oMimePart) + { + $oMimePart->SetParentCharset($sForceCharset); + $oMimePart->Headers->SetParentCharset($sForceCharset); + } + } + else + { + $sFirstNotNullCharset = (null !== $sFirstNotNullCharset) + ? $sFirstNotNullCharset : self::$DefaultCharset; + + foreach ($this->LineParts as /* @var $oMimePart \MailSo\Mime\Part */ &$oMimePart) + { + $sHeaderCharset = $oMimePart->HeaderCharset(); + $oMimePart->SetParentCharset((0 < strlen($sHeaderCharset)) ? $sHeaderCharset : $sFirstNotNullCharset); + $oMimePart->Headers->SetParentCharset($sHeaderCharset); + } + } + + $oParserClass->EndParse($this); + + return $this; + } + + /** + * @param resource $rStreamHandle + * @return \MailSo\Mime\Part + */ + public function ParseFromStreamRecursion($rStreamHandle, &$oCallbackClass, &$iOffset, + &$sPrevBuffer, &$sBuffer, &$aBoundaryStack, &$bIsOef, $bNotFirstRead = false) + { + $oCallbackClass->StartParseMimePart($this); + + $iPos = 0; + $iParsePosition = self::POS_HEADERS; + $sCurrentBoundary = ''; + $bIsBoundaryCheck = false; + $aHeadersLines = array(); + while (true) + { + if (!$bNotFirstRead) + { + $sPrevBuffer = $sBuffer; + $sBuffer = ''; + } + + if (!$bIsOef && !feof($rStreamHandle)) + { + if (!$bNotFirstRead) + { + $sBuffer = @fread($rStreamHandle, $this->iParseBuffer); + if (false === $sBuffer) + { + break; + } + + $oCallbackClass->ReadBuffer($sBuffer); + } + else + { + $bNotFirstRead = false; + } + } + else if ($bIsOef && 0 === strlen($sBuffer)) + { + break; + } + else + { + $bIsOef = true; + } + + while (true) + { + $sCurrentLine = $sPrevBuffer.$sBuffer; + if (self::POS_HEADERS === $iParsePosition) + { + $iEndLen = 4; + $iPos = strpos($sCurrentLine, "\r\n\r\n", $iOffset); + if (false === $iPos) + { + $iEndLen = 2; + $iPos = strpos($sCurrentLine, "\n\n", $iOffset); + } + + if (false !== $iPos) + { + $aHeadersLines[] = substr($sCurrentLine, $iOffset, $iPos + $iEndLen - $iOffset); + + $this->Headers->Parse(implode($aHeadersLines))->SetParentCharset($this->HeaderCharset()); + $aHeadersLines = array(); + + $oCallbackClass->InitMimePartHeader(); + + $sBoundary = $this->HeaderBoundary(); + if (0 < strlen($sBoundary)) + { + $sBoundary = '--'.$sBoundary; + $sCurrentBoundary = $sBoundary; + array_unshift($aBoundaryStack, $sBoundary); + } + + $iOffset = $iPos + $iEndLen; + $iParsePosition = self::POS_BODY; + continue; + } + else + { + $iBufferLen = strlen($sPrevBuffer); + if ($iBufferLen > $iOffset) + { + $aHeadersLines[] = substr($sPrevBuffer, $iOffset); + $iOffset = 0; + } + else + { + $iOffset -= $iBufferLen; + } + break; + } + } + else if (self::POS_BODY === $iParsePosition) + { + $iPos = false; + $sBoundaryLen = 0; + $bIsBoundaryEnd = false; + $bCurrentPartBody = false; + $bIsBoundaryCheck = 0 < count($aBoundaryStack); + + foreach ($aBoundaryStack as $sKey => $sBoundary) + { + if (false !== ($iPos = strpos($sCurrentLine, $sBoundary, $iOffset))) + { + if ($sCurrentBoundary === $sBoundary) + { + $bCurrentPartBody = true; + } + + $sBoundaryLen = strlen($sBoundary); + if ('--' === substr($sCurrentLine, $iPos + $sBoundaryLen, 2)) + { + $sBoundaryLen += 2; + $bIsBoundaryEnd = true; + unset($aBoundaryStack[$sKey]); + $sCurrentBoundary = (isset($aBoundaryStack[$sKey + 1])) + ? $aBoundaryStack[$sKey + 1] : ''; + } + + break; + } + } + + if (false !== $iPos) + { + $oCallbackClass->WriteBody(substr($sCurrentLine, $iOffset, $iPos - $iOffset)); + $iOffset = $iPos; + + if ($bCurrentPartBody) + { + $iParsePosition = self::POS_SUBPARTS; + continue; + } + + $oCallbackClass->EndParseMimePart($this); + return true; + } + else + { + $iBufferLen = strlen($sPrevBuffer); + if ($iBufferLen > $iOffset) + { + $oCallbackClass->WriteBody(substr($sPrevBuffer, $iOffset)); + $iOffset = 0; + } + else + { + $iOffset -= $iBufferLen; + } + break; + } + } + else if (self::POS_SUBPARTS === $iParsePosition) + { + $iPos = false; + $sBoundaryLen = 0; + $bIsBoundaryEnd = false; + $bCurrentPartBody = false; + $bIsBoundaryCheck = 0 < count($aBoundaryStack); + + foreach ($aBoundaryStack as $sKey => $sBoundary) + { + if (false !== ($iPos = strpos($sCurrentLine, $sBoundary, $iOffset))) + { + if ($sCurrentBoundary === $sBoundary) + { + $bCurrentPartBody = true; + } + + $sBoundaryLen = strlen($sBoundary); + if ('--' === substr($sCurrentLine, $iPos + $sBoundaryLen, 2)) + { + $sBoundaryLen += 2; + $bIsBoundaryEnd = true; + unset($aBoundaryStack[$sKey]); + $sCurrentBoundary = (isset($aBoundaryStack[$sKey + 1])) + ? $aBoundaryStack[$sKey + 1] : ''; + } + break; + } + } + + if (false !== $iPos && $bCurrentPartBody) + { + $iOffset = $iPos + $sBoundaryLen; + + $oSubPart = self::NewInstance(); + + $oSubPart + ->SetParseBuffer($this->iParseBuffer) + ->ParseFromStreamRecursion($rStreamHandle, $oCallbackClass, + $iOffset, $sPrevBuffer, $sBuffer, $aBoundaryStack, $bIsOef, true); + + $this->SubParts->Add($oSubPart); + $this->LineParts[] =& $oSubPart; + //$iParsePosition = self::POS_HEADERS; + unset($oSubPart); + } + else + { + $oCallbackClass->EndParseMimePart($this); + return true; + } + } + } + } + + if (0 < strlen($sPrevBuffer)) + { + if (self::POS_HEADERS === $iParsePosition) + { + $aHeadersLines[] = ($iOffset < strlen($sPrevBuffer)) + ? substr($sPrevBuffer, $iOffset) + : $sPrevBuffer; + + $this->Headers->Parse(implode($aHeadersLines))->SetParentCharset($this->HeaderCharset()); + $aHeadersLines = array(); + + $oCallbackClass->InitMimePartHeader(); + } + else if (self::POS_BODY === $iParsePosition) + { + if (!$bIsBoundaryCheck) + { + $oCallbackClass->WriteBody(($iOffset < strlen($sPrevBuffer)) + ? substr($sPrevBuffer, $iOffset) : $sPrevBuffer); + } + } + } + else + { + if (self::POS_HEADERS === $iParsePosition && 0 < count($aHeadersLines)) + { + $this->Headers->Parse(implode($aHeadersLines))->SetParentCharset($this->HeaderCharset()); + $aHeadersLines = array(); + + $oCallbackClass->InitMimePartHeader(); + } + } + + $oCallbackClass->EndParseMimePart($this); + + return $this; + } + + /** + * @return resorce + */ + public function ToStream() + { + $aSubStreams = array( + + $this->Headers->ToEncodedString(). + \MailSo\Mime\Enumerations\Constants::CRLF. + \MailSo\Mime\Enumerations\Constants::CRLF, + + null === $this->Body ? '' : $this->Body, + + \MailSo\Mime\Enumerations\Constants::CRLF + ); + + if (0 < $this->SubParts->Count()) + { + $sBoundary = $this->HeaderBoundary(); + if (0 < strlen($sBoundary)) + { + $aSubStreams[] = '--'.$sBoundary.\MailSo\Mime\Enumerations\Constants::CRLF; + + $rSubPartsStream = $this->SubParts->ToStream($sBoundary); + if (is_resource($rSubPartsStream)) + { + $aSubStreams[] = $rSubPartsStream; + } + + $aSubStreams[] = \MailSo\Mime\Enumerations\Constants::CRLF. + '--'.$sBoundary.'--'.\MailSo\Mime\Enumerations\Constants::CRLF; + } + } + + return \MailSo\Base\StreamWrappers\SubStreams::CreateStream($aSubStreams); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/PartCollection.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/PartCollection.php new file mode 100644 index 000000000..5634c22f3 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Mime/PartCollection.php @@ -0,0 +1,56 @@ +GetAsArray(); + foreach ($aParts as /* @var $oPart \MailSo\Mime\Part */ &$oPart) + { + if (0 < count($aResult)) + { + $aResult[] = \MailSo\Mime\Enumerations\Constants::CRLF. + '--'.$sBoundary.\MailSo\Mime\Enumerations\Constants::CRLF; + } + + $aResult[] = $oPart->ToStream(); + } + + return \MailSo\Base\StreamWrappers\SubStreams::CreateStream($aResult); + } + + return $rResult; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Enumerations/ConnectionSecurityType.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Enumerations/ConnectionSecurityType.php new file mode 100644 index 000000000..43fd82b38 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Enumerations/ConnectionSecurityType.php @@ -0,0 +1,60 @@ +sSocketMessage = $sSocketMessage; + $this->iSocketCode = $iSocketCode; + } + + /** + * @return string + */ + public function getSocketMessage() + { + return $this->sSocketMessage; + } + + /** + * @return int + */ + public function getSocketCode() + { + return $this->sSocketMessage; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Exceptions/SocketConnectionDoesNotAvailableException.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Exceptions/SocketConnectionDoesNotAvailableException.php new file mode 100644 index 000000000..765fee683 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Net/Exceptions/SocketConnectionDoesNotAvailableException.php @@ -0,0 +1,10 @@ +rConnect = null; + $this->bUnreadBuffer = false; + $this->oLogger = null; + + $this->sResponseBuffer = ''; + + $this->iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::NONE; + $this->sConnectedHost = ''; + $this->iConnectedPort = 0; + + $this->bSecure = false; + + $this->iConnectTimeOut = 10; + $this->iSocketTimeOut = 10; + + $this->Clear(); + } + + /** + * @return void + */ + public function __destruct() + { + $this->LogoutAndDisconnect(); + } + + /** + * @return void + */ + public function Clear() + { + $this->sResponseBuffer = ''; + + $this->sConnectedHost = ''; + $this->iConnectedPort = 0; + + $this->iStartConnectTime = 0; + $this->bSecure = false; + } + + /** + * @return string + */ + public function GetConnectedHost() + { + return $this->sConnectedHost; + } + + /** + * @return int + */ + public function GetConnectedPort() + { + return $this->iConnectedPort; + } + + /** + * @param int $iConnectTimeOut = 10 + * @param int $iSocketTimeOut = 10 + * + * @return void + */ + public function SetTimeOuts($iConnectTimeOut = 10, $iSocketTimeOut = 10) + { + $this->iConnectTimeOut = $iConnectTimeOut; + $this->iSocketTimeOut = $iSocketTimeOut; + } + + /** + * @return resource|null + */ + public function ConnectionResource() + { + return $this->rConnect; + } + + /** + * @param string $sServerName + * @param int $iPort + * @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT + * + * @return void + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\SocketAlreadyConnectedException + * @throws \MailSo\Net\Exceptions\SocketCanNotConnectToHostException + */ + public function Connect($sServerName, $iPort, + $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT) + { + if (!\MailSo\Base\Validator::NotEmptyString($sServerName, true) || !\MailSo\Base\Validator::PortInt($iPort)) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + if ($this->IsConnected()) + { + $this->writeLogException( + new Exceptions\SocketAlreadyConnectedException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $sServerName = \trim($sServerName); + + $sErrorStr = ''; + $iErrorNo = 0; + + $this->iSecurityType = $iSecurityType; + $this->iConnectedPort = $iPort; + $this->bSecure = \MailSo\Net\Enumerations\ConnectionSecurityType::UseSSL($iPort, $iSecurityType); + $this->sConnectedHost = $this->bSecure ? 'ssl://'.$sServerName : $sServerName; + + if (!$this->bSecure && \MailSo\Net\Enumerations\ConnectionSecurityType::SSL === $this->iSecurityType) + { + $this->writeLogException( + new \MailSo\Net\Exceptions\SocketUnsuppoterdSecureConnectionException('SSL isn\'t supported'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $this->iStartConnectTime = \microtime(true); + $this->writeLog('Start connection to "'.$this->sConnectedHost.':'.$this->iConnectedPort.'"', + \MailSo\Log\Enumerations\Type::NOTE); + + $this->rConnect = @\fsockopen($this->sConnectedHost, $this->iConnectedPort, + $iErrorNo, $sErrorStr, $this->iConnectTimeOut); + + if (!is_resource($this->rConnect)) + { + $this->writeLogException( + new Exceptions\SocketCanNotConnectToHostException( + $sErrorStr, $iErrorNo, + 'Can\'t connect to host "'.$this->sConnectedHost.':'.$this->iConnectedPort.'"' + ), \MailSo\Log\Enumerations\Type::NOTICE, true); + } + + $this->writeLog((\microtime(true) - $this->iStartConnectTime).' (raw connection)', + \MailSo\Log\Enumerations\Type::TIME); + + if ($this->rConnect) + { + if (\MailSo\Base\Utils::FunctionExistsAndEnabled('stream_set_timeout')) + { + @\stream_set_timeout($this->rConnect, $this->iSocketTimeOut); + } + + if (\MailSo\Base\Utils::FunctionExistsAndEnabled('stream_set_blocking')) + { + @\stream_set_blocking($this->rConnect, 1); + } + } + } + + /** + * @return void + */ + public function Disconnect() + { + if (\is_resource($this->rConnect)) + { + $bResult = \fclose($this->rConnect); + + $this->writeLog('Disconnected from "'.$this->sConnectedHost.':'.$this->iConnectedPort.'" ('. + (($bResult) ? 'success' : 'unsuccess').')', \MailSo\Log\Enumerations\Type::NOTE); + + if (0 !== $this->iStartConnectTime) + { + $this->writeLog((\microtime(true) - $this->iStartConnectTime).' (net session)', + \MailSo\Log\Enumerations\Type::TIME); + + $this->iStartConnectTime = 0; + } + + $this->rConnect = null; + } + } + + /** + * @retun void + * + * @throws \MailSo\Net\Exceptions\Exception + */ + public function LogoutAndDisconnect() + { + if (\method_exists($this, 'Logout') && !$this->bUnreadBuffer) + { + $this->Logout(); + } + + $this->Disconnect(); + } + + /** + * @param bool $bThrowExceptionOnFalse = false + * + * @return bool + */ + public function IsConnected($bThrowExceptionOnFalse = false) + { + $bResult = \is_resource($this->rConnect); + if (!$bResult && $bThrowExceptionOnFalse) + { + $this->writeLogException( + new Exceptions\SocketConnectionDoesNotAvailableException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + return $bResult; + } + + /** + * @return void + * + * @throws \MailSo\Net\Exceptions\SocketConnectionDoesNotAvailableException + */ + public function IsConnectedWithException() + { + $this->IsConnected(true); + } + + /** + * @param string $sRaw + * @param bool $bWriteToLog = true + * @param string $sFakeRaw = '' + * + * @return void + * + * @throws \MailSo\Net\Exceptions\SocketConnectionDoesNotAvailableException + * @throws \MailSo\Net\Exceptions\SocketWriteException + */ + protected function sendRaw($sRaw, $bWriteToLog = true, $sFakeRaw = '') + { + if ($this->bUnreadBuffer) + { + $this->writeLogException( + new Exceptions\SocketUnreadBufferException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $bFake = 0 < \strlen($sFakeRaw); + $sRaw .= "\r\n"; + if ($bFake) + { + $sFakeRaw .= "\r\n"; + } + + $mResult = @\fwrite($this->rConnect, $sRaw); + if (false === $mResult) + { + $this->IsConnected(true); + + $this->writeLogException( + new Exceptions\SocketWriteException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + else + { + \MailSo\Base\Loader::IncStatistic('NetWrite', $mResult); + + if ($bWriteToLog) + { + $this->writeLogWithCrlf('> '.($bFake ? $sFakeRaw : $sRaw), //.' ['.$iWriteSize.']', + $bFake ? \MailSo\Log\Enumerations\Type::SECURE : \MailSo\Log\Enumerations\Type::INFO); + } + } + } + + /** + * @param mixed $mReadLen = null + * @param bool $bForceLogin = false + * + * @return void + * + * @throws \MailSo\Net\Exceptions\SocketConnectionDoesNotAvailableException + * @throws \MailSo\Net\Exceptions\SocketReadException + */ + protected function getNextBuffer($mReadLen = null, $bForceLogin = false) + { + if (null === $mReadLen) + { + $this->sResponseBuffer = @\fgets($this->rConnect); + } + else + { + $this->sResponseBuffer = ''; + $iRead = $mReadLen; + while (0 < $iRead) + { + $sAddRead = @\fread($this->rConnect, $iRead); + if (false === $sAddRead) + { + $this->sResponseBuffer = false; + break; + } + + $this->sResponseBuffer .= $sAddRead; + $iRead -= \strlen($sAddRead); + } + } + + if (false === $this->sResponseBuffer) + { + $this->IsConnected(true); + $this->bUnreadBuffer = true; + + $aSocketStatus = @\stream_get_meta_data($this->rConnect); + if (isset($aSocketStatus['timed_out']) && $aSocketStatus['timed_out']) + { + $this->writeLogException( + new Exceptions\SocketReadTimeoutException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + else + { + $this->writeLogException( + new Exceptions\SocketReadException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + } + else + { + $iReadedLen = \strlen($this->sResponseBuffer); + if (null === $mReadLen || $bForceLogin) + { + $this->writeLogWithCrlf('< '.$this->sResponseBuffer, //.' ['.$iReadedLen.']', + \MailSo\Log\Enumerations\Type::INFO); + } + else + { + $this->writeLog('Received '.$iReadedLen.'/'.$mReadLen.' bytes.', + \MailSo\Log\Enumerations\Type::INFO); + } + + \MailSo\Base\Loader::IncStatistic('NetRead', $iReadedLen); + } + } + + /** + * @return string + */ + protected function getLogName() + { + return 'NET'; + } + + /** + * @param string $sDesc + * @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO + * + * @return void + */ + protected function writeLog($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO) + { + if ($this->oLogger) + { + $this->oLogger->Write($sDesc, $iDescType, $this->getLogName()); + } + } + + /** + * @param string $sDesc + * @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO + * + * @return void + */ + protected function writeLogWithCrlf($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO) + { + $this->writeLog(\strtr($sDesc, array("\r" => '\r', "\n" => '\n')), $iDescType); + } + + /** + * @param \Exception $oException + * @param int $iDescType = \MailSo\Log\Enumerations\Type::NOTICE + * @param bool $bThrowException = false + * + * @return void + */ + protected function writeLogException($oException, + $iDescType = \MailSo\Log\Enumerations\Type::NOTICE, $bThrowException = false) + { + if ($this->oLogger) + { + $this->oLogger->WriteException($oException, $iDescType, $this->getLogName()); + } + + if ($bThrowException) + { + throw $oException; + } + } + + /** + * @param \MailSo\Log\Logger $oLogger + * + * @return void + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function SetLogger($oLogger) + { + if (!($oLogger instanceof \MailSo\Log\Logger)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->oLogger = $oLogger; + } + + /** + * @return \MailSo\Log\Logger|null + */ + public function Logger() + { + return $this->oLogger; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Pop3/Exceptions/Exception.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Pop3/Exceptions/Exception.php new file mode 100644 index 000000000..b74cb4bcc --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Pop3/Exceptions/Exception.php @@ -0,0 +1,10 @@ +aResponses = $aResponses; + } + } + + /** + * @return array + */ + public function GetResponses() + { + return $this->aResponses; + } + + /** + * @return \MailSo\Pop3\Response | null + */ + public function GetLastResponse() + { + return 0 < count($this->aResponses) ? $this->aResponses[count($this->aResponses) - 1] : null; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Pop3/Exceptions/RuntimeException.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Pop3/Exceptions/RuntimeException.php new file mode 100644 index 000000000..5b1825168 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Pop3/Exceptions/RuntimeException.php @@ -0,0 +1,10 @@ +bIsLoggined = false; + $this->iRequestTime = 0; + $this->aCapa = null; + $this->sLastMessage = ''; + } + + /** + * @return \MailSo\Pop3\Pop3Client + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @param string $sServerName + * @param int $iPort = 110 + * @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT + * + * @return \MailSo\Pop3\Pop3Client + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Pop3\Exceptions\ResponseException + */ + public function Connect($sServerName, $iPort = 110, + $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT) + { + $this->iRequestTime = microtime(true); + + parent::Connect($sServerName, $iPort, $iSecurityType); + $this->validateResponse(); + + if (\MailSo\Net\Enumerations\ConnectionSecurityType::UseStartTLS( + in_array('STLS', $this->Capa()), $this->iSecurityType)) + { + $this->sendRequestWithCheck('STLS'); + if (!@stream_socket_enable_crypto($this->rConnect, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) + { + $this->writeLogException( + new \MailSo\Pop3\Exceptions\RuntimeException('Cannot enable STARTTLS'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $this->aCapa = null; + } + else if (\MailSo\Net\Enumerations\ConnectionSecurityType::STARTTLS === $this->iSecurityType) + { + $this->writeLogException( + new \MailSo\Net\Exceptions\SocketUnsuppoterdSecureConnectionException('STARTTLS is not supported'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + return $this; + } + + /** + * @param string $sLogin = '' + * @param string $sPassword = '' + * + * @return \MailSo\Pop3\Pop3Client + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Pop3\Exceptions\ResponseException + */ + public function Login($sLogin, $sPassword) + { + if ($this->bIsLoggined) + { + $this->writeLogException( + new Exceptions\RuntimeException('Already authenticated for this session'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $sLogin = trim($sLogin); + $sPassword = $sPassword; + + try + { + $this->sendRequestWithCheck('USER', $sLogin); + $this->sendRequestWithCheck('PASS', $sPassword); + } + catch (\MailSo\Pop3\Exceptions\NegativeResponseException $oException) + { + $this->writeLogException( + new \MailSo\Pop3\Exceptions\LoginBadCredentialsException( + $oException->GetResponses(), '', 0, $oException), + \MailSo\Log\Enumerations\Type::NOTICE, true); + } + + $this->bIsLoggined = true; + $this->aCapa = null; + + return $this; + } + + /** + * @return bool + */ + public function IsLoggined() + { + return $this->IsConnected() && $this->bIsLoggined; + } + + /** + * @return \MailSo\Pop3\Pop3Client + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Pop3\Exceptions\Exception + */ + public function Noop() + { + $this->sendRequestWithCheck('NOOP'); + return $this; + } + + /** + * @return array [MessagesCount, Size] + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Pop3\Exceptions\Exception + */ + public function Status() + { + $this->sendRequestWithCheck('STAT'); + + $iMessageCount = $iSize = 0; + sscanf($this->sLastMessage, '%d %d', $iMessageCount, $iSize); + + return array((int) $iMessageCount, (int) $iSize); + } + + /** + * @return \MailSo\Pop3\Pop3Client + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Pop3\Exceptions\Exception + */ + public function Capa() + { + if (null === $this->aCapa) + { + $this->sendRequestWithCheck('CAPA'); + + $this->aCapa = array_filter(explode("\n", $this->readMultilineResponse()), function (&$sCapa) { + return 0 < strlen(trim($sCapa)); + }); + + $this->aCapa = array_map('trim', $this->aCapa); + } + + return $this->aCapa; + } + + /** + * @return \MailSo\Pop3\Pop3Client + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Pop3\Exceptions\Exception + */ + public function Logout() + { + if ($this->bIsLoggined) + { + $this->sendRequestWithCheck('QUIT'); + } + + $this->bIsLoggined = false; + return $this; + } + + /** + * @param string $sCommand + * @param string $sAddToCommand = '' + * + * @return \MailSo\Pop3\Pop3Client + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + */ + protected function sendRequest($sCommand, $sAddToCommand = '') + { + if (0 === strlen(trim($sCommand))) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $this->IsConnected(true); + + $sCommand = trim($sCommand); + $sRealCommand = $sCommand.(0 === strlen($sAddToCommand) ? '' : ' '.$sAddToCommand); + + $sFakeCommand = ''; + $sFakeAddToCommand = $this->secureRequestParams($sCommand, $sAddToCommand); + if (0 < strlen($sFakeAddToCommand)) + { + $sFakeCommand = $sCommand.' '.$sFakeAddToCommand; + } + + $this->iRequestTime = microtime(true); + $this->sendRaw($sRealCommand, true, $sFakeCommand); + return $this; + } + + /** + * @param string $sCommand + * @param string $sAddToCommand + * + * @return string + */ + private function secureRequestParams($sCommand, $sAddToCommand) + { + $sResult = null; + if (0 < strlen($sAddToCommand)) + { + switch ($sCommand) + { + case 'PASS': + $sResult = '*******'; + break; + } + } + + return $sResult; + } + + /** + * @param string $sCommand + * @param string $sAddToCommand = '' + * + * @return \MailSo\Pop3\Pop3Client + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Pop3\Exceptions\Exception + */ + private function sendRequestWithCheck($sCommand, $sAddToCommand = '') + { + $this->sendRequest($sCommand, $sAddToCommand); + return $this->validateResponse(); + } + + /** + * @return string + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Pop3\Exceptions\ResponseException + */ + private function validateResponse() + { + $this->getNextBuffer(); + + $this->sLastMessage = ''; + $sStatus = $sMessage = ''; + $sBuffer = trim($this->sResponseBuffer); + $sStatus = $sBuffer; + if (false !== strpos($sBuffer, ' ')) + { + list($sStatus, $sMessage) = explode(' ', $sBuffer, 2); + } + + $this->sLastMessage = $sMessage; + + if ($sStatus != '+OK') + { + $this->writeLogException( + new Exceptions\NegativeResponseException(), + \MailSo\Log\Enumerations\Type::WARNING, true); + } + + $this->writeLog((microtime(true) - $this->iRequestTime), + \MailSo\Log\Enumerations\Type::TIME); + } + + /** + * @return string + * + * @throws \MailSo\Net\Exceptions\Exception + */ + private function readMultilineResponse() + { + $this->iRequestTime = microtime(true); + + $sResult = ''; + do + { + $this->getNextBuffer(); + if (0 === strpos($this->sResponseBuffer, '.')) + { + $sResult .= substr($this->sResponseBuffer, 1); + } + else + { + $sResult .= $this->sResponseBuffer; + } + } + while ('.' !== rtrim($this->sResponseBuffer, "\r\n")); + + $this->writeLog((microtime(true) - $this->iRequestTime), + \MailSo\Log\Enumerations\Type::TIME); + + return $sResult; + } + + /** + * @return string + */ + protected function getLogName() + { + return 'POP3'; + } + + /** + * @param \MailSo\Log\Logger $oLogger + * @return \MailSo\Pop3\Pop3Client + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function SetLogger($oLogger) + { + parent::SetLogger($oLogger); + + return $this; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Poppassd/Exceptions/Exception.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Poppassd/Exceptions/Exception.php new file mode 100644 index 000000000..3cd260832 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Poppassd/Exceptions/Exception.php @@ -0,0 +1,10 @@ +aResponses = $aResponses; + } + } + + /** + * @return array + */ + public function GetResponses() + { + return $this->aResponses; + } + + /** + * @return \MailSo\Poppassd\Response | null + */ + public function GetLastResponse() + { + return 0 < \count($this->aResponses) ? $this->aResponses[count($this->aResponses) - 1] : null; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Poppassd/Exceptions/RuntimeException.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Poppassd/Exceptions/RuntimeException.php new file mode 100644 index 000000000..634b91949 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Poppassd/Exceptions/RuntimeException.php @@ -0,0 +1,10 @@ +bIsLoggined = false; + $this->iRequestTime = 0; + + parent::__construct(); + } + + /** + * @return \MailSo\Poppassd\PoppassdClient + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @param string $sServerName + * @param int $iPort = 106 + * @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT + * + * @return \MailSo\Poppassd\PoppassdClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Poppassd\Exceptions\ResponseException + */ + public function Connect($sServerName, $iPort = 106, + $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT) + { + $this->iRequestTime = \microtime(true); + + parent::Connect($sServerName, $iPort, $iSecurityType); + $this->validateResponse(); + + return $this; + } + + /** + * @param string $sLogin = '' + * @param string $sPassword = '' + * + * @return \MailSo\Poppassd\PoppassdClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Poppassd\Exceptions\ResponseException + */ + public function Login($sLogin, $sPassword) + { + if ($this->bIsLoggined) + { + $this->writeLogException( + new Exceptions\RuntimeException('Already authenticated for this session'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $sLogin = \trim($sLogin); + $sPassword = $sPassword; + + try + { + $this->sendRequestWithCheck('user', $sLogin, true); + $this->sendRequestWithCheck('pass', $sPassword, true); + } + catch (\MailSo\Poppassd\Exceptions\NegativeResponseException $oException) + { + $this->writeLogException( + new \MailSo\Poppassd\Exceptions\LoginBadCredentialsException( + $oException->GetResponses(), '', 0, $oException), + \MailSo\Log\Enumerations\Type::NOTICE, true); + } + + $this->bIsLoggined = true; + + return $this; + } + + /** + * @return \MailSo\Poppassd\PoppassdClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Poppassd\Exceptions\Exception + */ + public function Logout() + { + if ($this->bIsLoggined) + { + $this->sendRequestWithCheck('quit'); + } + + $this->bIsLoggined = false; + return $this; + } + + /** + * @param string $sNewPassword + * + * @return \MailSo\Poppassd\PoppassdClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Poppassd\Exceptions\Exception + */ + public function NewPass($sNewPassword) + { + if ($this->bIsLoggined) + { + $this->sendRequestWithCheck('newpass', $sNewPassword); + } + else + { + $this->writeLogException( + new \MailSo\Poppassd\Exceptions\RuntimeException('Required login'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + return $this; + } + + /** + * @param string $sCommand + * @param string $sAddToCommand + * + * @return string + */ + private function secureRequestParams($sCommand, $sAddToCommand) + { + $sResult = null; + if (0 < \strlen($sAddToCommand)) + { + switch (\strtolower($sCommand)) + { + case 'pass': + case 'newpass': + $sResult = '*******'; + break; + } + } + + return $sResult; + } + + /** + * @param string $sCommand + * @param string $sAddToCommand = '' + * + * @return \MailSo\Poppassd\PoppassdClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + */ + private function sendRequest($sCommand, $sAddToCommand = '') + { + if (0 === \strlen(\trim($sCommand))) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $this->IsConnected(true); + + $sCommand = \trim($sCommand); + $sRealCommand = $sCommand.(0 === \strlen($sAddToCommand) ? '' : ' '.$sAddToCommand); + + $sFakeCommand = ''; + $sFakeAddToCommand = $this->secureRequestParams($sCommand, $sAddToCommand); + if (0 < \strlen($sFakeAddToCommand)) + { + $sFakeCommand = $sCommand.' '.$sFakeAddToCommand; + } + + $this->iRequestTime = \microtime(true); + $this->sendRaw($sRealCommand, true, $sFakeCommand); + + return $this; + } + + /** + * @param string $sCommand + * @param string $sAddToCommand = '' + * @param bool $bAuthRequestValidate = false + * + * @return \MailSo\Poppassd\PoppassdClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Poppassd\Exceptions\Exception + */ + private function sendRequestWithCheck($sCommand, $sAddToCommand = '', $bAuthRequestValidate = false) + { + $this->sendRequest($sCommand, $sAddToCommand); + $this->validateResponse($bAuthRequestValidate); + + return $this; + } + + /** + * @param bool $bAuthRequestValidate = false + * + * @return \MailSo\Poppassd\PoppassdClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Poppassd\Exceptions\ResponseException + */ + private function validateResponse($bAuthRequestValidate = false) + { + $this->getNextBuffer(); + + $bResult = false; + if ($bAuthRequestValidate) + { + $bResult = (bool) \preg_match('/^[23]\d\d/', trim($this->sResponseBuffer)); + } + else + { + $bResult = (bool) \preg_match('/^2\d\d/', trim($this->sResponseBuffer)); + } + + if (!$bResult) + { + $this->writeLogException( + new Exceptions\NegativeResponseException(), + \MailSo\Log\Enumerations\Type::WARNING, true); + } + + $this->writeLog((\microtime(true) - $this->iRequestTime), + \MailSo\Log\Enumerations\Type::TIME); + + return $this; + } + + /** + * @return string + */ + protected function getLogName() + { + return 'POPPASSD'; + } + + /** + * @param \MailSo\Log\Logger $oLogger + * + * @return \MailSo\Poppassd\PoppassdClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function SetLogger($oLogger) + { + parent::SetLogger($oLogger); + + return $this; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Sieve/Exceptions/Exception.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Sieve/Exceptions/Exception.php new file mode 100644 index 000000000..ed345fc6a --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Sieve/Exceptions/Exception.php @@ -0,0 +1,10 @@ +aResponses = $aResponses; + } + } + + /** + * @return array + */ + public function GetResponses() + { + return $this->aResponses; + } + + /** + * @return \MailSo\Sieve\Response | null + */ + public function GetLastResponse() + { + return 0 < count($this->aResponses) ? $this->aResponses[count($this->aResponses) - 1] : null; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Sieve/Exceptions/RuntimeException.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Sieve/Exceptions/RuntimeException.php new file mode 100644 index 000000000..134291f48 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Sieve/Exceptions/RuntimeException.php @@ -0,0 +1,10 @@ +bIsLoggined = false; + $this->iRequestTime = 0; + $this->aCapa = array(); + $this->aModules = array(); + } + + /** + * @return \MailSo\Sieve\ManageSieveClient + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @param string $sCapa + * + * @return bool + */ + public function IsSupported($sCapa) + { + return isset($this->aCapa[\strtoupper($sCapa)]); + } + + /** + * @param string $sModule + * + * @return bool + */ + public function IsModuleSupported($sModule) + { + return $this->IsSupported('SIEVE') && \in_array(\strtoupper($sModule), $this->aModules); + } + + /** + * @param string $sAuth + * + * @return bool + */ + public function IsAuthSupported($sAuth) + { + return $this->IsSupported('SASL') && \in_array(\strtoupper($sAuth), $this->aAuth); + } + + /** + * @param string $sServerName + * @param int $iPort + * @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT + * + * @return \MailSo\Sieve\ManageSieveClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Sieve\Exceptions\ResponseException + */ + public function Connect($sServerName, $iPort, + $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT) + { + $this->iRequestTime = microtime(true); + + parent::Connect($sServerName, $iPort, $iSecurityType); + + $mResponse = $this->parseResponse(); + $this->validateResponse($mResponse); + $this->parseStartupResponse($mResponse); + + if (\MailSo\Net\Enumerations\ConnectionSecurityType::UseStartTLS( + $this->IsSupported('STARTTLS'), $this->iSecurityType)) + { + $this->sendRequestWithCheck('STARTTLS'); + if (!@stream_socket_enable_crypto($this->rConnect, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) + { + $this->writeLogException( + new \MailSo\Sieve\Exceptions\RuntimeException('Cannot enable STARTTLS'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $mResponse = $this->parseResponse(); + $this->validateResponse($mResponse); + $this->parseStartupResponse($mResponse); + } + else if (\MailSo\Net\Enumerations\ConnectionSecurityType::STARTTLS === $this->iSecurityType) + { + $this->writeLogException( + new \MailSo\Net\Exceptions\SocketUnsuppoterdSecureConnectionException('STARTTLS is not supported'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + return $this; + } + + /** + * @param string $sLogin + * @param string $sPassword + * @param string $sLoginAuthKey = '' + * + * @return \MailSo\Sieve\ManageSieveClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Sieve\Exceptions\LoginException + */ + public function Login($sLogin, $sPassword, $sLoginAuthKey = '') + { + if (!\MailSo\Base\Validator::NotEmptyString($sLogin, true) || + !\MailSo\Base\Validator::NotEmptyString($sPassword, true)) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + if ($this->IsSupported('SASL')) + { + $bAuth = false; + try + { + if ($this->IsAuthSupported('PLAIN')) + { + $sAuth = base64_encode($sLoginAuthKey."\0".$sLogin."\0".$sPassword); + + $this->sendRequest('AUTHENTICATE "PLAIN" {'.strlen($sAuth).'+}'); + $this->sendRequest($sAuth); + + $mResponse = $this->parseResponse(); + $this->validateResponse($mResponse); + $this->parseStartupResponse($mResponse); + $bAuth = true; + } + else if ($this->IsAuthSupported('LOGIN')) + { + $sLogin = base64_encode($sLogin); + $sPassword = base64_encode($sPassword); + + $this->sendRequest('AUTHENTICATE "LOGIN"'); + $this->sendRequest('{'.strlen($sLogin).'+}'); + $this->sendRequest($sLogin); + $this->sendRequest('{'.strlen($sPassword).'+}'); + $this->sendRequest($sPassword); + + $mResponse = $this->parseResponse(); + $this->validateResponse($mResponse); + $this->parseStartupResponse($mResponse); + $bAuth = true; + } + } + catch (\MailSo\Sieve\Exceptions\NegativeResponseException $oException) + { + $this->writeLogException( + new \MailSo\Sieve\Exceptions\LoginBadCredentialsException( + $oException->GetResponses(), '', 0, $oException), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + if (!$bAuth) + { + $this->writeLogException( + new \MailSo\Sieve\Exceptions\LoginBadMethodException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + } + else + { + $this->writeLogException( + new \MailSo\Sieve\Exceptions\LoginException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $this->bIsLoggined = true; + + return $this; + } + + /** + * @return \MailSo\Sieve\ManageSieveClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Sieve\Exceptions\NegativeResponseException + */ + public function Logout() + { + if ($this->bIsLoggined) + { + $this->sendRequestWithCheck('LOGOUT'); + $this->bIsLoggined = false; + } + + return $this; + } + + /** + * @return array + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Sieve\Exceptions\NegativeResponseException + */ + public function ListScripts() + { + $this->sendRequest('LISTSCRIPTS'); + $mResponse = $this->parseResponse(); + $this->validateResponse($mResponse); + + $aResult = array(); + if (is_array($mResponse)) + { + foreach ($mResponse as $sLine) + { + $aTokens = $this->parseLine($sLine); + if (false === $aTokens) + { + continue; + } + + $aResult[$aTokens[0]] = 'ACTIVE' === substr($sLine, -6); + } + } + + return $aResult; + } + + /** + * @return array + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Sieve\Exceptions\NegativeResponseException + */ + public function Capability() + { + $this->sendRequest('CAPABILITY'); + $mResponse = $this->parseResponse(); + $this->validateResponse($mResponse); + $this->parseStartupResponse($mResponse); + + return $this->aCapa; + } + + /** + * @return \MailSo\Sieve\ManageSieveClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Sieve\Exceptions\NegativeResponseException + */ + public function Noop() + { + $this->sendRequestWithCheck('NOOP'); + + return $this; + } + + /** + * @param string $sScriptName + * + * @return string + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Sieve\Exceptions\NegativeResponseException + */ + public function GetScript($sScriptName) + { + $this->sendRequest('GETSCRIPT "'.$sScriptName.'"'); + $mResponse = $this->parseResponse(); + $this->validateResponse($mResponse); + + $sScript = ''; + if (is_array($mResponse) && 0 < count($mResponse)) + { + if ('{' === $mResponse[0]{0}) + { + array_shift($mResponse); + } + + if (\in_array(\substr($mResponse[\count($mResponse) - 1], 0, 2), array('OK', 'NO'))) + { + array_pop($mResponse); + } + + $sScript = \implode("\n", $mResponse); + } + + return $sScript; + } + + /** + * @param string $sScriptName + * @param string $sScriptSource + * + * @return \MailSo\Sieve\ManageSieveClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Sieve\Exceptions\NegativeResponseException + */ + public function PutScript($sScriptName, $sScriptSource) + { + $sScriptSource = stripslashes($sScriptSource); + + $this->sendRequest('PUTSCRIPT "'.$sScriptName.'" {'.strlen($sScriptSource).'+}'); + $this->sendRequestWithCheck($sScriptSource); + + return $this; + } + + /** + * @param string $sScriptSource + * + * @return \MailSo\Sieve\ManageSieveClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Sieve\Exceptions\NegativeResponseException + */ + public function CheckScript($sScriptSource) + { + $sScriptSource = stripslashes($sScriptSource); + + $this->sendRequest('CHECKSCRIPT {'.strlen($sScriptSource).'+}'); + $this->sendRequestWithCheck($sScriptSource); + + return $this; + } + + /** + * @param string $sScriptName + * + * @return \MailSo\Sieve\ManageSieveClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Sieve\Exceptions\NegativeResponseException + */ + public function SetActiveScript($sScriptName) + { + $this->sendRequestWithCheck('SETACTIVE "'.$sScriptName.'"'); + + return $this; + } + + /** + * @param string $sScriptName + * + * @return \MailSo\Sieve\ManageSieveClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Sieve\Exceptions\NegativeResponseException + */ + public function DeleteScript($sScriptName) + { + $this->sendRequestWithCheck('DELETESCRIPT "'.$sScriptName.'"'); + + return $this; + } + + /** + * @return string + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Sieve\Exceptions\NegativeResponseException + */ + public function GetActiveScriptName() + { + $aList = $this->ListScripts(); + if (is_array($aList) && 0 < count($aList)) + { + foreach ($aList as $sName => $bIsActive) + { + if ($bIsActive) + { + return $sName; + } + } + } + + return ''; + } + + /** + * @param string $sScriptName + * + * @return bool + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Sieve\Exceptions\NegativeResponseException + */ + public function IsActiveScript($sScriptName) + { + return $sScriptName === $this->GetActiveScriptName(); + } + + /** + * @param string $sLine + * @return array|false + */ + private function parseLine($sLine) + { + if (false === $sLine || null === $sLine || \in_array(\substr($sLine, 0, 2), array('OK', 'NO'))) + { + return false; + } + + $iStart = -1; + $iIndex = 0; + $aResult = false; + + for ($iPos = 0; $iPos < \strlen($sLine); $iPos++) + { + if ('"' === $sLine[$iPos] && '\\' !== $sLine[$iPos]) + { + if (-1 === $iStart) + { + $iStart = $iPos; + } + else + { + $aResult = \is_array($aResult) ? $aResult : array(); + $aResult[$iIndex++] = \substr($sLine, $iStart + 1, $iPos - $iStart - 1); + $iStart = -1; + } + } + } + + return \is_array($aResult) && isset($aResult[0]) ? $aResult : false; + } + + /** + * @param string $sCommand + * + * @return void + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + */ + private function parseStartupResponse($mResponse) + { + foreach ($mResponse as $sLine) + { + $aTokens = $this->parseLine($sLine); + + if (false === $aTokens || !isset($aTokens[0]) || + \in_array(\substr($sLine, 0, 2), array('OK', 'NO'))) + { + continue; + } + + $sToken = \strtoupper($aTokens[0]); + $this->aCapa[$sToken] = isset($aTokens[1]) ? $aTokens[1] : ''; + + if (isset($aTokens[1])) + { + switch ($sToken) { + case 'SASL': + $this->aAuth = \explode(' ', \strtoupper($aTokens[1])); + break; + case 'SIEVE': + $this->aModules = \explode(' ', \strtoupper($aTokens[1])); + break; + } + } + } + } + + /** + * @param string $sRequest + * + * @return void + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + */ + private function sendRequest($sRequest) + { + if (!\MailSo\Base\Validator::NotEmptyString($sRequest, true)) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $this->IsConnected(true); + + $sRequest = \trim($sRequest); + $this->sendRaw($sRequest); + } + + /** + * @param string $sRequest + * + * @return void + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Sieve\Exceptions\NegativeResponseException + */ + private function sendRequestWithCheck($sRequest) + { + $this->sendRequest($sRequest); + $this->validateResponse($this->parseResponse()); + } + + /** + * @param string $sLine + * + * @return string + */ + private function convertEndOfLine($sLine) + { + $sLine = \trim($sLine); + if ('}' === \substr($sLine, -1)) + { + $iPos = \strrpos($sLine, '{'); + if (false !== $iPos) + { + $sSunLine = \substr($sLine, $iPos + 1, -1); + if (\is_numeric($sSunLine) && 0 < (int) $sSunLine) + { + $iLen = (int) $sSunLine; + + $this->getNextBuffer($iLen, true); + + if (strlen($this->sResponseBuffer) === $iLen) + { + $sLine = \trim(\substr_replace($sLine, $this->sResponseBuffer, $iPos)); + } + } + } + } + + return $sLine; + } + + /** + * @return array|bool + */ + private function parseResponse() + { + $this->iRequestTime = \microtime(true); + + $aResult = array(); + do + { + $this->getNextBuffer(); + + $sLine = $this->sResponseBuffer; + if (false === $sLine) + { + break; + } + else if (\in_array(\substr($sLine, 0, 2), array('OK', 'NO'))) + { + $aResult[] = $this->convertEndOfLine($sLine); + break; + } + else + { + $aResult[] = $this->convertEndOfLine($sLine); + } + } + while (true); + + $this->writeLog((\microtime(true) - $this->iRequestTime), + \MailSo\Log\Enumerations\Type::TIME); + + return $aResult; + } + + /** + * @throws \MailSo\Sieve\Exceptions\NegativeResponseException + */ + private function validateResponse($aResponse) + { + if (!\is_array($aResponse) || 0 === \count($aResponse) || + 'OK' !== \substr($aResponse[\count($aResponse) - 1], 0, 2)) + { + $this->writeLogException( + new \MailSo\Sieve\Exceptions\NegativeResponseException(), + \MailSo\Log\Enumerations\Type::WARNING, true); + } + } + + /** + * @return string + */ + protected function getLogName() + { + return 'MANAGE-SIEVE'; + } + + /** + * @param \MailSo\Log\Logger $oLogger + * + * @return \MailSo\Sieve\ManageSieveClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function SetLogger($oLogger) + { + parent::SetLogger($oLogger); + + return $this; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Smtp/Exceptions/Exception.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Smtp/Exceptions/Exception.php new file mode 100644 index 000000000..476ca4b3c --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Smtp/Exceptions/Exception.php @@ -0,0 +1,10 @@ +aResponses = $aResponses; + } + } + + /** + * @return array + */ + public function GetResponses() + { + return $this->aResponses; + } + + /** + * @return \MailSo\Smtp\Response | null + */ + public function GetLastResponse() + { + return 0 < count($this->aResponses) ? $this->aResponses[count($this->aResponses) - 1] : null; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Smtp/Exceptions/RuntimeException.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Smtp/Exceptions/RuntimeException.php new file mode 100644 index 000000000..f771f914e --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Smtp/Exceptions/RuntimeException.php @@ -0,0 +1,10 @@ +bIsStartTSLSupported = false; + $this->aAuthTypes = array(); + + $this->iRequestTime = 0; + $this->iSizeCapaValue = 0; + $this->aResults = array(); + $this->aCapa = array(); + + $this->bHelo = false; + $this->bRcpt = false; + $this->bMail = false; + $this->bData = false; + } + + /** + * @return \MailSo\Smtp\SmtpClient + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @return bool + */ + public function IsSupported($sCapa) + { + return in_array(strtoupper($sCapa), $this->aCapa); + } + + /** + * @return bool + */ + public function IsAuthSupported($sAuth) + { + return in_array(strtoupper($sAuth), $this->aAuthTypes); + } + + /** + * @return bool + */ + public function HasSupportedAuth() + { + return $this->IsAuthSupported('PLAIN') || $this->IsAuthSupported('LOGIN'); + } + + /** + * @param string $sServerName + * @param int $iPort = 25 + * @param string $sEhloHost = '127.0.0.1' + * @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT + * + * @return \MailSo\Smtp\SmtpClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\ResponseException + */ + public function Connect($sServerName, $iPort = 25, $sEhloHost = '127.0.0.1', + $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT) + { + $this->iRequestTime = microtime(true); + + parent::Connect($sServerName, $iPort, $iSecurityType); + $this->validateResponse(220); + + $this->preLoginStartTLSAndEhloProcess($sEhloHost); + + return $this; + } + + /** + * @param string $sLogin + * @param string $sPassword + * + * @return \MailSo\Smtp\SmtpClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\Exception + */ + public function Login($sLogin, $sPassword) + { + if ($this->IsAuthSupported('PLAIN')) + { + try + { + $this->sendRequestWithCheck('AUTH', 334, 'PLAIN'); + } + catch (\MailSo\Smtp\Exceptions\NegativeResponseException $oException) + { + $this->writeLogException( + new \MailSo\Smtp\Exceptions\LoginBadMethodException( + $oException->GetResponses(), '', 0, $oException), + \MailSo\Log\Enumerations\Type::NOTICE, true); + } + + try + { + $this->sendRequestWithCheck(base64_encode("\0".$sLogin."\0".$sPassword), 235, '', true); + } + catch (\MailSo\Smtp\Exceptions\NegativeResponseException $oException) + { + $this->writeLogException( + new \MailSo\Smtp\Exceptions\LoginBadCredentialsException( + $oException->GetResponses(), '', 0, $oException), + \MailSo\Log\Enumerations\Type::NOTICE, true); + } + } + else if ($this->IsAuthSupported('LOGIN')) + { + try + { + $this->sendRequestWithCheck('AUTH', 334, 'LOGIN'); + } + catch (\MailSo\Smtp\Exceptions\NegativeResponseException $oException) + { + $this->writeLogException( + new \MailSo\Smtp\Exceptions\LoginBadMethodException( + $oException->GetResponses(), '', 0, $oException), + \MailSo\Log\Enumerations\Type::NOTICE, true); + } + + try + { + $this->sendRequestWithCheck(base64_encode($sLogin), 334, ''); + $this->sendRequestWithCheck(base64_encode($sPassword), 235, '', true); + } + catch (\MailSo\Smtp\Exceptions\NegativeResponseException $oException) + { + $this->writeLogException( + new \MailSo\Smtp\Exceptions\LoginBadCredentialsException( + $oException->GetResponses(), '', 0, $oException), + \MailSo\Log\Enumerations\Type::NOTICE, true); + } + } + else + { + $this->writeLogException( + new \MailSo\Smtp\Exceptions\LoginBadMethodException(), + \MailSo\Log\Enumerations\Type::NOTICE, true); + } + + return $this; + } + + /** + * @param string $sXOAuth2Token + * + * @return \MailSo\Smtp\SmtpClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\Exception + */ + public function LoginWithXOauth2($sXOAuth2Token) + { + if ($this->IsAuthSupported('XOAUTH2')) + { + try + { + $this->sendRequestWithCheck('AUTH', 235, 'XOAUTH2 '.trim($sXOAuth2Token)); + } + catch (\MailSo\Smtp\Exceptions\NegativeResponseException $oException) + { + $this->writeLogException( + new \MailSo\Smtp\Exceptions\LoginBadCredentialsException( + $oException->GetResponses(), '', 0, $oException), + \MailSo\Log\Enumerations\Type::NOTICE, true); + } + } + else + { + $this->writeLogException( + new \MailSo\Smtp\Exceptions\LoginBadMethodException(), + \MailSo\Log\Enumerations\Type::NOTICE, true); + } + + return $this; + } + + /** + * @param string $sFrom + * @param string $sSize = '' + * + * @return \MailSo\Smtp\SmtpClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\Exception + */ + public function MailFrom($sFrom, $sSizeIfSupported = '') + { + $sCmd = 'FROM:<'.$sFrom.'>'; + if (0 < strlen($sSizeIfSupported) && $this->IsSupported('SIZE')) + { + $sCmd .= ' SIZE='.$sSizeIfSupported; + } + + $this->sendRequestWithCheck('MAIL', 250, $sCmd); + + $this->bMail = true; + $this->bRcpt = false; + $this->bData = false; + + return $this; + } + + /** + * @param string $sTo + * + * @return \MailSo\Smtp\SmtpClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\Exception + */ + public function Rcpt($sTo) + { + if (!$this->bMail) + { + $this->writeLogException( + new Exceptions\RuntimeException('No sender reverse path has been supplied'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $this->sendRequestWithCheck('RCPT', array(250, 251), 'TO:<'.$sTo.'>'); + + $this->bRcpt = true; + + return $this; + } + + /** + * @param string $sTo + * + * @return \MailSo\Smtp\SmtpClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\Exception + */ + public function MailTo($sTo) + { + return $this->Rcpt($sTo); + } + + /** + * @param string $sData + * + * @return \MailSo\Smtp\SmtpClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\Exception + */ + public function Data($sData) + { + if (!\MailSo\Base\Validator::NotEmptyString($sData, true)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $rDataStream = \MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString($sData); + unset($sData); + $this->DataWithStream($rDataStream); + \MailSo\Base\ResourceRegistry::CloseMemoryResource($rDataStream); + + return $this; + } + + /** + * @param resource $rDataStream + * + * @return \MailSo\Smtp\SmtpClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\Exception + */ + public function DataWithStream($rDataStream) + { + if (!is_resource($rDataStream)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + if (!$this->bRcpt) + { + $this->writeLogException( + new Exceptions\RuntimeException('No recipient forward path has been supplied'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $this->sendRequestWithCheck('DATA', 354); + + $this->writeLog('Message data.', \MailSo\Log\Enumerations\Type::NOTE); + + $iTimer = 0; + while (!feof($rDataStream)) + { + $sBuffer = fgets($rDataStream); + if (false !== $sBuffer) + { + if (0 === strpos($sBuffer, '.')) + { + $sBuffer = '.'.$sBuffer; + } + + $this->sendRaw(rtrim($sBuffer, "\r\n"), false); + + \MailSo\Base\Utils::ResetTimeLimit($iTimer); + continue; + } + else if (!feof($rDataStream)) + { + $this->writeLogException( + new Exceptions\RuntimeException('Cannot read input resource'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + break; + } + + $this->sendRequestWithCheck('.', 250); + + $this->bData = true; + + return $this; + } + + /** + * @return \MailSo\Smtp\SmtpClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\Exception + */ + public function Rset() + { + $this->sendRequestWithCheck('RSET', array(250, 220)); + + $this->bMail = false; + $this->bRcpt = false; + $this->bData = false; + + return $this; + } + + /** + * @return \MailSo\Smtp\SmtpClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\Exception + */ + public function Vrfy($sUser) + { + $this->sendRequestWithCheck('VRFY', array(250, 251, 252), $sUser); + + return $this; + } + + /** + * @return \MailSo\Smtp\SmtpClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\Exception + */ + public function Noop() + { + $this->sendRequestWithCheck('NOOP', 250); + + return $this; + } + + /** + * @return \MailSo\Smtp\SmtpClient + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\Exception + */ + public function Logout() + { + if ($this->IsConnected()) + { + $this->sendRequestWithCheck('QUIT', 221); + } + + $this->bHelo = false; + $this->bMail = false; + $this->bRcpt = false; + $this->bData = false; + + return $this; + } + + /** + * @param string $sEhloHost + * + * @return void + */ + private function preLoginStartTLSAndEhloProcess($sEhloHost) + { + if ($this->bHelo) + { + $this->writeLogException( + new Exceptions\RuntimeException('Cannot issue EHLO/HELO to existing session'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $this->ehloOrHelo($sEhloHost); + + if (\MailSo\Net\Enumerations\ConnectionSecurityType::UseStartTLS( + $this->IsSupported('STARTTLS'), $this->iSecurityType, $this->HasSupportedAuth())) + { + $this->sendRequestWithCheck('STARTTLS', 220); + if (!@stream_socket_enable_crypto($this->rConnect, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) + { + $this->writeLogException( + new \MailSo\Smtp\Exceptions\RuntimeException('Cannot enable STARTTLS'), + \MailSo\Log\Enumerations\Type::WARNING, true); + } + + $this->ehloOrHelo($sEhloHost); + } + else if (\MailSo\Net\Enumerations\ConnectionSecurityType::STARTTLS === $this->iSecurityType) + { + $this->writeLogException( + new \MailSo\Net\Exceptions\SocketUnsuppoterdSecureConnectionException('STARTTLS is not supported'), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $this->bHelo = true; + } + + /** + * @param string $sCommand + * @param string $sAddToCommand = '' + * @param bool $bSecureLog = false + * + * @return void + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + */ + private function sendRequest($sCommand, $sAddToCommand = '', $bSecureLog = false) + { + if (!\MailSo\Base\Validator::NotEmptyString($sCommand, true)) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $this->IsConnected(true); + + $sCommand = trim($sCommand); + $sRealCommand = $sCommand.(0 === strlen($sAddToCommand) ? '' : ' '.$sAddToCommand); + + $sFakeCommand = ($bSecureLog) ? '**********' : ''; + + $this->iRequestTime = microtime(true); + $this->sendRaw($sRealCommand, true, $sFakeCommand); + + return $this; + } + + /** + * @param string $sCommand + * @param int|array $mExpectCode + * @param string $sAddToCommand = '' + * @param bool $bSecureLog = false + * + * @return void + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\Exception + */ + private function sendRequestWithCheck($sCommand, $mExpectCode, $sAddToCommand = '', $bSecureLog = false) + { + $this->sendRequest($sCommand, $sAddToCommand, $bSecureLog); + $this->validateResponse($mExpectCode); + } + + /** + * @param string $sHost + * + * @return void + */ + private function ehloOrHelo($sHost) + { + try + { + $this->ehlo($sHost); + } + catch (\Exception $oException) + { + try + { + $this->helo($sHost); + } + catch (\Exception $oException) + { + throw $oException; + } + } + + return $this; + } + + /** + * @param string $sHost + * + * @return void + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\Exception + */ + private function ehlo($sHost) + { + $this->sendRequestWithCheck('EHLO', 250, $sHost); + + foreach ($this->aResults as $sLine) + { + $aMatch = array(); + if (\preg_match('/[\d]+[ \-](.+)$/', $sLine, $aMatch) && isset($aMatch[1]) && 0 < \strlen($aMatch[1])) + { + $sLine = \trim($aMatch[1]); + $aLine = \preg_split('/[ =]/', $sLine, 2); + if (\is_array($aLine) && 0 < \count($aLine) && !empty($aLine[0])) + { + $sCapa = \strtoupper($aLine[0]); + if (('AUTH' === $sCapa || 'SIZE' === $sCapa) && !empty($aLine[1])) + { + $sSubLine = \trim(\strtoupper($aLine[1])); + if (0 < \strlen($sSubLine)) + { + if ('AUTH' === $sCapa) + { + $this->aAuthTypes = \explode(' ', $sSubLine); + } + else if ('SIZE' === $sCapa && \is_numeric($sSubLine)) + { + $this->iSizeCapaValue = (int) $sSubLine; + } + } + } + + $this->aCapa[] = $sCapa; + } + } + } + } + + /** + * @param string $sHost + * + * @return void + * + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Smtp\Exceptions\Exception + */ + private function helo($sHost) + { + $this->sendRequestWithCheck('HELO', 250, $sHost); + $this->aAuthTypes = array(); + $this->iSizeCapaValue = 0; + $this->aCapa = array(); + } + + /** + * @param int|array $mExpectCode + * + * @return void + * + * @throws \MailSo\Smtp\Exceptions\ResponseException + */ + private function validateResponse($mExpectCode) + { + if (!is_array($mExpectCode)) + { + $mExpectCode = array((int) $mExpectCode); + } + else + { + $mExpectCode = array_map('intval', $mExpectCode); + } + + $aParts = array('', '', ''); + $this->aResults = array(); + do + { + $this->getNextBuffer(); + $aParts = preg_split('/([\s-]+)/', $this->sResponseBuffer, 2, PREG_SPLIT_DELIM_CAPTURE); + + if (is_array($aParts) && 3 === count($aParts) && is_numeric($aParts[0])) + { + if ('-' !== trim($aParts[1]) && !in_array((int) $aParts[0], $mExpectCode)) + { + $this->writeLogException( + new Exceptions\NegativeResponseException(trim( + (0 < count($this->aResults) ? implode("\r\n", $this->aResults)."\r\n" : ''). + $this->sResponseBuffer)), \MailSo\Log\Enumerations\Type::ERROR, true); + } + } + else + { + $this->writeLogException( + new Exceptions\ResponseException(trim( + (0 < count($this->aResults) ? implode("\r\n", $this->aResults)."\r\n" : ''). + $this->sResponseBuffer)), \MailSo\Log\Enumerations\Type::ERROR, true); + } + + $this->aResults[] = $this->sResponseBuffer; + } + while ('-' === \trim($aParts[1])); + + $this->writeLog((microtime(true) - $this->iRequestTime), + \MailSo\Log\Enumerations\Type::TIME); + } + + /** + * @return string + */ + protected function getLogName() + { + return 'SMTP'; + } + + /** + * @param \MailSo\Log\Logger $oLogger + * + * @return \MailSo\Smtp\SmtpClient + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function SetLogger($oLogger) + { + parent::SetLogger($oLogger); + + return $this; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/MailSo/Version.php b/rainloop/v/1.2.5.406/app/libraries/MailSo/Version.php new file mode 100644 index 000000000..cb167e88e --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/MailSo/Version.php @@ -0,0 +1,44 @@ +getSignature(); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/Client.php b/rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/Client.php new file mode 100644 index 000000000..0b59cf6b7 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/Client.php @@ -0,0 +1,513 @@ + + * @author Anis Berejeb + * @version 1.2-dev + */ +namespace OAuth2; + +class Client +{ + /** + * Different AUTH method + */ + const AUTH_TYPE_URI = 0; + const AUTH_TYPE_AUTHORIZATION_BASIC = 1; + const AUTH_TYPE_FORM = 2; + + /** + * Different Access token type + */ + const ACCESS_TOKEN_URI = 0; + const ACCESS_TOKEN_BEARER = 1; + const ACCESS_TOKEN_OAUTH = 2; + const ACCESS_TOKEN_MAC = 3; + + /** + * Different Grant types + */ + const GRANT_TYPE_AUTH_CODE = 'authorization_code'; + const GRANT_TYPE_PASSWORD = 'password'; + const GRANT_TYPE_CLIENT_CREDENTIALS = 'client_credentials'; + const GRANT_TYPE_REFRESH_TOKEN = 'refresh_token'; + + /** + * HTTP Methods + */ + const HTTP_METHOD_GET = 'GET'; + const HTTP_METHOD_POST = 'POST'; + const HTTP_METHOD_PUT = 'PUT'; + const HTTP_METHOD_DELETE = 'DELETE'; + const HTTP_METHOD_HEAD = 'HEAD'; + + /** + * HTTP Form content types + */ + const HTTP_FORM_CONTENT_TYPE_APPLICATION = 0; + const HTTP_FORM_CONTENT_TYPE_MULTIPART = 1; + + /** + * Client ID + * + * @var string + */ + protected $client_id = null; + + /** + * Client Secret + * + * @var string + */ + protected $client_secret = null; + + /** + * Client Authentication method + * + * @var int + */ + protected $client_auth = self::AUTH_TYPE_URI; + + /** + * Access Token + * + * @var string + */ + protected $access_token = null; + + /** + * Access Token Type + * + * @var int + */ + protected $access_token_type = self::ACCESS_TOKEN_URI; + + /** + * Access Token Secret + * + * @var string + */ + protected $access_token_secret = null; + + /** + * Access Token crypt algorithm + * + * @var string + */ + protected $access_token_algorithm = null; + + /** + * Access Token Parameter name + * + * @var string + */ + protected $access_token_param_name = 'access_token'; + + /** + * The path to the certificate file to use for https connections + * + * @var string Defaults to . + */ + protected $certificate_file = null; + + /** + * cURL options + * + * @var array + */ + protected $curl_options = array(); + + /** + * Construct + * + * @param string $client_id Client ID + * @param string $client_secret Client Secret + * @param int $client_auth (AUTH_TYPE_URI, AUTH_TYPE_AUTHORIZATION_BASIC, AUTH_TYPE_FORM) + * @param string $certificate_file Indicates if we want to use a certificate file to trust the server. Optional, defaults to null. + * @return void + */ + public function __construct($client_id, $client_secret, $client_auth = self::AUTH_TYPE_URI, $certificate_file = null) + { + if (!extension_loaded('curl')) { + throw new Exception('The PHP exention curl must be installed to use this library.', Exception::CURL_NOT_FOUND); + } + + $this->client_id = $client_id; + $this->client_secret = $client_secret; + $this->client_auth = $client_auth; + $this->certificate_file = $certificate_file; + if (!empty($this->certificate_file) && !is_file($this->certificate_file)) { + throw new InvalidArgumentException('The certificate file was not found', InvalidArgumentException::CERTIFICATE_NOT_FOUND); + } + } + + /** + * Get the client Id + * + * @return string Client ID + */ + public function getClientId() + { + return $this->client_id; + } + + /** + * Get the client Secret + * + * @return string Client Secret + */ + public function getClientSecret() + { + return $this->client_secret; + } + + /** + * getAuthenticationUrl + * + * @param string $auth_endpoint Url of the authentication endpoint + * @param string $redirect_uri Redirection URI + * @param array $extra_parameters Array of extra parameters like scope or state (Ex: array('scope' => null, 'state' => '')) + * @return string URL used for authentication + */ + public function getAuthenticationUrl($auth_endpoint, $redirect_uri, array $extra_parameters = array()) + { + $parameters = array_merge(array( + 'response_type' => 'code', + 'client_id' => $this->client_id, + 'redirect_uri' => $redirect_uri + ), $extra_parameters); + return $auth_endpoint . '?' . http_build_query($parameters, null, '&'); + } + + /** + * getAccessToken + * + * @param string $token_endpoint Url of the token endpoint + * @param int $grant_type Grant Type ('authorization_code', 'password', 'client_credentials', 'refresh_token', or a custom code (@see GrantType Classes) + * @param array $parameters Array sent to the server (depend on which grant type you're using) + * @return array Array of parameters required by the grant_type (CF SPEC) + */ + public function getAccessToken($token_endpoint, $grant_type, array $parameters) + { + if (!$grant_type) { + throw new InvalidArgumentException('The grant_type is mandatory.', InvalidArgumentException::INVALID_GRANT_TYPE); + } + $grantTypeClassName = $this->convertToCamelCase($grant_type); + $grantTypeClass = __NAMESPACE__ . '\\GrantType\\' . $grantTypeClassName; + if (!class_exists($grantTypeClass)) { + throw new InvalidArgumentException('Unknown grant type \'' . $grant_type . '\'', InvalidArgumentException::INVALID_GRANT_TYPE); + } + $grantTypeObject = new $grantTypeClass(); + $grantTypeObject->validateParameters($parameters); + if (!defined($grantTypeClass . '::GRANT_TYPE')) { + throw new Exception('Unknown constant GRANT_TYPE for class ' . $grantTypeClassName, Exception::GRANT_TYPE_ERROR); + } + $parameters['grant_type'] = $grantTypeClass::GRANT_TYPE; + $http_headers = array(); + switch ($this->client_auth) { + case self::AUTH_TYPE_URI: + case self::AUTH_TYPE_FORM: + $parameters['client_id'] = $this->client_id; + $parameters['client_secret'] = $this->client_secret; + break; + case self::AUTH_TYPE_AUTHORIZATION_BASIC: + $parameters['client_id'] = $this->client_id; + $http_headers['Authorization'] = 'Basic ' . base64_encode($this->client_id . ':' . $this->client_secret); + break; + default: + throw new Exception('Unknown client auth type.', Exception::INVALID_CLIENT_AUTHENTICATION_TYPE); + break; + } + + return $this->executeRequest($token_endpoint, $parameters, self::HTTP_METHOD_POST, $http_headers, self::HTTP_FORM_CONTENT_TYPE_APPLICATION); + } + + /** + * setToken + * + * @param string $token Set the access token + * @return void + */ + public function setAccessToken($token) + { + $this->access_token = $token; + } + + /** + * Set the client authentication type + * + * @param string $client_auth (AUTH_TYPE_URI, AUTH_TYPE_AUTHORIZATION_BASIC, AUTH_TYPE_FORM) + * @return void + */ + public function setClientAuthType($client_auth) + { + $this->client_auth = $client_auth; + } + + /** + * Set an option for the curl transfer + * + * @param int $option The CURLOPT_XXX option to set + * @param mixed $value The value to be set on option + * @return void + */ + public function setCurlOption($option, $value) + { + $this->curl_options[$option] = $value; + } + + /** + * Set multiple options for a cURL transfer + * + * @param array $options An array specifying which options to set and their values + * @return void + */ + public function setCurlOptions($options) + { + $this->curl_options = array_merge($this->curl_options, $options); + } + + /** + * Set the access token type + * + * @param int $type Access token type (ACCESS_TOKEN_BEARER, ACCESS_TOKEN_MAC, ACCESS_TOKEN_URI) + * @param string $secret The secret key used to encrypt the MAC header + * @param string $algorithm Algorithm used to encrypt the signature + * @return void + */ + public function setAccessTokenType($type, $secret = null, $algorithm = null) + { + $this->access_token_type = $type; + $this->access_token_secret = $secret; + $this->access_token_algorithm = $algorithm; + } + + /** + * Fetch a protected ressource + * + * @param string $protected_ressource_url Protected resource URL + * @param array $parameters Array of parameters + * @param string $http_method HTTP Method to use (POST, PUT, GET, HEAD, DELETE) + * @param array $http_headers HTTP headers + * @param int $form_content_type HTTP form content type to use + * @return array + */ + public function fetch($protected_resource_url, $parameters = array(), $http_method = self::HTTP_METHOD_GET, array $http_headers = array(), $form_content_type = self::HTTP_FORM_CONTENT_TYPE_MULTIPART) + { + if ($this->access_token) { + switch ($this->access_token_type) { + case self::ACCESS_TOKEN_URI: + if (is_array($parameters)) { + $parameters[$this->access_token_param_name] = $this->access_token; + } else { + throw new InvalidArgumentException( + 'You need to give parameters as array if you want to give the token within the URI.', + InvalidArgumentException::REQUIRE_PARAMS_AS_ARRAY + ); + } + break; + case self::ACCESS_TOKEN_BEARER: + $http_headers['Authorization'] = 'Bearer ' . $this->access_token; + break; + case self::ACCESS_TOKEN_OAUTH: + $http_headers['Authorization'] = 'OAuth ' . $this->access_token; + break; + case self::ACCESS_TOKEN_MAC: + $http_headers['Authorization'] = 'MAC ' . $this->generateMACSignature($protected_resource_url, $parameters, $http_method); + break; + default: + throw new Exception('Unknown access token type.', Exception::INVALID_ACCESS_TOKEN_TYPE); + break; + } + } + return $this->executeRequest($protected_resource_url, $parameters, $http_method, $http_headers, $form_content_type); + } + + /** + * Generate the MAC signature + * + * @param string $url Called URL + * @param array $parameters Parameters + * @param string $http_method Http Method + * @return string + */ + private function generateMACSignature($url, $parameters, $http_method) + { + $timestamp = time(); + $nonce = uniqid(); + $parsed_url = parse_url($url); + if (!isset($parsed_url['port'])) + { + $parsed_url['port'] = ($parsed_url['scheme'] == 'https') ? 443 : 80; + } + if ($http_method == self::HTTP_METHOD_GET) { + if (is_array($parameters)) { + $parsed_url['path'] .= '?' . http_build_query($parameters, null, '&'); + } elseif ($parameters) { + $parsed_url['path'] .= '?' . $parameters; + } + } + + $signature = base64_encode(hash_hmac($this->access_token_algorithm, + $timestamp . "\n" + . $nonce . "\n" + . $http_method . "\n" + . $parsed_url['path'] . "\n" + . $parsed_url['host'] . "\n" + . $parsed_url['port'] . "\n\n" + , $this->access_token_secret, true)); + + return 'id="' . $this->access_token . '", ts="' . $timestamp . '", nonce="' . $nonce . '", mac="' . $signature . '"'; + } + + /** + * Execute a request (with curl) + * + * @param string $url URL + * @param mixed $parameters Array of parameters + * @param string $http_method HTTP Method + * @param array $http_headers HTTP Headers + * @param int $form_content_type HTTP form content type to use + * @return array + */ + private function executeRequest($url, $parameters = array(), $http_method = self::HTTP_METHOD_GET, array $http_headers = null, $form_content_type = self::HTTP_FORM_CONTENT_TYPE_MULTIPART) + { + $curl_options = array( + CURLOPT_RETURNTRANSFER => true, + CURLOPT_SSL_VERIFYPEER => true, + CURLOPT_CUSTOMREQUEST => $http_method + ); + + switch($http_method) { + case self::HTTP_METHOD_POST: + $curl_options[CURLOPT_POST] = true; + /* No break */ + case self::HTTP_METHOD_PUT: + + /** + * Passing an array to CURLOPT_POSTFIELDS will encode the data as multipart/form-data, + * while passing a URL-encoded string will encode the data as application/x-www-form-urlencoded. + * http://php.net/manual/en/function.curl-setopt.php + */ + if(is_array($parameters) && self::HTTP_FORM_CONTENT_TYPE_APPLICATION === $form_content_type) { + $parameters = http_build_query($parameters, null, '&'); + } + $curl_options[CURLOPT_POSTFIELDS] = $parameters; + break; + case self::HTTP_METHOD_HEAD: + $curl_options[CURLOPT_NOBODY] = true; + /* No break */ + case self::HTTP_METHOD_DELETE: + case self::HTTP_METHOD_GET: + if (is_array($parameters)) { + $url .= '?' . http_build_query($parameters, null, '&'); + } elseif ($parameters) { + $url .= '?' . $parameters; + } + break; + default: + break; + } + + $curl_options[CURLOPT_URL] = $url; + + if (is_array($http_headers)) { + $header = array(); + foreach($http_headers as $key => $parsed_urlvalue) { + $header[] = "$key: $parsed_urlvalue"; + } + $curl_options[CURLOPT_HTTPHEADER] = $header; + } + + $ch = curl_init(); + curl_setopt_array($ch, $curl_options); + // https handling + if (!empty($this->certificate_file)) { + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); + curl_setopt($ch, CURLOPT_CAINFO, $this->certificate_file); + } else { + // bypass ssl verification + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + } + if (!empty($this->curl_options)) { + curl_setopt_array($ch, $this->curl_options); + } + $result = curl_exec($ch); + $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); + if ($curl_error = curl_error($ch)) { + throw new Exception($curl_error, Exception::CURL_ERROR); + } else { + $json_decode = json_decode($result, true); + } + curl_close($ch); + + return array( + 'result' => (null === $json_decode) ? $result : $json_decode, + 'code' => $http_code, + 'content_type' => $content_type + ); + } + + /** + * Set the name of the parameter that carry the access token + * + * @param string $name Token parameter name + * @return void + */ + public function setAccessTokenParamName($name) + { + $this->access_token_param_name = $name; + } + + /** + * Converts the class name to camel case + * + * @param mixed $grant_type the grant type + * @return string + */ + private function convertToCamelCase($grant_type) + { + $parts = explode('_', $grant_type); + array_walk($parts, function(&$item) { $item = ucfirst($item);}); + return implode('', $parts); + } +} + +class Exception extends \Exception +{ + const CURL_NOT_FOUND = 0x01; + const CURL_ERROR = 0x02; + const GRANT_TYPE_ERROR = 0x03; + const INVALID_CLIENT_AUTHENTICATION_TYPE = 0x04; + const INVALID_ACCESS_TOKEN_TYPE = 0x05; +} + +class InvalidArgumentException extends \InvalidArgumentException +{ + const INVALID_GRANT_TYPE = 0x01; + const CERTIFICATE_NOT_FOUND = 0x02; + const REQUIRE_PARAMS_AS_ARRAY = 0x03; + const MISSING_PARAMETER = 0x04; +} diff --git a/rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/GrantType/AuthorizationCode.php b/rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/GrantType/AuthorizationCode.php new file mode 100644 index 000000000..f3436e4c5 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/GrantType/AuthorizationCode.php @@ -0,0 +1,41 @@ +getAuthenticationUrl(AUTHORIZATION_ENDPOINT, REDIRECT_URI); + header('Location: ' . $auth_url); + die('Redirect'); +} +else +{ + $params = array('code' => $_GET['code'], 'redirect_uri' => REDIRECT_URI); + $response = $client->getAccessToken(TOKEN_ENDPOINT, 'authorization_code', $params); + parse_str($response['result'], $info); + $client->setAccessToken($info['access_token']); + $response = $client->fetch('https://graph.facebook.com/me'); + var_dump($response, $response['result']); +} + +How can I add a new Grant Type ? +================================ +Simply write a new class in the namespace OAuth2\GrantType. You can place the class file under GrantType. +Here is an example : + +namespace OAuth2\GrantType; + +/** + * MyCustomGrantType Grant Type + */ +class MyCustomGrantType implements IGrantType +{ + /** + * Defines the Grant Type + * + * @var string Defaults to 'my_custom_grant_type'. + */ + const GRANT_TYPE = 'my_custom_grant_type'; + + /** + * Adds a specific Handling of the parameters + * + * @return array of Specific parameters to be sent. + * @param mixed $parameters the parameters array (passed by reference) + */ + public function validateParameters(&$parameters) + { + if (!isset($parameters['first_mandatory_parameter'])) + { + throw new \Exception('The \'first_mandatory_parameter\' parameter must be defined for the Password grant type'); + } + elseif (!isset($parameters['second_mandatory_parameter'])) + { + throw new \Exception('The \'seconde_mandatory_parameter\' parameter must be defined for the Password grant type'); + } + } +} + +call the OAuth client getAccessToken with the grantType you defined in the GRANT_TYPE constant, As following : +$response = $client->getAccessToken(TOKEN_ENDPOINT, 'my_custom_grant_type', $params); + diff --git a/rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/composer.json b/rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/composer.json new file mode 100644 index 000000000..2e052a52e --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/PHP-OAuth2/composer.json @@ -0,0 +1,19 @@ +{ + "name": "adoy/oauth2", + "description": "Light PHP wrapper for the OAuth 2.0 protocol (based on OAuth 2.0 Authorization Protocol draft-ietf-oauth-v2-15)", + "authors": [ + { + "name": "Charron Pierrick", + "email": "pierrick@webstart.fr" + }, + { + "name": "Berejeb Anis", + "email": "anis.berejeb@gmail.com" + } + ], + "autoload": { + "classmap": [ + "../" + ] + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Account.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Account.php new file mode 100644 index 000000000..08f979d8b --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Account.php @@ -0,0 +1,197 @@ +sEmail = \strtolower($sEmail); + $this->sLogin = $sLogin; + $this->sPassword = $sPassword; + $this->oDomain = $oDomain; + $this->bPasswordIsXOAuth2 = $bPasswordIsXOAuth2; + $this->sSignMeToken = $sSignMeToken; + $this->sParentEmail = \strtolower($sParentEmail); + } + + /** + * @param string $sEmail + * @param string $sLogin + * @param string $sPassword + * @param \RainLoop\Domain $oDomain + * @param bool $bPasswordIsXOAuth2 = false + * @param string $sSignMeToken = '' + * @param string $sParentEmail = '' + * + * @return \RainLoop\Account + */ + public static function NewInstance($sEmail, $sLogin, $sPassword, \RainLoop\Domain $oDomain, $bPasswordIsXOAuth2 = false, $sSignMeToken = '', $sParentEmail = '') + { + return new self($sEmail, $sLogin, $sPassword, $oDomain, $bPasswordIsXOAuth2, $sSignMeToken, $sParentEmail); + } + + /** + * @return string + */ + public function Email() + { + return $this->sEmail; + } + + /** + * @return string + */ + public function ParentEmail() + { + return $this->sParentEmail; + } + + /** + * @return string + */ + public function ParentEmailHelper() + { + return 0 < \strlen($this->sParentEmail) ? $this->sParentEmail : $this->sEmail; + } + + /** + * @return string + */ + public function Login() + { + return $this->sLogin; + } + + /** + * @return string + */ + public function Password() + { + return $this->sPassword; + } + + /** + * @return bool + */ + public function PasswordIsXOAuth2() + { + return $this->bPasswordIsXOAuth2; + } + + /** + * @return bool + */ + public function SignMe() + { + return 0 < \strlen($this->sSignMeToken); + } + + /** + * @return string + */ + public function SignMeToken() + { + return $this->sSignMeToken; + } + + /** + * @return \RainLoop\Domain + */ + public function Domain() + { + return $this->oDomain; + } + + /** + * @return \RainLoop\Domain + */ + public function Hash() + { + return md5(APP_SALT.$this->Email().APP_SALT.$this->oDomain->IncHost().APP_SALT.$this->oDomain->IncPort(). + APP_SALT.$this->Password().APP_SALT.($this->PasswordIsXOAuth2() ? '1' : '0').APP_SALT.$this->ParentEmail().APP_SALT); + } + + /** + * @param string $sPassword + * + * @return void + */ + public function SetPassword($sPassword) + { + $this->sPassword = $sPassword; + } + + /** + * @param string $sParentEmail + * + * @return void + */ + public function SetParentEmail($sParentEmail) + { + $this->sParentEmail = \strtolower($sParentEmail); + } + + /** + * @return string + */ + public function GetAuthToken() + { + return \RainLoop\Utils::EncodeKeyValues(array( + 'token', + $this->sEmail, + $this->sLogin, + $this->sPassword, + $this->bPasswordIsXOAuth2 ? '1' : '0', + $this->sSignMeToken, + $this->sParentEmail, + \microtime(true).\mt_rand(1000, 9999) + )); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Actions.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Actions.php new file mode 100644 index 000000000..f86f76668 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Actions.php @@ -0,0 +1,5099 @@ +aCurrentActionParams = array(); + + $this->oHttp = null; + $this->oLogger = null; + $this->oPlugins = null; + $this->oMailClient = null; + $this->oSocial = null; + $this->oConfig = null; + $this->oCacher = null; + $this->oCacherFile = null; + + $this->oStorageProvider = null; + $this->oSettingsProvider = null; + $this->oDomainProvider = null; + $this->oLoginProvider = null; + $this->oSuggestionsProvider = null; + $this->oChangePasswordProvider = null; + + $this->sSpecAuthToken = ''; + + $oConfig = $this->Config(); + $this->Plugins()->RunHook('filter.application-config', array(&$oConfig)); + } + + /** + * @return \RainLoop\Actions + */ + public static function NewInstance() + { + return new self(); + } + + /** + * @param string $sSpecAuthToken + * + * @return \RainLoop\Application + */ + public function SetSpecAuthToken($sSpecAuthToken) + { + $this->sSpecAuthToken = $sSpecAuthToken; + + return $this; + } + + /** + * @return string + */ + public function GetSpecAuthToken() + { + return $this->sSpecAuthToken; + } + + /** + * @return \RainLoop\Application + */ + public function Config() + { + if (null === $this->oConfig) + { + $this->oConfig = new \RainLoop\Config\Application(); + + $bSave = defined('APP_INSTALLED_START'); + if (!$this->oConfig->Load()) + { + $bSave = true; + } + else if (!$bSave) + { + $bSave = APP_VERSION !== $this->oConfig->Get('version', 'current'); + } + + if ($bSave) + { + $this->oConfig->Save(); + } + } + + return $this->oConfig; + } + + /** + * @param string $sName + * + * @return mixed + */ + private function fabrica($sName) + { + $oResult = null; + $this->Plugins()->RunHook('main.fabrica', array($sName, &$oResult), false); + + if (null === $oResult) + { + switch ($sName) + { + case 'storage': + // RainLoop\Providers\Storage\StorageInterface + $oResult = new \RainLoop\Providers\Storage\DefaultStorage(APP_PRIVATE_DATA.'storage'); + break; + case 'settings': + // RainLoop\Providers\Settings\SettingsInterface + $oResult = new \RainLoop\Providers\Settings\DefaultSettings($this->StorageProvider()); + break; + case 'login': + // \RainLoop\Providers\Login\LoginInterface + $oResult = new \RainLoop\Providers\Login\DefaultLogin(); + break; + case 'domain': + // \RainLoop\Providers\Domain\DomainSimpleInterface + // \RainLoop\Providers\Domain\DomainAdminInterface + $oResult = new \RainLoop\Providers\Domain\DefaultDomain(APP_PRIVATE_DATA.'domains'); + break; + case 'contacts': + // \RainLoop\Providers\Contacts\ContactsInterface + $oResult = new \RainLoop\Providers\Contacts\DefaultContacts($this->Logger()); + break; + case 'suggestions': + // \RainLoop\Providers\Suggestions\SuggestionsInterface + break; + case 'change-password': + // \RainLoop\Providers\ChangePassword\ChangePasswordInterface + break; + } + } + + return $oResult; + } + + /** + * @return string + */ + public function ParseQueryAuthString() + { + if ('' === $this->GetSpecAuthToken()) + { + $sQuery = \trim(\trim($this->Http()->GetServer('QUERY_STRING', '')), ' /'); + $iPos = \strpos($sQuery, '&'); + if (0 < $iPos) + { + $sQuery = \substr($sQuery, 0, $iPos); + } + + $aPaths = \explode('/', $sQuery); + if (!empty($aPaths[0]) && !empty($aPaths[1]) && '_' === substr($aPaths[1], 0, 1)) + { + $this->SetSpecAuthToken($aPaths[1]); + } + } + } + + /** + * @return string + */ + private function compileLogFileName() + { + $sFileName = (string) $this->Config()->Get('logs', 'filename', ''); + + if (false !== \strpos($sFileName, '{date:')) + { + $sFileName = \preg_replace_callback('/\{date:([^}]+)\}/', function ($aMatch) { + return \gmdate($aMatch[1]); + }, $sFileName); + + $sFileName = \preg_replace('/\{date:([^}]*)\}/', 'date', $sFileName); + } + + if (false !== \strpos($sFileName, '{user:')) + { + if (false !== \strpos($sFileName, '{user:uid}')) + { + $sFileName = \str_replace('{user:uid}', + \base_convert(\sprintf('%u', \crc32(md5(\RainLoop\Utils::GetConnectionToken()))), 10, 32), + $sFileName + ); + } + + $this->ParseQueryAuthString(); + + $oAccount = $this->getAccountFromToken(false); + if ($oAccount) + { + $sFileName = \str_replace('{user:email}', \strtolower($oAccount->Email()), $sFileName); + $sFileName = \str_replace('{user:login}', $oAccount->Login(), $sFileName); + $sFileName = \str_replace('{user:domain}', \strtolower($oAccount->Domain()->Name()), $sFileName); + } + + $sFileName = \preg_replace('/\{user:([^}]*)\}/', 'unknown', $sFileName); + } + + if (false !== \strpos($sFileName, '{labs:')) + { + $sFileName = \preg_replace_callback('/\{labs:rand:([1-9])\}/', function ($aMatch) { + return \mt_rand(\pow(10, $aMatch[1] - 1), \pow(10, $aMatch[1]) - 1); + }, $sFileName); + + $sFileName = \preg_replace('/\{labs:([^}]*)\}/', 'labs', $sFileName); + } + + if (0 === strlen($sFileName)) + { + $sFileName = 'rainlooplog.txt'; + } + + $sFileName = \preg_replace('/[\/]+/', '/', \preg_replace('/[.]+/', '.', $sFileName)); + $sFileName = \preg_replace('/[^a-zA-Z0-9@_+=\-\.\/!()]/', '', $sFileName); + + return $sFileName; + } + + private function generateSpecAuthKey() + { + return 'Account/SpecAuthToken/'.$this->GetSpecAuthToken().'/'.\RainLoop\Utils::GetConnectionToken().'/'.self::AUTH_TOKEN_KEY.'/'; + } + + /** + * @param \RainLoop\Account $oAccount + * @param bool $bRandomToken = false + * + * @return void + */ + public function SetAuthToken($oAccount, $bRandomToken = false) + { + if ($oAccount) + { + $sSpecAuthToken = '_'.\md5(APP_SALT.\RainLoop\Utils::GetConnectionToken().$oAccount->Email(). + ($bRandomToken ? microtime(true).rand(1000, 9999) : '').APP_SALT); + + $this->SetSpecAuthToken($sSpecAuthToken); + $this->CacherFile()->Set($this->generateSpecAuthKey(), $oAccount->GetAuthToken()); + + \RainLoop\Utils::SetCookie(self::AUTH_SPEC_TOKEN_KEY, $sSpecAuthToken, 0, '/', null, null, true); + + if ($oAccount->SignMe() && 0 < \strlen($oAccount->SignMeToken())) + { + \RainLoop\Utils::SetCookie(self::AUTH_SIGN_ME_TOKEN_KEY, $oAccount->SignMeToken(), + \time() + 60 * 60 * 24 * 30, '/', null, null, true); + + $this->StorageProvider()->Put(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + 'SignMe/UserToken/'.$oAccount->SignMeToken(), + $oAccount->GetAuthToken()); + } + } + } + + /** + * @return string + */ + public function GetSpecAuthTokenWithDeletion() + { + $sResult = \RainLoop\Utils::GetCookie(self::AUTH_SPEC_TOKEN_KEY, ''); + if (0 < strlen($sResult)) + { + \RainLoop\Utils::ClearCookie(self::AUTH_SPEC_TOKEN_KEY); + } + + return $sResult; + } + + /** + * @return void + */ + private function setAdminAuthToken($sToken) + { + \RainLoop\Utils::SetCookie(self::AUTH_ADMIN_TOKEN_KEY, $sToken, 0, '/', null, null, true); + } + + /** + * @return string + */ + private function getAuthToken() + { + return $this->CacherFile()->Get($this->generateSpecAuthKey()); + } + + /** + * @return string + */ + private function getAdminAuthToken() + { + return \RainLoop\Utils::GetCookie(self::AUTH_ADMIN_TOKEN_KEY, ''); + } + + /** + * @return void + */ + public function ClearAuthToken() + { + $this->CacherFile()->Delete($this->generateSpecAuthKey()); + } + + /** + * @return void + */ + public function ClearAdminAuthToken() + { + \RainLoop\Utils::ClearCookie(self::AUTH_ADMIN_TOKEN_KEY); + } + + /** + * @param bool $bThrowExceptionOnFalse = false + * + * @return \RainLoop\Account|bool + * @throws \RainLoop\Exceptions\ClientException + */ + public function GetAccount($bThrowExceptionOnFalse = false) + { + return $this->getAccountFromToken($bThrowExceptionOnFalse); + } + + /** + * @return \MailSo\Base\Http + */ + public function Http() + { + if (null === $this->oHttp) + { + $this->oHttp = \MailSo\Base\Http::SingletonInstance(); + } + + return $this->oHttp; + } + + /** + * @return \RainLoop\Social + */ + public function Social() + { + if (null === $this->oSocial) + { + $this->oSocial = new \RainLoop\Social($this->Http(), $this); + } + + return $this->oSocial; + } + + /** + * @return \MailSo\Mail\MailClient + */ + public function MailClient() + { + if (null === $this->oMailClient) + { + $this->oMailClient = \MailSo\Mail\MailClient::NewInstance(); + $this->oMailClient->SetLogger($this->Logger()); + } + + return $this->oMailClient; + } + + /** + * @return \RainLoop\Providers\Settings + */ + public function SettingsProvider() + { + if (null === $this->oSettingsProvider) + { + $this->oSettingsProvider = new \RainLoop\Providers\Settings( + $this->fabrica('settings')); + } + + return $this->oSettingsProvider; + } + + /** + * @return \RainLoop\Providers\ChangePassword + */ + public function ChangePasswordProvider() + { + if (null === $this->oChangePasswordProvider) + { + $this->oChangePasswordProvider = new \RainLoop\Providers\ChangePassword( + $this, $this->fabrica('change-password') + ); + } + + return $this->oChangePasswordProvider; + } + + /** + * @return \RainLoop\Providers\Storage + */ + public function StorageProvider() + { + if (null === $this->oStorageProvider) + { + $this->oStorageProvider = new \RainLoop\Providers\Storage( + $this->fabrica('storage')); + } + + return $this->oStorageProvider; + } + + /** + * @return \RainLoop\Providers\Domain + */ + public function DomainProvider() + { + if (null === $this->oDomainProvider) + { + $this->oDomainProvider = new \RainLoop\Providers\Domain( + $this->fabrica('domain')); + } + + return $this->oDomainProvider; + } + + /** + * @return \RainLoop\Providers\Suggestions + */ + public function SuggestionsProvider() + { + if (null === $this->oSuggestionsProvider) + { + $this->oSuggestionsProvider = new \RainLoop\Providers\Suggestions($this->fabrica('suggestions')); + } + + return $this->oSuggestionsProvider; + } + + /** + * @return \RainLoop\Providers\Contacts + */ + public function ContactsProvider() + { + if (null === $this->oContactsProvider) + { + $this->oContactsProvider = new \RainLoop\Providers\Contacts($this->fabrica('contacts')); + } + + return $this->oContactsProvider; + } + + /** + * @return \RainLoop\Providers\Login + */ + public function LoginProvider() + { + if (null === $this->oLoginProvider) + { + $this->oLoginProvider = new \RainLoop\Providers\Login( + $this->fabrica('login'), $this->DomainProvider()); + } + + return $this->oLoginProvider; + } + + /** + * @return \OAuth2\Client|null + */ + public function GoogleConnector() + { + $oGoogle = false; + $oConfig = $this->Config(); + if ($oConfig->Get('social', 'google_enable', false) && + '' !== \trim($oConfig->Get('social', 'google_client_id', '')) && + '' !== \trim($oConfig->Get('social', 'google_client_secret', ''))) + { + include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/Client.php'; + include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/IGrantType.php'; + include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/AuthorizationCode.php'; + include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/RefreshToken.php'; + + try + { + $oGoogle = new \OAuth2\Client( + \trim($oConfig->Get('social', 'google_client_id', '')), + \trim($oConfig->Get('social', 'google_client_secret', ''))); + } + catch (\Exception $oException) + { + $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + } + + return false === $oGoogle ? null : $oGoogle; + } + + /** + * @return \tmhOAuth|null + */ + public function TwitterConnector() + { + $oTwitter = false; + $oConfig = $this->Config(); + if ($oConfig->Get('social', 'twitter_enable', false) && + '' !== \trim($oConfig->Get('social', 'twitter_consumer_key', '')) && + '' !== \trim($oConfig->Get('social', 'twitter_consumer_secret', ''))) + { + include_once APP_VERSION_ROOT_PATH.'app/libraries/tmhOAuth/tmhOAuth.php'; + include_once APP_VERSION_ROOT_PATH.'app/libraries/tmhOAuth/tmhUtilities.php'; + + $oTwitter = new \tmhOAuth(array( + 'consumer_key' => \trim($oConfig->Get('social', 'twitter_consumer_key', '')), + 'consumer_secret' => \trim($oConfig->Get('social', 'twitter_consumer_secret', '')) + )); + } + + return false === $oTwitter ? null : $oTwitter; + } + + /** + * @param \RainLoop\Account|null $oAccount = null + * + * @return \Facebook|null + */ + public function FacebookConnector($oAccount = null) + { + $oFacebook = false; + $oConfig = $this->Config(); + if ($oConfig->Get('social', 'fb_enable', false) && + '' !== \trim($oConfig->Get('social', 'fb_app_id', '')) && + '' !== \trim($oConfig->Get('social', 'fb_app_secret', ''))) + { + include_once APP_VERSION_ROOT_PATH.'app/libraries/facebook/facebook.php'; + + $oFacebook = new \RainLoopFacebook(array( + 'rlAccount' => $oAccount, + 'rlUserHash' => \RainLoop\Utils::GetConnectionToken(), + 'rlStorageProvaider' => $this->StorageProvider(), + 'appId' => \trim($oConfig->Get('social', 'fb_app_id', '')), + 'secret' => \trim($oConfig->Get('social', 'fb_app_secret', '')), + 'fileUpload' => false, + 'cookie' => true + )); + } + + return false === $oFacebook ? null : $oFacebook; + } + + /** + * @return \MailSo\Cache\CacheClient + */ + public function CacherFile() + { + if (null === $this->oCacherFile) + { + $this->oCacherFile = \MailSo\Cache\CacheClient::NewInstance(); + $this->oCacherFile->SetDriver(\MailSo\Cache\Drivers\File::NewInstance(APP_PRIVATE_DATA.'cache')); + $this->oCacherFile->SetCacheIndex($this->Config()->Get('cache', 'index', '')); + } + + return $this->oCacherFile; + } + + /** + * @return \MailSo\Cache\CacheClient + */ + public function Cacher() + { + if (null === $this->oCacher) + { + $this->oCacher = \MailSo\Cache\CacheClient::NewInstance(); + + $oDriver = null; + $sDriver = \strtoupper(\trim($this->Config()->Get('cache', 'fast_cache_driver', 'files'))); + + switch (true) + { + case 'APC' === $sDriver && \MailSo\Base\Utils::FunctionExistsAndEnabled('apc_store'): + $oDriver = \MailSo\Cache\Drivers\APC::NewInstance(); + break; + case 'MEMCACHE' === $sDriver && \MailSo\Base\Utils::FunctionExistsAndEnabled('memcache_connect'): + case 'MEMCACHED' === $sDriver && \MailSo\Base\Utils::FunctionExistsAndEnabled('memcache_connect'): + $oDriver = \MailSo\Cache\Drivers\Memcache::NewInstance( + $this->Config()->Get('labs', 'fast_cache_memcache_host', '127.0.0.1'), + (int) $this->Config()->Get('labs', 'fast_cache_memcache_port', 11211) + ); + break; + default: + $oDriver = \MailSo\Cache\Drivers\File::NewInstance(APP_PRIVATE_DATA.'cache'); + break; + } + + if ($oDriver) + { + $this->oCacher->SetDriver($oDriver); + } + + $this->oCacher->SetCacheIndex($this->Config()->Get('cache', 'fast_cache_index', '')); + } + + return $this->oCacher; + } + + /** + * @return \RainLoop\Plugins\Manager + */ + public function Plugins() + { + if (null === $this->oPlugins) + { + $this->oPlugins = new \RainLoop\Plugins\Manager($this); + $this->oPlugins->SetLogger($this->Logger()); + } + + return $this->oPlugins; + } + + /** + * @return \MailSo\Log\Logger + */ + public function Logger() + { + if (null === $this->oLogger) + { + $this->oLogger = \MailSo\Log\Logger::SingletonInstance(); + + if (!!$this->Config()->Get('logs', 'enable', true)) + { + $sLogFileFullPath = \APP_PRIVATE_DATA.'logs/'.$this->compileLogFileName(); + $sLogFileDir = dirname($sLogFileFullPath); + + if (!@is_dir($sLogFileDir)) + { + @mkdir($sLogFileDir, 0777, true); + } + + $this->oLogger->Add(\MailSo\Log\Drivers\File::NewInstance($sLogFileFullPath) + ->WriteOnErrorOnly($this->Config()->Get('logs', 'write_on_error_only', true))); + + if (!$this->Config()->Get('debug', 'enable', false)) + { + $this->oLogger->AddForbiddenType(\MailSo\Log\Enumerations\Type::TIME); + } + + $this->oLogger->WriteEmptyLine(); + + $oHttp = $this->Http(); + $this->oLogger->Write( + $oHttp->GetMethod().': '.$oHttp->GetHost().$oHttp->GetServer('REQUEST_URI', ''), + \MailSo\Log\Enumerations\Type::NOTE, 'REQUEST'); + } + } + + return $this->oLogger; + } + + /** + * @return array + */ + private function getAdminToken() + { + return \RainLoop\Utils::EncodeKeyValues(array('token', \md5(APP_SALT))); + } + + /** + * @param bool $bThrowExceptionOnFalse = true + * + * @return bool + */ + public function IsAdminLoggined($bThrowExceptionOnFalse = true) + { + $bResult = false; + $aAdminHash = \RainLoop\Utils::DecodeKeyValues($this->getAdminAuthToken()); + if ((!empty($aAdminHash[0]) && !empty($aAdminHash[1]) && + 'token' === $aAdminHash[0] && \md5(APP_SALT) === $aAdminHash[1])) + { + $bResult = true; + } + else if ($bThrowExceptionOnFalse) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AuthError); + } + + return $bResult; + } + + /** + * @param string $sToken + * @param bool $bThrowExceptionOnFalse = true + * + * @return \RainLoop\Account|bool + * @throws \RainLoop\Exceptions\ClientException + */ + public function GetAccountFromCustomToken($sToken, $bThrowExceptionOnFalse = true) + { + $oResult = false; + if (!empty($sToken)) + { + $aAccountHash = \RainLoop\Utils::DecodeKeyValues($sToken); + if (!empty($aAccountHash[0]) && 'token' === $aAccountHash[0] && 8 === \count($aAccountHash)) + { + $oAccount = $this->LoginProvider()->Provide( + $aAccountHash[1], $aAccountHash[2], $aAccountHash[3], '1' === $aAccountHash[4], empty($aAccountHash[5]) ? '' : $aAccountHash[5]); + + if ($oAccount instanceof \RainLoop\Account) + { + if (!$oAccount->PasswordIsXOAuth2()) + { + $this->Logger()->AddSecret($oAccount->Password()); + } + + $oAccount->SetParentEmail($aAccountHash[6]); + $oResult = $oAccount; + } + else + { + $oDomain = $this->DomainProvider()->Load(\MailSo\Base\Utils::GetDomainFromEmail($aAccountHash[1])); + if (!($oDomain instanceof \RainLoop\Domain) || $oDomain->Disabled()) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::DomainNotAllowed); + } + } + } + else if ($bThrowExceptionOnFalse) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AuthError); + } + } + + if ($bThrowExceptionOnFalse && !($oResult instanceof \RainLoop\Account)) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AuthError); + } + + return $oResult; + } + + /** + * @param bool $bThrowExceptionOnFalse = true + * + * @return \RainLoop\Account|bool + * @throws \RainLoop\Exceptions\ClientException + */ + private function getAccountFromToken($bThrowExceptionOnFalse = true) + { + return $this->GetAccountFromCustomToken($this->getAuthToken(), $bThrowExceptionOnFalse); + } + + /** + * @param bool $bAdmin + * @param string $sAuthAccountHash = '' + * + * @return array + */ + public function AppData($bAdmin, $sAuthAccountHash = '') + { + $oConfig = $this->Config(); + + $aResult = array( + 'Version' => APP_VERSION, + 'Auth' => false, + 'AccountHash' => '', + 'AuthAccountHash' => '', + 'Email' => '', + 'Title' => $oConfig->Get('webmail', 'title', ''), + 'Token' => $oConfig->Get('security', 'csrf_protection', false) ? \RainLoop\Utils::GetCsrfToken() : '', + 'InIframe' => $oConfig->Get('labs', 'in_iframe', false), + 'CustomLogoutLink' => $oConfig->Get('labs', 'custom_logout_link', ''), + 'AllowAdditionalAccounts' => !!$oConfig->Get('webmail', 'allow_additional_accounts', true), + 'AllowCustomTheme' => !!$oConfig->Get('webmail', 'allow_custom_theme', true), + 'SuggestionsLimit' => $oConfig->Get('labs', 'suggestions_limit', 50), + 'RemoteChangePassword' => false, + 'ContactsIsSupported' => (bool) $this->ContactsProvider()->IsSupported(), + 'JsHash' => \md5(\RainLoop\Utils::GetConnectionToken()), + 'UseImapThread' => (bool) $oConfig->Get('labs', 'use_imap_thread', false), + 'AllowAppendMessage' => (bool) $oConfig->Get('labs', 'allow_message_append', false), + 'CdnStaticDomain' => $oConfig->Get('labs', 'cdn_static_domain', ''), + 'IndexFile' => \APP_SHORT_INDEX_FILE_NAME, + 'Plugins' => array() + ); + + if (0 < \strlen($sAuthAccountHash)) + { + $aResult['AuthAccountHash'] = $sAuthAccountHash; + } + + $oSettings = null; + if (!$bAdmin) + { + $oAccount = $this->getAccountFromToken(false); + if ($oAccount instanceof \RainLoop\Account) + { + $aResult['Email'] = $oAccount->Email(); + $aResult['Login'] = $oAccount->Login(); + $aResult['Auth'] = true; + $aResult['AccountHash'] = $oAccount->Hash(); + $aResult['RemoteChangePassword'] = $this->ChangePasswordProvider()->PasswordChangePossibility($oAccount); + + $oSettings = $this->SettingsProvider()->Load($oAccount); + } + else + { + $aResult['DevEmail'] = $oConfig->Get('labs', 'dev_email', ''); + $aResult['DevLogin'] = $oConfig->Get('labs', 'dev_login', ''); + $aResult['DevPassword'] = $oConfig->Get('labs', 'dev_password', ''); + } + + $aResult['AllowGoogleSocial'] = (bool) $oConfig->Get('social', 'google_enable', false); + if ($aResult['AllowGoogleSocial'] && ( + '' === \trim($oConfig->Get('social', 'google_client_id', '')) || '' === \trim($oConfig->Get('social', 'google_client_secret', '')))) + { + $aResult['AllowGoogleSocial'] = false; + } + + $aResult['AllowFacebookSocial'] = (bool) $oConfig->Get('social', 'fb_enable', false); + if ($aResult['AllowFacebookSocial'] && ( + '' === \trim($oConfig->Get('social', 'fb_app_id', '')) || '' === \trim($oConfig->Get('social', 'fb_app_secret', '')))) + { + $aResult['AllowFacebookSocial'] = false; + } + + $aResult['AllowTwitterSocial'] = (bool) $oConfig->Get('social', 'twitter_enable', false); + if ($aResult['AllowTwitterSocial'] && ( + '' === \trim($oConfig->Get('social', 'twitter_consumer_key', '')) || '' === \trim($oConfig->Get('social', 'twitter_consumer_secret', '')))) + { + $aResult['AllowTwitterSocial'] = false; + } + + $aResult['AllowDropboxSocial'] = (bool) $oConfig->Get('social', 'dropbox_enable', false); + $aResult['DropboxApiKey'] = \trim($oConfig->Get('social', 'dropbox_api_key', '')); + if (!$aResult['AllowDropboxSocial']) + { + $aResult['DropboxApiKey'] = ''; + } + else if (0 === strlen($aResult['DropboxApiKey'])) + { + $aResult['AllowDropboxSocial'] = false; + } + } + else + { + $aResult['Auth'] = $this->IsAdminLoggined(false); + $aResult['AdminLogin'] = $oConfig->Get('security', 'admin_login', ''); + $aResult['AdminDomain'] = APP_SITE; + $aResult['UseTokenProtection'] = (bool) $oConfig->Get('security', 'csrf_protection', true); + $aResult['EnabledPlugins'] = (bool) $oConfig->Get('plugins', 'enable', false); + + $aResult['AllowGoogleSocial'] = (bool) $oConfig->Get('social', 'google_enable', false); + $aResult['GoogleClientID'] = (string) $oConfig->Get('social', 'google_client_id', ''); + $aResult['GoogleClientSecret'] = (string) $oConfig->Get('social', 'google_client_secret', ''); + + $aResult['AllowFacebookSocial'] = (bool) $oConfig->Get('social', 'fb_enable', false); + $aResult['FacebookAppID'] = (string) $oConfig->Get('social', 'fb_app_id', ''); + $aResult['FacebookAppSecret'] = (string) $oConfig->Get('social', 'fb_app_secret', ''); + + $aResult['AllowTwitterSocial'] = (bool) $oConfig->Get('social', 'twitter_enable', false); + $aResult['TwitterConsumerKey'] = (string) $oConfig->Get('social', 'twitter_consumer_key', ''); + $aResult['TwitterConsumerKey'] = (string) $oConfig->Get('social', 'twitter_consumer_key', ''); + + $aResult['AllowDropboxSocial'] = (bool) $oConfig->Get('social', 'dropbox_enable', false); + $aResult['DropboxApiKey'] = (string) $oConfig->Get('social', 'dropbox_api_key', ''); + } + + $aResult['ProjectHash'] = md5($aResult['AccountHash'].APP_VERSION); + + $sLanguage = $oConfig->Get('webmail', 'language', 'en'); + $sTheme = $oConfig->Get('webmail', 'theme', 'Default'); + + $aResult['Domains'] = $this->DomainProvider()->GetList(1); + $aResult['Themes'] = $this->GetThemes($bAdmin); + $aResult['Languages'] = $this->GetLanguages(); + $aResult['AllowCustomLogin'] = (bool) $oConfig->Get('login', 'allow_custom_login', false); + $aResult['AttachmentLimit'] = ((int) $oConfig->Get('webmail', 'attachment_size_limit', 10)) * 1024 * 1024; + $aResult['SignMe'] = (string) $oConfig->Get('login', 'sign-me', \RainLoop\Enumerations\SignMeType::DEFAILT_OFF); + + // user + $aResult['EditorDefaultType'] = (string) $oConfig->Get('webmail', 'editor_default_type', ''); + $aResult['ShowImages'] = (bool) $oConfig->Get('webmail', 'show_images', false); + $aResult['IgnoreFolderSubscribe'] = (bool) $oConfig->Get('labs', 'ignore_folders_subscription', false); + $aResult['MPP'] = (int) $oConfig->Get('webmail', 'messages_per_page', 25); + $aResult['DesktopNotifications'] = false; + $aResult['ShowAnimation'] = true; + $aResult['UseThreads'] = false; + $aResult['ReplySameFolder'] = false; + $aResult['UsePreviewPane'] = true; + $aResult['UseCheckboxesInList'] = true; + $aResult['DisplayName'] = ''; + $aResult['ReplyTo'] = ''; + $aResult['Signature'] = ''; + $aResult['ParentEmail'] = ''; + $aResult['CustomThemeType'] = \RainLoop\Enumerations\CustomThemeType::LIGHT; + $aResult['CustomThemeImg'] = ''; + + if (!$bAdmin && $oSettings instanceof \RainLoop\Settings) + { + $sLanguage = $oSettings->GetConf('Language', $sLanguage); + $sTheme = $oSettings->GetConf('Theme', $sTheme); + + $aResult['SentFolder'] = $oSettings->GetConf('SentFolder', ''); + $aResult['DraftFolder'] = $oSettings->GetConf('DraftFolder', ''); + $aResult['SpamFolder'] = $oSettings->GetConf('SpamFolder', ''); + $aResult['TrashFolder'] = $oSettings->GetConf('TrashFolder', ''); + $aResult['EditorDefaultType'] = $oSettings->GetConf('EditorDefaultType', $aResult['EditorDefaultType']); + $aResult['ShowImages'] = (bool) $oSettings->GetConf('ShowImages', $aResult['ShowImages']); + $aResult['MPP'] = (int) $oSettings->GetConf('MPP', $aResult['MPP']); + $aResult['DesktopNotifications'] = (bool) $oSettings->GetConf('DesktopNotifications', $aResult['DesktopNotifications']); + $aResult['ShowAnimation'] = (bool) $oSettings->GetConf('ShowAnimation', $aResult['ShowAnimation']); + $aResult['UseThreads'] = (bool) $oSettings->GetConf('UseThreads', $aResult['UseThreads']); + $aResult['ReplySameFolder'] = (bool) $oSettings->GetConf('ReplySameFolder', $aResult['ReplySameFolder']); + $aResult['UsePreviewPane'] = (bool) $oSettings->GetConf('UsePreviewPane', $aResult['UsePreviewPane']); + $aResult['UseCheckboxesInList'] = (bool) $oSettings->GetConf('UseCheckboxesInList', $aResult['UseCheckboxesInList']); + $aResult['CustomThemeType'] = (string) $oSettings->GetConf('CustomThemeType', $aResult['CustomThemeType']); + $aResult['CustomThemeImg'] = (string) $oSettings->GetConf('CustomThemeImg', $aResult['CustomThemeImg']); + + $aResult['DisplayName'] = $oSettings->GetConf('DisplayName', $aResult['DisplayName']); + $aResult['ReplyTo'] = $oSettings->GetConf('ReplyTo', $aResult['ReplyTo']); + $aResult['Signature'] = $oSettings->GetConf('Signature', $aResult['Signature']); + + $aResult['ParentEmail'] = $oAccount->ParentEmail(); + } + if (!in_array($aResult['CustomThemeType'], array( + \RainLoop\Enumerations\CustomThemeType::LIGHT, \RainLoop\Enumerations\CustomThemeType::DARK + ))) + { + $aResult['CustomThemeType'] = \RainLoop\Enumerations\CustomThemeType::LIGHT; + } + + if (0 < \strlen($aResult['ParentEmail'])) + { + $aResult['AllowGoogleSocial'] = false; + $aResult['AllowFacebookSocial'] = false; + $aResult['AllowTwitterSocial'] = false; + } + + $sStaticCache = \md5(APP_VERSION.$this->Plugins()->Hash()); + + $aResult['Theme'] = $this->ValidateTheme($sTheme); + $aResult['Language'] = $this->ValidateLanguage($sLanguage); + $aResult['PluginsLink'] = APP_SHORT_INDEX_FILE_NAME.'?/Plugins/0/'. + ($bAdmin ? 'Admin' : 'User').'/'.$sStaticCache.'/'; + $aResult['NewThemeLink'] = APP_SHORT_INDEX_FILE_NAME.'?/Css/0/'. + ($bAdmin ? 'Admin' : 'User').'/-/'.($bAdmin ? 'Default' : $aResult['Theme']).'/-/'.$sStaticCache.'/'; + $aResult['LangLink'] = APP_SHORT_INDEX_FILE_NAME.'?/Lang/0/'. + ($bAdmin ? 'en' : $aResult['Language']).'/'.$sStaticCache.'/'; + $aResult['EditorDefaultType'] = 'Html' === $aResult['EditorDefaultType'] ? 'Html' : 'Plain'; + + $this->Plugins()->InitAppData($bAdmin, $aResult); + + return $aResult; + } + + private function loginErrorDelay() + { + $iDelay = (int) $this->Config()->Get('labs', 'login_fault_delay', 0); + if (0 < $iDelay) + { + \sleep($iDelay); + } + } + /** + * @param \RainLoop\Account $oAccount + * @param bool $bRandomToken = false + */ + public function AuthProcess($oAccount, $bRandomToken = false) + { + $this->SetAuthToken($oAccount, $bRandomToken); + + if ($oAccount instanceof \RainLoop\Account) + { + $aAccounts = $this->GetAccounts($oAccount); + if (isset($aAccounts[$oAccount->Email()])) + { + $aAccounts[$oAccount->Email()] = $oAccount->GetAuthToken(); + $this->SetAccounts($oAccount, $aAccounts); + } + } + } + + /** + * @param string $sEmail + * @param string $sLogin + * @param string $sPassword + * @param string $sSignMeToken = '' + * @param bool $bPasswordIsXOAuth2 = false + * + * @return \RainLoop\Account + * @throws \RainLoop\Exceptions\ClientException + */ + public function LoginProcess($sEmail, $sLogin, $sPassword, $sSignMeToken = '', $bPasswordIsXOAuth2 = false) + { + $sSpecAuthToken = '_'.\md5(APP_SALT.\RainLoop\Utils::GetConnectionToken().$sEmail.APP_SALT); + $this->SetSpecAuthToken($sSpecAuthToken); + + $this->Plugins()->RunHook('filter.login-params', array(&$sEmail, &$sLogin, &$sPassword)); + + $oAccount = $this->LoginProvider()->Provide($sEmail, $sLogin, $sPassword, $bPasswordIsXOAuth2, $sSignMeToken); + if (!($oAccount instanceof \RainLoop\Account)) + { + $this->loginErrorDelay(); + + $oDomain = $this->DomainProvider()->Load(\MailSo\Base\Utils::GetDomainFromEmail($sEmail)); + if (!($oDomain instanceof \RainLoop\Domain) || $oDomain->Disabled()) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::DomainNotAllowed); + } + else + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AuthError); + } + } + + try + { + $this->MailClient() + ->Connect($oAccount->Domain()->IncHost(), $oAccount->Domain()->IncPort(), $oAccount->Domain()->IncSecure()); + + if ($oAccount->PasswordIsXOAuth2()) + { + $this->MailClient()->LoginWithXOauth2($oAccount->Password()); + } + else + { + $this->MailClient()->Login($oAccount->Login(), $oAccount->Password()); + } + } + catch (\RainLoop\Exceptions\ClientException $oException) + { + $this->loginErrorDelay(); + throw $oException; + } + catch (\MailSo\Net\Exceptions\ConnectionException $oException) + { + $this->loginErrorDelay(); + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::ConnectionError, $oException); + } + catch (\Exception $oException) + { + $this->loginErrorDelay(); + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AuthError, $oException); + } + + return $oAccount; + } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoLogin() + { + $sEmail = trim($this->GetActionParam('Email', '')); + $sLogin = trim($this->GetActionParam('Login', '')); + $sPassword = $this->GetActionParam('Password', ''); + $bSignMe = '1' === $this->GetActionParam('SignMe', '0'); + + if (!$this->Config()->Get('login', 'allow_custom_login', false) || 0 === strlen($sLogin)) + { + $sLogin = $sEmail; + } + + $sSignMeToken = ''; + if ($bSignMe) + { + $sSignMeToken = \md5(\microtime(true).APP_SALT.\rand(10000, 99999).$sEmail); + } + + $this->Logger()->AddSecret($sPassword); + + $oAccount = $this->LoginProcess($sEmail, $sLogin, $sPassword, $sSignMeToken, false); + $this->AuthProcess($oAccount); + + return $this->TrueResponse(__FUNCTION__); + } + + /** + * @param \RainLoop\Account $oAccount + * + * @return array + */ + public function GetAccounts($oAccount) + { + $sParentEmail = 0 < \strlen($oAccount->ParentEmail()) ? $oAccount->ParentEmail() : $oAccount->Email(); + + $sAccounts = $this->StorageProvider()->Get(null, \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + 'Webmail/Accounts/'.$sParentEmail.'/Array', null); + + $aAccounts = $sAccounts ? @\unserialize($sAccounts) : array(); + + if (\is_array($aAccounts) && 0 < \count($aAccounts)) + { + return $aAccounts; + } + + $aAccounts = array(); + if ($sParentEmail === $oAccount->Email()) + { + $aAccounts[$oAccount->Email()] = $oAccount->GetAuthToken(); + } + + return $aAccounts; + } + + /** + * @param \RainLoop\Account $oAccount + * @param array $aAccounts = array() + * + * @return array + */ + public function SetAccounts($oAccount, $aAccounts = array()) + { + $sParentEmail = 0 < \strlen($oAccount->ParentEmail()) ? $oAccount->ParentEmail() : $oAccount->Email(); + if (!\is_array($aAccounts) || 0 === \count($aAccounts)) + { + $this->StorageProvider()->Clear(null, \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + 'Webmail/Accounts/'.$sParentEmail.'/Array'); + } + else + { + $this->StorageProvider()->Put(null, \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + 'Webmail/Accounts/'.$sParentEmail.'/Array', @\serialize($aAccounts)); + } + } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoAccountAdd() + { + $oAccount = $this->getAccountFromToken(); + + if (!$this->Config()->Get('webmail', 'allow_additional_accounts', true)) + { + return $this->FalseResponse(__FUNCTION__); + } + + $sEmail = \trim($this->GetActionParam('Email', '')); + $sLogin = \trim($this->GetActionParam('Login', '')); + $sPassword = $this->GetActionParam('Password', ''); + + if (!$this->Config()->Get('login', 'allow_custom_login', false) || 0 === strlen($sLogin)) + { + $sLogin = $sEmail; + } + + $this->Logger()->AddSecret($sPassword); + + $sParentEmail = 0 < \strlen($oAccount->ParentEmail()) ? $oAccount->ParentEmail() : $oAccount->Email(); + + $sEmail = \strtolower($sEmail); + if ($oAccount->Email() === $sEmail || $sParentEmail === $sEmail) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AccountAlreadyExists); + } + + $oNewAccount = $this->LoginProcess($sEmail, $sLogin, $sPassword, false, false); + $oNewAccount->SetParentEmail($sParentEmail); + + $aAccounts = $this->GetAccounts($oAccount); + if (\is_array($aAccounts)) + { + if (isset($aAccounts[$oNewAccount->Email()])) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AccountAlreadyExists); + } + else + { + $aAccounts[$oNewAccount->Email()] = $oNewAccount->GetAuthToken(); + } + } + else + { + $aAccounts = array(); + } + + if (0 === \strlen($oAccount->ParentEmail())) + { + $aAccounts[$oAccount->Email()] = $oAccount->GetAuthToken(); + } + + $this->SetAccounts($oAccount, $aAccounts); + return $this->TrueResponse(__FUNCTION__); + } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoAccountDelete() + { + $oAccount = $this->getAccountFromToken(); + + if (!$this->Config()->Get('webmail', 'allow_additional_accounts', true)) + { + return $this->FalseResponse(__FUNCTION__); + } + + $sParentEmail = 0 < \strlen($oAccount->ParentEmail()) ? $oAccount->ParentEmail() : $oAccount->Email(); + $sEmailToDelete = \strtolower(\trim($this->GetActionParam('EmailToDelete', ''))); + + $aAccounts = $this->GetAccounts($oAccount); + + if (0 < \strlen($sEmailToDelete) && $sEmailToDelete !== $sParentEmail && \is_array($aAccounts) && isset($aAccounts[$sEmailToDelete])) + { + unset($aAccounts[$sEmailToDelete]); + + if (1 === count($aAccounts) && isset($aAccounts[$sParentEmail])) + { + $aAccounts = array(); + } + + $this->SetAccounts($oAccount, $aAccounts); + return $this->TrueResponse(__FUNCTION__); + } + + return $this->FalseResponse(__FUNCTION__); + } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoAccounts() + { + $oAccount = $this->getAccountFromToken(); + + if ($this->Config()->Get('webmail', 'allow_additional_accounts', true)) + { + $aAccounts = $this->GetAccounts($oAccount); + $aAccounts = \array_keys($aAccounts); + + return $this->DefaultResponse(__FUNCTION__, $aAccounts); + } + + return $this->FalseResponse(__FUNCTION__); + } + + /** + * @return array + */ + public function DoLogout() + { + $oAccount = $this->getAccountFromToken(false); + if ($oAccount && $oAccount->SignMe()) + { + \RainLoop\Utils::ClearCookie(\RainLoop\Actions::AUTH_SIGN_ME_TOKEN_KEY); + + $this->StorageProvider()->Clear(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + 'SignMe/UserToken/'.$oAccount->SignMeToken()); + } + + $this->ClearAuthToken(); + + return $this->TrueResponse(__FUNCTION__); + } + + /** + * @return array + */ + public function DoAppDelayStart() + { +// $oAccount = $this->getAccountFromToken(); + + \RainLoop\Utils::UpdateConnectionToken(); + + $bUserCache = false; + $bMainCache = false; + $bUserStatistic = false; + + if ($this->CacherFile()->IsInited()) + { + $iTime = $this->CacherFile()->GetTimer('Cache/LastMainCache'); + if (0 === $iTime || $iTime + 60 * 60 * 24 < \time()) + { + if ($this->CacherFile()->SetTimer('Cache/LastMainCache')) + { + $bUserCache = true; + } + } + + $iTime = $this->CacherFile()->GetTimer('Statistic/Activity') ; + if (0 === $iTime || $iTime + 60 * 60 * 24 < \time()) + { + if ($this->CacherFile()->SetTimer('Statistic/Activity')) + { + $bUserStatistic = true; + } + } + + $iTime = $this->CacherFile()->GetTimer('Cache/LastUserCache'); + if (0 === $iTime || $iTime + 60 * 60 * 24 < \time()) + { + if ($this->CacherFile()->SetTimer('Cache/LastUserCache')) + { + $bMainCache = true; + } + } + } + + return $this->DefaultResponse(__FUNCTION__, array( + 'Version' => APP_VERSION, + 'Debug' => !!$this->Config()->Get('debug', 'enable', false), + 'UserCache' => $bUserCache ? $this->StorageProvider()->GC(48) : false, + 'MainCache' => $bMainCache ? $this->CacherFile()->GC(48) : false, + 'UserStatistic' => $bUserStatistic ? $this->KeenIO('Activity') : false + )); + } + + /** + * @return array + */ + public function DoSystemFoldersUpdate() + { + $oAccount = $this->getAccountFromToken(); + + $oSettings = $this->SettingsProvider()->Load($oAccount); + + $oSettings->SetConf('SentFolder', $this->GetActionParam('SentFolder', '')); + $oSettings->SetConf('DraftFolder', $this->GetActionParam('DraftFolder', '')); + $oSettings->SetConf('TrashFolder', $this->GetActionParam('TrashFolder', '')); + $oSettings->SetConf('SpamFolder', $this->GetActionParam('SpamFolder', '')); + + return $this->DefaultResponse(__FUNCTION__, + $this->SettingsProvider()->Save($oAccount, $oSettings)); + } + + /** + * @param \RainLoop\Config\Application $oConfig + * @param string $sParamName + * @param string $sConfigSector + * @param string $sConfigName + * @param string $sType = 'string' + * @param callable|null $mStringCallback = null + */ + private function setConfigFromParams(&$oConfig, $sParamName, $sConfigSector, $sConfigName, $sType = 'string', $mStringCallback = null) + { + $sValue = $this->GetActionParam($sParamName, ''); + if ($this->HasActionParam($sParamName)) + { + switch ($sType) + { + default: + case 'string': + $sValue = (string) $sValue; + if ($mStringCallback && is_callable($mStringCallback)) + { + $sValue = call_user_func($mStringCallback, $sValue); + } + + $oConfig->Set($sConfigSector, $sConfigName, (string) $sValue); + break; + + case 'int': + $iValue = (int) $sValue; + $oConfig->Set($sConfigSector, $sConfigName, $iValue); + break; + + case 'bool': + $oConfig->Set($sConfigSector, $sConfigName, '1' === (string) $sValue); + break; + } + } + } + + /** + * @param \RainLoop\Settings $oSettings + * @param string $sConfigName + * @param string $sType = 'string' + * @param callable|null $mStringCallback = null + */ + private function setSettingsFromParams(&$oSettings, $sConfigName, $sType = 'string', $mStringCallback = null) + { + if ($this->HasActionParam($sConfigName)) + { + $sValue = $this->GetActionParam($sConfigName, ''); + switch ($sType) + { + default: + case 'string': + $sValue = (string) $sValue; + if ($mStringCallback && is_callable($mStringCallback)) + { + $sValue = call_user_func($mStringCallback, $sValue); + } + + $oSettings->SetConf($sConfigName, (string) $sValue); + break; + + case 'int': + $iValue = (int) $sValue; + $oSettings->SetConf($sConfigName, $iValue); + break; + + case 'bool': + $oSettings->SetConf($sConfigName, '1' === (string) $sValue); + break; + } + } + } + + /** + * @return array + */ + public function DoAdminSettingsUpdate() + { + $this->IsAdminLoggined(); + + $oConfig = $this->Config(); + + $self = $this; + + $this->setConfigFromParams($oConfig, 'Language', 'webmail', 'language', 'string', function ($sLanguage) use ($self) { + return $self->ValidateLanguage($sLanguage); + }); + + $this->setConfigFromParams($oConfig, 'Theme', 'webmail', 'theme', 'string', function ($sTheme) use ($self) { + return $self->ValidateTheme($sTheme); + }); + + $this->setConfigFromParams($oConfig, 'AllowCustomTheme', 'webmail', 'allow_custom_theme', 'bool'); + $this->setConfigFromParams($oConfig, 'AllowAdditionalAccounts', 'webmail', 'allow_additional_accounts', 'bool'); + + $this->setConfigFromParams($oConfig, 'Title', 'webmail', 'title', 'string'); + $this->setConfigFromParams($oConfig, 'TokenProtection', 'security', 'csrf_protection', 'bool'); + $this->setConfigFromParams($oConfig, 'EnabledPlugins', 'plugins', 'enable', 'bool'); + + $this->setConfigFromParams($oConfig, 'GoogleEnable', 'social', 'google_enable', 'bool'); + $this->setConfigFromParams($oConfig, 'GoogleClientID', 'social', 'google_client_id', 'string'); + $this->setConfigFromParams($oConfig, 'GoogleClientSecret', 'social', 'google_client_secret', 'string'); + + $this->setConfigFromParams($oConfig, 'FacebookEnable', 'social', 'fb_enable', 'bool'); + $this->setConfigFromParams($oConfig, 'FacebookAppID', 'social', 'fb_app_id', 'string'); + $this->setConfigFromParams($oConfig, 'FacebookAppSecret', 'social', 'fb_app_secret', 'string'); + + $this->setConfigFromParams($oConfig, 'TwitterEnable', 'social', 'twitter_enable', 'bool'); + $this->setConfigFromParams($oConfig, 'TwitterConsumerKey', 'social', 'twitter_consumer_key', 'string'); + $this->setConfigFromParams($oConfig, 'TwitterConsumerSecret', 'social', 'twitter_consumer_secret', 'string'); + + $this->setConfigFromParams($oConfig, 'DropboxEnable', 'social', 'dropbox_enable', 'bool'); + $this->setConfigFromParams($oConfig, 'DropboxApiKey', 'social', 'dropbox_api_key', 'string'); + + return $this->DefaultResponse(__FUNCTION__, $oConfig->Save()); + } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoAdminLogin() + { + $sLogin = trim($this->GetActionParam('Login', '')); + $sPassword = $this->GetActionParam('Password', ''); + + $this->Logger()->AddSecret($sPassword); + + if (0 === strlen($sLogin) || 0 === strlen($sPassword) || + $sLogin !== $this->Config()->Get('security', 'admin_login', '') || + !$this->Config()->ValidatePassword($sPassword)) + { + $this->loginErrorDelay(); + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AuthError); + } + + $this->setAdminAuthToken($this->getAdminToken()); + + return $this->TrueResponse(__FUNCTION__); + } + + /** + * @return array + */ + public function DoAdminLogout() + { + $this->ClearAdminAuthToken(); + return $this->TrueResponse(__FUNCTION__); + } + + /** + * @return array + */ + public function DoAdminPing() + { + $this->IsAdminLoggined(); + + return $this->DefaultResponse(__FUNCTION__, true); + } + + /** + * @return array + */ + public function DoAdminLicensing() + { + $iStart = \time(); + $this->IsAdminLoggined(); + + $sForce = '1' === (string) $this->GetActionParam('Force', '0'); + + $mResult = false; + $iErrorCode = -1; + + $oHttp = \MailSo\Base\Http::SingletonInstance(); + if ($oHttp->CheckLocalhost(APP_SITE)) + { + return $this->DefaultResponse(__FUNCTION__, $mResult); + } + + $sDomain = APP_SITE; + if (2 < \strlen($sDomain)) + { + $sValue = ''; + $iTime = $this->Cacher()->GetTimer('Licensing/DomainKey/Value/'.$sDomain); + if (!$sForce && $iTime + 60 * 5 > \time()) + { + $sValue = $this->Cacher()->Get('Licensing/DomainKey/Value/'.$sDomain); + } + + if (0 === \strlen($sValue)) + { + $iCode = 0; + $sContentType = ''; + + $sValue = $oHttp->GetUrlAsString(APP_API_PATH.'status/'.\urlencode($sDomain), + 'RainLoop', $sContentType, $iCode, $this->Logger()); + + if (200 !== $iCode) + { + $sValue = ''; + } + + if ($iStart === \time()) + { + \sleep(1); + } + + $this->Cacher()->Set('Licensing/DomainKey/Value/'.$sDomain, $sValue); + $this->Cacher()->SetTimer('Licensing/DomainKey/Value/'.$sDomain); + } + + $aMatch = array(); + if (5 < \strlen($sValue) && \preg_match('/^EXPIRED:([\d]+)$/', $sValue, $aMatch)) + { + $mResult = array( + 'Banned' => false, + 'Expired' => (int) $aMatch[1], + ); + } + else if ($sValue === 'NO') + { + $iErrorCode = -1; + } + else if ($sValue === 'TOO_MANY_CONNECTIONS') + { + $iErrorCode = -1; + } + else + { + $iErrorCode = \RainLoop\Notifications::LicensingServerIsUnavailable; + } + } + + if (0 < $iErrorCode && !$mResult) + { + throw new \RainLoop\Exceptions\ClientException($iErrorCode); + } + + return $this->DefaultResponse(__FUNCTION__, $mResult); + } + + /** + * @return array + */ + public function DoAdminLicensingActivate() + { + $iStart = \time(); + $this->IsAdminLoggined(); + + $sDomain = (string) $this->GetActionParam('Domain', ''); + $sKey = (string) $this->GetActionParam('Key', ''); + + $mResult = false; + $iErrorCode = -1; + + if (2 < \strlen($sDomain) && 2 < \strlen($sKey) && $sDomain === APP_SITE) + { + $iCode = 0; + $sContentType = ''; + + $oHttp = \MailSo\Base\Http::SingletonInstance(); + + \sleep(1); + $sValue = $oHttp->GetUrlAsString(APP_API_PATH.'activate/'.\urlencode($sDomain).'/'.\urlencode($sKey), + 'RainLoop', $sContentType, $iCode, $this->Logger()); + + if (200 !== $iCode) + { + $sValue = ''; + } + + if ($iStart + 2 > \time()) + { + \sleep(1); + } + + $aMatch = array(); + if ('OK' === $sValue) + { + $mResult = true; + } + else if ('TOO_MANY_CONNECTIONS' === $sValue) + { + $mResult = 'Too many connections. Please try again later.'; + } + else if (\preg_match('/^ERROR:(.+)$/', $sValue, $aMatch) && !empty($aMatch[1])) + { + $mResult = trim($aMatch[1]); + $this->Logger()->Write('Activation error for: '.$sKey.' ('.$sDomain.')', \MailSo\Log\Enumerations\Type::ERROR); + $this->Logger()->Write($mResult, \MailSo\Log\Enumerations\Type::ERROR); + } + else + { + $iErrorCode = \RainLoop\Notifications::LicensingServerIsUnavailable; + } + } + + if (0 < $iErrorCode && !$mResult) + { + throw new \RainLoop\Exceptions\ClientException($iErrorCode); + } + + return $this->DefaultResponse(__FUNCTION__, $mResult); + } + + /** + * @return array + */ + public function DoAdminPasswordUpdate() + { + $this->IsAdminLoggined(); + + $bResult = false; + $oConfig = $this->Config(); + + $sPassword = $this->GetActionParam('Password', ''); + $sNewPassword = $this->GetActionParam('NewPassword', ''); + + if ($oConfig->ValidatePassword($sPassword)) + { + $bResult = true; + $oConfig->SetPassword($sNewPassword); + } + + return $this->DefaultResponse(__FUNCTION__, $bResult ? $oConfig->Save() : false); + } + + /** + * @return array + */ + public function DoAdminDomainLoad() + { + $this->IsAdminLoggined(); + + return $this->DefaultResponse(__FUNCTION__, + $this->DomainProvider()->Load($this->GetActionParam('Name', ''))); + } + + /** + * @return array + */ + public function DoAdminDomainList() + { + $this->IsAdminLoggined(); + + $iOffset = (int) $this->GetActionParam('Offset', 0); + $sSearch = (string) $this->GetActionParam('Search', ''); + + return $this->DefaultResponse(__FUNCTION__, + $this->DomainProvider()->GetList($iOffset, 20, $sSearch)); + } + + /** + * @return array + */ + public function DoAdminDomainDelete() + { + $this->IsAdminLoggined(); + + return $this->DefaultResponse(__FUNCTION__, + $this->DomainProvider()->Delete((string) $this->GetActionParam('Name', ''))); + } + + /** + * @return array + */ + public function DoAdminDomainDisable() + { + $this->IsAdminLoggined(); + + return $this->DefaultResponse(__FUNCTION__, $this->DomainProvider()->Disable( + (string) $this->GetActionParam('Name', ''), + '1' === (string) $this->GetActionParam('Disabled', '0') + )); + } + + /** + * @return array + */ + public function DoAdminDomainSave() + { + $this->IsAdminLoggined(); + + $oDomain = $this->DomainProvider()->LoadOrCreateNewFromAction($this); + + return $this->DefaultResponse(__FUNCTION__, + $oDomain instanceof \RainLoop\Domain ? $this->DomainProvider()->Save($oDomain) : false); + } + + /** + * @return array + */ + public function DoAdminDomainTest() + { + $this->IsAdminLoggined(); + + $bImapResult = false; + $bSmtpResult = false; + + $iImapTime = 0; + $iSmtpTime = 0; + + $oDomain = $this->DomainProvider()->LoadOrCreateNewFromAction($this, 'domain-test-connection.de'); + if ($oDomain) + { + try + { + $oImapClient = \MailSo\Imap\ImapClient::NewInstance()->SetLogger($this->Logger()); + $oImapClient->SetTimeOuts(5); + + $iTime = microtime(true); + $oImapClient->Connect($oDomain->IncHost(), $oDomain->IncPort(), $oDomain->IncSecure()); + $iImapTime = microtime(true) - $iTime; + $oImapClient->Disconnect(); + $bImapResult = true; + } + catch (\Exception $oException) + { + $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + + try + { + $oSmtpClient = \MailSo\Smtp\SmtpClient::NewInstance()->SetLogger($this->Logger()); + $oSmtpClient->SetTimeOuts(5); + + $iTime = microtime(true); + $oSmtpClient->Connect($oDomain->OutHost(), $oDomain->OutPort(), '127.0.0.1', $oDomain->OutSecure()); + $iSmtpTime = microtime(true) - $iTime; + $oSmtpClient->Disconnect(); + $bSmtpResult = true; + } + catch (\Exception $oException) + { + $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + } + + return $this->DefaultResponse(__FUNCTION__, array( + 'Imap' => $bImapResult ? $iImapTime : false, + 'Smtp' => $bSmtpResult ? $iSmtpTime : false + )); + } + + /** + * @param bool $bAdditionalOnly = false + * + * @return string + */ + private function rainloopRepo($bAdditionalOnly = false) + { + if ($bAdditionalOnly) + { + $sUrl = $this->Config()->Get('labs', 'additional_repo', ''); + } + else + { + $sUrl = $this->Config()->Get('labs', 'custom_repo', ''); + if (0 === \strlen($sUrl)) + { + $sUrl = APP_REP_PATH; + } + } + + if ('' !== $sUrl) + { + $sUrl = rtrim($sUrl, '\\/').'/'; + } + + return $sUrl; + } + + private function rainLoopUpdatable() + { + return @file_exists(APP_INDEX_ROOT_PATH.APP_INDEX_FILE_NAME) && @is_writable(APP_INDEX_ROOT_PATH.APP_INDEX_FILE_NAME); + } + + private function rainLoopCoreAccess() + { + return $this->Http()->CheckLocalhost(APP_SITE) || APP_SITE === APP_CORE_INSTALL_ACCESS_SITE; + } + + private function getRepositoryDataByUrl($sRepo, &$bReal = false) + { + $bReal = false; + $aRep = null; + + $sRep = ''; + $iRepTime = 0; + + $oHttp = \MailSo\Base\Http::SingletonInstance(); + + $sCacheKey = 'UPDATER/('.$sRepo.')/repository.json'; + $sRep = $this->Cacher()->Get($sCacheKey); + if ('' !== $sRep) + { + $iRepTime = $this->Cacher()->GetTimer($sCacheKey); + } + + if ('' === $sRep || 0 === $iRepTime || time() - 3600 > $iRepTime) + { + $iCode = 0; + $sContentType = ''; + + $sRepPath = $sRepo.'repository.json'; + $sRep = '' !== $sRepo ? $oHttp->GetUrlAsString($sRepPath, 'RainLoop', $sContentType, $iCode, $this->Logger()) : false; + if (false !== $sRep) + { + $aRep = @\json_decode($sRep); + $bReal = \is_array($aRep) && 0 < \count($aRep); + + if ($bReal) + { + $this->Cacher()->Set($sCacheKey, $sRep); + $this->Cacher()->SetTimer($sCacheKey); + } + } + else + { + $this->Logger()->Write('Cannot read remote repository file: '.$sRepPath, \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); + } + } + else if ('' !== $sRep) + { + $aRep = @\json_decode($sRep, false, 10); + $bReal = \is_array($aRep) && 0 < \count($aRep); + } + + $bCoreAccess = $this->rainLoopCoreAccess(); + + $aResult = array(); + if (\is_array($aRep)) + { + foreach ($aRep as $oItem) + { + if ($oItem && isset($oItem->type, $oItem->id, $oItem->name, + $oItem->version, $oItem->release, $oItem->file, $oItem->description)) + { + if (!empty($oItem->required) && APP_DEV_VERSION !== APP_VERSION && version_compare(APP_VERSION, $oItem->required, '<')) + { + continue; + } + + if (!empty($oItem->depricated) && APP_DEV_VERSION !== APP_VERSION && version_compare(APP_VERSION, $oItem->depricated, '>=')) + { + continue; + } + + if ('core' === $oItem->type) + { + if ($bCoreAccess) + { + $aResult[] = array( + 'type' => $oItem->type, + 'id' => $oItem->id, + 'name' => $oItem->name, + 'installed' => APP_VERSION, + 'version' => $oItem->version, + 'file' => $oItem->file, + 'release' => $oItem->release, + 'desc' => $oItem->description + ); + } + } + else if ('plugin' === $oItem->type) + { + $aResult[] = array( + 'type' => $oItem->type, + 'id' => $oItem->id, + 'name' => $oItem->name, + 'installed' => '', + 'version' => $oItem->version, + 'file' => $oItem->file, + 'release' => $oItem->release, + 'desc' => $oItem->description + ); + } + } + } + } + + return $aResult; + } + + private function getRepositoryData(&$bReal, &$bRainLoopUpdatable) + { + $bRainLoopUpdatable = $this->rainLoopUpdatable(); + $bCoreAccess = $this->rainLoopCoreAccess(); + + $aResult = $this->getRepositoryDataByUrl($this->rainloopRepo(), $bReal); + + $sAddRepo = $this->rainloopRepo(true); + if (0 < \strlen($sAddRepo)) + { + $aAddData = $this->getRepositoryDataByUrl($sAddRepo); + if (\is_array($aAddData) && 0 < \count($aAddData)) + { + $aResult = \array_merge($aResult, $aAddData); + } + } + + $bAddCore = false; + foreach ($aResult as $aItem) + { + if ($aItem && 'core' === $aItem['type']) + { + $bAddCore = true; + break; + } + } + + if ($bCoreAccess && !$bAddCore) + { + \array_unshift($aResult, array( + 'type' => 'core', + 'id' => 'rainloop', + 'name' => 'RainLoop Webmail (core)', + 'installed' => APP_VERSION, + 'version' => '', + 'file' => '', + 'release' => '', + 'desc' => '' + )); + } + + $aInstalled = $this->Plugins()->InstalledPlugins(); + if (\is_array($aInstalled)) + { + foreach ($aResult as &$aItem) + { + if ('plugin' === $aItem['type']) + { + foreach ($aInstalled as &$aSubItem) + { + if (\is_array($aSubItem) && isset($aSubItem[0]) && $aSubItem[0] === $aItem['id']) + { + $aSubItem[2] = true; + $aItem['installed'] = $aSubItem[1]; + } + } + } + } + + foreach ($aInstalled as $aSubItemSec) + { + if ($aSubItemSec && !isset($aSubItemSec[2])) + { + \array_push($aResult, array( + 'type' => 'plugin', + 'id' => $aSubItemSec[0], + 'name' => $aSubItemSec[0], + 'installed' => $aSubItemSec[1], + 'version' => '', + 'file' => '', + 'release' => '', + 'desc' => '' + )); + } + } + } + + foreach ($aResult as &$aItem) + { + $aItem['compare'] = \version_compare($aItem['installed'], $aItem['version'], '<'); + $aItem['canBeDeleted'] = '' !== $aItem['installed'] && 'plugin' === $aItem['type']; + $aItem['canBeUpdated'] = $aItem['compare']; + + if (!$bRainLoopUpdatable && 'plugin' !== $aItem['type']) + { + $aItem['canBeUpdated'] = false; + $aItem['compare'] = false; + } + } + +// if (!$bReal) +// { +// $iTime = $this->CacherFile()->GetTimer('Statistic/PackagesRepositoryUnreal') ; +// if (0 === $iTime || $iTime + 60 * 60 * 24 < \time()) +// { +// $this->CacherFile()->SetTimer('Statistic/PackagesRepositoryUnreal'); +// $this->KeenIO('PackagesRepositoryUnreal'); +// } +// } + + return $aResult; + } + + /** + * @return array + */ + public function DoAdminPackagesList() + { + $this->IsAdminLoggined(); + + $bReal = false; + $bRainLoopUpdatable = false; + $aList = $this->getRepositoryData($bReal, $bRainLoopUpdatable); + + return $this->DefaultResponse(__FUNCTION__, array( + 'Real' => $bReal, + 'MainUpdatable' => $bRainLoopUpdatable, + 'List' => $aList + )); + } + + /** + * @return array + */ + public function DoAdminPackageDelete() + { + $this->IsAdminLoggined(); + + $sId = $this->GetActionParam('Id', ''); + + $bReal = false; + $bRainLoopUpdatable = false; + $aList = $this->getRepositoryData($bReal, $bRainLoopUpdatable); + + $sResultId = ''; + foreach ($aList as $oItem) + { + if ($oItem && 'plugin' === $oItem['type'] && $sId === $oItem['id']) + { + $sResultId = $sId; + break; + } + } + + $bResult = false; + if ('' !== $sResultId) + { + $bResult = \MailSo\Base\Utils::RecRmDir(APP_PLUGINS_PATH.$sResultId); + if ($bResult) + { + $this->pluginEnable($sResultId, false); + } + } + + return $this->DefaultResponse(__FUNCTION__, $bResult); + } + + /** + * @return array + */ + public function DoAdminPackageInstall() + { + $this->IsAdminLoggined(); + + $sType = $this->GetActionParam('Type', ''); + $sId = $this->GetActionParam('Id', ''); + $sFile = $this->GetActionParam('File', ''); + + $this->Logger()->Write('Start package install: '.$sFile.' ('.$sType.')', \MailSo\Log\Enumerations\Type::INFO, 'INSTALLER'); + + $sRealFile = ''; + + $bReal = false; + $bRainLoopUpdatable = false; + $aList = $this->getRepositoryData($bReal, $bRainLoopUpdatable); + + if (('plugin' !== $sType && $bRainLoopUpdatable) || 'plugin' === $sType) + { + foreach ($aList as $oItem) + { + if ($oItem && $sFile === $oItem['file'] && $sId === $oItem['id']) + { + $sRealFile = $sFile; + break; + } + } + } + + $sTmp = ''; + $bResult = false; + if ('' !== $sRealFile) + { + $sUrl = $this->rainloopRepo().$sRealFile; + $pSrc = @fopen($sUrl, 'rb'); + if ($pSrc) + { + $sTmp = APP_PRIVATE_DATA.md5(microtime(true).$sRealFile).'.zip'; + $pDest = @fopen($sTmp, 'w+b'); + if ($pDest) + { + $iCopy = stream_copy_to_stream($pSrc, $pDest); + + $bResult = is_int($iCopy) && 0 < $iCopy; + + if (!$bResult) + { + $this->Logger()->Write('Cannot copy remote stream to local: '.$pDest, \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); + } + + @fclose($pDest); + } + else + { + $this->Logger()->Write('Cannot create temp file: '.$pDest, \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); + } + + @fclose($pSrc); + } + else + { + $this->Logger()->Write('Can not open remote file: '.$sUrl, \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); + } + } + + if ($bResult && '' !== $sTmp) + { + include_once APP_VERSION_ROOT_PATH.'app/libraries/pclzip/pclzip.lib.php'; + + $oArchive = new \PclZip($sTmp); + if ('plugin' !== $sType) + { + $bResult = false; + + $sTmpFolder = APP_PRIVATE_DATA.\md5($sTmp); + + mkdir($sTmpFolder); + if (is_dir($sTmpFolder)) + { + $bResult = 0 !== $oArchive->extract(PCLZIP_OPT_PATH, $sTmpFolder); + if (!$bResult) + { + $this->Logger()->Write('Cannot extract package files: '.$oArchive->errorInfo(), \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); + } + + if ($bResult && file_exists($sTmpFolder.'/index.php') && + is_writable(APP_INDEX_ROOT_PATH.'rainloop/') && + file_exists($sTmpFolder.'/data/VERSION') && + is_dir($sTmpFolder.'/rainloop/')) + { + \MailSo\Base\Utils::CopyDir($sTmpFolder.'/rainloop/', APP_INDEX_ROOT_PATH.'rainloop/'); + + copy($sTmpFolder.'/data/VERSION', APP_DATA_FOLDER_PATH.'VERSION'); + copy($sTmpFolder.'/index.php', APP_INDEX_ROOT_PATH.'index.php'); + + $bResult = true; + } + else if ($bResult) + { + $this->Logger()->Write('Cannot validate package files', \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); + } + + \MailSo\Base\Utils::RecRmDir($sTmpFolder); + } + } + else + { + $bResult = true; + if (is_dir(APP_PLUGINS_PATH.$sId)) + { + $bResult = \MailSo\Base\Utils::RecRmDir(APP_PLUGINS_PATH.$sId); + if (!$bResult) + { + $this->Logger()->Write('Cannot remove previous plugin folder: '.$sId, \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); + } + } + + if ($bResult) + { + $bResult = 0 !== $oArchive->extract(PCLZIP_OPT_PATH, APP_PLUGINS_PATH); + if (!$bResult) + { + $this->Logger()->Write('Cannot extract package files: '.$oArchive->errorInfo(), \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); + } + } + } + + @unlink($sTmp); + } + +// $this->KeenIO('PackagesInstallation', array( +// 'type' => $sType, +// 'name' => $sId, +// 'file' => $sFile, +// 'repo-available' => $bReal ? 1 : 0, +// 'core-updatable' => $bRainLoopUpdatable ? 1 : 0, +// 'result' => $bResult ? 1 : 0 +// )); + + return $this->DefaultResponse(__FUNCTION__, $bResult); + } + + /** + * @return array + */ + public function DoAdminPluginList() + { + $this->IsAdminLoggined(); + + $aResult = array(); + + $sEnabledPlugins = $this->Config()->Get('plugins', 'enabled_list', ''); + $aEnabledPlugins = \explode(',', \strtolower($sEnabledPlugins)); + $aEnabledPlugins = \array_map('trim', $aEnabledPlugins); + + $aList = $this->Plugins()->InstalledPlugins(); + foreach ($aList as $aItem) + { + $aResult[] = array( + 'Name' => $aItem[0], + 'Enabled' => \in_array(\strtolower($aItem[0]), $aEnabledPlugins), + 'Configured' => false + ); + } + + return $this->DefaultResponse(__FUNCTION__, $aResult); + } + + /** + * @param string $sName + * @param bool $bEnable = true + * @return bool + */ + private function pluginEnable($sName, $bEnable = true) + { + if (0 === \strlen($sName)) + { + return false; + } + + $oConfig = $this->Config(); + + $sEnabledPlugins = $oConfig->Get('plugins', 'enabled_list', ''); + $aEnabledPlugins = \explode(',', \strtolower($sEnabledPlugins)); + $aEnabledPlugins = \array_map('trim', $aEnabledPlugins); + + $aNewEnabledPlugins = array(); + if ($bEnable) + { + $aNewEnabledPlugins = $aEnabledPlugins; + $aNewEnabledPlugins[] = $sName; + } + else + { + foreach ($aEnabledPlugins as $sPlugin) + { + if ($sName !== $sPlugin && 0 < \strlen($sPlugin)) + { + $aNewEnabledPlugins[] = $sPlugin; + } + } + } + + $aNewEnabledPlugins = \array_unique($aNewEnabledPlugins); + $oConfig->Set('plugins', 'enabled_list', \trim(\implode(',', $aNewEnabledPlugins), ' ,')); + + return $oConfig->Save(); + } + + /** + * @return array + */ + public function DoAdminPluginDisable() + { + $this->IsAdminLoggined(); + + $sName = (string) $this->GetActionParam('Name', ''); + $bDisable = '1' === (string) $this->GetActionParam('Disabled', '1'); + + if (!$bDisable) + { + $oPlugin = $this->Plugins()->CreatePluginByName($sName); + if ($oPlugin instanceof \RainLoop\Plugins\AbstractPlugin) + { + $sValue = $oPlugin->Supported(); + if (0 < \strlen($sValue)) + { + return $this->FalseResponse(__FUNCTION__, \RainLoop\Notifications::UnsupportedPluginPackage, $sValue); + } + } + else + { + return $this->FalseResponse(__FUNCTION__, \RainLoop\Notifications::InvalidPluginPackage); + } + } + + return $this->DefaultResponse(__FUNCTION__, $this->pluginEnable($sName, !$bDisable)); + } + + /** + * @return array + */ + public function DoAdminPluginLoad() + { + $this->IsAdminLoggined(); + + $mResult = false; + $sName = (string) $this->GetActionParam('Name', ''); + + if (!empty($sName)) + { + $oPlugin = $this->Plugins()->CreatePluginByName($sName); + if ($oPlugin) + { + $mResult = array( + 'Name' => $sName, + 'Readme' => file_exists($oPlugin->Path().'/README') ? file_get_contents($oPlugin->Path().'/README') : '', + 'Config' => array() + ); + + $aMap = $oPlugin->ConfigMap(); + $oConfig = $oPlugin->Config(); + if (is_array($aMap) && 0 < count($aMap)) + { + foreach ($aMap as $oItem) + { + if ($oItem && $oItem instanceof \RainLoop\Plugins\Property) + { + $aItem = $oItem->ToArray(); + $aItem[0] = $oConfig->Get('plugin', $oItem->Name(), ''); + if (\RainLoop\Enumerations\PluginPropertyType::PASSWORD === $oItem->Type()) + { + $aItem[0] = APP_DUMMY; + } + + $mResult['Config'][] = $aItem; + } + } + } + } + } + + return $this->DefaultResponse(__FUNCTION__, $mResult); + } + + /** + * @return array + */ + public function DoAdminPluginSettingsUpdate() + { + $this->IsAdminLoggined(); + + $mResult = false; + $sName = (string) $this->GetActionParam('Name', ''); + + if (!empty($sName)) + { + $oPlugin = $this->Plugins()->CreatePluginByName($sName); + if ($oPlugin) + { + $oConfig = $oPlugin->Config(); + $aMap = $oPlugin->ConfigMap(); + if (is_array($aMap) && 0 < count($aMap)) + { + foreach ($aMap as $oItem) + { + $sValue = $this->GetActionParam('_'.$oItem->Name(), $oConfig->Get('plugin', $oItem->Name())); + if (\RainLoop\Enumerations\PluginPropertyType::PASSWORD !== $oItem->Type() || APP_DUMMY !== $sValue) + { + $mResultValue = null; + switch ($oItem->Type()) { + case \RainLoop\Enumerations\PluginPropertyType::INT: + $mResultValue = (int) $sValue; + break; + case \RainLoop\Enumerations\PluginPropertyType::BOOL: + $mResultValue = '1' === (string) $sValue; + break; + case \RainLoop\Enumerations\PluginPropertyType::SELECTION: + if (is_array($oItem->DefaultValue()) && in_array($sValue, $oItem->DefaultValue())) + { + $mResultValue = (string) $sValue; + } + break; + case \RainLoop\Enumerations\PluginPropertyType::PASSWORD: + case \RainLoop\Enumerations\PluginPropertyType::STRING: + case \RainLoop\Enumerations\PluginPropertyType::STRING_TEXT: + $mResultValue = (string) $sValue; + break; + } + + if (null !== $mResultValue) + { + $oConfig->Set('plugin', $oItem->Name(), $mResultValue); + } + } + } + } + + $mResult = $oConfig->Save(); + } + } + + if (!$mResult) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantSavePluginSettings); + } + + return $this->DefaultResponse(__FUNCTION__, true); + } + + /** + * @return array + */ + public function DoSettingsUpdate() + { + $oAccount = $this->getAccountFromToken(); + + $oSettings = $this->SettingsProvider()->Load($oAccount); + + $self = $this; + + $this->setSettingsFromParams($oSettings, 'Language', 'string', function ($sLanguage) use ($self) { + return $self->ValidateLanguage($sLanguage); + }); + + $this->setSettingsFromParams($oSettings, 'Theme', 'string', function ($sTheme) use ($self) { + return $self->ValidateTheme($sTheme); + }); + + $this->setSettingsFromParams($oSettings, 'CustomThemeType', 'string', function ($sCustomThemeType) { + return in_array($sCustomThemeType, array( + \RainLoop\Enumerations\CustomThemeType::LIGHT, \RainLoop\Enumerations\CustomThemeType::DARK)) ? + $sCustomThemeType : \RainLoop\Enumerations\CustomThemeType::LIGHT; + }); + + $this->setSettingsFromParams($oSettings, 'MPP', 'int', function ($iMpp) { + return (int) (in_array($iMpp, array(10, 20, 30, 50, 100/*, 150, 200*/)) ? $iMpp : 20); + }); + + $this->setSettingsFromParams($oSettings, 'EditorDefaultType', 'string'); + $this->setSettingsFromParams($oSettings, 'ShowImages', 'bool'); + $this->setSettingsFromParams($oSettings, 'ShowAnimation', 'bool'); + $this->setSettingsFromParams($oSettings, 'DesktopNotifications', 'bool'); + $this->setSettingsFromParams($oSettings, 'UseThreads', 'bool'); + $this->setSettingsFromParams($oSettings, 'ReplySameFolder', 'bool'); + + $this->setSettingsFromParams($oSettings, 'UsePreviewPane', 'bool'); + $this->setSettingsFromParams($oSettings, 'UseCheckboxesInList', 'bool'); + + $this->setSettingsFromParams($oSettings, 'DisplayName', 'string'); + $this->setSettingsFromParams($oSettings, 'ReplyTo', 'string'); + $this->setSettingsFromParams($oSettings, 'Signature', 'string'); + + $this->setSettingsFromParams($oSettings, 'CustomThemeImg', 'string'); + + if ('' === $oSettings->GetConf('CustomThemeImg', '')) + { + $this->StorageProvider()->Clear($oAccount, StorageType::USER, 'CustomThemeBackground'); + } + + return $this->DefaultResponse(__FUNCTION__, + $this->SettingsProvider()->Save($oAccount, $oSettings)); + } + + /** + * @return array + */ + public function DoNoop() + { + $this->initMailClientConnection(); + return $this->TrueResponse(__FUNCTION__); + } + + /** + * @return array + */ + public function DoPing() + { + return $this->DefaultResponse(__FUNCTION__, 'Pong'); + } + + /** + * @return array + */ + public function DoChangePassword() + { + $bResult = false; + $oAccount = $this->getAccountFromToken(); + + if ($oAccount) + { + $bResult = $this->ChangePasswordProvider()->ChangePassword( + $oAccount, + $this->GetActionParam('PrevPassword', ''), + $this->GetActionParam('NewPassword', '') + ); + + if (!$bResult) + { + $this->loginErrorDelay(); + $this->Logger()->Write('Error: Can\'t change password for '.$oAccount->Email().' account.', \MailSo\Log\Enumerations\Type::NOTICE); + } + } + + return $this->DefaultResponse(__FUNCTION__, $bResult); + } + + /** + * @return array + */ + public function DoJsError() + { + $sMessage = $this->GetActionParam('Message', ''); + if (0 < strlen($sMessage)) + { + $sFileName = $this->GetActionParam('FileName', ''); + $iLineNo = $this->GetActionParam('LineNo', ''); + + $this->Logger()->Write($sMessage.' ('.$sFileName.' ~ '.$iLineNo.')', \MailSo\Log\Enumerations\Type::ERROR, 'JS'); + } + + return $this->DefaultResponse(__FUNCTION__, true); + } + + /** + * @param \MailSo\Mail\FolderCollection $oFolders + * @return array + */ + private function recFoldersNames($oFolders) + { + $aResult = array(); + if ($oFolders) + { + $aFolders =& $oFolders->GetAsArray(); + + foreach ($aFolders as $oFolder) + { + $aResult[] = $oFolder->FullNameRaw()."|". + implode("|", $oFolder->Flags()).($oFolder->IsSubscribed() ? '1' : '0'); + + $oSub = $oFolder->SubFolders(); + if ($oSub && 0 < $oSub->Count()) + { + $aResult = array_merge($aResult, $this->recFoldersNames($oSub)); + } + } + } + + return $aResult; + } + + /** + * @return array + */ + public function DoFolders() + { + $sRawKey = (string) $this->GetActionParam('RawKey', ''); + if (0 < strlen($sRawKey)) + { + $this->verifyCacheByKey($sRawKey); + } + + $this->initMailClientConnection(); + + $oFolderCollection = $this->MailClient()->Folders('', '*', + !!$this->Config()->Get('labs', 'use_imap_list_status', false)); + + if ($oFolderCollection instanceof \MailSo\Mail\FolderCollection) + { + $oFolderCollection->FoldersHash = md5(implode("\x0", $this->recFoldersNames($oFolderCollection))); + + $this->cacheByKey($sRawKey); + } + + return $this->DefaultResponse(__FUNCTION__, $oFolderCollection); + } + + /** + * @return array + */ + public function DoFolderCreate() + { + $this->initMailClientConnection(); + + try + { + $sFolderNameInUtf = $this->GetActionParam('Folder', ''); + $sFolderParentFullNameRaw = $this->GetActionParam('Parent', ''); + + $this->MailClient()->FolderCreate($sFolderNameInUtf, $sFolderParentFullNameRaw); + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantCreateFolder, $oException); + } + + return $this->TrueResponse(__FUNCTION__); + } + + /** + * @return array + */ + public function DoFolderSubscribe() + { + $this->initMailClientConnection(); + + $sFolderNameInUtf = $this->GetActionParam('Folder', ''); + $bSubscribe = '1' === (string) $this->GetActionParam('Subscribe', '0'); + + try + { + $this->MailClient()->FolderSubscribe($sFolderNameInUtf, !!$bSubscribe); + } + catch (\Exception $oException) + { + if ($bSubscribe) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantSubscribeFolder, $oException); + } + else + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantUnsubscribeFolder, $oException); + } + } + + return $this->TrueResponse(__FUNCTION__); + } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoFolderRename() + { + $this->initMailClientConnection(); + + $sPrevFolderFullNameRaw = $this->GetActionParam('Folder', ''); + $sNewTopFolderNameInUtf = $this->GetActionParam('NewFolderName', ''); + + try + { + $this->MailClient()->FolderRename($sPrevFolderFullNameRaw, $sNewTopFolderNameInUtf); + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantRenameFolder, $oException); + } + + return $this->TrueResponse(__FUNCTION__); + } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoFolderDelete() + { + $this->initMailClientConnection(); + + $sFolderFullNameRaw = $this->GetActionParam('Folder', ''); + + try + { + $this->MailClient()->FolderDelete($sFolderFullNameRaw); + } + catch (\MailSo\Mail\Exceptions\NonEmptyFolder $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantDeleteNonEmptyFolder, $oException); + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantDeleteFolder, $oException); + } + + return $this->TrueResponse(__FUNCTION__); + } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoFolderClear() + { + $this->initMailClientConnection(); + + $sFolderFullNameRaw = $this->GetActionParam('Folder', ''); + + try + { + $this->MailClient()->FolderClear($sFolderFullNameRaw); + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::MailServerError, $oException); + } + + return $this->TrueResponse(__FUNCTION__); + } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoFolderInformation() + { + $sFolder = $this->GetActionParam('Folder', ''); + $sPrevUidNext = $this->GetActionParam('UidNext', ''); + $aFlagsUids = array(); + $sFlagsUids = (string) $this->GetActionParam('FlagsUids', ''); + + $aFlagsFilteredUids = array(); + if (0 < strlen($sFlagsUids)) + { + $aFlagsUids = explode(',', (string) $this->GetActionParam('FlagsUids', '')); + $aFlagsFilteredUids = array_filter($aFlagsUids, function (&$sUid) { + $sUid = (int) trim($sUid); + return 0 < (int) trim($sUid); + }); + } + + $oAccount = $this->initMailClientConnection(); + + $sForwardedFlag = $oAccount ? strtolower($oAccount->Domain()->ForwardFlag()) : ''; + + try + { + $aInboxInformation = $this->MailClient()->FolderInformation($sFolder, $sPrevUidNext, $aFlagsFilteredUids); + foreach ($aInboxInformation['Flags'] as $iUid => $aFlags) + { + $aLowerFlags = array_map('strtolower', $aFlags); + $aInboxInformation['Flags'][$iUid] = array( + 'IsSeen' => in_array('\\seen', $aLowerFlags), + 'IsFlagged' => in_array('\\flagged', $aLowerFlags), + 'IsAnswered' => in_array('\\answered', $aLowerFlags), + 'IsForwarded' => 0 < strlen($sForwardedFlag) && in_array(strtolower($sForwardedFlag), $aLowerFlags) + ); + } + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::MailServerError, $oException); + } + + return $this->DefaultResponse(__FUNCTION__, $aInboxInformation); + } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoMessageList() + { +// throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantGetMessageList); + + $sFolder = ''; + $iOffset = 0; + $iLimit = 20; + $sSearch = ''; + $sUidNext = ''; + $bUseThreads = false; + $sExpandedThreadUid = ''; + + $sRawKey = $this->GetActionParam('RawKey', ''); + $aValues = $this->getDecodedClientRawKeyValue($sRawKey, 9); + if (is_array($aValues) && 9 === count($aValues)) + { + $sFolder =(string) $aValues[0]; + $iOffset = (int) $aValues[1]; + $iLimit = (int) $aValues[2]; + $sSearch = (string) $aValues[3]; + $sUidNext = (string) $aValues[6]; + $bUseThreads = (bool) $aValues[7]; + $sExpandedThreadUid = (string) $aValues[8]; + + $this->verifyCacheByKey($sRawKey); + } + else + { + $sFolder = $this->GetActionParam('Folder', ''); + $iOffset = (int) $this->GetActionParam('Offset', 0); + $iLimit = (int) $this->GetActionParam('Limit', 10); + $sSearch = $this->GetActionParam('Search', ''); + $sUidNext = $this->GetActionParam('UidNext', ''); + $bUseThreads = '1' === (string) $this->GetActionParam('UseThreads', '0'); + $sExpandedThreadUid = (string) $this->GetActionParam('ExpandedThreadUid', ''); + } + + if (0 === strlen($sFolder)) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantGetMessageList); + } + + $this->initMailClientConnection(); + + try + { + if (!$this->Config()->Get('labs', 'use_imap_thread', false)) + { + $bUseThreads = false; + $sExpandedThreadUid = ''; + } + + $aExpandedThreadUid = array(); + if (0 < \strlen($sExpandedThreadUid)) + { + $aExpandedThreadUid = \explode(',', $sExpandedThreadUid); + + $aExpandedThreadUid = \array_map(function ($sValue) { + $sValue = \trim($sValue); + return is_numeric($sValue) ? (int) $sValue : 0; + }, $aExpandedThreadUid); + + $aExpandedThreadUid = \array_filter($aExpandedThreadUid, function ($iValue) { + return 0 < $iValue; + }); + } + + $oMessageList = $this->MailClient()->MessageList( + $sFolder, $iOffset, $iLimit, $sSearch, $sUidNext, + ($this->Config()->Get('cache', 'enable', true) && $this->Config()->Get('cache', 'server_uids', false)) ? $this->Cacher() : null, + !!$this->Config()->Get('labs', 'use_imap_sort', false), + $bUseThreads, + $aExpandedThreadUid + ); + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantGetMessageList, $oException); + } + + if ($oMessageList instanceof \MailSo\Mail\MessageCollection) + { + $this->cacheByKey($sRawKey); + } + + return $this->DefaultResponse(__FUNCTION__, $oMessageList); + } + + /** + * @param \RainLoop\Account $oAccount + * @param bool $bWithDraftInfo = true + * + * @return \MailSo\Mime\Message + */ + private function buildMessage($oAccount, $bWithDraftInfo = true) + { + $sTo = $this->GetActionParam('To', ''); + $sCc = $this->GetActionParam('Cc', ''); + $sBcc = $this->GetActionParam('Bcc', ''); + $sSubject = $this->GetActionParam('Subject', ''); + $bTextIsHtml = '1' === $this->GetActionParam('TextIsHtml', '0'); + $sText = $this->GetActionParam('Text', ''); + $aAttachments = $this->GetActionParam('Attachments', null); + + $aDraftInfo = $this->GetActionParam('DraftInfo', null); + $sInReplyTo = $this->GetActionParam('InReplyTo', ''); + $sReferences = $this->GetActionParam('References', ''); + + $oMessage = \MailSo\Mime\Message::NewInstance(); + $oMessage->RegenerateMessageId(); + $oMessage->SetXMailer('RainLoop/'.APP_VERSION); + + $oSettings = $this->SettingsProvider()->Load($oAccount); + $sDisplayName = \trim($oSettings->GetConf('DisplayName', '')); + $sReplyTo = \trim($oSettings->GetConf('ReplyTo', '')); + + $oMessage + ->SetFrom(\MailSo\Mime\Email::NewInstance($oAccount->Email(), $sDisplayName)) + ->SetSubject($sSubject) + ; + + if (!empty($sReplyTo)) + { + $oReplyTo = \MailSo\Mime\EmailCollection::NewInstance($sReplyTo); + if ($oReplyTo && $oReplyTo->Count()) + { + $oMessage->SetReplyTo($oReplyTo); + } + } + + $oToEmails = \MailSo\Mime\EmailCollection::NewInstance($sTo); + if ($oToEmails && $oToEmails->Count()) + { + $oMessage->SetTo($oToEmails); + } + + $oCcEmails = \MailSo\Mime\EmailCollection::NewInstance($sCc); + if ($oCcEmails && $oCcEmails->Count()) + { + $oMessage->SetCc($oCcEmails); + } + + $oBccEmails = \MailSo\Mime\EmailCollection::NewInstance($sBcc); + if ($oBccEmails && $oBccEmails->Count()) + { + $oMessage->SetBcc($oBccEmails); + } + + if ($bWithDraftInfo && is_array($aDraftInfo) && !empty($aDraftInfo[0]) && !empty($aDraftInfo[1]) && !empty($aDraftInfo[2])) + { + $oMessage->SetDraftInfo($aDraftInfo[0], $aDraftInfo[1], $aDraftInfo[2]); + } + + if (0 < strlen($sInReplyTo)) + { + $oMessage->SetInReplyTo($sInReplyTo); + } + + if (0 < strlen($sReferences)) + { + $oMessage->SetReferences($sReferences); + } + + $aFoundedCids = array(); + $oMessage->AddText($bTextIsHtml ? + \MailSo\Base\HtmlUtils::BuildHtml($sText, $aFoundedCids) : $sText, $bTextIsHtml); + + if (is_array($aAttachments)) + { + foreach ($aAttachments as $sTempName => $aData) + { + $sFileName = (string) $aData[0]; + $bIsInline = (bool) $aData[1]; + $sCID = (string) $aData[2]; + + $rResource = $this->StorageProvider()->GetFile($oAccount, StorageType::TEMP, $sTempName); + if (is_resource($rResource)) + { + $iFileSize = $this->StorageProvider()->FileSize($oAccount, StorageType::TEMP, $sTempName); + + $oMessage->Attachments()->Add( + \MailSo\Mime\Attachment::NewInstance($rResource, $sFileName, $iFileSize, $bIsInline, + in_array(trim(trim($sCID), '<>'), $aFoundedCids), $sCID) + ); + } + } + } + + $this->Plugins()->RunHook('filter.build-message', array(&$oMessage)); + + return $oMessage; + } + + /** + * @return array + */ + public function DoSaveMessage() + { + $oAccount = $this->initMailClientConnection(); + + $sMessageFolder = $this->GetActionParam('MessageFolder', ''); + $sMessageUid = $this->GetActionParam('MessageUid', ''); + + $sDraftFolder = $this->GetActionParam('DraftFolder', ''); + if (0 === strlen($sDraftFolder)) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::UnknownError); + } + + $oMessage = $this->buildMessage($oAccount); + + $this->Plugins()->RunHook('filter.save-message', array(&$oMessage)); + + $mResult = false; + if ($oMessage) + { + $rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource(); + + $iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter( + $oMessage->ToStream(false), array($rMessageStream), 8192, true, true); + + if (false !== $iMessageStreamSize) + { + rewind($rMessageStream); + + $iNewUid = 0; + $this->MailClient()->MessageAppendStream( + $rMessageStream, $iMessageStreamSize, $sDraftFolder, array( + \MailSo\Imap\Enumerations\MessageFlag::SEEN + ), $iNewUid); + + if (null === $iNewUid || 0 === $iNewUid) + { + $sMessageId = $oMessage->MessageId(); + if (!empty($sMessageId)) + { + $iNewUid = $this->MailClient()->FindMessageUidByMessageId($sDraftFolder, $sMessageId); + } + } + + $mResult = true; + + if (0 < strlen($sMessageFolder) && 0 < strlen($sMessageUid)) + { + $this->MailClient()->MessageDelete($sMessageFolder, array($sMessageUid), true, true); + } + + if (null !== $iNewUid && 0 < $iNewUid) + { + $mResult = array( + 'NewFolder' => $sDraftFolder, + 'NewUid' => $iNewUid + ); + } + } + } + + return $this->DefaultResponse(__FUNCTION__, $mResult); + } + + /** + * @return array + */ + public function DoSendMessage() + { + $oAccount = $this->initMailClientConnection(); + + $sDraftFolder = $this->GetActionParam('MessageFolder', ''); + $sDraftUid = $this->GetActionParam('MessageUid', ''); + $sSentFolder = $this->GetActionParam('SentFolder', ''); + $aDraftInfo = $this->GetActionParam('DraftInfo', null); + + $oMessage = $this->buildMessage($oAccount, false); + + $this->Plugins()->RunHook('filter.send-message', array(&$oMessage)); + + $mResult = false; + try + { + if ($oMessage) + { + $rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource(); + + $iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter( + $oMessage->ToStream(true), array($rMessageStream), 8192, true, true); + + if (false !== $iMessageStreamSize) + { + rewind($rMessageStream); + + $oRcpt = $oMessage->GetRcpt(); + if ($oRcpt && 0 < $oRcpt->Count()) + { + try + { + $sHostName = function_exists('gethostname') ? gethostname() : 'localhost'; + + $oSmtpClient = \MailSo\Smtp\SmtpClient::NewInstance()->SetLogger($this->Logger()); + + $oSmtpClient->Connect($oAccount->Domain()->OutHost(), $oAccount->Domain()->OutPort(), + $sHostName, $oAccount->Domain()->OutSecure()); + + if ($oAccount->Domain()->OutAuth()) + { + if ($oAccount->PasswordIsXOAuth2()) + { + $oSmtpClient->LoginWithXOauth2($oAccount->Password()); + } + else + { + $oSmtpClient->Login($oAccount->Login(), $oAccount->Password()); + } + } + + $oSmtpClient->MailFrom($oAccount->Email()); + + $aRcpt =& $oRcpt->GetAsArray(); + foreach ($aRcpt as /* @var $oEmail \MailSo\Mime\Email */ $oEmail) + { + $oSmtpClient->Rcpt($oEmail->GetEmail()); + } + + $oSmtpClient->DataWithStream($rMessageStream); + + $oSmtpClient->LogoutAndDisconnect(); + } + catch (\MailSo\Net\Exceptions\ConnectionException $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::ConnectionError, $oException); + } + catch (\MailSo\Smtp\Exceptions\LoginException $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AuthError, $oException); + } + + rewind($rMessageStream); + + if (is_array($aDraftInfo) && 3 === count($aDraftInfo)) + { + $sDraftInfoType = $aDraftInfo[0]; + $sDraftInfoUid = $aDraftInfo[1]; + $sDraftInfoFolder = $aDraftInfo[2]; + + try + { + switch (strtolower($sDraftInfoType)) + { + case 'reply': + case 'reply-all': + $this->MailClient()->MessageSetFlag($sDraftInfoFolder, array($sDraftInfoUid), true, + \MailSo\Imap\Enumerations\MessageFlag::ANSWERED, true); + break; + case 'forward': + $sForwardFlag = $oAccount->Domain()->ForwardFlag(); + if (0 < strlen($sForwardFlag)) + { + $this->MailClient()->MessageSetFlag($sDraftInfoFolder, array($sDraftInfoUid), true, + $sForwardFlag, true); + } + break; + } + } + catch (\Exception $oException) + { + $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + } + + if (0 < strlen($sSentFolder)) + { + try + { + $this->MailClient()->MessageAppendStream( + $rMessageStream, $iMessageStreamSize, $sSentFolder, array( + \MailSo\Imap\Enumerations\MessageFlag::SEEN + )); + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantSaveMessage, $oException); + } + } + + if (0 < strlen($sDraftFolder) && 0 < strlen($sDraftUid)) + { + try + { + $this->MailClient()->MessageDelete($sDraftFolder, array($sDraftUid), true, true); + } + catch (\Exception $oException) + { + $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + } + + $mResult = true; + } + else + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::InvalidRecipients); + } + } + } + } + catch (\RainLoop\Exceptions\ClientException $oException) + { + throw $oException; + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantSendMessage, $oException); + } + + if (false === $mResult) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantSendMessage); + } + +// if ($oMessage && $this->ContactsProvider()->IsActive()) +// { +// $oToCollection = $oMessage->GetTo(); +// $oTo = $oToCollection->GetByIndex(0); +// if ($oTo) +// { +// $oContact = new \RainLoop\Providers\Contacts\Classes\Contact(); +// /* @var $oTo \MailSo\Mime\Email */ +// $oContact->Name = $oTo->GetDisplayName(); +// +// $i = 30; +// while ($i > 0) +// { +// $i--; +// $oContact->Emails = array('u'.$i.'-'.$oTo->GetEmail()); +// $this->ContactsProvider()->CreateContact($oAccount, $oContact); +// } +// } +// +// } + + return $this->TrueResponse(__FUNCTION__); + } + + /** + * @return array + */ + public function DoQuota() + { + $this->initMailClientConnection(); + + try + { + $aQuota = $this->MailClient()->Quota(); + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::MailServerError, $oException); + } + + return $this->DefaultResponse(__FUNCTION__, $aQuota); + } + + /** + * @return array + */ + public function DoContacts() + { + $oAccount = $this->getAccountFromToken(); + $sSearch = \trim($this->GetActionParam('Search', '')); + + $bMore = false; + $mResult = false; + if ($this->ContactsProvider()->IsActive()) + { + $mResult = $this->ContactsProvider()->GetContacts($oAccount, 0, RL_CONTACTS_MAX + 1, $sSearch); + if (is_array($mResult)) + { + $bMore = RL_CONTACTS_MAX < \count($mResult); + if ($bMore) + { + $mResult = \array_slice($mResult, 0, RL_CONTACTS_MAX); + } + } + } + + return $this->DefaultResponse(__FUNCTION__, array( + 'Limit' => RL_CONTACTS_MAX, + 'More' => $bMore, + 'List' => $mResult + )); + } + + /** + * @return array + */ + public function DoContactsDelete() + { + $oAccount = $this->getAccountFromToken(); + $aUids = \explode(',', (string) $this->GetActionParam('Uids', '')); + + $aFilteredUids = \array_filter($aUids, function (&$mUid) { + $mUid = (int) \trim($mUid); + return 0 < $mUid; + }); + + $bResult = false; + if ($this->ContactsProvider()->IsActive()) + { + $bResult = $this->ContactsProvider()->DeleteContacts($oAccount, $aFilteredUids); + } + + return $this->DefaultResponse(__FUNCTION__, $bResult); + } + + /** + * @return array + */ + public function DoContactSave() + { + sleep(1); + $oAccount = $this->getAccountFromToken(); + + $bResult = false; + $sResultID = ''; + + $sRequestUid = \trim($this->GetActionParam('RequestUid', '')); + if ($this->ContactsProvider()->IsActive() && 0 < \strlen($sRequestUid)) + { + $sUid = \trim($this->GetActionParam('Uid', '')); + $sName = \trim($this->GetActionParam('Name', '')); + $sEmail = \trim($this->GetActionParam('Email', '')); + + $sImageData = \trim($this->GetActionParam('ImageData', '')); + + $oContact = null; + if (0 < \strlen($sUid)) + { + if (\is_numeric($sUid)) + { + $oContact = $this->ContactsProvider()->GetContactById($oAccount, (int) $sUid); + } + } + else + { + $oContact = new \RainLoop\Providers\Contacts\Classes\Contact(); + } + + if ($oContact) + { + $oContact->Name = $sName; + $oContact->Emails = array($sEmail); + + if (0 < \strlen($sImageData) && 'data:image/' === substr($sImageData, 0, 11)) + { + $oContact->ImageHash = \md5($sImageData); + } + + if (0 < $oContact->IdContact) + { + $bResult = $this->ContactsProvider()->UpdateContact($oAccount, $oContact); + } + else + { + $bResult = $this->ContactsProvider()->CreateContact($oAccount, $oContact); + } + + if ($bResult && 0 < $oContact->IdContact) + { + $sResultID = $oContact->IdContact; + $aMatches = array(); + if ($bResult && $oContact && 0 < $oContact->IdContact && 0 < \strlen($oContact->ImageHash) && + 0 < \strlen($sImageData) && + \preg_match('/^data:(image\/(jpeg|jpg|png|bmp));base64,(.+)$/i', $sImageData, $aMatches) && + !empty($aMatches[1]) && !empty($aMatches[3])) + { + $this->StorageProvider()->Put($oAccount, StorageType::USER, + 'contacts/'.$oContact->ImageHash, $aMatches[1].'|||'.$aMatches[3]); + } + } + else + { + $bResult = false; + } + } + } + + return $this->DefaultResponse(__FUNCTION__, array( + 'RequestUid' => $sRequestUid, + 'ResultID' => $sResultID, + 'Result' => $bResult + )); + } + + /** + * @return array + */ + public function DoSuggestions() + { + $oAccount = $this->getAccountFromToken(); + + $sQuery = \trim($this->GetActionParam('Query', '')); + $iPage = (int) $this->GetActionParam('Page', 0); + + $bMore = false; + $aResult = array(); + if (0 < \strlen($sQuery) && 0 < $iPage && $this->ContactsProvider()->IsActive()) + { + $mResult = $this->ContactsProvider()->GetContacts($oAccount, ($iPage - 1) * RL_CONTACTS_PER_PAGE, RL_CONTACTS_PER_PAGE + 1, $sQuery); + if (\is_array($mResult) && 0 < \count($mResult)) + { + $bMore = RL_CONTACTS_PER_PAGE < \count($mResult); + if ($bMore) + { + $mResult = \array_slice($mResult, 0, RL_CONTACTS_PER_PAGE); + } + + foreach ($mResult as $oItem) + { + /* @var $oItem \RainLoop\Providers\Contacts\Classes\Contact */ + $aEmails = $oItem->Emails; + if (0 < \count($aEmails)) + { + foreach ($aEmails as $sEmail) + { + if (0 < \strlen($sEmail)) + { + $aResult[] = array($sEmail, $oItem->Name); + } + } + } + } + } + } + + return $this->DefaultResponse(__FUNCTION__, array( + 'More' => $bMore, + 'List' => $aResult + )); + + $oAccount = $this->getAccountFromToken(); + + $aResult = array(); + $sQuery = \trim($this->GetActionParam('Query', '')); + if (0 < \strlen($sQuery) && $oAccount) + { + $aResult = $this->SuggestionsProvider()->Process($oAccount, $sQuery); + + if (0 === count($aResult) && false !== \strpos(strtolower($oAccount->Email()), \strtolower($sQuery))) + { + $aResult[] = array($oAccount->Email(), $oAccount->Name()); + } + } + + return $this->DefaultResponse(__FUNCTION__, $aResult); + } + + /** + * @return array + */ + public function DoEmailsPicsHashes() + { + $oAccount = $this->getAccountFromToken(); + + $aResult = array(); + if ($this->ContactsProvider()->IsActive()) + { + $mResult = $this->ContactsProvider()->GetContactsImageHashes($oAccount); + if (\is_array($mResult) && 0 < \count($mResult)) + { + $aResult = $mResult; + } + } + + return $this->DefaultResponse(__FUNCTION__, $aResult); + } + + /** + * @return array + */ + public function DoServicesPics() + { + $aData = \RainLoop\Utils::ServicesPics(); + $aResult = array(); + + foreach ($aData as $sDomain => $sPic) + { + $aResult[$sDomain] = APP_WEB_STATIC_PATH.'services/'.$sPic; + } + + return $this->DefaultResponse(__FUNCTION__, $aResult); + } + + /** + * @return array + */ + private function messageSetFlag($sActionFunction, $sResponseFunction) + { + $this->initMailClientConnection(); + + $sFolder = $this->GetActionParam('Folder', ''); + $bSetAction = '1' === (string) $this->GetActionParam('SetAction', '0'); + $aUids = explode(',', (string) $this->GetActionParam('Uids', '')); + $aFilteredUids = array_filter($aUids, function (&$sUid) { + $sUid = (int) trim($sUid); + return 0 < $sUid; + }); + + try + { + $this->MailClient()->{$sActionFunction}($sFolder, $aFilteredUids, true, $bSetAction); + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::MailServerError, $oException); + } + + return $this->TrueResponse($sResponseFunction); + } + + /** + * @return array + */ + public function DoMessageSetSeen() + { + return $this->messageSetFlag('MessageSetSeen', __FUNCTION__); + } + + /** + * @return array + */ + public function DoMessageSetSeenToAll() + { + $this->initMailClientConnection(); + + $sFolder = $this->GetActionParam('Folder', ''); + $bSetAction = '1' === (string) $this->GetActionParam('SetAction', '0'); + + try + { + $this->MailClient()->MessageSetSeenToAll($sFolder, $bSetAction); + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::MailServerError, $oException); + } + + return $this->TrueResponse(__FUNCTION__); + } + + /** + * @return array + */ + public function DoMessageSetFlagged() + { + return $this->messageSetFlag('MessageSetFlagged', __FUNCTION__); + } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoMessage() + { + $sRawKey = (string) $this->GetActionParam('RawKey', ''); + + $sFolder = ''; + $iUid = 0; + + $aValues = $this->getDecodedClientRawKeyValue($sRawKey, 4); + if (is_array($aValues) && 4 === count($aValues)) + { + $sFolder = (string) $aValues[0]; + $iUid = (int) $aValues[1]; + + $this->verifyCacheByKey($sRawKey); + } + else + { + $sFolder = $this->GetActionParam('Folder', ''); + $iUid = (int) $this->GetActionParam('Uid', 0); + } + + $this->initMailClientConnection(); + + try + { + $oMessage = $this->MailClient()->Message($sFolder, $iUid, true, + !!$this->Config()->Get('labs', 'use_imap_thread', false) ? $this->Cacher() : null); + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantGetMessage, $oException); + } + + if ($oMessage instanceof \MailSo\Mail\Message) + { + $this->Plugins()->RunHook('filter.result-message', array(&$oMessage)); + + $this->cacheByKey($sRawKey); + } + + return $this->DefaultResponse(__FUNCTION__, $oMessage); + } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoMessageDelete() + { + $this->initMailClientConnection(); + + $sFolder = $this->GetActionParam('Folder', ''); + $aUids = explode(',', (string) $this->GetActionParam('Uids', '')); + + $aFilteredUids = array_filter($aUids, function (&$sUid) { + $sUid = (int) trim($sUid); + return 0 < $sUid; + }); + + try + { + $this->MailClient()->MessageDelete($sFolder, $aFilteredUids, true); + $sHash = $this->MailClient()->FolderHash($sFolder); + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantDeleteMessage, $oException); + } + + return $this->DefaultResponse(__FUNCTION__, '' === $sHash ? false : array($sFolder, $sHash)); + } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoMessageMove() + { + $this->initMailClientConnection(); + + $sFromFolder = $this->GetActionParam('FromFolder', ''); + $sToFolder = $this->GetActionParam('ToFolder', ''); + $aUids = explode(',', (string) $this->GetActionParam('Uids', '')); + + $aFilteredUids = array_filter($aUids, function (&$mUid) { + $mUid = (int) trim($mUid); + return 0 < $mUid; + }); + + try + { + $this->MailClient()->MessageMove($sFromFolder, $sToFolder, + $aFilteredUids, true, $this->Config()->Get('labs', 'use_imap_move', true)); + + $sHash = $this->MailClient()->FolderHash($sFromFolder); + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantMoveMessage, $oException); + } + + return $this->DefaultResponse(__FUNCTION__, + '' === $sHash ? false : array($sFromFolder, $sHash)); + } + + /** + * @param string $sFileName + * @param string $sContentType + * @param string $sMimeIndex + * + * @return string + */ + public function MainClearFileName($sFileName, $sContentType, $sMimeIndex) + { + $sFileName = 0 === strlen($sFileName) ? preg_replace('/[^a-zA-Z0-9]/', '.', (empty($sMimeIndex) ? '' : $sMimeIndex.'.').$sContentType) : $sFileName; + $sClearedFileName = preg_replace('/[\s]+/', ' ', preg_replace('/[\.]+/', '.', $sFileName)); + $sExt = \MailSo\Base\Utils::GetFileExtension($sClearedFileName); + + $iSize = 50; + if ($iSize < strlen($sClearedFileName) - strlen($sExt)) + { + $sClearedFileName = substr($sClearedFileName, 0, $iSize).(empty($sExt) ? '' : '.'.$sExt); + } + + return \MailSo\Base\Utils::ClearFileName(\MailSo\Base\Utils::Utf8Clear($sClearedFileName)); + } + + /** + * @return array + */ + public function DoMessageUploadAttachments() + { + $oAccount = $this->initMailClientConnection(); + + $mResult = false; + $self = $this; + + try + { + $aAttachments = $this->GetActionParam('Attachments', array()); + if (is_array($aAttachments) && 0 < count($aAttachments)) + { + $mResult = array(); + foreach ($aAttachments as $sAttachment) + { + $aValues = \RainLoop\Utils::DecodeKeyValues($sAttachment); + if (is_array($aValues)) + { + $sFolder = isset($aValues['Folder']) ? $aValues['Folder'] : ''; + $iUid = (int) isset($aValues['Uid']) ? $aValues['Uid'] : 0; + $sMimeIndex = (string) isset($aValues['MimeIndex']) ? $aValues['MimeIndex'] : ''; + + $sTempName = md5($sAttachment); + if (!$this->StorageProvider()->FileExists($oAccount, StorageType::TEMP, $sTempName)) + { + $this->MailClient()->MessageMimeStream( + function($rResource, $sContentType, $sFileName, $sMimeIndex = '') use ($oAccount, &$mResult, $sTempName, $sAttachment, $self) { + if (is_resource($rResource)) + { + $sContentType = (empty($sFileName)) ? 'text/plain' : \MailSo\Base\Utils::MimeContentType($sFileName); + $sFileName = $self->MainClearFileName($sFileName, $sContentType, $sMimeIndex); + + if ($self->StorageProvider()->PutFile($oAccount, StorageType::TEMP, $sTempName, $rResource)) + { + $mResult[$sTempName] = $sAttachment; + } + } + }, $sFolder, $iUid, true, $sMimeIndex); + } + else + { + $mResult[$sTempName] = $sAttachment; + } + } + } + } + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::MailServerError, $oException); + } + + return $this->DefaultResponse(__FUNCTION__, $mResult); + } + + /** + * @return array + */ + public function DoComposeUploadExternals() + { + $oAccount = $this->getAccountFromToken(); + + $mResult = false; + $aExternals = $this->GetActionParam('Externals', array()); + if (\is_array($aExternals) && 0 < \count($aExternals)) + { + $oHttp = \MailSo\Base\Http::SingletonInstance(); + + $mResult = array(); + foreach ($aExternals as $sUrl) + { + $mResult[$sUrl] = ''; + + $sTempName = \md5($sUrl); + + $iCode = 0; + $sContentType = ''; + + $rFile = $this->StorageProvider()->GetFile($oAccount, StorageType::TEMP, $sTempName, 'wb+'); + if ($rFile && $oHttp->SaveUrlToFile($sUrl, $rFile, '', $sContentType, $iCode, $this->Logger())) + { + $mResult[$sUrl] = $sTempName; + } + + if (\is_resource($rFile)) + { + @\fclose($rFile); + } + } + } + + return $this->DefaultResponse(__FUNCTION__, $mResult); + } + + /** + * @return array + */ + public function DoSocialUsers() + { + $oAccount = $this->getAccountFromToken(); + + $oSettings = $this->SettingsProvider()->Load($oAccount); + + $aData = array( + 'Google' => '', + 'Facebook' => '', + 'Twitter' => '' + ); + + if ($oSettings) + { + $aData['Google'] = $oSettings->GetConf('GoogleSocialName', ''); + $aData['Facebook'] = $oSettings->GetConf('FacebookSocialName', ''); + $aData['Twitter'] = $oSettings->GetConf('TwitterSocialName', ''); + } + + return $this->DefaultResponse(__FUNCTION__, $aData); + } + + /** + * @return array + */ + public function DoSocialGoogleDisconnect() + { + $oAccount = $this->getAccountFromToken(); + return $this->DefaultResponse(__FUNCTION__, $this->Social()->GoogleDisconnect($oAccount)); + } + + /** + * @return array + */ + public function DoSocialTwitterDisconnect() + { + $oAccount = $this->getAccountFromToken(); + return $this->DefaultResponse(__FUNCTION__, $this->Social()->TwitterDisconnect($oAccount)); + } + + /** + * @return array + */ + public function DoSocialFacebookDisconnect() + { + $oAccount = $this->getAccountFromToken(); + return $this->DefaultResponse(__FUNCTION__, $this->Social()->FacebookDisconnect($oAccount)); + } + + /** + * @param int $iError + * @param int $iClientError + * + * @return string + */ + private function getUploadErrorMessageByCode($iError, &$iClientError) + { + $sError = ''; + $iClientError = UploadClientError::NORMAL; + switch($iError) + { + case UPLOAD_ERR_OK: + break; + case UPLOAD_ERR_INI_SIZE: + case UPLOAD_ERR_FORM_SIZE: + case UploadError::CONFIG_SIZE: + case UploadError::EMPTY_FILES_DATA: + $sError = 'File is too big'; + $iClientError = UploadClientError::FILE_IS_TOO_BIG; + break; + case UPLOAD_ERR_PARTIAL: + $sError = 'File partially uploaded'; + $iClientError = UploadClientError::FILE_PARTIALLY_UPLOADED; + break; + case UPLOAD_ERR_NO_FILE: + $sError = 'No file uploaded'; + $iClientError = UploadClientError::FILE_NO_UPLOADED; + break; + case UPLOAD_ERR_NO_TMP_DIR: + case UPLOAD_ERR_CANT_WRITE: + case UPLOAD_ERR_EXTENSION: + $sError = 'Missing temp folder'; + $iClientError = UploadClientError::MISSING_TEMP_FOLDER; + break; + case UploadError::ON_SAVING: + $sError = 'Error on saving file'; + $iClientError = UploadClientError::FILE_ON_SAVING_ERROR; + break; + case UploadError::FILE_TYPE: + $sError = 'Invalid file type'; + $iClientError = UploadClientError::FILE_TYPE; + break; + case UploadError::UNKNOWN: + default: + $sError = 'Unknown error'; + $iClientError = UploadClientError::UNKNOWN; + break; + } + + return $sError; + } + + /** + * @return array + */ + public function Upload() + { + $oAccount = $this->getAccountFromToken(); + $oConfig = $this->Config(); + + $sInputName = 'uploader'; + $aResponse = array(); + + $iError = UploadError::UNKNOWN; + $iSizeLimit = ((int) $oConfig->Get('webmail', 'attachment_size_limit', 0)) * 1024 * 1024; + if ($oAccount) + { + $iError = UPLOAD_ERR_OK; + $_FILES = isset($_FILES) ? $_FILES : null; + if (isset($_FILES, $_FILES[$sInputName], $_FILES[$sInputName]['name'], $_FILES[$sInputName]['tmp_name'], $_FILES[$sInputName]['size'])) + { + $iError = (isset($_FILES[$sInputName]['error'])) ? (int) $_FILES[$sInputName]['error'] : UPLOAD_ERR_OK; + + if (UPLOAD_ERR_OK === $iError && 0 < $iSizeLimit && $iSizeLimit < (int) $_FILES[$sInputName]['size']) + { + $iError = UploadError::CONFIG_SIZE; + } + + $sSavedName = 'upload-post-'.md5($_FILES[$sInputName]['name'].$_FILES[$sInputName]['tmp_name']); + + if (UPLOAD_ERR_OK === $iError) + { + if (!$this->StorageProvider()->MoveUploadedFile($oAccount, StorageType::TEMP, + $sSavedName, $_FILES[$sInputName]['tmp_name'])) + { + $iError = UploadError::ON_SAVING; + } + } + + $sUploadName = $_FILES[$sInputName]['name']; + $iSize = $_FILES[$sInputName]['size']; + $sMimeType = $_FILES[$sInputName]['type']; + + $aResponse['Attachment'] = array( + 'Name' => $sUploadName, + 'TempName' => $sSavedName, + 'MimeType' => $sMimeType, + 'Size' => (int) $iSize + ); + } + else if (!isset($_FILES) || !is_array($_FILES) || 0 === count($_FILES)) + { + $iError = UPLOAD_ERR_INI_SIZE; + } + else + { + $iError = UploadError::EMPTY_FILES_DATA; + } + } + + if (UPLOAD_ERR_OK !== $iError) + { + $iClientError = UploadClientError::NORMAL; + $sError = $this->getUploadErrorMessageByCode($iError, $iClientError); + if (!empty($sError)) + { + $aResponse['ErrorCode'] = $iClientError; + $aResponse['Error'] = $sError; + } + } + + return $this->DefaultResponse(__FUNCTION__, $aResponse); + } + + /** + * @return array + */ + public function UploadBackground() + { + $oAccount = $this->getAccountFromToken(); + + $sInputName = 'uploader'; + $mResponse = false; + + $iError = UploadError::UNKNOWN; + $iSizeLimit = 1024 * 1024; + if ($oAccount) + { + $iError = UPLOAD_ERR_OK; + $_FILES = isset($_FILES) ? $_FILES : null; + if (isset($_FILES, $_FILES[$sInputName], $_FILES[$sInputName]['name'], $_FILES[$sInputName]['tmp_name'], $_FILES[$sInputName]['size'])) + { + $iError = (isset($_FILES[$sInputName]['error'])) ? (int) $_FILES[$sInputName]['error'] : UPLOAD_ERR_OK; + + if (UPLOAD_ERR_OK === $iError && 0 < $iSizeLimit && $iSizeLimit < (int) $_FILES[$sInputName]['size']) + { + $iError = UploadError::CONFIG_SIZE; + } + + if (UPLOAD_ERR_OK === $iError && !\in_array(\strtolower($_FILES[$sInputName]['type']), array('image/png', 'image/jpg', 'image/jpeg'))) + { + $iError = UploadError::FILE_TYPE; + } + + $sSavedName = 'upload-post-'.md5($_FILES[$sInputName]['name'].$_FILES[$sInputName]['tmp_name']); + + if (UPLOAD_ERR_OK === $iError) + { + if (!$this->StorageProvider()->MoveUploadedFile($oAccount, StorageType::TEMP, + $sSavedName, $_FILES[$sInputName]['tmp_name'])) + { + $iError = UploadError::ON_SAVING; + } + + $mData = $this->StorageProvider()->Get($oAccount, StorageType::TEMP, $sSavedName); + if (!empty($mData)) + { + $this->StorageProvider()->Put($oAccount, StorageType::USER, 'CustomThemeBackground', + 'data:'.$_FILES[$sInputName]['type'].';base64,'.base64_encode($mData) + ); + } + + unset($mData); + $this->StorageProvider()->Clear($oAccount, StorageType::TEMP, $sSavedName); + + $mResponse = $_FILES[$sInputName]['name']; + } + + } + else if (!isset($_FILES) || !is_array($_FILES) || 0 === count($_FILES)) + { + $iError = UPLOAD_ERR_INI_SIZE; + } + else + { + $iError = UploadError::EMPTY_FILES_DATA; + } + } + + if (UPLOAD_ERR_OK !== $iError) + { + $iClientError = UploadClientError::NORMAL; + $sError = $this->getUploadErrorMessageByCode($iError, $iClientError); + if (!empty($sError)) + { + return $this->FalseResponse($sSavedName, $iClientError, $sError); + } + } + + return $this->DefaultResponse(__FUNCTION__, $mResponse); + } + + /** + * @return bool + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function RawViewAsPlain() + { + $this->initMailClientConnection(); + + $sRawKey = (string) $this->GetActionParam('RawKey', ''); + $aValues = $this->getDecodedRawKeyValue($sRawKey); + + $sFolder = isset($aValues['Folder']) ? $aValues['Folder'] : ''; + $iUid = (int) (isset($aValues['Uid']) ? $aValues['Uid'] : 0); + $sMimeIndex = (string) (isset($aValues['MimeIndex']) ? $aValues['MimeIndex'] : ''); + + header('Content-Type: text/plain', true); + + return $this->MailClient()->MessageMimeStream(function ($rResource) { + if (is_resource($rResource)) + { + \MailSo\Base\Utils::FpassthruWithTimeLimitReset($rResource); + } + }, $sFolder, $iUid, true, $sMimeIndex); + } + + /** + * @return bool + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function Append() + { + $oAccount = $this->initMailClientConnection(); + + $sFolderFullNameRaw = $this->GetActionParam('Folder', ''); + + $_FILES = isset($_FILES) ? $_FILES : null; + if ($oAccount instanceof \RainLoop\Account && + $this->Config()->Get('labs', 'allow_message_append', false) && + isset($_FILES, $_FILES['AppendFile'], $_FILES['AppendFile']['name'], + $_FILES['AppendFile']['tmp_name'], $_FILES['AppendFile']['size'])) + { + if (is_string($_FILES['AppendFile']['tmp_name']) && 0 < strlen($_FILES['AppendFile']['tmp_name'])) + { + if (\UPLOAD_ERR_OK === (int) $_FILES['AppendFile']['error'] && !empty($sFolderFullNameRaw)) + { + $sSavedName = 'append-post-'.md5($sFolderFullNameRaw.$_FILES['AppendFile']['name'].$_FILES['AppendFile']['tmp_name']); + + if ($this->StorageProvider()->MoveUploadedFile($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::TEMP, + $sSavedName, $_FILES['AppendFile']['tmp_name'])) + { + $iMessageStreamSize = $this->StorageProvider()->FileSize($oAccount, \RainLoop\Providers\Storage\Enumerations\StorageType::TEMP, $sSavedName); + $rMessageStream = $this->StorageProvider()->GetFile($oAccount, \RainLoop\Providers\Storage\Enumerations\StorageType::TEMP, $sSavedName); + + $this->MailClient()->MessageAppendStream($rMessageStream, $iMessageStreamSize, $sFolderFullNameRaw); + } + } + } + } + + return $this->DefaultResponse(__FUNCTION__, true); + } + + /** + * @param string $sKey + * @param bool $bForce = false + * + * @return bool + */ + public function cacheByKey($sKey, $bForce = false) + { + $bResult = false; + if (!empty($sKey) && ($bForce || $this->Config()->Get('cache', 'enable', true) && $this->Config()->Get('cache', 'http', true))) + { + $iUtcTimeStamp = \time(); + $iExpireTime = 3600 * 24 * 5; + + header('Cache-Control: private', true); + header('Pragma: private', true); + header('Etag: '.\md5('Etag:'.\md5($sKey.\md5($this->Config()->Get('cache', 'index', '')))), true); + header('Last-Modified: '.\gmdate('D, d M Y H:i:s', $iUtcTimeStamp - $iExpireTime).' UTC', true); + header('Expires: '.\gmdate('D, j M Y H:i:s', $iUtcTimeStamp + $iExpireTime).' UTC', true); + $bResult = true; + } + + return $bResult; + } + + /** + * @param string $sKey + * @param bool $bForce = false + * + * @return void + */ + public function verifyCacheByKey($sKey, $bForce = false) + { + if (!empty($sKey) && ($bForce || $this->Config()->Get('cache', 'enable', true) && $this->Config()->Get('cache', 'http', true))) + { + $sIfModifiedSince = $this->Http()->GetHeader('If-Modified-Since', ''); + if (!empty($sIfModifiedSince)) + { + $this->Http()->StatusHeader(304); + $this->cacheByKey($sKey); + exit(); + } + } + } + + /** + * @param bool $bDownload + * + * @return bool + */ + private function rawSmart($bDownload) + { + $sRawKey = (string) $this->GetActionParam('RawKey', ''); + $aValues = $this->getDecodedRawKeyValue($sRawKey); + + $sFolder = isset($aValues['Folder']) ? $aValues['Folder'] : ''; + $iUid = (int) isset($aValues['Uid']) ? $aValues['Uid'] : 0; + $sMimeIndex = (string) isset($aValues['MimeIndex']) ? $aValues['MimeIndex'] : ''; + + $sContentTypeIn = (string) isset($aValues['MimeType']) ? $aValues['MimeType'] : ''; + $sFileNameIn = (string) isset($aValues['FileName']) ? $aValues['FileName'] : ''; + + if (!empty($sFolder) && 0 < $iUid) + { + $this->verifyCacheByKey($sRawKey); + } + + $this->initMailClientConnection(); + + $self = $this; + return $this->MailClient()->MessageMimeStream( + function($rResource, $sContentType, $sFileName, $sMimeIndex = '') use ($self, $sRawKey, $sContentTypeIn, $sFileNameIn, $bDownload) { + if (is_resource($rResource)) + { + $sContentTypeOut = $sContentTypeIn; + if (empty($sContentTypeOut)) + { + $sContentTypeOut = $sContentType; + if (empty($sContentTypeOut)) + { + $sContentTypeOut = (empty($sFileName)) ? 'text/plain' : \MailSo\Base\Utils::MimeContentType($sFileName); + } + } + + $sFileNameOut = $sFileNameIn; + if (empty($sFileNameOut)) + { + $sFileNameOut = $sFileName; + } + + $sFileNameOut = $self->MainClearFileName($sFileNameOut, $sContentTypeOut, $sMimeIndex); + + header('Content-Type: '.$sContentTypeOut); + header('Content-Disposition: '.($bDownload ? 'attachment' : 'inline').'; filename="'.$sFileNameOut.'"; charset=utf-8', true); + header('Accept-Ranges: none', true); + header('Content-Transfer-Encoding: binary'); + + $self->cacheByKey($sRawKey); + + \MailSo\Base\Utils::FpassthruWithTimeLimitReset($rResource); + } + }, $sFolder, $iUid, true, $sMimeIndex); + } + + /** + * @return bool + */ + public function RawDownload() + { + return $this->rawSmart(true); + } + + /** + * @return bool + */ + public function RawView() + { + return $this->rawSmart(false); + } + + /** + * @return bool + */ + public function RawUserPic() + { + $sRawKey = (string) $this->GetActionParam('RawKey', ''); + if (!empty($sRawKey)) + { + $this->verifyCacheByKey($sRawKey); + } + + $oAccount = $this->getAccountFromToken(); + + $sData = $this->StorageProvider()->Get($oAccount, StorageType::USER, 'contacts/'.$sRawKey); + if ($sData) + { + $aData = \explode('|||', $sData, 2); + if (\is_array($aData) && 2 === \count($aData) && !empty($aData[0]) && !empty($aData[1])) + { + header('Content-Type: '.$aData[0]); + header('Content-Disposition: inline; filename="'.\preg_replace('/[^a-zA-Z0-9]+/', '.', $aData[0]).'"', true); + header('Accept-Ranges: none', true); + header('Content-Transfer-Encoding: binary'); + + $this->cacheByKey($sRawKey); + + echo \MailSo\Base\Utils::Base64Decode($aData[1]); + + return true; + } + } + + return false; + } + + /** + * @return \RainLoop\Account | bool + */ + private function initMailClientConnection() + { + $oAccount = null; + + if (!$this->MailClient()->IsLoggined()) + { + $oAccount = $this->getAccountFromToken(); + + try + { + $this->MailClient() + ->Connect($oAccount->Domain()->IncHost(), $oAccount->Domain()->IncPort(), $oAccount->Domain()->IncSecure()); + + if ($oAccount->PasswordIsXOAuth2()) + { + $this->MailClient()->LoginWithXOauth2($oAccount->Password()); + } + else + { + $this->MailClient()->Login($oAccount->Login(), $oAccount->Password()); + } + } + catch (\MailSo\Net\Exceptions\ConnectionException $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::ConnectionError, $oException); + } + catch (\Exception $oException) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AuthError, $oException); + } + } + + return $oAccount; + } + + /** + * @param string $sRawKey + * + * @return array | false + */ + private function getDecodedRawKeyValue($sRawKey) + { + $bResult = false; + if (!empty($sRawKey)) + { + $aValues = \RainLoop\Utils::DecodeKeyValues($sRawKey); + if (is_array($aValues)) + { + $bResult = $aValues; + } + } + + return $bResult; + } + + /** + * @param string $sRawKey + * @param int | null $iLenCache + * @return array | bool + */ + private function getDecodedClientRawKeyValue($sRawKey, $iLenCache = null) + { + $mResult = false; + if (!empty($sRawKey)) + { + $sRawKey = \MailSo\Base\Utils::UrlSafeBase64Decode($sRawKey); + $aValues = explode("\x0", $sRawKey); + + if (is_array($aValues) && (null === $iLenCache || $iLenCache === count($aValues))) + { + $mResult = $aValues; + } + } + + return $mResult; + } + + /** + * @param string $sTheme + * + * @return string + */ + public function ValidateTheme($sTheme) + { + return in_array($sTheme, $this->GetThemes()) ? + $sTheme : $this->Config()->Get('themes', 'default', 'Default'); + } + + /** + * @param $sLanguage $sLanguage + * + * @return $sLanguage + */ + public function ValidateLanguage($sLanguage) + { + return in_array($sLanguage, $this->GetLanguages()) ? + $sLanguage : $this->Config()->Get('i18n', 'default', 'en'); + } + + /** + * @staticvar array $aCache + * @param bool $bAdmin = false + * + * @return array + */ + public function GetThemes($bAdmin = false) + { + static $aCache = null; + if (is_array($aCache)) + { + return $aCache; + } + + $bClear = false; + $bDefault = false; + $sList = array(); + $sDir = APP_VERSION_ROOT_PATH.'themes'; + if (@is_dir($sDir)) + { + $rDirH = opendir($sDir); + if ($rDirH) + { + while (($sFile = readdir($rDirH)) !== false) + { + if ('.' !== $sFile{0} && is_dir($sDir.'/'.$sFile) && file_exists($sDir.'/'.$sFile.'/styles.less')) + { + if ('Default' !== $sFile && 'Clear' !== $sFile && 'Custom' !== $sFile) + { + $sList[] = $sFile; + } + else + { + if ('Default' === $sFile) + { + $bDefault = true; + } + else if ('Clear' === $sFile) + { + $bClear = true; + } + } + } + } + @closedir($rDirH); + } + } + + sort($sList); + if ($bDefault) + { + array_unshift($sList, 'Default'); + } + + if ($bClear) + { + array_push($sList, 'Clear'); + } + + if (!$bAdmin && $this->Config()->Get('webmail', 'allow_custom_theme', true)) + { + array_push($sList, 'Custom'); + } + + $aCache = $sList; + return $sList; + } + + /** + * @staticvar array $aCache + * + * @return array + */ + public function GetLanguages() + { + static $aCache = null; + if (is_array($aCache)) + { + return $aCache; + } + + $sList = array(); + $sDir = APP_VERSION_ROOT_PATH.'langs/'; + if (@is_dir($sDir)) + { + $rDirH = opendir($sDir); + if ($rDirH) + { + while (($sFile = readdir($rDirH)) !== false) + { + if ('.' !== $sFile{0} && is_file($sDir.'/'.$sFile) && '.ini' === substr($sFile, -4)) + { + $sLang = strtolower(substr($sFile, 0, -4)); + if (0 < strlen($sLang) && 'always' !== $sLang) + { + $sList[] = $sLang; + } + } + } + + @closedir($rDirH); + } + } + + $aCache = $sList; + return $sList; + } + + /** + * @param string $sName + * @param string $sHtml + * + * @return string + */ + public function ProcessTemplate($sName, $sHtml) + { + $sHtml = $this->Plugins()->ProcessTemplate($sName, $sHtml); + $sHtml = \preg_replace('/\{\{INCLUDE\/([a-zA-Z]+)\/PLACE\}\}/', '', $sHtml); + + return \RainLoop\Utils::ClearHtmlOutput($sHtml); + } + + /** + * @staticvar bool $bOnce + * @param string $sName + * @param array $aData = array() + * + * @return bool + */ + public function KeenIO($sName, $aData = array()) + { + static $bOnce = null; + if (false === $bOnce) + { + return false; + } + + if (APP_VERSION === APP_DEV_VERSION || + \in_array(APP_SITE, array('localhost', 'demo.rainloop.net', 'demo.rainloop.de'))) + { + return true; + } + + if (null === $bOnce && !\MailSo\Base\Utils::FunctionExistsAndEnabled('curl_init')) + { + $bOnce = false; + return false; + } + + try + { + if (!$bOnce) + { + $bOnce = true; + \KeenIO\Service\KeenIO::setProjectId('2ab5998ce84d445b889b84c881caacac'); + } + + \KeenIO\Service\KeenIO::addEvent($sName, \array_merge($aData, array( + 'site' => APP_SITE, + 'uid' => \md5(APP_SITE.APP_SALT), + 'version' => APP_VERSION + ))); + + $this->Logger()->Write('KeenIO: addEvent = '.$sName); + return true; + } + catch (\Exception $oException) + { + $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::WARNING); + } + + return false; + } + + /** + * @param string $sActionName + * @param mixed $mResult = false + * + * @return array + */ + private function mainDefaultResponse($sActionName, $mResult = false) + { + $sActionName = 'Do' === substr($sActionName, 0, 2) ? substr($sActionName, 2) : $sActionName; + + $aResult = array( + 'Action' => $sActionName, + 'Result' => $this->responseObject($mResult, $sActionName) + ); + + return $aResult; + } + /** + * @param string $sActionName + * @param mixed $mResult = false + * + * @return array + */ + public function DefaultResponse($sActionName, $mResult = false) + { + $aResponseItem = $this->mainDefaultResponse($sActionName, $mResult); + $this->Plugins()->RunHook('main.default-response', array($sActionName, &$aResponseItem)); + return $aResponseItem; + } + + /** + * @param string $sActionName + * + * @return array + */ + public function TrueResponse($sActionName) + { + $aResponseItem = $this->mainDefaultResponse($sActionName, true); + $this->Plugins()->RunHook('main.default-response', array($sActionName, &$aResponseItem)); + return $aResponseItem; + } + + /** + * @param string $sActionName + * @param int $iErrorCode = null + * @param string $sErrorMessage = null + * + * @return array + */ + public function FalseResponse($sActionName, $iErrorCode = null, $sErrorMessage = null) + { + $aResponseItem = $this->mainDefaultResponse($sActionName, false); + + if (null !== $iErrorCode) + { + $aResponseItem['ErrorCode'] = (int) $iErrorCode; + $aResponseItem['ErrorMessage'] = null === $sErrorMessage ? '' : (string) $sErrorMessage; + } + + $this->Plugins()->RunHook('main.default-response', array($sActionName, &$aResponseItem)); + return $aResponseItem; + } + + /** + * @param string $sActionName + * @param \Exception $oException + * + * @return array + */ + public function ExceptionResponse($sActionName, $oException) + { + $iErrorCode = null; + $sErrorMessage = null; + + if ($oException instanceof \RainLoop\Exceptions\ClientException) + { + $iErrorCode = $oException->getCode(); + $sErrorMessage = null; + } + else + { + $iErrorCode = \RainLoop\Notifications::UnknownError; + $sErrorMessage = $oException->getCode().' - '.$oException->getMessage(); + } + + $oPrevious = $oException->getPrevious(); + if ($oPrevious) + { + $this->Logger()->WriteException($oPrevious); + } + else + { + $this->Logger()->WriteException($oException); + } + + return $this->FalseResponse($sActionName, $iErrorCode); + } + + /** + * @param array $aCurrentActionParams + * @param string $sMethodName = '' + * + * @return \RainLoop\Actions + */ + public function SetActionParams($aCurrentActionParams, $sMethodName = '') + { + $this->Plugins()->RunHook('filter.action-params', array($sMethodName, &$aCurrentActionParams)); + + $this->aCurrentActionParams = $aCurrentActionParams; + + return $this; + } + + /** + * @param string $sKey + * @param mixed $mDefaul = null + * + * @return mixed + */ + public function GetActionParam($sKey, $mDefault = null) + { + return is_array($this->aCurrentActionParams) && isset($this->aCurrentActionParams[$sKey]) ? + $this->aCurrentActionParams[$sKey] : $mDefault; + } + + /** + * @param string $sKey + * + * @return bool + */ + public function HasActionParam($sKey) + { + return isset($this->aCurrentActionParams[$sKey]); + } + + /** + * @param string $sUrl + */ + public function Location($sUrl) + { + $this->Logger()->Write('Location: '.$sUrl); + @\header('Location: '.$sUrl); + } + + /** + * @param string $sTitle + * @param string $sDesc + * + * @return mixed + */ + public function ErrorTemplates($sTitle, $sDesc, $bShowBackLink = true) + { + return strtr(file_get_contents(APP_VERSION_ROOT_PATH.'app/templates/Error.html'), array( + '{{BaseWebStaticPath}}' => APP_WEB_STATIC_PATH, + '{{ErrorTitle}}' => $sTitle, + '{{ErrorHeader}}' => $sTitle, + '{{ErrorDesc}}' => $sDesc, + '{{BackLinkVisibility}}' => $bShowBackLink ? 'inline-block' : 'none', + '{{BackLink}}' => $this->StaticI18N('STATIC/BACK_LINK'), + '{{BackHref}}' => APP_SHORT_INDEX_FILE_NAME + )); + } + + /** + * @param object $oData + * @param string $sParent + * @param array $aParameters = array() + * + * @return array | false + */ + private function objectData($oData, $sParent, $aParameters = array()) + { + $mResult = false; + if (is_object($oData)) + { + $aNames = explode('\\', get_class($oData)); + $mResult = array( +// '@Action' => $sParent, + '@Object' => end($aNames) + ); + + if ($oData instanceof \MailSo\Base\Collection) + { + $mResult['@Object'] = 'Collection/'.$mResult['@Object']; + $mResult['@Count'] = $oData->Count(); + $mResult['@Collection'] = $this->responseObject($oData->GetAsArray(), $sParent, $aParameters); + } + else + { + $mResult['@Object'] = 'Object/'.$mResult['@Object']; + } + } + + return $mResult; + } + + /** + * @param string $sFolderFullName + * + * @return string + */ + private function hashFolderFullName($sFolderFullName) + { +// return \in_array(\strtolower($sFolderFullName), array('inbox', 'sent', 'send', 'drafts', 'spam', 'junk', 'bin', 'trash')) ? +// \ucfirst(\strtolower($sFolderFullName)) : +// \RainLoop\Utils::CustomBaseConvert(\sprintf('%u', \crc32(md5($sFolderFullName).$sFolderFullName)), '0123456789', +// '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'); + + return \in_array(\strtolower($sFolderFullName), array('inbox', 'sent', 'send', 'drafts', 'spam', 'junk', 'bin', 'trash')) ? + \ucfirst(\strtolower($sFolderFullName)) : \md5($sFolderFullName); + + return \preg_match('/^[a-zA-Z0-9]+$/', $sFolderFullName) ? $sFolderFullName : \md5($sFolderFullName); + return \preg_match('/^[a-zA-Z0-9]+$/', $sFolderFullName) ? $sFolderFullName : \rtrim(\base_convert(\md5($sFolderFullName), 16, 32), '0'); + return 'INBOX' === $sFolderFullName ? $sFolderFullName : \base_convert(\sprintf('%u', \crc32(\md5($sFolderFullName))), 10, 32); + } + + /** + * @return array + */ + public function GetLanguageAndTheme() + { + $oAccount = $this->GetAccount(); + $oSettings = $oAccount instanceof \RainLoop\Account ? $this->SettingsProvider()->Load($oAccount) : null; + + $sLanguage = $this->Config()->Get('webmail', 'language', 'en'); + $sTheme = $this->Config()->Get('webmail', 'theme', 'Default'); + + if ($oSettings instanceof \RainLoop\Settings) + { + $sLanguage = $oSettings->GetConf('Language', $sLanguage); + $sTheme = $oSettings->GetConf('Theme', $sTheme); + } + + $sLanguage = $this->ValidateLanguage($sLanguage); + $sTheme = $this->ValidateTheme($sTheme); + + return array($sLanguage, $sTheme); + } + + /** + * @param string $sKey + * + * @return string + */ + public function StaticI18N($sKey) + { + static $sLang = null; + static $aLang = null; + + if (null === $sLang) + { + $aList = $this->GetLanguageAndTheme(); + $sLang = $aList[0]; + } + + if (null === $aLang) + { + $aLang = array(); + \RainLoop\Utils::ReadAndAddLang(APP_VERSION_ROOT_PATH.'app/i18n/langs.ini', $aLang); + \RainLoop\Utils::ReadAndAddLang(APP_VERSION_ROOT_PATH.'langs/'.$sLang.'.ini', $aLang); + + $this->Plugins()->ReadLang($sLang, $aLang); + } + + return isset($aLang[$sKey]) ? $aLang[$sKey] : $sKey; + } + + /** + * @param mixed $mResponse + * @param string $sParent + * @param array $aParameters = array() + * + * @return mixed + */ + protected function responseObject($mResponse, $sParent = '', $aParameters = array()) + { + $mResult = $mResponse; + if (is_object($mResponse)) + { + $sClassName = get_class($mResponse); +// if ($mResponse instanceof \MailSo\Mail\Message) + if ('MailSo\Mail\Message' === $sClassName) + { + $oAccount = $this->getAccountFromToken(false); + + $mResult = array_merge($this->objectData($mResponse, $sParent, $aParameters), array( + 'Folder' => $mResponse->Folder(), + 'Uid' => (string) $mResponse->Uid(), + 'Subject' => \MailSo\Base\Utils::Utf8Clear($mResponse->Subject()), + 'MessageId' => $mResponse->MessageId(), + 'Size' => $mResponse->Size(), + 'DateTimeStampInUTC' => !!$this->Config()->Get('labs', 'date_from_headers', false) + ? $mResponse->HeaderTimeStampInUTC() : $mResponse->InternalTimeStampInUTC(), + 'ReplyTo' => $this->responseObject($mResponse->ReplyTo(), $sParent, $aParameters), + 'From' => $this->responseObject($mResponse->From(), $sParent, $aParameters), + 'To' => $this->responseObject($mResponse->To(), $sParent, $aParameters), + 'Cc' => $this->responseObject($mResponse->Cc(), $sParent, $aParameters), + 'Bcc' => $this->responseObject($mResponse->Bcc(), $sParent, $aParameters), + 'Sender' => $this->responseObject($mResponse->Sender(), $sParent, $aParameters), + 'Priority' => $mResponse->Priority(), + 'Threads' => $mResponse->Threads(), + 'ThreadsLen' => $mResponse->ThreadsLen(), + 'ParentThread' => $mResponse->ParentThread(), + 'Sensitivity' => $mResponse->Sensitivity() +// 'ReadingConfirmation' => $mResponse->ReadingConfirmation(), + )); + + $oAttachments = $mResponse->Attachments(); + $mResult['HasAttachments'] = $oAttachments && 0 < $oAttachments->Count(); + + $mResult['RequestHash'] = \RainLoop\Utils::EncodeKeyValues(array( + 'V' => APP_VERSION, + 'Account' => $oAccount ? md5($oAccount->Hash()) : '', + 'Folder' => $mResult['Folder'], + 'Uid' => $mResult['Uid'], + 'MimeType' => 'message/rfc822', + 'FileName' => $mResult['Subject'].'.eml' + )); + + // Flags + $aFlags = $mResponse->FlagsLowerCase(); + $mResult['IsSeen'] = in_array('\\seen', $aFlags); + $mResult['IsFlagged'] = in_array('\\flagged', $aFlags); + $mResult['IsAnswered'] = in_array('\\answered', $aFlags); + + $sForwardedFlag = $oAccount ? strtolower($oAccount->Domain()->ForwardFlag()) : ''; + $mResult['IsForwarded'] = 0 < strlen($sForwardedFlag) && in_array(strtolower($sForwardedFlag), $aFlags); + + if ('Message' === $sParent) + { + $oAttachments = $mResponse->Attachments(); + + $bHasExternals = false; + $aFoundedCIDs = array(); + + $mResult['DraftInfo'] = $mResponse->DraftInfo(); + $mResult['InReplyTo'] = $mResponse->InReplyTo(); + $mResult['References'] = $mResponse->References(); + $mResult['Html'] = \MailSo\Base\HtmlUtils::ClearHtml($mResponse->Html(), $bHasExternals, $aFoundedCIDs); + $mResult['Plain'] = \MailSo\Base\HtmlUtils::ConvertPlainToHtml($mResponse->Plain()); + + $mResult['HasExternals'] = $bHasExternals; + $mResult['HasInternals'] = \is_array($aFoundedCIDs) && 0 < \count($aFoundedCIDs); + $mResult['FoundedCIDs'] = $aFoundedCIDs; + $mResult['Attachments'] = $this->responseObject($oAttachments, $sParent, array_merge($aParameters, array( + 'FoundedCIDs' => $aFoundedCIDs + ))); + } + } +// else if ($mResponse instanceof \MailSo\Mime\Email) + else if ('MailSo\Mime\Email' === $sClassName) + { + $mResult = array_merge($this->objectData($mResponse, $sParent, $aParameters), array( + 'Name' => \MailSo\Base\Utils::Utf8Clear($mResponse->GetDisplayName()), + 'Email' => \MailSo\Base\Utils::Utf8Clear($mResponse->GetEmail()) + )); + } + else if ('RainLoop\Providers\Contacts\Classes\Contact' === $sClassName) + { + $mResult = array_merge($this->objectData($mResponse, $sParent, $aParameters), array( + 'IdContact' => $mResponse->IdContact, + 'ImageHash' => $mResponse->ImageHash, + 'ListName' => \MailSo\Base\Utils::Utf8Clear($mResponse->ListName), + 'Name' => \MailSo\Base\Utils::Utf8Clear($mResponse->Name), + 'Emails' => $mResponse->Emails + )); + } +// else if ($mResponse instanceof \RainLoop\Domain) + else if ('RainLoop\Domain' === $sClassName) + { + $mResult = array_merge($this->objectData($mResponse, $sParent, $aParameters), array( + 'Name' => $mResponse->Name(), + 'IncHost' => $mResponse->IncHost(), + 'IncPort' => $mResponse->IncPort(), + 'IncSecure' => $mResponse->IncSecure(), + 'OutHost' => $mResponse->OutHost(), + 'OutPort' => $mResponse->OutPort(), + 'OutSecure' => $mResponse->OutSecure(), + 'OutAuth' => $mResponse->OutAuth() + )); + } +// else if ($mResponse instanceof \MailSo\Mail\Attachment) + else if ('MailSo\Mail\Attachment' === $sClassName) + { + $oAccount = $this->getAccountFromToken(false); + + $aFoundedCIDs = isset($aParameters['FoundedCIDs']) && is_array($aParameters['FoundedCIDs']) + ? $aParameters['FoundedCIDs'] : array(); + + $mResult = array_merge($this->objectData($mResponse, $sParent, $aParameters), array( + 'Folder' => $mResponse->Folder(), + 'Uid' => (string) $mResponse->Uid(), + 'MimeIndex' => (string) $mResponse->MimeIndex(), + 'MimeType' => $mResponse->MimeType(), + 'FileName' => $mResponse->FileName(true), + 'EstimatedSize' => $mResponse->EstimatedSize(), + 'CID' => $mResponse->Cid(), + 'IsInline' => $mResponse->IsInline(), + 'IsLinked' => in_array(trim(trim($mResponse->Cid()), '<>'), $aFoundedCIDs) + )); + + $mResult['Download'] = \RainLoop\Utils::EncodeKeyValues(array( + 'V' => APP_VERSION, + 'Account' => $oAccount ? md5($oAccount->Hash()) : '', + 'Folder' => $mResult['Folder'], + 'Uid' => $mResult['Uid'], + 'MimeIndex' => $mResult['MimeIndex'], + 'MimeType' => $mResult['MimeType'], + 'FileName' => $mResult['FileName'] + )); + } +// else if ($mResponse instanceof \MailSo\Mail\Folder) + else if ('MailSo\Mail\Folder' === $sClassName) + { + $bIgnoreFolderSubscribe = (bool) $this->Config()->Get('labs', 'ignore_folders_subscription', false); + + $aExtended = null; + $mStatus = $mResponse->Status(); + if (is_array($mStatus) && isset($mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT'])) + { + $aExtended = array( + 'MessageCount' => (int) $mStatus['MESSAGES'], + 'MessageUnseenCount' => (int) $mStatus['UNSEEN'], + 'UidNext' => (string) $mStatus['UIDNEXT'], + 'Hash' => \MailSo\Mail\MailClient::GenerateHash( + $mResponse->FullNameRaw(), $mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT']) + ); + } + + $mResult = array_merge($this->objectData($mResponse, $sParent, $aParameters), array( + 'Name' => $mResponse->Name(), + 'FullName' => $mResponse->FullName(), + 'FullNameRaw' => $mResponse->FullNameRaw(), + 'FullNameHash' => $this->hashFolderFullName($mResponse->FullNameRaw(), $mResponse->FullName()), + 'Delimiter' => (string) $mResponse->Delimiter(), + 'HasVisibleSubFolders' => $mResponse->HasVisibleSubFolders(), + 'IsSubscribed' => $bIgnoreFolderSubscribe ? true : $mResponse->IsSubscribed(), + 'IsExisten' => $mResponse->IsExisten(), + 'IsSelectable' => $mResponse->IsSelectable(), + 'Flags' => $mResponse->FlagsLowerCase(), + 'Extended' => $aExtended, + 'SubFolders' => $this->responseObject($mResponse->SubFolders(), $sParent, $aParameters) + )); + } +// else if ($mResponse instanceof \MailSo\Mail\MessageCollection) + else if ('MailSo\Mail\MessageCollection' === $sClassName) + { + $mResult = array_merge($this->objectData($mResponse, $sParent, $aParameters), array( + 'MessageCount' => $mResponse->MessageCount, + 'MessageUnseenCount' => $mResponse->MessageUnseenCount, + 'MessageResultCount' => $mResponse->MessageResultCount, + 'Folder' => $mResponse->FolderName, + 'FolderHash' => $mResponse->FolderHash, + 'UidNext' => $mResponse->UidNext, + 'NewMessages' => $this->responseObject($mResponse->NewMessages), + 'LastCollapsedThreadUids' => $mResponse->LastCollapsedThreadUids, + 'Offset' => $mResponse->Offset, + 'Limit' => $mResponse->Limit, + 'Search' => $mResponse->Search + )); + } +// else if ($mResponse instanceof \MailSo\Mail\AttachmentCollection) + else if ('MailSo\Mail\AttachmentCollection' === $sClassName) + { + $mResult = array_merge($this->objectData($mResponse, $sParent, $aParameters), array( + 'InlineCount' => $mResponse->InlineCount() + )); + } +// else if ($mResponse instanceof \MailSo\Mail\FolderCollection) + else if ('MailSo\Mail\FolderCollection' === $sClassName) + { + $mResult = array_merge($this->objectData($mResponse, $sParent, $aParameters), array( + 'Namespace' => $mResponse->GetNamespace(), + 'FoldersHash' => isset($mResponse->FoldersHash) ? $mResponse->FoldersHash : '' + )); + } + else if ($mResponse instanceof \MailSo\Base\Collection) + { + $aList =& $mResponse->GetAsArray(); + $mResult = $this->responseObject($aList, $sParent, $aParameters); + } + else + { + $mResult = '['.get_class($mResponse).']'; + } + } + else if (is_array($mResponse)) + { + foreach ($mResponse as $iKey => $oItem) + { + $mResponse[$iKey] = $this->responseObject($oItem, $sParent, $aParameters); + } + + $mResult = $mResponse; + } + + unset($mResponse); + return $mResult; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Config/AbstractConfig.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Config/AbstractConfig.php new file mode 100644 index 000000000..143aa231e --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Config/AbstractConfig.php @@ -0,0 +1,198 @@ +sFile = \APP_PRIVATE_DATA.'configs/'.$sFileName; + $this->sFilePrefix = $sFilePrefix; + $this->aData = $this->defaultValues(); + } + + /** + * @return array + */ + protected abstract function defaultValues(); + + /** + * @return bool + */ + public function IsInited() + { + return is_array($this->aData) && 0 < count($this->aData); + } + + /** + * @param string $sSection + * @param string $sName + * @param mixed $mDefault = null + * + * @return mixed + */ + public function Get($sSection, $sName, $mDefault = null) + { + $mResult = $mDefault; + if (isset($this->aData[$sSection][$sName][0])) + { + $mResult = $this->aData[$sSection][$sName][0]; + } + return $mResult; + } + + /** + * @param string $sSectionKey + * @param string $sParamKey + * @param mixed $mParamValue + * + * @return void + */ + public function Set($sSectionKey, $sParamKey, $mParamValue) + { + if (isset($this->aData[$sSectionKey][$sParamKey][0])) + { + $sType = gettype($this->aData[$sSectionKey][$sParamKey][0]); + switch ($sType) + { + default: + case 'string': + $this->aData[$sSectionKey][$sParamKey][0] = (string) $mParamValue; + break; + case 'int': + case 'integer': + $this->aData[$sSectionKey][$sParamKey][0] = (int) $mParamValue; + break; + case 'bool': + case 'boolean': + $this->aData[$sSectionKey][$sParamKey][0] = (bool) $mParamValue; + break; + } + } + else if ('custom' === $sSectionKey) + { + $this->aData[$sSectionKey][$sParamKey] = array((string) $mParamValue); + } + } + + /** + * @return bool + */ + public function Load() + { + if (\file_exists($this->sFile) && \is_readable($this->sFile)) + { + $aData = @\parse_ini_file($this->sFile, true); + if (\is_array($aData) && 0 < count($aData)) + { + foreach ($aData as $sSectionKey => $aSectionValue) + { + if (\is_array($aSectionValue)) + { + foreach ($aSectionValue as $sParamKey => $mParamValue) + { + $this->Set($sSectionKey, $sParamKey, $mParamValue); + } + } + } + + return true; + } + } + + return false; + } + + /** + * @return bool + */ + public function Save() + { + if (\file_exists($this->sFile) && !\is_writable($this->sFile)) + { + return false; + } + + $sNewLine = "\n"; + + $aResultLines = array(); + + foreach ($this->aData as $sSectionKey => $aSectionValue) + { + if (\is_array($aSectionValue)) + { + $aResultLines[] = ''; + $aResultLines[] = '['.$sSectionKey.']'; + $bFirst = true; + + foreach ($aSectionValue as $sParamKey => $mParamValue) + { + if (\is_array($mParamValue)) + { + if (!empty($mParamValue[1])) + { + $sDesk = \str_replace("\r", '', $mParamValue[1]); + $aDesk = \explode("\n", $sDesk); + $aDesk = \array_map(function (&$sLine) { + return '; '.$sLine; + }, $aDesk); + + if (!$bFirst) + { + $aResultLines[] = ''; + } + + $aResultLines[] = \implode($sNewLine, $aDesk); + } + + $bFirst = false; + + $sValue = '""'; + switch (\gettype($mParamValue[0])) + { + default: + case 'string': + $sValue = '"'.$mParamValue[0].'"'; + break; + case 'int': + case 'integer': + $sValue = $mParamValue[0]; + break; + case 'bool': + case 'boolean': + $sValue = $mParamValue[0] ? 'On' : 'Off'; + break; + } + + $aResultLines[] = $sParamKey.' = '.$sValue; + } + } + } + } + + return false !== \file_put_contents($this->sFile, + (0 < \strlen($this->sFilePrefix) ? $this->sFilePrefix : ''). + $sNewLine.\implode($sNewLine, $aResultLines)); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Config/Application.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Config/Application.php new file mode 100644 index 000000000..d2e3b2952 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Config/Application.php @@ -0,0 +1,209 @@ +Set('security', 'admin_password', \md5(APP_SALT.$sPassword.APP_SALT)); + } + + /** + * @param string $sPassword + * + * @return bool + */ + public function ValidatePassword($sPassword) + { + $sPassword = (string) $sPassword; + $sConfigPassword = (string) $this->Get('security', 'admin_password', ''); + + return 0 < \strlen($sPassword) && + ($sPassword === $sConfigPassword || \md5(APP_SALT.$sPassword.APP_SALT) === $sConfigPassword); + } + + /** + * @return bool + */ + public function Save() + { + $this->Set('version', 'current', APP_VERSION); + $this->Set('version', 'saved', \gmdate('r')); + + return parent::Save(); + } + + /** + * @return array + */ + protected function defaultValues() + { + return array( + 'webmail' => array( + + 'title' => array('RainLoop Webmail', 'Text displayed as page title'), + + 'theme' => array('Default', 'Theme used by default'), + + 'allow_custom_theme' => array(true, ''), + + 'language' => array('ru', 'Language used by default'), + + 'allow_additional_accounts' => array(true, ''), + + 'use_preview_pane' => array(true, 'Whether message preview pane should be used'), + + 'messages_per_page' => array(20, ' Number of messages displayed on page by default'), + + 'editor_default_type' => array('Html', 'Editor mode used by default (Html or Plain)'), + + 'attachment_size_limit' => array(5, + 'File size limit (MB) for file upload on compose screen +0 for unlimited.') + ), + + 'security' => array( + 'csrf_protection' => array(true, + 'Enable CSRF protection (http://en.wikipedia.org/wiki/Cross-site_request_forgery)'), + + 'custom_server_signature' => array('RainLoop'), + 'admin_login' => array('admin', 'Login and password for web admin panel'), + 'admin_password' => array('12345') + ), + + 'login' => array( + + 'allow_custom_login' => array(false, + 'Enable additional Login field on webmail login screen'), + + 'sign_me_auto' => array(\RainLoop\Enumerations\SignMeType::DEFAILT_OFF, + 'This option allows webmail to remember the logged in user +once they closed the browser window. + +Values: + "DefaultOff" - can be used, disabled by default; + "DefaultOn" - can be used, enabled by default; + "Unused" - cannot be used') + ), + + 'plugins' => array( + 'enable' => array(false, 'Enable plugin support'), + 'enabled_list' => array('', 'List of enabled plugins'), + ), + + 'logs' => array( + + 'enable' => array(true, 'Enable logging'), + + 'write_on_error_only' => array(true, 'Logs entire request only if error occured'), + + 'filename' => array('log-{date:Y-m-d}.txt', + 'Log filename. +For security reasons, some characters are removed from filename. +Allows for pattern-based folder creation (see examples below). + +Patterns: + {date:Y-m-d} - Replaced by pattern-based date + Detailed info: http://www.php.net/manual/en/function.date.php + {user:email} - Replaced by user\'s email address + If user is not logged in, value is set to "unknown" + {user:login} - Replaced by user\'s login + If user is not logged in, value is set to "unknown" + {user:domain} - Replaced by user\'s domain name + If user is not logged in, value is set to "unknown" + {user:uid} - Replaced by user\'s UID regardless of account currently used + +Examples: + filename = "log-{date:Y-m-d}.txt" + filename = "{date:Y-m-d}/{user:domain}/{user:email}_{user:uid}.log" + filename = "{user:email}-{date:Y-m-d}.txt"') + ), + + 'debug' => array( + 'enable' => array(false, 'Special option required for development purposes'), + ), + + 'version' => array( + 'current' => array(''), + 'saved' => array('') + ), + + 'social' => array( + 'google_enable' => array(false, 'Google'), + 'google_client_id' => array(''), + 'google_client_secret' => array(''), + + 'fb_enable' => array(false, 'Facebook'), + 'fb_app_id' => array(''), + 'fb_app_secret' => array(''), + + 'twitter_enable' => array(false, 'Twitter'), + 'twitter_consumer_key' => array(''), + 'twitter_consumer_secret' => array(''), + + 'dropbox_enable' => array(false, 'Dropbox'), + 'dropbox_api_key' => array(''), + ), + + 'cache' => array( + 'enable' => array(true, + 'The section controls caching of the entire application. + +Enables caching in the system'), + + 'index' => array('v1', 'Additional caching key. If changed, cache is purged'), + + 'fast_cache_driver' => array('files', 'Can be: files, APC, memcache'), + 'fast_cache_index' => array('v1', 'Additional caching key. If changed, fast cache is purged'), + + 'http' => array(true, 'Browser-level cache. If enabled, caching is maintainted without using files'), + 'server_uids' => array(false, 'Caching message UIDs when searching and sorting (threading)') + ), + + 'labs' => array( + 'ignore_folders_subscription' => array(false, + 'Experimental settings. Handle with care. +'), + 'allow_message_append' => array(false), + 'date_from_headers' => array(false), + 'cache_system_data' => array(true), + 'use_app_debug_js' => array(false), + 'login_fault_delay' => array(1), + 'log_ajax_response_write_limit' => array(300), + 'suggestions_limit' => array(50), + 'use_imap_sort' => array(false), + 'use_imap_list_status' => array(false), + 'use_imap_thread' => array(true), + 'use_imap_move' => array(true), + 'custom_repo' => array(''), + 'additional_repo' => array(''), + 'cdn_static_domain' => array(''), + 'in_iframe' => array(false), + 'custom_logout_link' => array(''), + 'allow_external_login' => array(false), + 'fast_cache_memcache_host' => array('127.0.0.1'), + 'fast_cache_memcache_port' => array(11211), + 'fast_cache_memcache_expire' => array(43200), + 'dev_email' => array(''), + 'dev_login' => array(''), + 'dev_password' => array('') + ) + ); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Config/Plugin.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Config/Plugin.php new file mode 100644 index 000000000..cd4605b37 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Config/Plugin.php @@ -0,0 +1,59 @@ +aMap = is_array($aMap) ? $this->convertConfigMap($aMap) : array(); + + parent::__construct('plugin-'.$sPluginName.'.ini', '; RainLoop Webmail plugin ('.$sPluginName.')'); + } + + /** + * @param array $aMap + * @return array + */ + private function convertConfigMap($aMap) + { + if (0 < count($aMap)) + { + $aResultMap = array(); + foreach ($aMap as /* @var $oProperty \RainLoop\Plugins\Property */ $oProperty) + { + if ($oProperty) + { + $mValue = $oProperty->DefaultValue(); + $sValue = is_array($mValue) && isset($mValue[0]) ? $mValue[0] : $mValue; + $aResultMap[$oProperty->Name()] = array($sValue, ''); + } + } + + if (0 < count($aResultMap)) + { + return array( + 'plugin' => $aResultMap + ); + } + } + + return array(); + } + + /** + * @return array + */ + protected function defaultValues() + { + return $this->aMap; + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Domain.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Domain.php new file mode 100644 index 000000000..cfe495825 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Domain.php @@ -0,0 +1,336 @@ +sName = $sName; + $this->sIncHost = $sIncHost; + $this->iIncPort = $iIncPort; + $this->iIncSecure = $iIncSecure; + $this->sOutHost = $sOutHost; + $this->iOutPort = $iOutPort; + $this->iOutSecure = $iOutSecure; + $this->bOutAuth = $bOutAuth; + $this->sForwardFlag = $sForwardFlag; + $this->bDisabled = false; + } + + /** + * @param string $sName + * @param string $sIncHost + * @param number $iIncPort + * @param number $iIncSecure + * @param string $sOutHost + * @param number $iOutPort + * @param number $iOutSecure + * @param bool $bOutAuth + * @param string $sForwardFlag = \RainLoop\Domain::DEFAULT_FORWARDED_FLAG + * + * @return \RainLoop\Domain + */ + public static function NewInstance($sName, $sIncHost, $iIncPort, $iIncSecure, + $sOutHost, $iOutPort, $iOutSecure, $bOutAuth, $sForwardFlag = \RainLoop\Domain::DEFAULT_FORWARDED_FLAG) + { + return new self( + $sName, + $sIncHost, $iIncPort, $iIncSecure, + $sOutHost, $iOutPort, $iOutSecure, $bOutAuth, $sForwardFlag); + } + + /** + * @param array $aDomain + * + * @return \RainLoop\Domain | null + */ + public static function NewInstanceFromDomainConfigArray($sName, $aDomain) + { + $oDomain = null; + + if (0 < strlen($sName) && is_array($aDomain) && !empty($aDomain['imap_host']) && !empty($aDomain['imap_port']) && + !empty($aDomain['smpt_host']) && !empty($aDomain['smpt_port'])) + { + $sIncHost = (string) $aDomain['imap_host']; + $iIncPort = (int) $aDomain['imap_port']; + $iIncSecure = self::StrConnectionSecurityTypeToCons( + !empty($aDomain['imap_secure']) ? $aDomain['imap_secure'] : ''); + + $sOutHost = (string) $aDomain['smpt_host']; + $iOutPort = (int) $aDomain['smpt_port']; + $iOutSecure = self::StrConnectionSecurityTypeToCons( + !empty($aDomain['smpt_secure']) ? $aDomain['smpt_secure'] : ''); + + $bOutAuth = isset($aDomain['smpt_auth']) ? (bool) $aDomain['smpt_auth'] : true; + $sForwardFlag = isset($aDomain['imap_custom_forward_flag']) ? + (string) $aDomain['imap_custom_forward_flag'] : ''; + + if (!empty($sForwardFlag)) + { + $oDomain = self::NewInstance( + $sName, + $sIncHost, $iIncPort, $iIncSecure, + $sOutHost, $iOutPort, $iOutSecure, $bOutAuth, $sForwardFlag); + } + else + { + $oDomain = self::NewInstance( + $sName, + $sIncHost, $iIncPort, $iIncSecure, + $sOutHost, $iOutPort, $iOutSecure, $bOutAuth); + } + + } + + return $oDomain; + } + + /** + * @param string $sStr + * + * @return string + */ + private function encodeIniString($sStr) + { + return str_replace('"', '\\"', $sStr); + } + + /** + * @param bool0 $bDisabled + */ + public function SetDisabled($bDisabled) + { + $this->bDisabled = (bool) $bDisabled; + } + + /** + * @return string + */ + public function ToIniString() + { + return implode("\n", array( + 'imap_host = "'.$this->encodeIniString($this->sIncHost).'"', + 'imap_port = '.$this->iIncPort, + 'imap_secure = "'.self::ConstConnectionSecurityTypeToStr($this->iIncSecure).'"', + 'smpt_host = "'.$this->encodeIniString($this->sOutHost).'"', + 'smpt_port = '.$this->iOutPort, + 'smpt_secure = "'.self::ConstConnectionSecurityTypeToStr($this->iOutSecure).'"', + 'smpt_auth = '.($this->bOutAuth ? 'On' : 'Off') + )); + } + + /** + * @param string $sType + * + * @return int + */ + public static function StrConnectionSecurityTypeToCons($sType) + { + $iSecurityType = ConnectionSecurityType::NONE; + switch (strtoupper($sType)) + { + case 'SSL': + $iSecurityType = ConnectionSecurityType::SSL; + break; + case 'TLS': + $iSecurityType = ConnectionSecurityType::STARTTLS; + break; + } + return $iSecurityType; + } + + /** + * @param int $iSecurityType + * + * @return string + */ + public static function ConstConnectionSecurityTypeToStr($iSecurityType) + { + $sType = 'None'; + switch ($iSecurityType) + { + case ConnectionSecurityType::SSL: + $sType = 'SSL'; + break; + case ConnectionSecurityType::STARTTLS: + $sType = 'TLS'; + break; + } + + return $sType; + } + + /** + * @param string $sIncHost + * @param int $iIncPort + * @param int $iIncSecure + * @param string $sOutHost + * @param int $iOutPort + * @param int $iOutSecure + * @param bool $bOutAuth + * @param string $sForwardFlag = \RainLoop\Domain::DEFAULT_FORWARDED_FLAG + * + * @return \RainLoop\Domain + */ + public function UpdateInstance($sIncHost, $iIncPort, $iIncSecure, + $sOutHost, $iOutPort, $iOutSecure, $bOutAuth, $sForwardFlag = \RainLoop\Domain::DEFAULT_FORWARDED_FLAG) + { + $this->sIncHost = $sIncHost; + $this->iIncPort = $iIncPort; + $this->iIncSecure = $iIncSecure; + $this->sOutHost = $sOutHost; + $this->iOutPort = $iOutPort; + $this->iOutSecure = $iOutSecure; + $this->bOutAuth = $bOutAuth; + $this->sForwardFlag = $sForwardFlag; + + return $this; + } + + /** + * @return string + */ + public function Name() + { + return $this->sName; + } + + /** + * @return string + */ + public function IncHost() + { + return $this->sIncHost; + } + + /** + * @return int + */ + public function IncPort() + { + return $this->iIncPort; + } + + /** + * @return int + */ + public function IncSecure() + { + return $this->iIncSecure; + } + + /** + * @return string + */ + public function OutHost() + { + return $this->sOutHost; + } + + /** + * @return int + */ + public function OutPort() + { + return $this->iOutPort; + } + + /** + * @return int + */ + public function OutSecure() + { + return $this->iOutSecure; + } + + /** + * @return bool + */ + public function OutAuth() + { + return $this->bOutAuth; + } + + /** + * @return string + */ + public function ForwardFlag() + { + return $this->sForwardFlag; + } + + /** + * @return bool + */ + public function Disabled() + { + return $this->bDisabled; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Enumerations/CustomThemeType.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Enumerations/CustomThemeType.php new file mode 100644 index 000000000..4b3445dc2 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Enumerations/CustomThemeType.php @@ -0,0 +1,9 @@ + 'InvalidToken', + self::AuthError => 'AuthError', + self::AccessError => 'AccessError', + self::ConnectionError => 'ConnectionError', + self::CaptchaError => 'CaptchaError', + self::SocialFacebookLoginAccessDisable => 'SocialFacebookLoginAccessDisable', + self::SocialTwitterLoginAccessDisable => 'SocialTwitterLoginAccessDisable', + self::SocialGoogleLoginAccessDisable => 'SocialGoogleLoginAccessDisable', + self::CantGetMessageList => 'CantGetMessageList', + self::CantGetMessage => 'CantGetMessage', + self::CantDeleteMessage => 'CantDeleteMessage', + self::CantMoveMessage => 'CantMoveMessage', + self::CantSaveMessage => 'CantSaveMessage', + self::CantSendMessage => 'CantSendMessage', + self::InvalidRecipients => 'InvalidRecipients', + self::CantCreateFolder => 'CantCreateFolder', + self::CantRenameFolder => 'CantRenameFolder', + self::CantDeleteFolder => 'CantDeleteFolder', + self::CantSubscribeFolder => 'CantSubscribeFolder', + self::CantUnsubscribeFolder => 'CantUnsubscribeFolder', + self::CantDeleteNonEmptyFolder => 'CantDeleteNonEmptyFolder', + self::CantSaveSettings => 'CantSaveSettings', + self::CantSavePluginSettings => 'CantSavePluginSettings', + self::DomainAlreadyExists => 'DomainAlreadyExists', + self::CantInstallPackage => 'CantInstallPackage', + self::CantDeletePackage => 'CantDeletePackage', + self::InvalidPluginPackage => 'InvalidPluginPackage', + self::UnsupportedPluginPackage => 'UnsupportedPluginPackage', + self::AccountAlreadyExists => 'AccountAlreadyExists', + self::MailServerError => 'MailServerError', + self::UnknownError => 'UnknownError' + ); + + return isset($aMap[$iCode]) ? $aMap[$iCode].'['.$iCode.']' : 'UnknownNotification['.$iCode.']'; + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Plugins/AbstractPlugin.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Plugins/AbstractPlugin.php new file mode 100644 index 000000000..9db3fdf3e --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Plugins/AbstractPlugin.php @@ -0,0 +1,317 @@ +sName = ''; + $this->sPath = ''; + $this->aConfigMap = null; + + $this->oPluginManager = null; + $this->oPluginConfig = null; + $this->bPluginConfigLoaded = false; + $this->bLangs = false; + } + + /** + * @return \RainLoop\Config\Plugin + */ + public function Config() + { + if (!$this->bPluginConfigLoaded && $this->oPluginConfig) + { + $this->bPluginConfigLoaded = true; + if ($this->oPluginConfig->IsInited()) + { + if (!$this->oPluginConfig->Load()) + { + $this->oPluginConfig->Save(); + } + } + } + + return $this->oPluginConfig; + } + + /** + * @return \RainLoop\Plugins\Manager + */ + public function Manager() + { + return $this->oPluginManager; + } + + /** + * @return string + */ + public function Path() + { + return $this->sPath; + } + + /** + * @return string + */ + public function Name() + { + return $this->sName; + } + + /** + * @param bool | null $bLangs = null + * @return bool + */ + public function UseLangs($bLangs = null) + { + if (null !== $bLangs) + { + $this->bLangs = (bool) $bLangs; + } + + return $this->bLangs; + } + + /** + * @return array + */ + protected function configMapping() + { + return array(); + } + + /** + * @return string + */ + public function Hash() + { + return ''; + } + + /** + * @return string + */ + public function Supported() + { + return ''; + } + + /** + * @final + * @return array + */ + final public function ConfigMap() + { + if (null === $this->aConfigMap) + { + $this->aConfigMap = $this->configMapping(); + if (!is_array($this->aConfigMap)) + { + $this->aConfigMap = array(); + } + } + + return $this->aConfigMap; + } + + /** + * @param string $sPath + * @param string $sName + * + * @return self + */ + public function SetValues($sPath, $sName) + { + $this->sName = $sName; + $this->sPath = $sPath; + + return $this; + } + + /** + * @param \RainLoop\Plugins\Manager $oPluginManager + * + * @return self + */ + public function SetPluginManager(\RainLoop\Plugins\Manager $oPluginManager) + { + $this->oPluginManager = $oPluginManager; + + return $this; + } + + /** + * @param \RainLoop\Config\Plugin $oPluginConfig + * + * @return self + */ + public function SetPluginConfig(\RainLoop\Config\Plugin $oPluginConfig) + { + $this->oPluginConfig = $oPluginConfig; + + return $this; + } + + /** + * @return void + */ + public function PreInit() + { + + } + + /** + * @return void + */ + public function Init() + { + + } + + /** + * @param bool $bAdmin + * @param bool $bAuth + * @param array $aConfig + * + * @return void + */ + public function FilterAppDataPluginSection($bAdmin, $bAuth, &$aConfig) + { + + } + + /** + * @param string $sHookName + * @param string $sFunctionName + * + * @return self + */ + protected function addHook($sHookName, $sFunctionName) + { + if ($this->oPluginManager) + { + $this->oPluginManager->AddHook($sHookName, array(&$this, $sFunctionName)); + } + + return $this; + } + + /** + * @param string $sFile + * @param bool $bAdminScope = false + * + * @return self + */ + protected function addJs($sFile, $bAdminScope = false) + { + if ($this->oPluginManager) + { + $this->oPluginManager->AddJs($this->sPath.'/'.$sFile, $bAdminScope); + } + + return $this; + } + + /** + * @param string $sFile + * @param bool $bAdminScope = false + * + * @return self + */ + protected function addTemplate($sFile, $bAdminScope = false) + { + if ($this->oPluginManager) + { + $this->oPluginManager->AddTemplate($this->sPath.'/'.$sFile, $bAdminScope); + } + + return $this; + } + + /** + * @param string $sActionName + * @param string $sFunctionName + * + * @return self + */ + protected function addPartHook($sActionName, $sFunctionName) + { + if ($this->oPluginManager) + { + $this->oPluginManager->AddAdditionalPartAction($sActionName, array(&$this, $sFunctionName)); + } + + return $this; + } + + /** + * @param string $sActionName + * @param string $sFunctionName + * + * @return self + */ + protected function addAjaxHook($sActionName, $sFunctionName) + { + if ($this->oPluginManager) + { + $this->oPluginManager->AddAdditionalAjaxAction($sActionName, array(&$this, $sFunctionName)); + } + + return $this; + } + + /** + * @param string $sName + * @param string $sPlace + * @param string $sHtml + * @param bool $bPrepend = false + * + * @return self + */ + protected function processTemplate($sName, $sPlace, $sHtml, $bPrepend = false) + { + if ($this->oPluginManager) + { + $this->oPluginManager->AddProcessTemplateAction($sName, $sPlace, $sHtml, $bPrepend); + } + + return $this; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Plugins/Manager.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Plugins/Manager.php new file mode 100644 index 000000000..9c0755e1f --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Plugins/Manager.php @@ -0,0 +1,642 @@ +oLogger = null; + $this->oActions = $oActions; + $this->aPlugins = array(); + + $this->aHooks = array(); + $this->aJs = array(); + $this->aAdminJs = array(); + $this->aTemplates = array(); + $this->aAdminTemplates = array(); + + $this->aAjaxFilters = array(); + $this->aAdditionalAjax = array(); + $this->aProcessTemplate = array(); + + $this->bIsEnabled = (bool) $this->oActions->Config()->Get('plugins', 'enable', false); + if ($this->bIsEnabled) + { + $sList = \strtolower($this->oActions->Config()->Get('plugins', 'enabled_list', '')); + if (0 < \strlen($sList)) + { + $aList = \explode(',', $sList); + $aList = \array_map('trim', $aList); + + foreach ($aList as $sName) + { + if (0 < \strlen($sName)) + { + $oPlugin = $this->CreatePluginByName($sName); + if ($oPlugin) + { + $oPlugin->PreInit(); + $oPlugin->Init(); + + $this->aPlugins[] = $oPlugin; + } + } + } + } + } + } + + /** + * @param string $sName + * + * @return \RainLoop\Plugins\AbstractPlugin | null + */ + public function CreatePluginByName($sName) + { + $oPlugin = null; + if (preg_match('/^[a-z0-9\-]+$/', $sName) && + file_exists(APP_PLUGINS_PATH.$sName.'/index.php')) + { + $sClassName = $this->convertPluginFolderNameToClassName($sName); + + if (!class_exists($sClassName)) + { + include APP_PLUGINS_PATH.$sName.'/index.php'; + } + + if (class_exists($sClassName)) + { + $oPlugin = new $sClassName(); + if ($oPlugin instanceof \RainLoop\Plugins\AbstractPlugin) + { + $oPlugin + ->SetValues(APP_PLUGINS_PATH.$sName, $sName) + ->SetPluginManager($this) + ->SetPluginConfig(new \RainLoop\Config\Plugin($sName, $oPlugin->ConfigMap())) + ; + } + else + { + $oPlugin = null; + } + } + } + + return $oPlugin; + } + + /** + * @return array + */ + public function InstalledPlugins() + { + $aList = array(); + + foreach (glob(APP_PLUGINS_PATH.'*', GLOB_ONLYDIR|GLOB_NOSORT) as $sPathName) + { + $sName = basename($sPathName); + if (preg_match('/^[a-z0-9\-]+$/', $sName) && + file_exists($sPathName.'/index.php')) + { + $sVersion = @file_get_contents($sPathName.'/VERSION'); + $aList[] = array( + $sName, $sVersion + ); + } + } + + return $aList; + } + + /** + * @param string $sFolderName + * + * @return string + */ + private function convertPluginFolderNameToClassName($sFolderName) + { + $aParts = array_map('ucfirst', array_map('strtolower', + explode(' ', preg_replace('/[^a-z0-9]+/', ' ', $sFolderName)))); + + return implode($aParts).'Plugin'; + } + + /** + * @return \RainLoop\Actions + */ + public function Actions() + { + return $this->oActions; + } + + /** + * @return \RainLoop\Actions + */ + public function Hash() + { + $sResult = \md5(APP_VERSION); + foreach ($this->aPlugins as $oPlugin) + { + $sResult = \md5($sResult.$oPlugin->Path().$oPlugin->Hash()); + } + + return $sResult; + } + + /** + * @param bool $bAdminScope = false + * + * @return string + */ + public function CompileJs($bAdminScope = false) + { + $aResult = array(); + if ($this->bIsEnabled) + { + $aJs = $bAdminScope ? $this->aAdminJs : $this->aJs; + foreach ($aJs as $sFile) + { + if (file_exists($sFile)) + { + $aResult[] = file_get_contents($sFile); + } + } + } + + return implode("\n", $aResult); + } + + /** + * @todo + * @param bool $bAdminScope = false + * + * @return string + */ + public function CompileCss($bAdminScope = false) + { + return ''; + } + + /** + * @param bool $bAdminScope = false + * @return string + */ + public function CompileTemplate($bAdminScope = false) + { + $sResult = ''; + if ($this->bIsEnabled) + { + $aTemplates = $bAdminScope ? $this->aAdminTemplates : $this->aTemplates; + foreach ($aTemplates as $sFile) + { + if (file_exists($sFile)) + { + $sTemplateName = substr(basename($sFile), 0, -5); + $sResult .= ''; + } + } + } + + return $sResult; + } + + /** + * @param bool $bAdmin + * @param array $aAppData + * + * @return \RainLoop\Plugins\Manager + */ + public function InitAppData($bAdmin, &$aAppData) + { + if ($this->bIsEnabled && isset($aAppData['Plugins']) && is_array($aAppData['Plugins'])) + { + $bAuth = isset($aAppData['Auth']) && !!$aAppData['Auth']; + foreach ($this->aPlugins as $oPlugin) + { + if ($oPlugin) + { + $aConfig = array(); + $aMap = $oPlugin->ConfigMap(); + if (\is_array($aMap)) + { + foreach ($aMap as /* @var $oPluginProperty \RainLoop\Plugins\Property */$oPluginProperty) + { + if ($oPluginProperty && $oPluginProperty->AllowedInJs()) + { + $aConfig[$oPluginProperty->Name()] = + $oPlugin->Config()->Get('plugin', + $oPluginProperty->Name(), + $oPluginProperty->DefaultValue()); + } + } + } + + $oPlugin->FilterAppDataPluginSection($bAdmin, $bAuth, $aConfig); + + if (0 < \count($aConfig)) + { + $aAppData['Plugins'][$oPlugin->Name()] = $aConfig; + } + } + } + + $this->RunHook('filter.app-data', array($bAdmin, &$aAppData)); + } + + return $this; + } + + /** + * @param string $sHookName + * @param mixed $mCallbak + * + * @return \RainLoop\Plugins\Manager + */ + public function AddHook($sHookName, $mCallbak) + { + if ($this->bIsEnabled && is_callable($mCallbak)) + { + if (!isset($this->aHooks[$sHookName])) + { + $this->aHooks[$sHookName] = array(); + } + + $this->aHooks[$sHookName][] = $mCallbak; + } + + return $this; + } + + /** + * @param string $sHookName + * @param bool $bAdminScope = false + * + * @return \RainLoop\Plugins\Manager + */ + public function AddJs($sFile, $bAdminScope = false) + { + if ($this->bIsEnabled) + { + if ($bAdminScope) + { + $this->aAdminJs[$sFile] = $sFile; + } + else + { + $this->aJs[$sFile] = $sFile; + } + } + + return $this; + } + + /** + * @param string $sHookName + * @param bool $bAdminScope = false + * + * @return \RainLoop\Plugins\Manager + */ + public function AddTemplate($sFile, $bAdminScope = false) + { + if ($this->bIsEnabled) + { + if ($bAdminScope) + { + $this->aAdminTemplates[$sFile] = $sFile; + } + else + { + $this->aTemplates[$sFile] = $sFile; + } + } + + return $this; + } + + /** + * @param string $sHookName + * @param array $aArg = array() + * @param bool $bLogHook = true + * + * @return \RainLoop\Plugins\Manager + */ + public function RunHook($sHookName, $aArg = array(), $bLogHook = true) + { + if ($this->bIsEnabled) + { + if (isset($this->aHooks[$sHookName])) + { + if ($bLogHook) + { + $this->WriteLog('Hook: '.$sHookName, \MailSo\Log\Enumerations\Type::NOTE); + } + + foreach ($this->aHooks[$sHookName] as $mCallbak) + { + call_user_func_array($mCallbak, $aArg); + } + } + } + + return $this; + } + + /** + * @param string $sActionName + * @param mixed $mCallbak + * + * @return \RainLoop\Plugins\Manager + */ + public function AddAdditionalPartAction($sActionName, $mCallbak) + { + if ($this->bIsEnabled && is_callable($mCallbak)) + { + $sActionName = strtolower($sActionName); + if (!isset($this->aAdditionalParts[$sActionName])) + { + $this->aAdditionalParts[$sActionName] = array(); + } + + $this->aAdditionalParts[$sActionName][] = $mCallbak; + } + + return $this; + } + + /** + * @param string $sActionName + * @param array $aParts = array() + * + * @return \RainLoop\Plugins\Manager + */ + public function RunAdditionalPart($sActionName, $aParts = array()) + { + $bResult = false; + if ($this->bIsEnabled) + { + $sActionName = strtolower($sActionName); + if (isset($this->aAdditionalParts[$sActionName])) + { + foreach ($this->aAdditionalParts[$sActionName] as $mCallbak) + { + $bCallResult = call_user_func_array($mCallbak, $aParts); + if ($bCallResult && !$bResult) + { + $bResult = true; + } + } + } + } + + return $bResult; + } + + /** + * @param string $sName + * @param string $sPlace + * @param string $sHtml + * @param bool $bPrepend = false + * + * @return \RainLoop\Plugins\Manager + */ + public function AddProcessTemplateAction($sName, $sPlace, $sHtml, $bPrepend = false) + { + if ($this->bIsEnabled) + { + if (!isset($this->aProcessTemplate[$sName])) + { + $this->aProcessTemplate[$sName] = array(); + } + + if (!isset($this->aProcessTemplate[$sName][$sPlace])) + { + $this->aProcessTemplate[$sName][$sPlace] = array(); + } + + if ($bPrepend) + { + array_unshift($this->aProcessTemplate[$sName][$sPlace], $sHtml); + } + else + { + array_push($this->aProcessTemplate[$sName][$sPlace], $sHtml); + } + } + + return $this; + } + + /** + * @param string $sActionName + * @param mixed $mCallbak + * + * @return \RainLoop\Plugins\Manager + */ + public function AddAdditionalAjaxAction($sActionName, $mCallbak) + { + if ($this->bIsEnabled && is_callable($mCallbak) && 0 < strlen($sActionName)) + { + $sActionName = 'Do'.$sActionName; + + if (!isset($this->aAdditionalAjax[$sActionName])) + { + $this->aAdditionalAjax[$sActionName] = $mCallbak; + } + } + + return $this; + } + + /** + * @param string $sActionName + * + * @return bool + */ + public function HasAdditionalAjax($sActionName) + { + return $this->bIsEnabled && isset($this->aAdditionalAjax[$sActionName]); + } + + /** + * @param string $sActionName + * + * @return mixed + */ + public function RunAdditionalAjax($sActionName) + { + if ($this->bIsEnabled) + { + if (isset($this->aAdditionalAjax[$sActionName])) + { + return call_user_func($this->aAdditionalAjax[$sActionName]); + } + } + + return false; + } + + /** + * @param string $sLang + * @param array $sActionName + * + * @return \RainLoop\Plugins\Manager + */ + public function ReadLang($sLang, &$aLang) + { + if ($this->bIsEnabled) + { + foreach ($this->aPlugins as $oPlugin) + { + if ($oPlugin->UseLangs()) + { + $sPath = $oPlugin->Path(); + + \RainLoop\Utils::ReadAndAddLang($sPath.'/langs/en.ini', $aLang); + if ('en' !== $sLang) + { + \RainLoop\Utils::ReadAndAddLang($sPath.'/langs/'.$sLang.'.ini', $aLang); + } + } + } + } + + return $this; + } + + /** + * @param string $sName + * @param string $sHtml + * + * @return string + */ + public function ProcessTemplate($sName, $sHtml) + { + if (isset($this->aProcessTemplate[$sName])) + { + foreach ($this->aProcessTemplate[$sName] as $sPlace => $aAddHtml) + { + if (is_array($aAddHtml) && 0 < count($aAddHtml)) + { + foreach ($aAddHtml as $sAddHtml) + { + $sHtml = str_replace('{{INCLUDE/'.$sPlace.'/PLACE}}', $sAddHtml.'{{INCLUDE/'.$sPlace.'/PLACE}}', $sHtml); + } + } + } + } + + return $sHtml; + } + + /** + * @param \MailSo\Log\Logger $oLogger + * + * @return \RainLoop\Plugins\Manager + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function SetLogger($oLogger) + { + if (!($oLogger instanceof \MailSo\Log\Logger)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->oLogger = $oLogger; + + return $this; + } + + /** + * @param string $sDesc + * @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO + * + * @return void + */ + public function WriteLog($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO) + { + if ($this->oLogger) + { + $this->oLogger->Write($sDesc, $iDescType, 'PLUGIN'); + } + } + + /** + * @param string $sDesc + * @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO + * + * @return void + */ + public function WriteException($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO) + { + if ($this->oLogger) + { + $this->oLogger->WriteException($sDesc, $iDescType, 'PLUGIN'); + } + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Plugins/Property.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Plugins/Property.php new file mode 100644 index 000000000..7cb756150 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Plugins/Property.php @@ -0,0 +1,178 @@ +sName = $sName; + $this->iType = \RainLoop\Enumerations\PluginPropertyType::STRING; + $this->mDefaultValue = ''; + $this->sLabel = ''; + $this->sDesc = ''; + $this->bAllowedInJs = false; + } + + /** + * @param string $sName + * + * @return \RainLoop\Plugins\Property + */ + public static function NewInstance($sName) + { + return new self($sName); + } + + /** + * @param int $iType + * + * @return \RainLoop\Plugins\Property + */ + public function SetType($iType) + { + $this->iType = (int) $iType; + + return $this; + } + + /** + * @param mixed $mDefaultValue + * + * @return \RainLoop\Plugins\Property + */ + public function SetDefaultValue($mDefaultValue) + { + $this->mDefaultValue = $mDefaultValue; + + return $this; + } + + /** + * @param string $sLabel + * + * @return \RainLoop\Plugins\Property + */ + public function SetLabel($sLabel) + { + $this->sLabel = $sLabel; + + return $this; + } + + /** + * @param string $sDesc + * + * @return \RainLoop\Plugins\Property + */ + public function SetDescription($sDesc) + { + $this->sDesc = $sDesc; + + return $this; + } + + /** + * @param bool $bValue = true + * @return \RainLoop\Plugins\Property + */ + public function SetAllowedInJs($bValue = true) + { + $this->bAllowedInJs = !!$bValue; + + return $this; + } + + /** + * @return string + */ + public function Name() + { + return $this->sName; + } + + /** + * @return bool + */ + public function AllowedInJs() + { + return $this->bAllowedInJs; + } + + /** + * @return string + */ + public function Description() + { + return $this->sDesc; + } + + /** + * @return string + */ + public function Label() + { + return $this->sLabel; + } + + /** + * @return int + */ + public function Type() + { + return $this->iType; + } + + /** + * @return mixed + */ + public function DefaultValue() + { + return $this->mDefaultValue; + } + + /** + * @return array + */ + public function ToArray() + { + return array( + '', + $this->sName, + $this->iType, + $this->sLabel, + $this->mDefaultValue, + $this->sDesc + ); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/AbstractProvider.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/AbstractProvider.php new file mode 100644 index 000000000..c8def51c7 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/AbstractProvider.php @@ -0,0 +1,14 @@ +oActions = $oActions; + $this->oDriver = $oDriver; + } + + /** + * @param \RainLoop\Account $oAccount + * + * @return bool + */ + public function PasswordChangePossibility($oAccount) + { + return $this->IsActive() && + $oAccount instanceof \RainLoop\Account && + !$oAccount->PasswordIsXOAuth2() && + $this->oDriver && $this->oDriver->PasswordChangePossibility($oAccount) + ; + } + + /** + * @param \RainLoop\Account $oAccount + * @param string $sPrevPassword + * @param string $sNewPassword + * + * @return bool + */ + public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword) + { + $bResult = false; + if ($this->oDriver instanceof \RainLoop\Providers\ChangePassword\ChangePasswordInterface && + $this->PasswordChangePossibility($oAccount) && $sPrevPassword === $oAccount->Password()) + { + if ($this->oDriver->ChangePassword($oAccount, $sPrevPassword, $sNewPassword)) + { + $oAccount->SetPassword($sNewPassword); + $this->oActions->SetAuthToken($oAccount); + $bResult = true; + } + } + + return $bResult; + } + + /** + * @return bool + */ + public function IsActive() + { + return $this->oDriver instanceof \RainLoop\Providers\ChangePassword\ChangePasswordInterface; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/ChangePassword/ChangePasswordInterface.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/ChangePassword/ChangePasswordInterface.php new file mode 100644 index 000000000..4e1c20561 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/ChangePassword/ChangePasswordInterface.php @@ -0,0 +1,22 @@ +oDriver = null; + if ($oDriver instanceof \RainLoop\Providers\Contacts\ContactsInterface) + { + $this->oDriver = $oDriver; + } + } + + /** + * @return bool + */ + public function IsActive() + { + return $this->oDriver instanceof \RainLoop\Providers\Contacts\ContactsInterface; + } + + /** + * @return bool + */ + public function IsSupported() + { + return $this->oDriver instanceof \RainLoop\Providers\Contacts\ContactsInterface && + $this->oDriver->IsSupported(); + } + + /** + * @param \RainLoop\Account $oAccount + * @param int $iIdContact + * + * @return array + */ + public function GetContactById($oAccount, $iIdContact) + { + return $this->oDriver ? $this->oDriver->GetContactById($oAccount, $iIdContact) : null; + } + + /** + * @param \RainLoop\Account $oAccount + * @param int $iOffset = 0 + * @param int $iLimit = 20 + * @param string $sSearch = '' + * + * @return array + */ + public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '') + { + return $this->oDriver ? $this->oDriver->GetContacts($oAccount, $iOffset, $iLimit, $sSearch) : array(); + } + + /** + * @param \RainLoop\Account $oAccount + * + * @return array + */ + public function GetContactsImageHashes($oAccount) + { + return $this->oDriver ? $this->oDriver->GetContactsImageHashes($oAccount) : array(); + } + + /** + * @param \RainLoop\Account $oAccount + * @param \RainLoop\Providers\Contacts\Classes\Contact $oContact + * + * @return bool + */ + public function CreateContact($oAccount, &$oContact) + { + return $this->oDriver ? $this->oDriver->CreateContact($oAccount, $oContact) : false; + } + + /** + * @param \RainLoop\Account $oAccount + * @param \RainLoop\Providers\Contacts\Classes\Contact $oContact + * + * @return bool + */ + public function UpdateContact($oAccount, &$oContact) + { + return $this->oDriver ? $this->oDriver->UpdateContact($oAccount, $oContact) : false; + } + + /** + * @param \RainLoop\Account $oAccount + * @param array $aContactIds + * + * @return bool + */ + public function DeleteContacts($oAccount, $aContactIds) + { + return $this->oDriver ? $this->oDriver->DeleteContacts($oAccount, $aContactIds) : false; + } + + /** + * @param \RainLoop\Account $oAccount + * @param array $aContactIds + * + * @return bool + */ + public function IncFrec($oAccount, $aContactIds) + { + return $this->oDriver ? $this->oDriver->IncFrec($oAccount, $aContactIds) : false; + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Contacts/Classes/Contact.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Contacts/Classes/Contact.php new file mode 100644 index 000000000..e91d9a478 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Contacts/Classes/Contact.php @@ -0,0 +1,111 @@ +Clear(); + } + + public function Clear() + { + $this->IdContact = 0; + $this->IdUser = 0; + $this->Type = 0; + $this->Frec = 0; + $this->ListName = ''; + $this->Name = ''; + $this->ImageHash = ''; + $this->Emails = array(); + $this->Data = array(); + } + + /** + * @return string + */ + public function GenarateListName() + { + return 0 < \strlen($this->Name) ? $this->Name : (!empty($this->Emails[0]) ? $this->Emails[0] : ''); + } + + /** + * @return string + */ + public function EmailsAsString() + { + return \trim(\implode(' ', $this->Emails)); + } + + /** + * @return string + */ + public function DataAsString() + { + return @\serialize($this->Data); + } + + /** + * @param string $sData + */ + public function ParseData($sData) + { + $sData = (string) $sData; + $sData = \trim($sData); + + if (!empty($sData)) + { + $aData = @\unserialize($sData); + if (\is_array($aData)) + { + $this->Data = $aData; + } + } + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Contacts/Classes/Db.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Contacts/Classes/Db.php new file mode 100644 index 000000000..3cf7ae6a1 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Contacts/Classes/Db.php @@ -0,0 +1,38 @@ + array( + 'IdUser' => 'INTEGER PRIMARY KEY', + 'Email' => 'TEXT' + ), + 'rlContactsItems' => array( + 'IdContact' => 'INTEGER PRIMARY KEY', + 'IdUser' => 'INTEGER', + 'Type' => 'INTEGER', + 'Frec' => 'INTEGER', + 'ImageHash' => 'TEXT', + 'ListName' => 'TEXT', + 'Name' => 'TEXT', + 'Emails' => 'TEXT', + 'Data' => 'TEXT' + ) + ); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Contacts/ContactsInterface.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Contacts/ContactsInterface.php new file mode 100644 index 000000000..6f08e605d --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Contacts/ContactsInterface.php @@ -0,0 +1,68 @@ +oLogger = $oLogger instanceof \MailSo\Log\Logger ? $oLogger : null; + $this->bUseDbPerUser = true; + } + + /** + * @param \RainLoop\Account $oAccount + * @staticvar array $aPdoCache + * @return \PDO + */ + private function getPDO($oAccount) + { + static $aPdoCache = array(); + + $sEmail = $oAccount->ParentEmailHelper(); + if (isset($aPdoCache[$sEmail])) + { + return $aPdoCache[$sEmail]; + } + + if (!\class_exists('PDO')) + { + throw new \Exception('class_exists=PDO'); + } + + $sVersionFile = ''; + $sDsn = ''; + + if ($this->bUseDbPerUser) + { + $sSubPath = APP_PRIVATE_DATA.'storage/contacts/'.\rtrim(\substr($sEmail, 0, 2), '@').'/'.$sEmail.'/'; + if (!\is_dir($sSubPath)) + { + if (\mkdir($sSubPath, 0777, true) && \is_dir($sSubPath)) + { + $sVersionFile = $sSubPath.'.version'; + $sDsn = 'sqlite:'.$sSubPath.'contacts.sqlite'; + } + } + else + { + $sVersionFile = $sSubPath.'.version'; + $sDsn = 'sqlite:'.$sSubPath.'contacts.sqlite'; + } + } + else + { + $sVersionFile = APP_PRIVATE_DATA.'.version'; + $sDsn = 'sqlite:'.APP_PRIVATE_DATA.'contacts.sqlite'; + } + + $sDbLogin = ''; + $sDbPassword = ''; + + $oPdo = false; + try + { + $oPdo = new \PDO($sDsn, $sDbLogin, $sDbPassword); + if ($oPdo) + { + $oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + + if (!@\file_exists($sVersionFile) || + (string) @file_get_contents($sVersionFile) !== (string) \RainLoop\Providers\Contacts\Classes\Db::Version()) + { + $this->syncTables($oPdo, $sVersionFile); + } + + $oPdo->sqliteCreateFunction('SIMPLESEARCH', function ($sEmailValue, $sNameValue, $sMask) { + return \preg_match('/'.\preg_quote($sMask, '/').'/ui', + $sEmailValue.' '.$sNameValue) ? 1 : 0; + }); + + } + } + catch (\Exception $oException) + { + throw $oException; + $oPdo = false; + } + + if ($oPdo) + { + $aPdoCache[$oAccount->ParentEmailHelper()] = $oPdo; + } + + return $oPdo; + } + + protected function getWantedColumnsInfo($sTableName, $aCurrent) + { + $aColumns = array(); + foreach ($aCurrent as $sName => $sType) + { + $sSql = $sName.' '.$sType; + switch ($sType) + { + case 'INTEGER': + $sSql .= ' DEFAILT \'0\''; + break; + case 'TEXT': + $sSql .= ' DEFAILT \'\''; + break; + } + + $aColumns[$sName] = $sSql; + } + + if (0 === \count($aColumns)) + { + return ''; + } + + return 'CREATE TABLE '.$sTableName.' (' .\implode(', ', $aColumns).')'; + } + + /** + * @param \PDO $oAccount + * @param string $sTableName + */ + protected function getCurrentColumnsInfo($oPdo, $sTableName) + { + $oStmt = $this->prepareAndExecute($oPdo, 'SELECT `sql` FROM `sqlite_master` WHERE `tbl_name` = :TableName AND `type` = :Type', array( + ':TableName' => array($sTableName, \PDO::PARAM_STR), + ':Type' => array('table', \PDO::PARAM_STR) + )); + + if ($oStmt) + { + $mRow = $oStmt->fetch(\PDO::FETCH_ASSOC); + if ($mRow && isset($mRow['sql'])) + { + return (string) $mRow['sql']; + } + } + + return ''; + } + + /** + * @param \PDO $oPdo + * @param string $sVersionFile = '' + */ + private function syncTables($oPdo, $sVersionFile = '') + { + if ($this->oLogger) + { + $this->oLogger->Write('Start to sync', \MailSo\Log\Enumerations\Type::INFO); + } + + $aStrucure = \RainLoop\Providers\Contacts\Classes\Db::Strucure(); + foreach ($aStrucure as $sTableName => $aField) + { + $sCurrent = $this->getCurrentColumnsInfo($oPdo, $sTableName); + $sWanted = $this->getWantedColumnsInfo($sTableName, $aField); + + if (empty($sCurrent)) + { + $this->prepareAndExecute($oPdo, $sWanted); + } + else if ($sCurrent !== $sWanted) + { + $this->prepareAndExecute($oPdo, 'DROP TABLE IF EXISTS `'.$sTableName.'_old`'); + $this->prepareAndExecute($oPdo, 'ALTER TABLE `'.$sTableName.'` RENAME TO `'.$sTableName.'_old`'); + $this->prepareAndExecute($oPdo, $sWanted); + + $aNewKeys = array(); + $aOldKeys = array(); + foreach ($aField as $sKey => $sType) + { + $aNewKeys[] = $sKey; + $aOldKeys[] = false !== \strpos($sCurrent, $sKey.' ') ? $sKey : + (0 === \strpos($sType, 'INT') ? '\'0\'' : '\'\''); + } + + $sNewKeys = \implode(', ', $aNewKeys); + $sOldKeys = \implode(', ', $aOldKeys); + $this->prepareAndExecute($oPdo, 'INSERT INTO `'.$sTableName.'` ('.$sNewKeys.') SELECT '.$sOldKeys.' FROM `'.$sTableName.'_old`'); + + $this->prepareAndExecute($oPdo, 'DROP TABLE `'.$sTableName.'_old`'); + } + } + + @\file_put_contents($sVersionFile, \RainLoop\Providers\Contacts\Classes\Db::Version()); + + if ($this->oLogger) + { + $this->oLogger->Write('Stop to sync', \MailSo\Log\Enumerations\Type::INFO); + } + } + + /** + * @param \RainLoop\Account|\PDO $oAccountOrPdo + * @param string $sSql + * @param array $aParams + * + * @return \PDOStatement|null + */ + private function prepareAndExecute($oAccountOrPdo, $sSql, $aParams = array()) + { + if ($this->oLogger) + { + $this->oLogger->Write($sSql, \MailSo\Log\Enumerations\Type::INFO, 'SQLITE'); + } + + $oPdo = $oAccountOrPdo instanceof \PDO ? $oAccountOrPdo : $this->getPDO($oAccountOrPdo); + $oStmt = $oPdo->prepare($sSql); + foreach ($aParams as $sName => $aValue) + { + $oStmt->bindValue($sName, $aValue[0], $aValue[1]); + } + +// $sLogSql = $sSql; +// foreach($aParams as $sName => $aValue) +// { +// $sLogSql = \str_replace($sName, $aValue[1] === \PDO::PARAM_INT ? $aValue[0] : '\''.$aValue[0].'\'', $sLogSql); +// } +// +// if ($this->oLogger) +// { +// $this->oLogger->Write($sLogSql, \MailSo\Log\Enumerations\Type::INFO, 'SQLITE'); +// } + + $mResult = $oStmt->execute() ? $oStmt : null; + +// if ($this->oLogger) +// { +// $this->oLogger->Write('RESULT: '.($mResult ? 'true' : 'false'), \MailSo\Log\Enumerations\Type::INFO, 'SQLITE'); +// } + + return $mResult; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param bool $bSkipInsert = false + * + * @return int + */ + private function getUserId($oAccount, $bSkipInsert = false) + { + if (!$this->bUseDbPerUser) + { + $oStmt = $this->prepareAndExecute($oAccount, + 'SELECT IdUser FROM rlContactsUsers WHERE Email = :Email LIMIT 1', + array( + ':Email' => array($oAccount->ParentEmailHelper(), \PDO::PARAM_STR) + )); + + $mRow = $oStmt->fetch(\PDO::FETCH_ASSOC); + if ($mRow && isset($mRow['IdUser']) && \is_numeric($mRow['IdUser'])) + { + return (int) $mRow['IdUser']; + } + + if (!$bSkipInsert) + { + $oStmt->closeCursor(); + + $oStmt = $this->prepareAndExecute($oAccount, + 'INSERT INTO rlContactsUsers (Email) VALUES (:Email)', + array( + ':Email' => array($oAccount->ParentEmailHelper(), \PDO::PARAM_STR) + )); + + return $this->getUserId($oAccount, true); + } + + throw new \Exception('IdUser=0'); + } + + return 0; + } + + /** + * @param string $sSearch + * @return string + */ + private function convertSearchValue($sSearch) + { + return '%'.$sSearch.'%'; + } + + private function populateContactFromDB($iUserID, $aItem) + { + $oContact = null; + if (isset($aItem['IdContact'])) + { + $oContact = new \RainLoop\Providers\Contacts\Classes\Contact(); + $oContact->IdContact = (int) $aItem['IdContact']; + $oContact->IdUser = $iUserID; + $oContact->Type = (int) $aItem['Type']; + $oContact->Frec = (int) $aItem['Frec']; + $oContact->ListName = (string) $aItem['ListName']; + $oContact->Name = (string) $aItem['Name']; + $oContact->Emails = \explode(' ', \trim((string) $aItem['Emails'])); + $oContact->ImageHash = (string) $aItem['ImageHash']; + + $oContact->ParseData($aItem['Data']); + } + + return $oContact; + } + + /** + * @param \RainLoop\Account $oAccount + * @param int $iIdContact + * + * @return $oContact|null + */ + public function GetContactById($oAccount, $iIdContact) + { + $oResultContact = null; + + $iUserID = $this->getUserId($oAccount); + + $oStmt = $this->prepareAndExecute($oAccount, + 'SELECT IdContact, Type, Frec, ListName, Name, Emails, ImageHash, Data'. + ' FROM rlContactsItems WHERE IdContact = :IdContact AND IdUser = :IdUser LIMIT 1', + array( + ':IdContact' => array($iIdContact, \PDO::PARAM_INT), + ':IdUser' => array($iUserID, \PDO::PARAM_INT) + )); + + $aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC); + if (\is_array($aFetch) && isset($aFetch[0]) && \is_array($aFetch[0])) + { + $oContact = $this->populateContactFromDB($iUserID, $aFetch[0]); + if ($oContact instanceof \RainLoop\Providers\Contacts\Classes\Contact) + { + $oResultContact = $oContact; + } + } + + return $oResultContact; + } + + /** + * @param \RainLoop\Account $oAccount + * @param int $iOffset = 0 + * @param int $iLimit = 20 + * @param string $sSearch = '' + * + * @return array + */ + public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '') + { + $iOffset = 0 <= $iOffset ? $iOffset : 0; + $iLimit = 0 < $iLimit ? (int) $iLimit : 0; + $sSearch = \trim($sSearch); + + $iUserID = $this->getUserId($oAccount); + + $sSql = 'SELECT IdContact, Type, Frec, ListName, Name, Emails, ImageHash, Data'. + ' FROM rlContactsItems WHERE IdUser = :IdUser' + ; + + $aParams = array( + ':IdUser' => array($iUserID, \PDO::PARAM_INT), + ':limit' => array($iLimit, \PDO::PARAM_INT), + ':offset' => array($iOffset, \PDO::PARAM_INT) + ); + + if (0 < strlen($sSearch)) + { + if (\MailSo\Base\Utils::IsAscii($sSearch)) + { + $sSql .= ' AND Name LIKE :Search OR Emails LIKE :Search'; + $aParams[':Search'] = array($this->convertSearchValue($sSearch), \PDO::PARAM_STR); + } + else + { + $sSql .= ' AND SIMPLESEARCH(Emails, Name, :Search)'; + $aParams[':Search'] = array($sSearch, \PDO::PARAM_STR); + } + } + + $sSql .= ' ORDER BY ListName ASC LIMIT :limit OFFSET :offset'; + + $oStmt = $this->prepareAndExecute($oAccount, $sSql, $aParams); + + $aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC); + $aResult = array(); + if (\is_array($aFetch) && 0 < \count($aFetch)) + { + foreach ($aFetch as $aItem) + { + $oContact = $this->populateContactFromDB($iUserID, $aItem); + if ($oContact instanceof \RainLoop\Providers\Contacts\Classes\Contact) + { + $aResult[] = $oContact; + } + } + } + + unset($aFetch); + return $aResult; + } + + /** + * @param \RainLoop\Account $oAccount + * + * @return array + */ + public function GetContactsImageHashes($oAccount) + { + $iUserID = $this->getUserId($oAccount); + + $oStmt = $this->prepareAndExecute($oAccount, + 'SELECT Emails, ImageHash FROM rlContactsItems WHERE IdUser = :IdUser AND ImageHash <> :ImageHash', + array( + ':IdUser' => array($iUserID, \PDO::PARAM_INT), + ':ImageHash' => array('', \PDO::PARAM_STR) + )); + + $aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC); + $aResult = array(); + + if (\is_array($aFetch) && 0 < \count($aFetch)) + { + foreach ($aFetch as $aItem) + { + if (!empty($aItem['Emails']) && !empty($aItem['ImageHash'])) + { + $aEmails = \explode(' ', $aItem['Emails']); + foreach ($aEmails as $sEmail) + { + $sEmail = \trim($sEmail); + if (0 < strlen($sEmail)) + { + $aResult[$sEmail] = $aItem['ImageHash']; + } + } + } + } + } + + unset($aFetch); + return $aResult; + } + + /** + * @param \RainLoop\Account $oAccount + * @param \RainLoop\Providers\Contacts\Classes\Contact $oContact + * + * @return bool + */ + public function CreateContact($oAccount, &$oContact) + { + $iUserID = $this->getUserId($oAccount); + + $oContact->IdUser = $iUserID; + + $oStmt = $this->prepareAndExecute($oAccount, + 'INSERT INTO rlContactsItems '. + '( IdUser, Type, Frec, ListName, Name, Emails, ImageHash, Data) VALUES '. + '(:IdUser, :Type, 0, :ListName, :Name, :Emails, :ImageHash, :Data)', + array( + ':IdUser' => array($oContact->IdUser, \PDO::PARAM_INT), + ':Type' => array($oContact->Type, \PDO::PARAM_INT), + ':ListName' => array($oContact->GenarateListName(), \PDO::PARAM_STR), + ':Name' => array($oContact->Name, \PDO::PARAM_STR), + ':Emails' => array($oContact->EmailsAsString(), \PDO::PARAM_STR), + ':ImageHash' => array($oContact->ImageHash, \PDO::PARAM_STR), + ':Data' => array($oContact->DataAsString(), \PDO::PARAM_STR), + )); + + if ($oStmt) + { + $iContactID = $this->getPDO($oAccount)->lastInsertId('IdContact'); + if (is_numeric($iContactID) && 0 < (int) $iContactID) + { + $oContact->IdContact = (int) $iContactID; + return true; + } + } + + throw new \Exception('CreateContact'); + } + + /** + * @param \RainLoop\Account $oAccount + * @param \RainLoop\Providers\Contacts\Classes\Contact $oContact + * + * @return bool + */ + public function UpdateContact($oAccount, &$oContact) + { + $iUserID = $this->getUserId($oAccount); + + $oContact->IdUser = $iUserID; + + return !!$this->prepareAndExecute($oAccount, + 'UPDATE rlContactsItems SET'. + ' Type = :Type, ListName = :ListName, Name = :Name, Emails = :Emails,'. + ' ImageHash = :ImageHash, Data = :Data'. + ' WHERE IdContact = :IdContact AND IdUser = :IdUser', + array( + ':IdContact' => array($oContact->IdContact, \PDO::PARAM_INT), + ':IdUser' => array($oContact->IdUser, \PDO::PARAM_INT), + ':Type' => array($oContact->Type, \PDO::PARAM_INT), + ':ListName' => array($oContact->GenarateListName(), \PDO::PARAM_STR), + ':Name' => array($oContact->Name, \PDO::PARAM_STR), + ':Emails' => array($oContact->EmailsAsString(), \PDO::PARAM_STR), + ':ImageHash' => array($oContact->ImageHash, \PDO::PARAM_STR), + ':Data' => array($oContact->DataAsString(), \PDO::PARAM_STR), + )); + } + + /** + * @param \RainLoop\Account $oAccount + * @param array $aContactIds + * + * @return bool + */ + public function DeleteContacts($oAccount, $aContactIds) + { + $iUserID = $this->getUserId($oAccount); + + $aParams = array( + ':IdUser' => array($iUserID, \PDO::PARAM_INT), + ); + + $aInQuery = array(); + foreach ($aContactIds as $iIndex => $iId) + { + $aInQuery[] = ':IdContact_'.$iIndex; + $aParams[':IdContact_'.$iIndex] = array($iId, \PDO::PARAM_INT); + } + + if (0 === \count($aInQuery)) + { + return false; + } + + return !!$this->prepareAndExecute($oAccount, + 'DELETE FROM rlContactsItems WHERE IdUser = :IdUser AND IdContact IN ('.\implode(', ', $aInQuery).')', + $aParams); + } + + /** + * @return bool + */ + public function IsSupported() + { + $aDrivers = \class_exists('PDO') ? \PDO::getAvailableDrivers() : array(); + return \is_array($aDrivers) ? \in_array('sqlite', $aDrivers) : false; + } + + /** + * @param \RainLoop\Account $oAccount + * @param array $aContactIds + * + * @return bool + */ + public function IncFrec($oAccount, $aContactIds) + { + if (\is_array($aContactIds) && 0 < \count($aContactIds)) + { + $iUserID = $this->getUserId($oAccount); + + $aParams = array( + ':IdUser' => array($iUserID, \PDO::PARAM_INT), + ); + + $aInQuery = array(); + foreach ($aContactIds as $iIndex => $iId) + { + $aInQuery[] = ':IdContact_'.$iIndex; + $aParams[':IdContact_'.$iIndex] = array($iId, \PDO::PARAM_INT); + } + + return !!$this->prepareAndExecute($oAccount, + 'UPDATE rlContactsItems SET Frec = Frec + 1 WHERE IdUser = :IdUser AND IdContact IN ('.\implode(', ', $aInQuery).')', + $aParams); + } + + return false; + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Domain.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Domain.php new file mode 100644 index 000000000..a20d58019 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Domain.php @@ -0,0 +1,153 @@ +oDriver = $oDriver; + $this->bAdmin = $this->oDriver instanceof \RainLoop\Providers\Domain\DomainAdminInterface; + } + + /** + * @return bool + */ + public function IsAdmin() + { + return $this->bAdmin; + } + + /** + * @param string $sName + * + * @return \RainLoop\Domain | null + */ + public function Load($sName) + { + return $this->oDriver->Load($sName); + } + + /** + * @param \RainLoop\Domain $oDomain + * + * @return bool + */ + public function Save(\RainLoop\Domain $oDomain) + { + return $this->bAdmin ? $this->oDriver->Save($oDomain) : false; + } + + /** + * @param string $sName + * + * @return bool + */ + public function Delete($sName) + { + return $this->bAdmin ? $this->oDriver->Delete($sName) : false; + } + + /** + * @param string $sName + * @param bool $bDisabled + * + * @return bool + */ + public function Disable($sName, $bDisabled) + { + return $this->bAdmin ? $this->oDriver->Disable($sName, $bDisabled) : false; + } + + /** + * @param int $iOffset + * @param int $iLimit = 20 + * @param string $sSearch = '' + * + * @return array + */ + public function GetList($iOffset, $iLimit = 20, $sSearch = '') + { + return $this->bAdmin ? $this->oDriver->GetList($iOffset, $iLimit, $sSearch) : array(); + } + + /** + * @param string $sSearch = '' + * + * @return int + */ + public function Count($sSearch = '') + { + return $this->bAdmin ? $this->oDriver->Count($sSearch) : 0; + } + + /** + * @param \RainLoop\Actions $oActions + * @param string $sNameForTest = '' + * + * @return \RainLoop\Domain | null + */ + public function LoadOrCreateNewFromAction(\RainLoop\Actions $oActions, $sNameForTest = '') + { + $oDomain = null; + + if ($this->bAdmin) + { + $bCreate = '1' === (string) $oActions->GetActionParam('Create', '0'); + $sName = (string) $oActions->GetActionParam('Name', ''); + $sIncHost = (string) $oActions->GetActionParam('IncHost', ''); + $iIncPort = (int) $oActions->GetActionParam('IncPort', 143); + $iIncSecure = (int) $oActions->GetActionParam('IncSecure', \MailSo\Net\Enumerations\ConnectionSecurityType::NONE); + $sOutHost = (string) $oActions->GetActionParam('OutHost', ''); + $iOutPort = (int) $oActions->GetActionParam('OutPort', 25); + $iOutSecure = (int) $oActions->GetActionParam('OutSecure', \MailSo\Net\Enumerations\ConnectionSecurityType::NONE); + $bOutAuth = '1' === (string) $oActions->GetActionParam('OutAuth', '1'); + + if (0 < strlen($sName) || 0 < strlen($sNameForTest)) + { + $oDomain = 0 < strlen($sNameForTest) ? null : $this->Load($sName); + if ($oDomain instanceof \RainLoop\Domain) + { + if ($bCreate) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::DomainAlreadyExists); + } + else + { + $oDomain->UpdateInstance($sIncHost, $iIncPort, $iIncSecure, $sOutHost, $iOutPort, $iOutSecure, $bOutAuth); + } + } + else + { + $oDomain = \RainLoop\Domain::NewInstance(0 < strlen($sNameForTest) ? $sNameForTest : $sName, + $sIncHost, $iIncPort, $iIncSecure, $sOutHost, $iOutPort, $iOutSecure, $bOutAuth); + } + } + } + + return $oDomain; + } + + /** + * @return bool + */ + public function IsActive() + { + return $this->oDriver instanceof \RainLoop\Providers\Domain\DomainInterface; + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Domain/DefaultDomain.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Domain/DefaultDomain.php new file mode 100644 index 000000000..396c7194c --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Domain/DefaultDomain.php @@ -0,0 +1,172 @@ +sDomainPath = rtrim(trim($sDomainPath), '\\/'); + } + + /** + * @param string $sName + * @param bool $bDisable + * + * @return bool + */ + public function Disable($sName, $bDisable) + { + $sFile = ''; + if (file_exists($this->sDomainPath.'/disabled')) + { + $sFile = @file_get_contents($this->sDomainPath.'/disabled'); + } + + $aResult = array(); + $aNames = explode(',', $sFile); + if ($bDisable) + { + array_push($aNames, $sName); + $aResult = $aNames; + } + else + { + foreach ($aNames as $sItem) + { + if ($sName !== $sItem) + { + $aResult[] = $sItem; + } + } + } + + $aResult = array_unique($aResult); + return false !== file_put_contents($this->sDomainPath.'/disabled', trim(implode(',', $aResult), ', ')); + } + + /** + * @param string $sName + * + * @return \RainLoop\Domain | null + */ + public function Load($sName) + { + $mResult = null; + $sName = strtolower($sName); + if (file_exists($this->sDomainPath.'/'.$sName.'.ini')) + { + $mResult = \RainLoop\Domain::NewInstanceFromDomainConfigArray( + $sName, @parse_ini_file($this->sDomainPath.'/'.$sName.'.ini')); + + if ($mResult instanceof \RainLoop\Domain) + { + if (file_exists($this->sDomainPath.'/disabled')) + { + $sDisabled = @file_get_contents($this->sDomainPath.'/disabled'); + if (false !== $sDisabled && 0 < strlen($sDisabled)) + { + $mResult->SetDisabled(false !== strpos(strtolower(','.$sDisabled.','), strtolower(','.$sName.','))); + } + } + } + } + + return $mResult; + } + + /** + * @param \RainLoop\Domain $oDomain + * + * @return bool + */ + public function Save(\RainLoop\Domain $oDomain) + { + $mResult = file_put_contents($this->sDomainPath.'/'.strtolower($oDomain->Name()).'.ini', $oDomain->ToIniString()); + return is_int($mResult) && 0 < $mResult; + } + + /** + * @param string $sName + * + * @return bool + */ + public function Delete($sName) + { + $bResult = true; + $sName = strtolower($sName); + if (0 < strlen($sName) && file_exists($this->sDomainPath.'/'.$sName.'.ini')) + { + $bResult = unlink($this->sDomainPath.'/'.$sName.'.ini'); + } + + return $bResult; + } + + /** + * @param int $iOffset + * @param int $iLimit = 20 + * @param string $sSearch = '' + * + * @return array + */ + public function GetList($iOffset, $iLimit = 20, $sSearch = '') + { + $aResult = array(); + $aList = glob($this->sDomainPath.'/*.ini'); + + $sSearch = strtolower($sSearch); + foreach ($aList as $sFile) + { + $sName = strtolower(substr(basename($sFile), 0, -4)); + if (0 === strlen($sSearch) || false !== strpos($sName, $sSearch)) + { + $aResult[] = $sName; + } + } + + $iOffset = (0 > $iOffset) ? 0 : $iOffset; + $iLimit = (0 > $iLimit) ? 0 : ((999 < $iLimit) ? 999 : $iLimit); + + $aResult = array_slice($aResult, $iOffset, $iLimit); + + $aDisabledNames = array(); + if (0 < count($aResult) && file_exists($this->sDomainPath.'/disabled')) + { + $sDisabled = @file_get_contents($this->sDomainPath.'/disabled'); + if (false !== $sDisabled && 0 < strlen($sDisabled)) + { + $aDisabledNames = explode(',', strtolower($sDisabled)); + $aDisabledNames = array_unique($aDisabledNames); + } + } + + $aReturn = array(); + foreach ($aResult as $sName) + { + $aReturn[$sName] = !in_array(strtolower($sName), $aDisabledNames); + } + + return $aReturn; + } + + /** + * @param string $sSearch = '' + * + * @return int + */ + public function Count($sSearch = '') + { + return count($this->GetList(0, 999, $sSearch)); + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Domain/DomainAdminInterface.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Domain/DomainAdminInterface.php new file mode 100644 index 000000000..e15f6ee57 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Domain/DomainAdminInterface.php @@ -0,0 +1,52 @@ +oDriver = $oDriver; + $this->oDomainProvider = $oDomainProvider; + } + + /** + * @param string $sEmail + * @param string $sLogin + * @param string $sPassword + * @param bool $bPasswordIsXOAuth2 = false + * @param bool $sSignMeToken = '' + * + * @return \RainLoop\Account|null + */ + public function Provide($sEmail, $sLogin, $sPassword, $bPasswordIsXOAuth2 = false, $sSignMeToken = '') + { + $oResult = null; + + if ($this->oDriver->ProvideParameters($sEmail, $sLogin, $sPassword)) + { + $oDomain = $this->oDomainProvider->Load(\MailSo\Base\Utils::GetDomainFromEmail($sEmail)); + if ($oDomain instanceof \RainLoop\Domain && !$oDomain->Disabled()) + { + $oResult = \RainLoop\Account::NewInstance($sEmail, $sLogin, $sPassword, $oDomain, $bPasswordIsXOAuth2, $sSignMeToken); + } + } + + return $oResult; + } + + /** + * @return bool + */ + public function IsActive() + { + return $this->oDriver instanceof \RainLoop\Providers\Login\LoginInterface; + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Login/DefaultLogin.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Login/DefaultLogin.php new file mode 100644 index 000000000..54ade2454 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Login/DefaultLogin.php @@ -0,0 +1,18 @@ +oDriver = $oDriver; + } + + /** + * @param \RainLoop\Account $oAccount + * + * @return \RainLoop\Settings + */ + public function Load(\RainLoop\Account $oAccount) + { + $oSettings = new \RainLoop\Settings(); + $oSettings->InitData($this->oDriver->Load($oAccount)); + return $oSettings; + } + + /** + * @param \RainLoop\Account $oAccount + * @param \RainLoop\Settings $oSettings + * + * @return bool + */ + public function Save(\RainLoop\Account $oAccount, \RainLoop\Settings $oSettings) + { + return $this->oDriver->Save($oAccount, $oSettings->DataAsArray()); + } + + /** + * @return bool + */ + public function IsActive() + { + return $this->oDriver instanceof \RainLoop\Providers\Settings\SettingsInterface; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php new file mode 100644 index 000000000..33862237f --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php @@ -0,0 +1,59 @@ +oStorageProvider = $oStorageProvider; + } + + /** + * @param \RainLoop\Account $oAccount + * + * @return array + */ + public function Load(\RainLoop\Account $oAccount) + { + $sValue = $this->oStorageProvider->Get($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + \RainLoop\Providers\Settings\DefaultSettings::FILE_NAME); + + $aSettings = array(); + if (\is_string($sValue)) + { + $aData = \json_decode($sValue, true); + if (\is_array($aData)) + { + $aSettings = $aData; + } + } + + return $aSettings; + } + + /** + * @param \RainLoop\Account $oAccount + * @param array $aSettings + * + * @return bool + */ + public function Save(\RainLoop\Account $oAccount, array $aSettings) + { + return $this->oStorageProvider->Put($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + \RainLoop\Providers\Settings\DefaultSettings::FILE_NAME, + \json_encode($aSettings)); + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Settings/SettingsInterface.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Settings/SettingsInterface.php new file mode 100644 index 000000000..05a0a83c0 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Settings/SettingsInterface.php @@ -0,0 +1,21 @@ +oDriver = $oDriver; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $iStorageType + * @param string $sValue + * + * @return bool + */ + public function Put($oAccount, $iStorageType, $sKey, $sValue) + { + if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType && !($oAccount instanceof \RainLoop\Account)) + { + return false; + } + + return $this->oDriver->Put($oAccount, $iStorageType, $sKey, $sValue); + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param resource $rSource + * + * @return bool + */ + public function PutFile($oAccount, $iStorageType, $sKey, $rSource) + { + if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType && !($oAccount instanceof \RainLoop\Account)) + { + return false; + } + + return $this->oDriver->PutFile($oAccount, $iStorageType, $sKey, $rSource); + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param string $sSource + * + * @return bool + */ + public function MoveUploadedFile($oAccount, $iStorageType, $sKey, $sSource) + { + if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType && !($oAccount instanceof \RainLoop\Account)) + { + return false; + } + + return $this->oDriver->MoveUploadedFile($oAccount, $iStorageType, $sKey, $sSource); + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param mixed $mDefault = false + * + * @return mixed + */ + public function Get($oAccount, $iStorageType, $sKey, $mDefault = false) + { + if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType && !($oAccount instanceof \RainLoop\Account)) + { + return $mDefault; + } + + return $this->oDriver->Get($oAccount, $iStorageType, $sKey, $mDefault); + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param string $sOpenMode = 'rb' + * + * @return resource | bool + */ + public function GetFile($oAccount, $iStorageType, $sKey, $sOpenMode = 'rb') + { + if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType && !($oAccount instanceof \RainLoop\Account)) + { + return false; + } + + return $this->oDriver->GetFile($oAccount, $iStorageType, $sKey, $sOpenMode); + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * + * @return string | bool + */ + public function GetFileName($oAccount, $iStorageType, $sKey) + { + if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType && !($oAccount instanceof \RainLoop\Account)) + { + return false; + } + + return $this->oDriver->GetFileName($oAccount, $iStorageType, $sKey); + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * + * @return bool + */ + public function Clear($oAccount, $iStorageType, $sKey) + { + if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType && !($oAccount instanceof \RainLoop\Account)) + { + return false; + } + + return $this->oDriver->Clear($oAccount, $iStorageType, $sKey); + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * + * @return int | bool + */ + public function FileSize($oAccount, $iStorageType, $sKey) + { + if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType && !($oAccount instanceof \RainLoop\Account)) + { + return false; + } + + return $this->oDriver->FileSize($oAccount, $iStorageType, $sKey); + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * + * @return bool + */ + public function FileExists($oAccount, $iStorageType, $sKey) + { + if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType && !($oAccount instanceof \RainLoop\Account)) + { + return false; + } + + return $this->oDriver->FileExists($oAccount, $iStorageType, $sKey); + } + + /** + * @param int $iTimeToClearInHours = 24 + * + * @return bool + */ + public function GC($iTimeToClearInHours = 24) + { + return $this->oDriver ? $this->oDriver->GC($iTimeToClearInHours) : false; + } + + /** + * @return bool + */ + public function IsActive() + { + return $this->oDriver instanceof \RainLoop\Providers\Storage\StorageInterface; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Storage/DefaultStorage.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Storage/DefaultStorage.php new file mode 100644 index 000000000..13809961d --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Storage/DefaultStorage.php @@ -0,0 +1,290 @@ +sDataPath = \rtrim(\trim($sStoragePath), '\\/'); + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param string $sValue + * + * @return bool + */ + public function Put($oAccount, $iStorageType, $sKey, $sValue) + { + return false !== @\file_put_contents( + $this->generateFileName($oAccount, $iStorageType, $sKey, true), $sValue); + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param resource $rSource + * + * @return bool + */ + public function PutFile($oAccount, $iStorageType, $sKey, $rSource) + { + $bResult = false; + if ($rSource) + { + $rOpenOutput = @\fopen($this->generateFileName($oAccount, $iStorageType, $sKey, true), 'w+b'); + if ($rOpenOutput) + { + $bResult = (false !== \MailSo\Base\Utils::MultipleStreamWriter($rSource, array($rOpenOutput))); + @\fclose($rOpenOutput); + } + } + return $bResult; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param string $sSource + * + * @return bool + */ + public function MoveUploadedFile($oAccount, $iStorageType, $sKey, $sSource) + { + return @\move_uploaded_file($sSource, + $this->generateFileName($oAccount, $iStorageType, $sKey, true)); + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sSource + * @param string $sDest + * + * @return bool + */ + public function SaveFileToBase64File($oAccount, $iStorageType, $sSource, $sDest) + { + $bResult = false; + $rOpenInput = @\fopen($this->generateFileName($oAccount, $iStorageType, $sSource), 'rb'); + $rOpenOutput = @\fopen($this->generateFileName($oAccount, $iStorageType, $sDest, true), 'wb'); + + if ($rOpenInput && $rOpenOutput) + { + $aParam = array('line-length' => 76, 'line-break-chars' => "\r\n"); + $rFilter = @\stream_filter_append($rOpenOutput, 'convert.base64-encode', STREAM_FILTER_WRITE, $aParam); + if (@\is_resource($rFilter)) + { + $bResult = true; + } + } + + if ($bResult) + { + $bResult = (false !== \MailSo\Base\Utils::MultipleStreamWriter($rOpenInput, array($rOpenOutput))); + } + + if ($rOpenInput && $rOpenOutput) + { + @\fclose($rOpenInput); + @\fclose($rOpenOutput); + } + + return $bResult; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param mixed $mDefault = false + * + * @return mixed + */ + public function Get($oAccount, $iStorageType, $sKey, $mDefault = false) + { + $mValue = false; + $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey); + if (\file_exists($sFileName)) + { + $mValue = \file_get_contents($sFileName); + } + + return false === $mValue ? $mDefault : $mValue; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param string $sOpenMode = 'rb' + * + * @return resource | bool + */ + public function GetFile($oAccount, $iStorageType, $sKey, $sOpenMode = 'rb') + { + $mResult = false; + $bCreate = !!\preg_match('/[wac]/', $sOpenMode); + + $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey, $bCreate); + if ($bCreate || \file_exists($sFileName)) + { + $mResult = @\fopen($sFileName, $sOpenMode); + } + + return $mResult; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * + * @return string | bool + */ + public function GetFileName($oAccount, $iStorageType, $sKey) + { + $mResult = false; + $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey); + if (\file_exists($sFileName)) + { + $mResult = $sFileName; + } + + return $mResult; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * + * @return bool + */ + public function Clear($oAccount, $iStorageType, $sKey) + { + $mResult = true; + $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey); + if (\file_exists($sFileName)) + { + $mResult = @\unlink($sFileName); + } + + return $mResult; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * + * @return int | bool + */ + public function FileSize($oAccount, $iStorageType, $sKey) + { + $mResult = false; + $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey); + if (\file_exists($sFileName)) + { + $mResult = \filesize($sFileName); + } + + return $mResult; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iType + * @param string $sKey + * + * @return bool + */ + public function FileExists($oAccount, $iStorageType, $sKey) + { + return @\file_exists($this->generateFileName($oAccount, $iStorageType, $sKey)); + } + + /** + * @param int $iTimeToClearInHours = 24 + * + * @return bool + */ + public function GC($iTimeToClearInHours = 24) + { + if (0 < $iTimeToClearInHours) + { + \MailSo\Base\Utils::RecTimeDirRemove($this->sDataPath.'/tmp', 60 * 60 * $iTimeToClearInHours, \time()); + return true; + } + + return false; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param bool $bMkDir = false + * + * @return string + */ + private function generateFileName($oAccount, $iStorageType, $sKey, $bMkDir = false) + { + $sEmail = $oAccount ? \preg_replace('/[^a-z0-9\-\.@]+/', '_', + ('' === $oAccount->ParentEmail() ? '' : $oAccount->ParentEmail().'/').$oAccount->Email()) : ''; + + $sTypePath = $sKeyPath = ''; + switch ($iStorageType) + { + case \RainLoop\Providers\Storage\Enumerations\StorageType::TEMP: + $sTypePath = 'tmp'; + $sKeyPath = \md5($sKey); + $sKeyPath = \substr($sKeyPath, 0, 2).'/'.$sKeyPath; + break; + case \RainLoop\Providers\Storage\Enumerations\StorageType::USER: + case \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY: + $sTypePath = 'data'; + $sKeyPath = \md5($sKey); + $sKeyPath = \substr($sKeyPath, 0, 2).'/'.$sKeyPath; + break; + case \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG: + $sTypePath = 'cfg'; + $sKeyPath = \preg_replace('/[_]+/', '_', \preg_replace('/[^a-zA-Z0-9\/]/', '_', $sKey)); + break; + } + + if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY === $iStorageType) + { + $sFilePath = $this->sDataPath.'/'.$sTypePath.'/__nobody__/'.$sKeyPath; + } + else if (!empty($sEmail)) + { + $sFilePath = $this->sDataPath.'/'.$sTypePath.'/'.rtrim(substr($sEmail, 0, 2), '@').'/'.$sEmail.'/'.$sKeyPath; + } + + if ($bMkDir && !empty($sFilePath) && !@\is_dir(\dirname($sFilePath))) + { + if (!@\mkdir(\dirname($sFilePath), 0777, true)) + { + throw new \RainLoop\Exceptions\Exception('Can\'t make storage directory "'.$sFilePath.'"'); + } + } + + return $sFilePath; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php new file mode 100644 index 000000000..7fef10005 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php @@ -0,0 +1,11 @@ +oDriver = $oDriver; + } + + /** + * @param \RainLoop\Account $oAccount + * @param string $sQuery + * + * @return array + */ + public function Process(\RainLoop\Account $oAccount, $sQuery) + { + return $this->oDriver && $this->IsActive() && 0 < \strlen($sQuery) ? $this->oDriver->Process($oAccount, $sQuery) : array(); + } + + /** + * @return bool + */ + public function IsActive() + { + return $this->oDriver instanceof \RainLoop\Providers\Suggestions\SuggestionsInterface; + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Suggestions/SuggestionsInterface.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Suggestions/SuggestionsInterface.php new file mode 100644 index 000000000..ffd3096d3 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Providers/Suggestions/SuggestionsInterface.php @@ -0,0 +1,14 @@ +oHttp = \MailSo\Base\Http::SingletonInstance(); + $this->oActions = Actions::NewInstance(); + + \set_error_handler(array(&$this, 'LogPhpErrorHandler')); + + $this->oServiceActions = new \RainLoop\ServiceActions($this->oHttp, $this->oActions); + + if ($this->oActions->Config()->Get('debug', 'enable', false)) + { + \error_reporting(E_ALL); + \ini_set('display_errors', 1); + } + + $sServer = \trim($this->oActions->Config()->Get('security', 'custom_server_signature', '')); + if (0 < \strlen($sServer)) + { + @\header('Server: '.$sServer, true); + } + } + + /** + * @return \RainLoop\Service + */ + public static function NewInstance() + { + return new self(); + } + + public function LogPhpErrorHandler($errno, $errstr, $errfile, $errline) + { + $iType = \MailSo\Log\Enumerations\Type::NOTICE; + switch ($errno) + { + case E_USER_ERROR: + $iType = \MailSo\Log\Enumerations\Type::ERROR; + break; + case E_USER_WARNING: + $iType = \MailSo\Log\Enumerations\Type::WARNING; + break; + } + + + $this->oActions->Logger()->Write($errfile.' [line:'.$errline.', code:'.$errno.']', $iType, 'PHP'); + $this->oActions->Logger()->Write('Error: '.$errstr, $iType, 'PHP'); + + return false; + } + + /** + * @return \RainLoop\Service + */ + public function Handle() + { + if (!\class_exists('MailSo\Version')) + { + return $this; + } + + $this->oActions->ParseQueryAuthString(); + +// if (defined('APP_INSTALLED_START') && defined('APP_INSTALLED_VERSION') && APP_INSTALLED_START) +// { +// $this->oActions->KeenIO('CoreInstallation', array( +// 'previos-version' => false !== APP_INSTALLED_VERSION ? APP_INSTALLED_VERSION : '' +// )); +// } + + $bCached = false; + $sResult = ''; + $sQuery = \trim(\trim($this->oHttp->GetServer('QUERY_STRING', '')), ' /'); + $iPos = \strpos($sQuery, '&'); + if (0 < $iPos) + { + $sQuery = \substr($sQuery, 0, $iPos); + } + + $this->oActions->Plugins()->RunHook('filter.http-query', array(&$sQuery)); + $aPaths = \explode('/', $sQuery); + $this->oActions->Plugins()->RunHook('filter.http-paths', array(&$aPaths)); + + if (0 < \count($aPaths) && !empty($aPaths[0]) && 'admin' !== \strtolower($aPaths[0]) && 'cp' !== \strtolower($aPaths[0])) + { + $sMethodName = 'Service'.$aPaths[0]; + if (\method_exists($this->oServiceActions, $sMethodName) && + \is_callable(array($this->oServiceActions, $sMethodName))) + { + $this->oServiceActions->SetQuery($sQuery)->SetPaths($aPaths); + $sResult = \call_user_func(array($this->oServiceActions, $sMethodName)); + } + else if (!$this->oActions->Plugins()->RunAdditionalPart($aPaths[0], $aPaths)) + { + $this->oActions->Logger()->Write('Unknown request', \MailSo\Log\Enumerations\Type::WARNING, 'RESPONSE'); + } + } + else + { + $bAdmin = !empty($aPaths[0]) && ('admin' === \strtolower($aPaths[0]) || 'cp' === \strtolower($aPaths[0])); + + @header('Content-Type: text/html; charset=utf-8'); + + $aData = $this->startUpData($bAdmin); + + $bCacheEnabled = $this->oActions->Config()->Get('labs', 'cache_system_data', true); + + $sCacheFileName = ''; + if ($bCacheEnabled) + { + $sCacheFileName = 'TMPL:'.$aData['Hash']; + $sResult = $this->oActions->Cacher()->Get($sCacheFileName); + } + + if (0 === \strlen($sResult)) + { + $sResult = \strtr(\file_get_contents(APP_VERSION_ROOT_PATH.'app/templates/Index.html'), array( + '{{BaseTemplates}}' => \RainLoop\Utils::CompileTemplates(APP_VERSION_ROOT_PATH.'app/templates/Views', $this->oActions). + $this->oActions->Plugins()->CompileTemplate($bAdmin), + '{{BaseIndexFile}}' => APP_SHORT_INDEX_FILE_NAME, + '{{BaseAppDataScriptLink}}' => APP_SHORT_INDEX_FILE_NAME.($bAdmin ? '?/AdminAppData/' : '?/AppData/'), + '{{BaseAppFaviconFile}}' => $aData['FaviconLink'], + '{{BaseAppMainCssLink}}' => $aData['AppCssLink'], + '{{BaseAppJqueryScriptLink}}' => $aData['JqueryJsLink'], + '{{BaseAppLibsScriptLink}}' => $aData['LibJsLink'], + '{{BaseAppMainScriptLink}}' => $aData['AppJsLink'], + '{{BaseDir}}' => \in_array($aData['Language'], array('ar', 'he', 'ur')) ? 'rtl' : 'ltr' + )); + + $sResult = \RainLoop\Utils::ClearHtmlOutput($sResult); + if (0 < \strlen($sCacheFileName)) + { + $this->oActions->Cacher()->Set($sCacheFileName, $sResult); + } + } + else + { + $bCached = true; + } + + $sResult .= ''; + } + + // Output result + echo $sResult; + unset($sResult); + + return $this; + } + + /** + * @param bool $bAppJsDebug + * @param bool $bAdmin + * + * @return string + */ + private function generateIndexCacheHash($bAppJsDebug, $bAdmin) + { + return \md5(APP_WEB_PATH.APP_SHORT_INDEX_FILE_NAME. + $this->oActions->Config()->Get('labs', 'cdn_static_domain', ''). + \md5($this->oActions->Config()->Get('cache', 'index', '')). + $this->oActions->Plugins()->Hash(). + APP_VERSION.($bAppJsDebug ? 'd' : 'm').($bAdmin ? 'a' : 'w')); + } + + /** + * @param bool $bAdmin + * + * @return array + */ + private function startUpData($bAdmin) + { + $sLanguage = 'en'; + $sTheme = 'Default'; + + if (!$bAdmin) + { + list($sLanguage, $sTheme) = $this->oActions->GetLanguageAndTheme(); + } + + $sLanguage = $this->oActions->ValidateLanguage($sLanguage); + $sTheme = $this->oActions->ValidateTheme($sTheme); + + $bAppJsDebug = !!$this->oActions->Config()->Get('labs', 'use_app_debug_js', false); + $sCdnStaticDomain = $this->oActions->Config()->Get('labs', 'cdn_static_domain', ''); + + $sStaticPrefix = APP_WEB_STATIC_PATH; + if (0 < \strlen($sCdnStaticDomain)) + { + $sStaticPrefix = \trim($sCdnStaticDomain, ' /\\').'/'.APP_VERSION.'/static/'; + } + + return array( + 'Language' => $sLanguage, + 'Theme' => $sTheme, + 'Hash' => $this->generateIndexCacheHash($bAppJsDebug, $bAdmin), + 'FaviconLink' => $sStaticPrefix.'favicon.png', + 'AppCssLink' => $sStaticPrefix.'css/app.css', + 'JqueryJsLink' => $sStaticPrefix.'js/jquery.js', + 'LibJsLink' => $sStaticPrefix.'js/libs.js', + 'AppJsLink' => $sStaticPrefix.'js/'.($bAdmin ? 'admin' : 'app').($bAppJsDebug ? '' : '.min').'.js' + ); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/ServiceActions.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/ServiceActions.php new file mode 100644 index 000000000..f660f5dab --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/ServiceActions.php @@ -0,0 +1,887 @@ +oHttp = $oHttp; + $this->oActions = $oActions; + $this->aPaths = array(); + } + + /** + * @return \MailSo\Log\Logger + */ + public function Logger() + { + return $this->oActions->Logger(); + } + + /** + * @return \RainLoop\Plugins\Manager + */ + public function Plugins() + { + return $this->oActions->Plugins(); + } + + /** + * @return \RainLoop\Application + */ + public function Config() + { + return $this->oActions->Config(); + } + + /** + * @return \MailSo\Cache\CacheClient + */ + public function Cacher() + { + return $this->oActions->Cacher(); + } + + /** + * @return \RainLoop\Providers\Storage + */ + public function StorageProvider() + { + return $this->oActions->StorageProvider(); + } + + /** + * @param array $aPaths + * + * @return \RainLoop\ServiceActions + */ + public function SetPaths($aPaths) + { + $this->aPaths = \is_array($aPaths) ? $aPaths : array(); + return $this; + } + + /** + * @param string $sQuery + * + * @return \RainLoop\ServiceActions + */ + public function SetQuery($sQuery) + { + $this->sQuery = $sQuery; + return $this; + } + + /** + * @return string + */ + public function ServiceAjax() + { + @\ob_start(); + + $aResponseItem = null; + $oException = null; + + $sAction = $this->oHttp->GetPost('Action', null); + if (empty($sAction) && $this->oHttp->IsGet() && !empty($this->aPaths[2])) + { + $sAction = $this->aPaths[2]; + } + + try + { + if ($this->oHttp->IsPost() && + $this->Config()->Get('security', 'csrf_protection', false) + && $this->oHttp->GetPost('XToken', '') !== \RainLoop\Utils::GetCsrfToken()) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::InvalidToken); + } + else if (!empty($sAction)) + { + $sMethodName = 'Do'.$sAction; + + $this->Logger()->Write('Action: '.$sMethodName, \MailSo\Log\Enumerations\Type::NOTE, 'AJAX'); + + $aPost = $this->oHttp->GetPostAsArray(); + if (\is_array($aPost) && 0 < \count($aPost)) + { + $this->oActions->SetActionParams($aPost, $sMethodName); + switch ($sMethodName) + { + case 'DoLogin': + case 'DoAdminLogin': + case 'DoAccountAdd': + $this->Logger()->AddSecret($this->oActions->GetActionParam('Password', '')); + break; + case 'DoChangePassword': + $this->Logger()->AddSecret($this->oActions->GetActionParam('PrevPassword', '')); + $this->Logger()->AddSecret($this->oActions->GetActionParam('NewPassword', '')); + break; + } + + $this->Logger()->Write(\MailSo\Base\Utils::Php2js($aPost), \MailSo\Log\Enumerations\Type::INFO, 'POST', true); + } + else if (3 < \count($this->aPaths) && $this->oHttp->IsGet()) + { + $this->oActions->SetActionParams(array( + 'RawKey' => empty($this->aPaths[3]) ? '' : $this->aPaths[3] + ), $sMethodName); + } + + if (\method_exists($this->oActions, $sMethodName) && + \is_callable(array($this->oActions, $sMethodName))) + { + $this->Plugins()->RunHook('ajax.action-pre-call', array($sAction)); + $aResponseItem = \call_user_func(array($this->oActions, $sMethodName)); + $this->Plugins()->RunHook('ajax.action-post-call', array($sAction, &$aResponseItem)); + } + else if ($this->Plugins()->HasAdditionalAjax($sMethodName)) + { + $this->Plugins()->RunHook('ajax.action-pre-call', array($sAction)); + $aResponseItem = $this->Plugins()->RunAdditionalAjax($sMethodName); + $this->Plugins()->RunHook('ajax.action-post-call', array($sAction, &$aResponseItem)); + } + } + + if (!\is_array($aResponseItem)) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::UnknownError); + } + } + catch (\Exception $oException) + { + $bLogout = ('Folders' === $sAction && $oException instanceof \RainLoop\Exceptions\ClientException); + if ($bLogout) + { + $this->oActions->ClearAuthToken(); + } + + $aResponseItem = $this->oActions->ExceptionResponse( + empty($sAction) ? 'Unknown' : $sAction, $oException); + + if ($bLogout && \is_array($aResponseItem)) + { + $aResponseItem['Logout'] = true; + } + } + + if (\is_array($aResponseItem)) + { + $aResponseItem['Time'] = (int) ((\microtime(true) - APP_START) * 1000); + } + + $this->Plugins()->RunHook('filter.ajax-response', array($sAction, &$aResponseItem)); + + @\header('Content-Type: application/json; charset=utf-8'); + $sResult = \MailSo\Base\Utils::Php2js($aResponseItem); + + $sObResult = @\ob_get_clean(); + + if ($this->Logger()->IsEnabled()) + { + if (0 < \strlen($sObResult)) + { + $this->Logger()->Write($sObResult, \MailSo\Log\Enumerations\Type::ERROR, 'OB-DATA'); + } + + if ($oException) + { + $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + + $iLimit = (int) $this->Config()->Get('labs', 'log_ajax_response_write_limit', 0); + $this->Logger()->Write(0 < $iLimit && $iLimit < \strlen($sResult) + ? \substr($sResult, 0, $iLimit).'...' : $sResult, \MailSo\Log\Enumerations\Type::INFO, 'AJAX'); + } + + return $sResult; + } + + /** + * @return string + */ + public function ServiceAppend() + { + @\ob_start(); + $bResponse = false; + $oException = null; + try + { + if (\method_exists($this->oActions, 'Append') && + \is_callable(array($this->oActions, 'Append'))) + { + $this->oActions->SetActionParams($this->oHttp->GetPostAsArray(), 'Append'); + $bResponse = \call_user_func(array($this->oActions, 'Append')); + } + } + catch (\Exception $oException) + { + $bResponse = false; + } + + @\header('Content-Type: text/plain; charset=utf-8'); + $sResult = true === $bResponse ? '1' : '0'; + + $sObResult = @\ob_get_clean(); + if (0 < \strlen($sObResult)) + { + $this->Logger()->Write($sObResult, \MailSo\Log\Enumerations\Type::ERROR, 'OB-DATA'); + } + + if ($oException) + { + $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + + $this->Logger()->Write($sResult, \MailSo\Log\Enumerations\Type::INFO, 'APPEND'); + + return $sResult; + } + + /** + * @param string $sAction + * + * @return string + */ + private function privateUpload($sAction) + { + @\ob_start(); + $aResponseItem = null; + try + { + if (\method_exists($this->oActions, $sAction) && + \is_callable(array($this->oActions, $sAction))) + { + $this->oActions->SetActionParams($this->oHttp->GetQueryAsArray(), $sAction); + + $aResponseItem = \call_user_func(array($this->oActions, $sAction)); + } + + if (!is_array($aResponseItem)) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::UnknownError); + } + } + catch (\Exception $oException) + { + $aResponseItem = $this->oActions->ExceptionResponse($sAction, $oException); + } + + if ('iframe' === $this->oHttp->GetPost('jua-post-type', '')) + { + @\header('Content-Type: text/html; charset=utf-8'); + } + else + { + @\header('Content-Type: application/json; charset=utf-8'); + } + + $this->Plugins()->RunHook('filter.upload-response', array(&$aResponseItem)); + $sResult = \MailSo\Base\Utils::Php2js($aResponseItem); + + $sObResult = @\ob_get_clean(); + if (0 < \strlen($sObResult)) + { + $this->Logger()->Write($sObResult, \MailSo\Log\Enumerations\Type::ERROR, 'OB-DATA'); + } + + $this->Logger()->Write($sResult, \MailSo\Log\Enumerations\Type::INFO, 'UPLOAD'); + + return $sResult; + } + + /** + * @return string + */ + public function ServiceUpload() + { + return $this->privateUpload('Upload'); + } + + /** + * @return string + */ + public function ServiceUploadBackground() + { + return $this->privateUpload('UploadBackground'); + } + + /** + * @return string + */ + public function ServiceRaw() + { + $sResult = ''; + $sRawError = ''; + $sAction = empty($this->aPaths[2]) ? '' : $this->aPaths[2]; + $oException = null; + + try + { + $sRawError = 'Invalid action'; + if (0 !== \strlen($sAction)) + { + $sMethodName = 'Raw'.$sAction; + if (\method_exists($this->oActions, $sMethodName)) + { + $sRawError = ''; + $this->oActions->SetActionParams(array( + 'RawKey' => empty($this->aPaths[3]) ? '' : $this->aPaths[3] + ), $sMethodName); + + if (!\call_user_func(array($this->oActions, $sMethodName))) + { + $sRawError = 'False result'; + } + else + { + $sRawError = ''; + } + } + } + } + catch (\RainLoop\Exceptions\ClientException $oException) + { + $sRawError = 'Exception as result'; + switch ($oException->getCode()) + { + case \RainLoop\Notifications::AuthError: + $sRawError = 'Authentication failed'; + break; + } + } + catch (\Exception $oException) + { + $sRawError = 'Exception as result'; + } + + if (0 < \strlen($sRawError)) + { + $this->oActions->Logger()->Write($sRawError, \MailSo\Log\Enumerations\Type::ERROR); + } + + if ($oException) + { + $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR, 'RAW'); + } + + return $sResult; + } + + /** + * @return string + */ + public function ServiceLang() + { + $sResult = ''; + @\header('Content-Type: application/javascript; charset=utf-8'); + + if (!empty($this->aPaths[2])) + { + $sLanguage = $this->oActions->ValidateLanguage($this->aPaths[2]); + + $bCacheEnabled = $this->Config()->Get('labs', 'cache_system_data', true); + if (!empty($sLanguage) && $bCacheEnabled) + { + $this->oActions->verifyCacheByKey($this->sQuery); + } + + $sCacheFileName = ''; + if ($bCacheEnabled) + { + $sCacheFileName = 'LANG:'.$sLanguage.APP_VERSION; + $sResult = $this->Cacher()->Get($sCacheFileName); + } + + if (0 === \strlen($sResult)) + { + $sResult = $this->compileLanguage($sLanguage, false); + if ($bCacheEnabled) + { + $this->oActions->cacheByKey($this->sQuery); + if (0 < \strlen($sCacheFileName)) + { + $this->Cacher()->Set($sCacheFileName, $sResult); + } + } + } + } + + return $sResult; + } + + /** + * @return string + */ + public function ServicePlugins() + { + $sResult = ''; + $bAdmin = !empty($this->aPaths[2]) && 'Admin' === $this->aPaths[2]; + + @\header('Content-Type: application/javascript; charset=utf-8'); + + $bCacheEnabled = $this->Config()->Get('labs', 'cache_system_data', true); + if ($bCacheEnabled) + { + $this->oActions->verifyCacheByKey($this->sQuery); + } + + $sCacheFileName = ''; + if ($bCacheEnabled) + { + $sCacheFileName = 'PLUGIN:'.$this->oActions->Plugins()->Hash(); + $sResult = $this->Cacher()->Get($sCacheFileName); + } + + if (0 === strlen($sResult)) + { + $sResult = $this->Plugins()->CompileJs($bAdmin); + if ($bCacheEnabled) + { + $this->oActions->cacheByKey($this->sQuery); + if (0 < \strlen($sCacheFileName)) + { + $this->Cacher()->Set($sCacheFileName, $sResult); + } + } + } + + return $sResult; + } + + /** + * @return string + */ + public function ServiceCss() + { + $sResult = ''; + $bCustom = false; + $oAccount = null; + $oSettings = null; + + $bAdmin = !empty($this->aPaths[2]) && 'Admin' === $this->aPaths[2]; + $bJson = !empty($this->aPaths[7]) && 'Json' === $this->aPaths[7]; + + if ($bJson) + { + @\header('Content-Type: application/json; charset=utf-8'); + } + else + { + @\header('Content-Type: text/css; charset=utf-8'); + } + + $sTheme = ''; + if (!empty($this->aPaths[4])) + { + $sTheme = $this->oActions->ValidateTheme($this->aPaths[4]); + if ('Custom' === $sTheme && !empty($this->aPaths[1]) && '0' !== $this->aPaths[1]) + { + $bCustom = true; + $oAccount = $this->oActions->GetAccount(false); + if ($oAccount) + { + $oSettings = $this->oActions->SettingsProvider()->Load($oAccount); + } + } + + $bCacheEnabled = $this->Config()->Get('labs', 'cache_system_data', true); + if ($bCacheEnabled && !$bCustom) + { + $this->oActions->verifyCacheByKey($this->sQuery); + } + + $sCacheFileName = ''; + if ($bCacheEnabled && !$bCustom) + { + $sCacheFileName = 'THEMES/PLUGINS:'.$sTheme.':'.$this->Plugins()->Hash(); + $sResult = $this->Cacher()->Get($sCacheFileName); + } + + if (0 === \strlen($sResult)) + { + try + { + include_once APP_VERSION_ROOT_PATH.'app/libraries/lessphp/ctype.php'; + include_once APP_VERSION_ROOT_PATH.'app/libraries/lessphp/lessc.inc.php'; + + $oLess = new \lessc(); + $oLess->setFormatter('compressed'); + + $aResult = array(); + + $sThemeValuesFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/values.less'; + if ($bCustom) + { + $sThemeFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/custom-values-light.less'; + if ($oSettings) + { + if (\RainLoop\Enumerations\CustomThemeType::LIGHT === (string) $oSettings->GetConf('CustomThemeType', \RainLoop\Enumerations\CustomThemeType::LIGHT)) + { + $sThemeFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/custom-values-light.less'; + } + else + { + $sThemeFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/custom-values-dark.less'; + } + } + } + else + { + $sThemeFile = APP_VERSION_ROOT_PATH.'themes/'.$sTheme.'/styles.less'; + } + + $sThemeTemplateFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/template.less'; + + if (\file_exists($sThemeFile) && \file_exists($sThemeTemplateFile) && \file_exists($sThemeValuesFile)) + { + $aResult[] = '@base: "'.APP_WEB_PATH.'themes/'.$sTheme.'/";'; + $aResult[] = \file_get_contents($sThemeValuesFile); + $aResult[] = \file_get_contents($sThemeFile); + $aResult[] = \file_get_contents($sThemeTemplateFile); + + if (\file_exists(APP_VERSION_ROOT_PATH.'themes/'.$sTheme.'/ext.less')) + { + $aResult[] = \file_get_contents(APP_VERSION_ROOT_PATH.'themes/'.$sTheme.'/ext.less'); + } + } + + $aResult[] = $this->Plugins()->CompileCss($bAdmin); + + $sResult = $oLess->compile(\implode("\n", $aResult)); + + if ($bCustom && $oAccount) + { + $mData = $this->oActions->StorageProvider()->Get($oAccount, StorageType::USER, 'CustomThemeBackground', ''); + if (!empty($mData) && 'data:' === \substr($mData, 0, 5)) + { + $sResult = \str_replace('background-image:link', 'background-image:url("'.$mData.'")', $sResult); + } + } + + if ($bCacheEnabled && !$bCustom) + { + $this->oActions->cacheByKey($this->sQuery); + if (0 < \strlen($sCacheFileName)) + { + $this->Cacher()->Set($sCacheFileName, $sResult); + } + } + } + catch (\Exception $oException) + { + $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR, 'LESS'); + } + } + } + + return $bJson ? \MailSo\Base\Utils::Php2js(array($sTheme, $sResult)) : $sResult; + } + + /** + * @return string + */ + public function ServiceSocialGoogle() + { + return $this->oActions->Social()->GooglePopupService(); + } + + /** + * @return string + */ + public function ServiceSocialFacebook() + { + return $this->oActions->Social()->FacebookPopupService(); + } + + /** + * @return string + */ + public function ServiceSocialTwitter() + { + return $this->oActions->Social()->TwitterPopupService(); + } + + /** + * @return string + */ + public function ServiceAppData() + { + return $this->localAppData(false); + } + + /** + * @return string + */ + public function ServiceAdminAppData() + { + return $this->localAppData(true); + } + + /** + * @return string + */ + public function ServiceNoScript() + { + return $this->localError($this->oActions->StaticI18N('STATIC/NO_SCRIPT_TITLE'), $this->oActions->StaticI18N('STATIC/NO_SCRIPT_DESC')); + } + + /** + * @return string + */ + public function ServiceNoCookie() + { + return $this->localError($this->oActions->StaticI18N('STATIC/NO_COOKIE_TITLE'), $this->oActions->StaticI18N('STATIC/NO_COOKIE_DESC')); + } + + /** + * @return string + */ + public function ServiceBadBrowser() + { + $sTitle = $this->oActions->StaticI18N('STATIC/BAD_BROWSER_TITLE'); + $sDesc = \nl2br($this->oActions->StaticI18N('STATIC/BAD_BROWSER_DESC')); + + @\header('Content-Type: text/html; charset=utf-8'); + return \strtr(\file_get_contents(APP_VERSION_ROOT_PATH.'app/templates/BadBrowser.html'), array( + '{{BaseWebStaticPath}}' => APP_WEB_STATIC_PATH, + '{{ErrorTitle}}' => $sTitle, + '{{ErrorHeader}}' => $sTitle, + '{{ErrorDesc}}' => $sDesc + )); + } + + /** + * @return string + */ + public function ServicePing() + { + @\header('Content-Type: text/plain; charset=utf-8'); + $this->oActions->Logger()->Write('Pong', \MailSo\Log\Enumerations\Type::INFO, 'PING'); + return 'Pong'; + } + + /** + * @return string + */ + public function ServiceInfo() + { + if ($this->oActions->IsAdminLoggined(false)) + { + @\header('Content-Type: text/html; charset=utf-8'); + \phpinfo(); + } + } + + /** + * @return string + */ + public function ServiceExternalLogin() + { + if ($this->oActions->Config()->Get('labs', 'allow_external_login', false)) + { + $oException = null; + try + { + $sEmail = trim($this->oHttp->GetRequest('Email', '')); + $sLogin = trim($this->oHttp->GetRequest('Login', '')); + $sPassword = $this->oHttp->GetRequest('Password', ''); + + $this->oActions->Logger()->AddSecret($sPassword); + + if (0 === \strlen($sLogin)) + { + $sLogin = $sEmail; + } + + $oAccount = $this->oActions->LoginProcess($sEmail, $sLogin, $sPassword); + $this->oActions->AuthProcess($oAccount); + } + catch (\Exception $oException) + { + $this->oActions->Logger()->WriteException($oException); + } + } + + $this->oActions->Location(APP_SHORT_INDEX_FILE_NAME); + return ''; + } + + /** + * @return string + */ + public function ServiceChange() + { + if ($this->Config()->Get('webmail', 'allow_additional_accounts', true)) + { + $oAccountToLogin = null; + $sEmail = empty($this->aPaths[2]) ? '' : \strtolower(\urldecode(\trim($this->aPaths[2]))); + if (!empty($sEmail)) + { + $oAccount = $this->oActions->GetAccount(); + if ($oAccount) + { + $aAccounts = $this->oActions->GetAccounts($oAccount); + if (isset($aAccounts[$sEmail])) + { + $oAccountToLogin = $this->oActions->GetAccountFromCustomToken($aAccounts[$sEmail], false); + } + } + } + + if ($oAccountToLogin) + { + $this->oActions->AuthProcess($oAccountToLogin, true); + } + } + + $this->oActions->Location(APP_SHORT_INDEX_FILE_NAME); + return ''; + } + + /** + * @param string $sTitle + * @param string $sDesc + * + * @return string + */ + private function localError($sTitle, $sDesc) + { + @header('Content-Type: text/html; charset=utf-8'); + return $this->oActions->ErrorTemplates($sTitle, \nl2br($sDesc)); + } + + /** + * @param bool $bAdmin = true + * + * @return string + */ + private function localAppData($bAdmin = false) + { + @\header('Content-Type: application/javascript; charset=utf-8'); + @\header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); + @\header('Last-Modified: '.\gmdate('D, d M Y H:i:s').' GMT'); + @\header('Cache-Control: no-store, no-cache, must-revalidate'); + @\header('Cache-Control: post-check=0, pre-check=0', false); + @\header('Pragma: no-cache'); + + $sAuthAccountHash = ''; + if (!$bAdmin) + { + $sAuthAccountHash = $this->oActions->GetSpecAuthTokenWithDeletion(); + if (empty($sAuthAccountHash)) + { + $sAuthAccountHash = $this->oActions->GetSpecAuthToken(); + } + + if (empty($sAuthAccountHash)) + { + $sSignMeToken = \RainLoop\Utils::GetCookie(\RainLoop\Actions::AUTH_SIGN_ME_TOKEN_KEY, ''); + if (!empty($sSignMeToken)) + { + $oAccount = $this->oActions->GetAccountFromCustomToken($this->StorageProvider()->Get(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + 'SignMe/UserToken/'.$sSignMeToken + ), false); + + if ($oAccount) + { + $this->oActions->AuthProcess($oAccount); + $sAuthAccountHash = $this->oActions->GetSpecAuthToken(); + } + } + } + + $this->oActions->SetSpecAuthToken($sAuthAccountHash); + } + + $sResult = $this->compileAppData($this->oActions->AppData($bAdmin, $sAuthAccountHash), false); + + $this->Logger()->Write($sResult, \MailSo\Log\Enumerations\Type::INFO, 'APPDATA'); + + return $sResult; + } + + /** + * @param string $sLanguage + * @param bool $bWrapByScriptTag = true + * + * @return string + */ + private function compileLanguage($sLanguage, $bWrapByScriptTag = true) + { + $aResultLang = array(); + + $sMoment = 'window.moment && window.moment.lang && window.moment.lang(\'en\');'; + $sMomentFileName = APP_VERSION_ROOT_PATH.'app/i18n/moment/'.$sLanguage.'.js'; + if (\file_exists($sMomentFileName)) + { + $sMoment = \file_get_contents($sMomentFileName); + $sMoment = \preg_replace('/\/\/[^\n]+\n/', '', $sMoment); + } + + \RainLoop\Utils::ReadAndAddLang(APP_VERSION_ROOT_PATH.'app/i18n/langs.ini', $aResultLang); + \RainLoop\Utils::ReadAndAddLang(APP_VERSION_ROOT_PATH.'langs/'.$sLanguage.'.ini', $aResultLang); + + $this->Plugins()->ReadLang($sLanguage, $aResultLang); + + $sLangJs = ''; + $aLangKeys = \array_keys($aResultLang); + foreach ($aLangKeys as $sKey) + { + $sString = isset($aResultLang[$sKey]) ? $aResultLang[$sKey] : $sKey; + + $sLangJs .= '"'.\str_replace('"', '\\"', \str_replace('\\', '\\\\', $sKey)).'":' + .'"'.\str_replace(array("\r", "\n", "\t"), array('\r', '\n', '\t'), + \str_replace('"', '\\"', \str_replace('\\', '\\\\', $sString))).'",'; + } + + $sResult = empty($sLangJs) ? 'null' : '{'.\substr($sLangJs, 0, -1).'}'; + + return + ($bWrapByScriptTag ? '' : '') + ; + } + + /** + * @param array $aAppData + * @param bool $bWrapByScriptTag = true + * + * @return string + */ + private function compileAppData($aAppData, $bWrapByScriptTag = true) + { + return + ($bWrapByScriptTag ? '' : '') + ; + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Settings.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Settings.php new file mode 100644 index 000000000..f766f13bd --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Settings.php @@ -0,0 +1,64 @@ +aData = array(); + } + + /** + * @param array $aData + * + * @return \RainLoop\Settings + */ + public function InitData($aData) + { + if (\is_array($aData)) + { + $this->aData = $aData; + } + + return $this; + } + + /** + * @return array + */ + public function DataAsArray() + { + return $this->aData; + } + + /** + * @param string $sName + * @param mixed $mDefValue = null + * + * @return mixed + */ + public function GetConf($sName, $mDefValue = null) + { + return isset($this->aData[$sName]) ? $this->aData[$sName] : $mDefValue; + } + + /** + * @param string $sName + * @param mixed $mValue + * + * @return void + */ + public function SetConf($sName, $mValue) + { + $this->aData[$sName] = $mValue; + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Social.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Social.php new file mode 100644 index 000000000..1781c8bdf --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Social.php @@ -0,0 +1,894 @@ +oHttp = $oHttp; + $this->oActions = $oActions; + } + + /** + * @param array $oItem + * @param array $aPics + * + * @return array|null + */ + private function convertGoogleJsonContactToResponseContact($oItem, &$aPics) + { + $mResult = null; + if (!empty($oItem['gd$email'][0]['address'])) + { + $mEmail = \strtolower($oItem['gd$email'][0]['address']); + if (\is_array($oItem['gd$email']) && 1 <\count($oItem['gd$email'])) + { + $mEmail = array(); + foreach ($oItem['gd$email'] as $oEmail) + { + if (!empty($oEmail['address'])) + { + $mEmail[] = \strtolower($oEmail['address']); + } + } + } + + $sImg = ''; + if (!empty($oItem['link']) && is_array($oItem['link'])) + { + foreach ($oItem['link'] as $oLink) + { + if ($oLink && isset($oLink['type'], $oLink['href'], $oLink['rel']) && + 'image/*' === $oLink['type'] && '#photo' === \substr($oLink['rel'], -6)) + { + $sImg = $oLink['href']; + break; + } + } + } + + $mResult = array( + 'email' => $mEmail, + 'name' => !empty($oItem['title']['$t']) ? $oItem['title']['$t'] : '' + ); + + if (0 < \strlen($sImg)) + { + $sHash = \RainLoop\Utils::EncodeKeyValues(array( + 'url' => $sImg, + 'type' => 'google_access_token' + )); + + $mData = array(); + if (isset($aPics[$sHash])) + { + $mData = $aPics[$sHash]; + if (!is_array($mData)) + { + $mData = array($mData); + } + } + + if (is_array($mEmail)) + { + $mData = array_merge($mData, $mEmail); + $mData = array_unique($mData); + } + else if (0 < strlen($mEmail)) + { + $mData[] = $mEmail; + } + + if (is_array($mData)) + { + if (1 === count($mData) && !empty($mData[0])) + { + $aPics[$sHash] = $mData[0]; + } + else if (1 < count($mData)) + { + $aPics[$sHash] = $mData; + } + } + } + } + + return $mResult; + } + + /** + * @return array + */ + public function GoogleUserContacts($oAccount) + { + $mResult = false; + $oGoogle = $this->GoogleConnector(); + $aPics = array(); + + if ($oAccount && $oGoogle) + { + $sAccessToken = $this->GoogleAccessToken($oAccount, $oGoogle); + if (!empty($sAccessToken)) + { + $oGoogle->setAccessToken($sAccessToken); + + $aResponse = $oGoogle->fetch('https://www.google.com/m8/feeds/contacts/default/full', array( + 'alt' => 'json' + )); + + if (!empty($aResponse['result']['feed']['entry']) && is_array($aResponse['result']['feed']['entry'])) + { + $mResult = array(); + foreach ($aResponse['result']['feed']['entry'] as $oItem) + { + $aItem = $this->convertGoogleJsonContactToResponseContact($oItem, $aPics); + if ($aItem) + { + if (is_array($aItem['email'])) + { + $aNewItem = $aItem; + unset($aNewItem['email']); + + foreach ($aItem['email'] as $sEmail) + { + $aNewItem['email'] = $sEmail; + $mResult[] = $aNewItem; + } + } + else + { + $mResult[] = $aItem; + } + } + } + } + } + else + { + $this->oActions->Logger()->Write('Empty Google Access Token', \MailSo\Log\Enumerations\Type::ERROR); + } + } + + return false !== $mResult ? array( + 'List' => $mResult, + 'Pics' => $aPics + ) : false; + } + + /** + * @return bool + */ + public function GoogleDisconnect($oAccount) + { + $oGoogle = $this->GoogleConnector(); + if ($oAccount && $oGoogle) + { + $oSettings = $this->oActions->SettingsProvider()->Load($oAccount); + $sEncodedeData = $oSettings->GetConf('GoogleAccessToken', ''); + + if (!empty($sEncodedeData)) + { + $aData = \RainLoop\Utils::DecodeKeyValues($sEncodedeData); + if (is_array($aData) && isset($aData['access_token'], $aData['id'])) + { + $this->oActions->StorageProvider()->Clear(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + $this->GoogleUserLoginStorageKey($oGoogle, $aData['id']) + ); + } + } + + $oSettings->SetConf('GoogleAccessToken', ''); + $oSettings->SetConf('GoogleSocialName', ''); + return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings); + } + + return false; + } + + /** + * @return bool + */ + public function FacebookDisconnect($oAccount) + { + $oFacebook = $this->FacebookConnector($oAccount ? $oAccount : null); + if ($oAccount && $oFacebook) + { + $oUser = $oFacebook->getUser(); + if ($oUser) + { + $mData = false; + try + { + $aData = $oFacebook->api(array( + 'method' => 'fql.query', + 'query' => 'SELECT uid FROM user WHERE uid = me()' + )); + + $mData = isset($aData[0], $aData[0]['uid']) ? $aData[0]['uid'] : false; + } + catch (\Exception $oException) + { + $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + + if (false !== $mData && 0 < \strlen($mData)) + { + $this->oActions->StorageProvider()->Clear(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + $this->FacebookUserLoginStorageKey($oFacebook, $mData)); + } + } + + $oFacebook->UserLogout(); + + $oSettings = $this->oActions->SettingsProvider()->Load($oAccount); + $oSettings->SetConf('FacebookSocialName', ''); + + return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings); + } + + return false; + } + + /** + * @return bool + */ + public function TwitterDisconnect($oAccount) + { + $oTwitter = $this->TwitterConnector(); + if ($oAccount && $oTwitter) + { + $oSettings = $this->oActions->SettingsProvider()->Load($oAccount); + $sEncodedeData = $oSettings->GetConf('TwitterAccessToken', ''); + + if (!empty($sEncodedeData)) + { + $aData = \RainLoop\Utils::DecodeKeyValues($sEncodedeData); + if (is_array($aData) && isset($aData['user_id'])) + { + $this->oActions->StorageProvider()->Clear(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + $this->TwitterUserLoginStorageKey($oTwitter, $aData['user_id']) + ); + } + } + + $oSettings->SetConf('TwitterAccessToken', ''); + $oSettings->SetConf('TwitterSocialName', ''); + return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings); + } + + return false; + } + + /** + * @return string + */ + public function GooglePopupService() + { + $sResult = ''; + $sLoginUrl = ''; + + $bLogin = false; + $iErrorCode = \RainLoop\Notifications::UnknownError; + + try + { + $oGoogle = $this->GoogleConnector(); + if ($this->oHttp->HasQuery('error')) + { + $iErrorCode = ('access_denied' === $this->oHttp->GetQuery('error')) ? + \RainLoop\Notifications::SocialGoogleLoginAccessDisable : \RainLoop\Notifications::UnknownError; + } + else if ($oGoogle) + { + $oAccount = $this->oActions->GetAccount(); + $bLogin = !$oAccount; + + $sCheckToken = ''; + $sCheckAuth = ''; + $sState = $this->oHttp->GetQuery('state'); + if (!empty($sState)) + { + $aParts = explode('|', $sState, 2); + $sCheckToken = !empty($aParts[0]) ? $aParts[0] : ''; + $sCheckAuth = !empty($aParts[1]) ? $aParts[1] : ''; + } + + $sRedirectUrl = $this->oHttp->GetFullUrl().'?SocialGoogle'; + if (!$this->oHttp->HasQuery('code')) + { +// https://www.google.com/m8/feeds/ + $aParams = array( + 'scope' => 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile', + 'state' => \RainLoop\Utils::GetConnectionToken().'|'.$this->oActions->GetSpecAuthToken(), +// 'access_type' => 'offline', +// 'approval_prompt' => 'force', + 'response_type' => 'code' + ); + + $sLoginUrl = $oGoogle->getAuthenticationUrl('https://accounts.google.com/o/oauth2/auth', $sRedirectUrl, $aParams); + } + else if (!empty($sState) && $sCheckToken === \RainLoop\Utils::GetConnectionToken()) + { + if (!empty($sCheckAuth)) + { + $this->oActions->SetSpecAuthToken($sCheckAuth); + $oAccount = $this->oActions->GetAccount(); + $bLogin = !$oAccount; + } + + $aParams = array('code' => $this->oHttp->GetQuery('code'), 'redirect_uri' => $sRedirectUrl); + $aAuthorizationResponse = $oGoogle->getAccessToken('https://accounts.google.com/o/oauth2/token', 'authorization_code', $aParams); + + if (!empty($aAuthorizationResponse['result']['access_token'])) + { + $oGoogle->setAccessToken($aAuthorizationResponse['result']['access_token']); + $aUserinfoResponse = $oGoogle->fetch('https://www.googleapis.com/oauth2/v2/userinfo'); + + if (!empty($aUserinfoResponse['result']['id'])) + { + if ($bLogin) + { + $sUserData = $this->oActions->StorageProvider()->Get(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + $this->GoogleUserLoginStorageKey($oGoogle, $aUserinfoResponse['result']['id']) + ); + + $aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData); + + if ($aUserData && \is_array($aUserData) && + !empty($aUserData['Email']) && + !empty($aUserData['Login']) && + isset($aUserData['Password'])) + { + $oAccount = $this->oActions->LoginProcess($aUserData['Email'], $aUserData['Login'], $aUserData['Password']); + if ($oAccount instanceof \RainLoop\Account) + { + $this->oActions->AuthProcess($oAccount); + + $iErrorCode = 0; + } + } + else + { + $iErrorCode = \RainLoop\Notifications::SocialGoogleLoginAccessDisable; + } + } + + if ($oAccount) + { + $aUserData = array( + 'Email' => $oAccount->Email(), + 'Login' => $oAccount->Login(), + 'Password' => $oAccount->Password() + ); + + $sSocialName = !empty($aUserinfoResponse['result']['name']) ? $aUserinfoResponse['result']['name'] : ''; + $sSocialName .= !empty($aUserinfoResponse['result']['email']) ? ' ('.$aUserinfoResponse['result']['email'].')' : ''; + $sSocialName = \trim($sSocialName); + + $oSettings = $this->oActions->SettingsProvider()->Load($oAccount); + $oSettings->SetConf('GoogleSocialName', $sSocialName); + $this->oActions->SettingsProvider()->Save($oAccount, $oSettings); + + $this->oActions->StorageProvider()->Put(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + $this->GoogleUserLoginStorageKey($oGoogle, $aUserinfoResponse['result']['id']), + \RainLoop\Utils::EncodeKeyValues($aUserData)); + + $iErrorCode = 0; + } + } + } + } + } + } + catch (\Exception $oException) + { + $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + + if ($sLoginUrl) + { + $this->oActions->Location($sLoginUrl); + } + else + { + @\header('Content-Type: text/html; charset=utf-8'); + $sCallBackType = $bLogin ? '_login' : ''; + $sConnectionFunc = 'rl_'.\md5(\RainLoop\Utils::GetConnectionToken()).'_google'.$sCallBackType.'_service'; + $sResult = ''; + } + + return $sResult; + } + + /** + * @return string + */ + public function FacebookPopupService() + { + $sResult = ''; + $sLoginUrl = ''; + $sSocialName = ''; + + $mData = false; + $aUserData = false; + + $bLogin = false; + $iErrorCode = \RainLoop\Notifications::UnknownError; + + $sRedirectUrl = $this->oHttp->GetFullUrl().'?SocialFacebook'; + if (0 < strlen($this->oActions->GetSpecAuthToken())) + { + $sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken(); + } + else if ($this->oHttp->HasQuery('rlah')) + { + $this->oActions->SetSpecAuthToken($this->oHttp->GetQuery('rlah', '')); + $sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken(); + } + + try + { + $oAccount = $this->oActions->GetAccount(); + + $oFacebook = $this->FacebookConnector($oAccount ? $oAccount : null); + if ($oFacebook) + { + if ($oAccount) + { + $oUser = $oFacebook->getUser(); + if (!$oUser && !$this->oHttp->HasQuery('state')) + { + $sLoginUrl = $oFacebook->getLoginUrl(array( + 'display' => 'popup', + 'redirect_uri' => $sRedirectUrl + )); + } + else + { + try + { + $aData = $oFacebook->api(array( + 'method' => 'fql.query', + 'query' => 'SELECT uid, name, username FROM user WHERE uid = me()' + )); + + $mData = isset($aData[0], $aData[0]['uid']) ? $aData[0]['uid'] : false; + + $sSocialName = !empty($aData[0]['name']) ? $aData[0]['name'] : ''; + $sSocialName .= !empty($aData[0]['username']) ? ' ('.$aData[0]['username'].')' : ''; + $sSocialName = \trim($sSocialName); + } + catch (\FacebookApiException $oException) + { + $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + + if (false !== $mData && 0 < \strlen($mData)) + { + $aUserData = array( + 'Email' => $oAccount->Email(), + 'Login' => $oAccount->Login(), + 'Password' => $oAccount->Password() + ); + + $oSettings = $this->oActions->SettingsProvider()->Load($oAccount); + $oSettings->SetConf('FacebookSocialName', $sSocialName); + $this->oActions->SettingsProvider()->Save($oAccount, $oSettings); + + $this->oActions->StorageProvider()->Put(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + $this->FacebookUserLoginStorageKey($oFacebook, $mData), + \RainLoop\Utils::EncodeKeyValues($aUserData)); + + $iErrorCode = 0; + } + } + } + else + { + $bLogin = true; + + $oUser = $oFacebook->getUser(); + if ($oUser) + { + try + { + $aData = $oFacebook->api(array( + 'method' => 'fql.query', + 'query' => 'SELECT uid FROM user WHERE uid = me()' + )); + + $mData = isset($aData[0], $aData[0]['uid']) ? $aData[0]['uid'] : false; + } + catch (\FacebookApiException $oException) + { + } + + if (false !== $mData && 0 < \strlen($mData)) + { + $sUserData = $this->oActions->StorageProvider()->Get(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + $this->FacebookUserLoginStorageKey($oFacebook, $mData)); + + if ($sUserData) + { + $aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData); + } + } + + if ($aUserData && \is_array($aUserData) && + !empty($aUserData['Email']) && + !empty($aUserData['Login']) && + isset($aUserData['Password'])) + { + $oAccount = $this->oActions->LoginProcess($aUserData['Email'], $aUserData['Login'], $aUserData['Password']); + if ($oAccount instanceof \RainLoop\Account) + { + $this->oActions->AuthProcess($oAccount); + + $iErrorCode = 0; + } + } + else + { + $iErrorCode = \RainLoop\Notifications::SocialFacebookLoginAccessDisable; + } + } + else + { + $sLoginUrl = $oFacebook->getLoginUrl(array( + 'display' => 'popup', + 'redirect_uri' => $sRedirectUrl + )); + } + } + } + } + catch (\Exception $oException) + { + $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + + if ($sLoginUrl) + { + $this->oActions->Location($sLoginUrl); + } + else + { + @\header('Content-Type: text/html; charset=utf-8'); + $sCallBackType = $bLogin ? '_login' : ''; + $sConnectionFunc = 'rl_'.\md5(\RainLoop\Utils::GetConnectionToken()).'_facebook'.$sCallBackType.'_service'; + $sResult = ''; + } + + return $sResult; + } + + /** + * @return string + */ + public function TwitterPopupService() + { + $sResult = ''; + $sLoginUrl = ''; + + $sSocialName = ''; + + $bLogin = false; + $iErrorCode = \RainLoop\Notifications::UnknownError; + + $sRedirectUrl = $this->oHttp->GetFullUrl().'?SocialTwitter'; + if (0 < strlen($this->oActions->GetSpecAuthToken())) + { + $sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken(); + } + else if ($this->oHttp->HasQuery('rlah')) + { + $this->oActions->SetSpecAuthToken($this->oHttp->GetQuery('rlah', '')); + $sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken(); + } + + try + { + $oTwitter = $this->TwitterConnector(); + if ($oTwitter) + { + $sSessionKey = \implode('_', array('twitter', + \md5($oTwitter->config['consumer_secret']), \md5(\RainLoop\Utils::GetConnectionToken()), 'AuthSessionData')); + + $oAccount = $this->oActions->GetAccount(); + if ($oAccount) + { + if (isset($_REQUEST['oauth_verifier'])) + { + $sAuth = $this->oActions->Cacher()->Get($sSessionKey); + $oAuth = $sAuth ? \json_decode($sAuth, true) : null; + + if ($oAuth && !empty($oAuth['oauth_token']) && !empty($oAuth['oauth_token_secret'])) + { + $oTwitter->config['user_token'] = $oAuth['oauth_token']; + $oTwitter->config['user_secret'] = $oAuth['oauth_token_secret']; + + $iCode = $oTwitter->request('POST', $oTwitter->url('oauth/access_token', ''), array( + 'oauth_callback' => $sRedirectUrl, + 'oauth_verifier' => $_REQUEST['oauth_verifier'] + )); + + if (200 === $iCode && isset($oTwitter->response['response'])) + { + $this->oActions->Logger()->WriteDump($oTwitter->response['response']); + $aAccessToken = $oTwitter->extract_params($oTwitter->response['response']); + $this->oActions->Logger()->WriteDump($aAccessToken); + if ($aAccessToken && isset($aAccessToken['oauth_token']) && !empty($aAccessToken['user_id'])) + { + $oTwitter->config['user_token'] = $aAccessToken['oauth_token']; + $oTwitter->config['user_secret'] = $aAccessToken['oauth_token_secret']; + + $sSocialName = !empty($aAccessToken['screen_name']) ? '@'.$aAccessToken['screen_name'] : $aAccessToken['user_id']; + $sSocialName = \trim($sSocialName); + + $aUserData = array( + 'Email' => $oAccount->Email(), + 'Login' => $oAccount->Login(), + 'Password' => $oAccount->Password() + ); + + $oSettings = $this->oActions->SettingsProvider()->Load($oAccount); + $oSettings->SetConf('TwitterAccessToken', \RainLoop\Utils::EncodeKeyValues($aAccessToken)); + $oSettings->SetConf('TwitterSocialName', $sSocialName); + $this->oActions->SettingsProvider()->Save($oAccount, $oSettings); + + $this->oActions->StorageProvider()->Put(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + $this->TwitterUserLoginStorageKey($oTwitter, $aAccessToken['user_id']), + \RainLoop\Utils::EncodeKeyValues($aUserData)); + + $iErrorCode = 0; + } + } + } + } + else + { + $aParams = array( + 'oauth_callback' => $sRedirectUrl, + 'x_auth_access_type' => 'read' + ); + + $iCode = $oTwitter->request('POST', $oTwitter->url('oauth/request_token', ''), $aParams); + if (200 === $iCode && isset($oTwitter->response['response'])) + { + $oAuth = $oTwitter->extract_params($oTwitter->response['response']); + if (!empty($oAuth['oauth_token'])) + { + $this->oActions->Cacher()->Set($sSessionKey, \json_encode($oAuth)); + $sLoginUrl = $oTwitter->url('oauth/authenticate', '').'?oauth_token='.$oAuth['oauth_token']; + } + } + } + } + else + { + $bLogin = true; + + if (isset($_REQUEST['oauth_verifier'])) + { + $sAuth = $this->oActions->Cacher()->Get($sSessionKey); + $oAuth = $sAuth ? \json_decode($sAuth, true) : null; + if ($oAuth && !empty($oAuth['oauth_token']) && !empty($oAuth['oauth_token_secret'])) + { + $oTwitter->config['user_token'] = $oAuth['oauth_token']; + $oTwitter->config['user_secret'] = $oAuth['oauth_token_secret']; + + $iCode = $oTwitter->request('POST', $oTwitter->url('oauth/access_token', ''), array( + 'oauth_callback' => $sRedirectUrl, + 'oauth_verifier' => $_REQUEST['oauth_verifier'] + )); + + if (200 === $iCode && isset($oTwitter->response['response'])) + { + $aAccessToken = $oTwitter->extract_params($oTwitter->response['response']); + if ($aAccessToken && isset($aAccessToken['oauth_token']) && !empty($aAccessToken['user_id'])) + { + $sUserData = $this->oActions->StorageProvider()->Get(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + $this->TwitterUserLoginStorageKey($oTwitter, $aAccessToken['user_id']) + ); + + $aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData); + + if ($aUserData && \is_array($aUserData) && + !empty($aUserData['Email']) && + !empty($aUserData['Login']) && + isset($aUserData['Password'])) + { + $oAccount = $this->oActions->LoginProcess($aUserData['Email'], $aUserData['Login'], $aUserData['Password']); + if ($oAccount instanceof \RainLoop\Account) + { + $this->oActions->AuthProcess($oAccount); + + $iErrorCode = 0; + } + } + else + { + $iErrorCode = \RainLoop\Notifications::SocialTwitterLoginAccessDisable; + } + + $this->oActions->Cacher()->Delete($sSessionKey); + } + } + } + } + else + { + $aParams = array( + 'oauth_callback' => $sRedirectUrl, + 'x_auth_access_type' => 'read' + ); + + $iCode = $oTwitter->request('POST', $oTwitter->url('oauth/request_token', ''), $aParams); + if (200 === $iCode && isset($oTwitter->response['response'])) + { + $oAuth = $oTwitter->extract_params($oTwitter->response['response']); + if (!empty($oAuth['oauth_token'])) + { + $this->oActions->Cacher()->Set($sSessionKey, \json_encode($oAuth)); + $sLoginUrl = $oTwitter->url('oauth/authenticate', '').'?oauth_token='.$oAuth['oauth_token']; + } + } + } + } + } + } + catch (\Exception $oException) + { + $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + + if ($sLoginUrl) + { + $this->oActions->Location($sLoginUrl); + } + else + { + @\header('Content-Type: text/html; charset=utf-8'); + $sCallBackType = $bLogin ? '_login' : ''; + $sConnectionFunc = 'rl_'.\md5(\RainLoop\Utils::GetConnectionToken()).'_twitter'.$sCallBackType.'_service'; + $sResult = ''; + } + + return $sResult; + } + + /** + * @return \OAuth2\Client|null + */ + public function GoogleConnector() + { + $oGoogle = false; + $oConfig = $this->oActions->Config(); + if ($oConfig->Get('social', 'google_enable', false) && + '' !== \trim($oConfig->Get('social', 'google_client_id', '')) && + '' !== \trim($oConfig->Get('social', 'google_client_secret', ''))) + { + include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/Client.php'; + include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/IGrantType.php'; + include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/AuthorizationCode.php'; + include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/RefreshToken.php'; + + try + { + $oGoogle = new \OAuth2\Client( + \trim($oConfig->Get('social', 'google_client_id', '')), + \trim($oConfig->Get('social', 'google_client_secret', ''))); + } + catch (\Exception $oException) + { + $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + } + + return false === $oGoogle ? null : $oGoogle; + } + + /** + * @return \tmhOAuth|null + */ + public function TwitterConnector() + { + $oTwitter = false; + $oConfig = $this->oActions->Config(); + if ($oConfig->Get('social', 'twitter_enable', false) && + '' !== \trim($oConfig->Get('social', 'twitter_consumer_key', '')) && + '' !== \trim($oConfig->Get('social', 'twitter_consumer_secret', ''))) + { + include_once APP_VERSION_ROOT_PATH.'app/libraries/tmhOAuth/tmhOAuth.php'; + include_once APP_VERSION_ROOT_PATH.'app/libraries/tmhOAuth/tmhUtilities.php'; + + $oTwitter = new \tmhOAuth(array( + 'consumer_key' => \trim($oConfig->Get('social', 'twitter_consumer_key', '')), + 'consumer_secret' => \trim($oConfig->Get('social', 'twitter_consumer_secret', '')) + )); + } + + return false === $oTwitter ? null : $oTwitter; + } + + /** + * @param \RainLoop\Account|null $oAccount = null + * + * @return \Facebook|null + */ + public function FacebookConnector($oAccount = null) + { + $oFacebook = false; + $oConfig = $this->oActions->Config(); + if ($oConfig->Get('social', 'fb_enable', false) && + '' !== \trim($oConfig->Get('social', 'fb_app_id', '')) && + '' !== \trim($oConfig->Get('social', 'fb_app_secret', ''))) + { + include_once APP_VERSION_ROOT_PATH.'app/libraries/facebook/facebook.php'; + + $oFacebook = new \RainLoopFacebook(array( + 'rlAccount' => $oAccount, + 'rlUserHash' => \RainLoop\Utils::GetConnectionToken(), + 'rlStorageProvaider' => $this->oActions->StorageProvider(), + 'appId' => \trim($oConfig->Get('social', 'fb_app_id', '')), + 'secret' => \trim($oConfig->Get('social', 'fb_app_secret', '')), + 'fileUpload' => false, + 'cookie' => true + )); + } + + return false === $oFacebook ? null : $oFacebook; + } + + /** + * @return string + */ + public function GoogleUserLoginStorageKey($oGoogle, $sGoogleUserId) + { + return \implode('_', array('google', \md5($oGoogle->getClientId()), $sGoogleUserId, APP_SALT)); + } + + /** + * @return string + */ + public function FacebookUserLoginStorageKey($oFacebook, $sFacebookUserId) + { + return \implode('_', array('facebook', \md5($oFacebook->getAppId()), $sFacebookUserId, APP_SALT)); + } + + /** + * @return string + */ + public function TwitterUserLoginStorageKey($oTwitter, $sTwitterUserId) + { + return \implode('_', array('twitter', \md5($oTwitter->config['consumer_secret']), $sTwitterUserId, APP_SALT)); + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/RainLoop/Utils.php b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Utils.php new file mode 100644 index 000000000..5aa74235a --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/RainLoop/Utils.php @@ -0,0 +1,392 @@ +isFile() ? \md5_file($oFile) : $oFile)); + } + } + + return $sResult; + } + + /** + * @param string $FileName + * @param array $aResultLang + * + * @return void + */ + public static function ReadAndAddLang($FileName, &$aResultLang) + { + if (\file_exists($FileName)) + { + $aLang = @\parse_ini_file($FileName, true); + if (\is_array($aLang)) + { + foreach ($aLang as $sKey => $mValue) + { + if (\is_array($mValue)) + { + foreach ($mValue as $sSecKey => $mSecValue) + { + $aResultLang[$sKey.'/'.$sSecKey] = $mSecValue; + } + } + else + { + $aResultLang[$sKey] = $mValue; + } + } + } + } + } + + /** + * @param string $sDir + * @param string $sType = '' + * @return array + */ + public static function FolderFiles($sDir, $sType = '') + { + $aResult = array(); + if (@\is_dir($sDir)) + { + if (false !== ($rDirHandle = @\opendir($sDir))) + { + while (false !== ($sFile = @\readdir($rDirHandle))) + { + if (empty($sType) || $sType === \substr($sFile, -\strlen($sType))) + { + if (\is_file($sDir.'/'.$sFile)) + { + $aResult[] = $sFile; + } + } + } + + @\closedir($rDirHandle); + } + } + + return $aResult; + } + + /** + * @param string $sHtml + * + * @return string + */ + public static function ClearHtmlOutput($sHtml) + { +// return $sHtml; + return \str_replace('> <', '><', + \preg_replace('/[\s]+ /i', ' ', + \preg_replace('/ [\s]+/i', ' ', + \preg_replace('/[\r\n\t]+/', ' ', + $sHtml + )))); + } + + /** + * @param string $sKey + * @return bool + */ + public static function FastCheck($sKey) + { + $bResult = false; + + $aMatches = array(); + if (!empty($sKey) && 0 < \strlen($sKey) && \preg_match('/^(RL[\d]+)\-(.+)\-([^\-]+)$/', $sKey, $aMatches) && 3 === \count($aMatches)) + { + $bResult = $aMatches[3] === \strtoupper(\base_convert(\crc32(\md5( + $aMatches[1].'-'.$aMatches[2].'-')), 10, 32)); + } + + return $bResult; + } + + /** + * @param string $sDirName + * + * @return string + */ + public static function CompileTemplates($sDirName, $oAction) + { + $sResult = ''; + if (\file_exists($sDirName)) + { + $aList = \RainLoop\Utils::FolderFiles($sDirName, '.html'); + + foreach ($aList as $sName) + { + $sTemplateName = \substr($sName, 0, -5); + $sResult .= ''; + } + + $sResult = \trim($sResult); + } + + return $sResult; + } + + /** + * @param string $sName + * @param mixed $mDefault = null + * @return mixed + */ + public static function GetCookie($sName, $mDefault = null) + { + if (null === self::$Cookies) + { + self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); + } + + return isset(self::$Cookies[$sName]) ? self::$Cookies[$sName] : $mDefault; + } + + public static function SetCookie($sName, $sValue = '', $iExpire = 0, $sPath = '/', $sDomain = '', $sSecure = false, $bHttpOnly = false) + { + if (null === self::$Cookies) + { + self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); + } + + self::$Cookies[$sName] = $sValue; + @\setcookie($sName, $sValue, $iExpire, $sPath, $sDomain, $sSecure, $bHttpOnly); + } + + public static function ClearCookie($sName) + { + if (null === self::$Cookies) + { + self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); + } + + unset(self::$Cookies[$sName]); + @\setcookie($sName, '', \time() - 3600 * 24 * 30, '/'); + } + + /** + * @return array + */ + public static function ServicesPics() + { + return array( + 'ebay.com' => 'ebay.jpg', + 'reply.ebay.com' => 'ebay.jpg', + 'reply1.ebay.com' => 'ebay.jpg', + 'reply2.ebay.com' => 'ebay.jpg', + 'reply3.ebay.com' => 'ebay.jpg', + + 'facebook.com' => 'facebook.png', + 'facebookmail.com' => 'facebook.png', + + 'cnet.online.com' => 'cnet.jpg', + 'github.com' => 'github.png', + 'steampowered.com' => 'steam.png', + 'myspace.com' => 'myspace.png', + 'new.myspace.com' => 'myspace.png', + 'youtube.com' => 'youtube.gif', + 'amazon.com' => 'amazon.png', + 'ted.com' => 'ted.png', + 'icloud.com' => 'icloud.jpg', + 'google.com' => 'google.png', + 'plus.google.com' => 'google-plus.png', + + 'email.microsoft.com' => 'microsoft.jpg', + 'microsoftonline.com' => 'microsoft.jpg', + 'microsoft.com' => 'microsoft.jpg', + + 'paypal.com' => 'paypal.jpg', + 'intl.paypal.com' => 'paypal.jpg', + 'e.paypal.com' => 'paypal.jpg', + + 'ea.com' => 'ea.png', + 'em.ea.com' => 'ea.png', + 'battlefieldheroes.com' => 'ea.png', + + 'battle.net' => 'battle.net.png', + 'blizzard.com' => 'battle.net.png', + 'email.blizzard.com' => 'battle.net.png', + 'battlefieldheroes.com' => 'battle.net.png', + + 'twitter.com' => 'twitter.jpg', + 'postmaster.twitter.com' => 'twitter.jpg', + + 'skype.com' => 'skype.png', + 'email.skype.com' => 'skype.png', + + 'apple.com' => 'apple.jpg', + 'id.apple.com' => 'apple.jpg', + + 'onlive.com' => 'onlive.png', + 'news.onlive.com' => 'onlive.png', + + 'asana.com' => 'asana.png', + 'connect.asana.com' => 'asana.png', + ); + } + + public static function CustomBaseConvert($sNumberInput, $sFromBaseInput = '0123456789', $sToBaseInput = '0123456789') + { + if ($sFromBaseInput === $sToBaseInput) + { + return $sNumberInput; + } + + $mFromBase = \str_split($sFromBaseInput, 1); + $mToBase = \str_split($sToBaseInput, 1); + $aNumber = \str_split($sNumberInput, 1); + $iFromLen = \strlen($sFromBaseInput); + $iToLen = \strlen($sToBaseInput); + $numberLen = \strlen($sNumberInput); + $mRetVal = ''; + + if ($sToBaseInput === '0123456789') + { + $mRetVal = 0; + for ($iIndex = 1; $iIndex <= $numberLen; $iIndex++) + { + $mRetVal = \bcadd($mRetVal, \bcmul(\array_search($aNumber[$iIndex - 1], $mFromBase), \bcpow($iFromLen, $numberLen - $iIndex))); + } + + return $mRetVal; + } + + if ($sFromBaseInput != '0123456789') + { + $sBase10 = \RainLoop\Utils::CustomBaseConvert($sNumberInput, $sFromBaseInput, '0123456789'); + } + else + { + $sBase10 = $sNumberInput; + } + + if ($sBase10 < \strlen($sToBaseInput)) + { + return $mToBase[$sBase10]; + } + + while ($sBase10 !== '0') + { + $mRetVal = $mToBase[\bcmod($sBase10, $iToLen)].$mRetVal; + $sBase10 = \bcdiv($sBase10, $iToLen, 0); + } + + return $mRetVal; + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/facebook/base_facebook.php b/rainloop/v/1.2.5.406/app/libraries/facebook/base_facebook.php new file mode 100644 index 000000000..e66e0db11 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/facebook/base_facebook.php @@ -0,0 +1,1442 @@ + + */ +class FacebookApiException extends Exception +{ + /** + * The result from the API server that represents the exception information. + */ + protected $result; + + /** + * Make a new API Exception with the given result. + * + * @param array $result The result from the API server + */ + public function __construct($result) { + $this->result = $result; + + $code = isset($result['error_code']) ? $result['error_code'] : 0; + + if (isset($result['error_description'])) { + // OAuth 2.0 Draft 10 style + $msg = $result['error_description']; + } else if (isset($result['error']) && is_array($result['error'])) { + // OAuth 2.0 Draft 00 style + $msg = $result['error']['message']; + } else if (isset($result['error_msg'])) { + // Rest server style + $msg = $result['error_msg']; + } else { + $msg = 'Unknown Error. Check getResult()'; + } + + parent::__construct($msg, $code); + } + + /** + * Return the associated result object returned by the API server. + * + * @return array The result from the API server + */ + public function getResult() { + return $this->result; + } + + /** + * Returns the associated type for the error. This will default to + * 'Exception' when a type is not available. + * + * @return string + */ + public function getType() { + if (isset($this->result['error'])) { + $error = $this->result['error']; + if (is_string($error)) { + // OAuth 2.0 Draft 10 style + return $error; + } else if (is_array($error)) { + // OAuth 2.0 Draft 00 style + if (isset($error['type'])) { + return $error['type']; + } + } + } + + return 'Exception'; + } + + /** + * To make debugging easier. + * + * @return string The string representation of the error + */ + public function __toString() { + $str = $this->getType() . ': '; + if ($this->code != 0) { + $str .= $this->code . ': '; + } + return $str . $this->message; + } +} + +/** + * Provides access to the Facebook Platform. This class provides + * a majority of the functionality needed, but the class is abstract + * because it is designed to be sub-classed. The subclass must + * implement the four abstract methods listed at the bottom of + * the file. + * + * @author Naitik Shah + */ +abstract class BaseFacebook +{ + /** + * Version. + */ + const VERSION = '3.2.2'; + + /** + * Signed Request Algorithm. + */ + const SIGNED_REQUEST_ALGORITHM = 'HMAC-SHA256'; + + /** + * Default options for curl. + */ + public static $CURL_OPTS = array( + CURLOPT_CONNECTTIMEOUT => 10, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 60, + CURLOPT_USERAGENT => 'facebook-php-3.2', + ); + + /** + * List of query parameters that get automatically dropped when rebuilding + * the current URL. + */ + protected static $DROP_QUERY_PARAMS = array( + 'code', + 'state', + 'signed_request', + ); + + /** + * Maps aliases to Facebook domains. + */ + public static $DOMAIN_MAP = array( + 'api' => 'https://api.facebook.com/', + 'api_video' => 'https://api-video.facebook.com/', + 'api_read' => 'https://api-read.facebook.com/', + 'graph' => 'https://graph.facebook.com/', + 'graph_video' => 'https://graph-video.facebook.com/', + 'www' => 'https://www.facebook.com/', + ); + + /** + * The Application ID. + * + * @var string + */ + protected $appId; + + /** + * The Application App Secret. + * + * @var string + */ + protected $appSecret; + + /** + * The ID of the Facebook user, or 0 if the user is logged out. + * + * @var integer + */ + protected $user; + + /** + * The data from the signed_request token. + */ + protected $signedRequest; + + /** + * A CSRF state variable to assist in the defense against CSRF attacks. + */ + protected $state; + + /** + * The OAuth access token received in exchange for a valid authorization + * code. null means the access token has yet to be determined. + * + * @var string + */ + protected $accessToken = null; + + /** + * Indicates if the CURL based @ syntax for file uploads is enabled. + * + * @var boolean + */ + protected $fileUploadSupport = false; + + /** + * Indicates if we trust HTTP_X_FORWARDED_* headers. + * + * @var boolean + */ + protected $trustForwarded = false; + + /** + * Initialize a Facebook Application. + * + * The configuration: + * - appId: the application ID + * - secret: the application secret + * - fileUpload: (optional) boolean indicating if file uploads are enabled + * + * @param array $config The application configuration + */ + public function __construct($config) { + $this->setAppId($config['appId']); + $this->setAppSecret($config['secret']); + if (isset($config['fileUpload'])) { + $this->setFileUploadSupport($config['fileUpload']); + } + if (isset($config['trustForwarded']) && $config['trustForwarded']) { + $this->trustForwarded = true; + } + $state = $this->getPersistentData('state'); + if (!empty($state)) { + $this->state = $state; + } + } + + /** + * Set the Application ID. + * + * @param string $appId The Application ID + * @return BaseFacebook + */ + public function setAppId($appId) { + $this->appId = $appId; + return $this; + } + + /** + * Get the Application ID. + * + * @return string the Application ID + */ + public function getAppId() { + return $this->appId; + } + + /** + * Set the App Secret. + * + * @param string $apiSecret The App Secret + * @return BaseFacebook + * @deprecated + */ + public function setApiSecret($apiSecret) { + $this->setAppSecret($apiSecret); + return $this; + } + + /** + * Set the App Secret. + * + * @param string $appSecret The App Secret + * @return BaseFacebook + */ + public function setAppSecret($appSecret) { + $this->appSecret = $appSecret; + return $this; + } + + /** + * Get the App Secret. + * + * @return string the App Secret + * @deprecated + */ + public function getApiSecret() { + return $this->getAppSecret(); + } + + /** + * Get the App Secret. + * + * @return string the App Secret + */ + public function getAppSecret() { + return $this->appSecret; + } + + /** + * Set the file upload support status. + * + * @param boolean $fileUploadSupport The file upload support status. + * @return BaseFacebook + */ + public function setFileUploadSupport($fileUploadSupport) { + $this->fileUploadSupport = $fileUploadSupport; + return $this; + } + + /** + * Get the file upload support status. + * + * @return boolean true if and only if the server supports file upload. + */ + public function getFileUploadSupport() { + return $this->fileUploadSupport; + } + + /** + * DEPRECATED! Please use getFileUploadSupport instead. + * + * Get the file upload support status. + * + * @return boolean true if and only if the server supports file upload. + */ + public function useFileUploadSupport() { + return $this->getFileUploadSupport(); + } + + /** + * Sets the access token for api calls. Use this if you get + * your access token by other means and just want the SDK + * to use it. + * + * @param string $access_token an access token. + * @return BaseFacebook + */ + public function setAccessToken($access_token) { + $this->accessToken = $access_token; + return $this; + } + + /** + * Extend an access token, while removing the short-lived token that might + * have been generated via client-side flow. Thanks to http://bit.ly/b0Pt0H + * for the workaround. + */ + public function setExtendedAccessToken() { + try { + // need to circumvent json_decode by calling _oauthRequest + // directly, since response isn't JSON format. + $access_token_response = $this->_oauthRequest( + $this->getUrl('graph', '/oauth/access_token'), + $params = array( + 'client_id' => $this->getAppId(), + 'client_secret' => $this->getAppSecret(), + 'grant_type' => 'fb_exchange_token', + 'fb_exchange_token' => $this->getAccessToken(), + ) + ); + } + catch (FacebookApiException $e) { + // most likely that user very recently revoked authorization. + // In any event, we don't have an access token, so say so. + return false; + } + + if (empty($access_token_response)) { + return false; + } + + $response_params = array(); + parse_str($access_token_response, $response_params); + + if (!isset($response_params['access_token'])) { + return false; + } + + $this->destroySession(); + + $this->setPersistentData( + 'access_token', $response_params['access_token'] + ); + } + + /** + * Determines the access token that should be used for API calls. + * The first time this is called, $this->accessToken is set equal + * to either a valid user access token, or it's set to the application + * access token if a valid user access token wasn't available. Subsequent + * calls return whatever the first call returned. + * + * @return string The access token + */ + public function getAccessToken() { + if ($this->accessToken !== null) { + // we've done this already and cached it. Just return. + return $this->accessToken; + } + + // first establish access token to be the application + // access token, in case we navigate to the /oauth/access_token + // endpoint, where SOME access token is required. + $this->setAccessToken($this->getApplicationAccessToken()); + $user_access_token = $this->getUserAccessToken(); + if ($user_access_token) { + $this->setAccessToken($user_access_token); + } + + return $this->accessToken; + } + + /** + * Determines and returns the user access token, first using + * the signed request if present, and then falling back on + * the authorization code if present. The intent is to + * return a valid user access token, or false if one is determined + * to not be available. + * + * @return string A valid user access token, or false if one + * could not be determined. + */ + protected function getUserAccessToken() { + // first, consider a signed request if it's supplied. + // if there is a signed request, then it alone determines + // the access token. + $signed_request = $this->getSignedRequest(); + if ($signed_request) { + // apps.facebook.com hands the access_token in the signed_request + if (array_key_exists('oauth_token', $signed_request)) { + $access_token = $signed_request['oauth_token']; + $this->setPersistentData('access_token', $access_token); + return $access_token; + } + + // the JS SDK puts a code in with the redirect_uri of '' + if (array_key_exists('code', $signed_request)) { + $code = $signed_request['code']; + if ($code && $code == $this->getPersistentData('code')) { + // short-circuit if the code we have is the same as the one presented + return $this->getPersistentData('access_token'); + } + + $access_token = $this->getAccessTokenFromCode($code, ''); + if ($access_token) { + $this->setPersistentData('code', $code); + $this->setPersistentData('access_token', $access_token); + return $access_token; + } + } + + // signed request states there's no access token, so anything + // stored should be cleared. + $this->clearAllPersistentData(); + return false; // respect the signed request's data, even + // if there's an authorization code or something else + } + + $code = $this->getCode(); + if ($code && $code != $this->getPersistentData('code')) { + $access_token = $this->getAccessTokenFromCode($code); + if ($access_token) { + $this->setPersistentData('code', $code); + $this->setPersistentData('access_token', $access_token); + return $access_token; + } + + // code was bogus, so everything based on it should be invalidated. + $this->clearAllPersistentData(); + return false; + } + + // as a fallback, just return whatever is in the persistent + // store, knowing nothing explicit (signed request, authorization + // code, etc.) was present to shadow it (or we saw a code in $_REQUEST, + // but it's the same as what's in the persistent store) + return $this->getPersistentData('access_token'); + } + + /** + * Retrieve the signed request, either from a request parameter or, + * if not present, from a cookie. + * + * @return string the signed request, if available, or null otherwise. + */ + public function getSignedRequest() { + if (!$this->signedRequest) { + if (!empty($_REQUEST['signed_request'])) { + $this->signedRequest = $this->parseSignedRequest( + $_REQUEST['signed_request']); + } else if (!empty($_COOKIE[$this->getSignedRequestCookieName()])) { + $this->signedRequest = $this->parseSignedRequest( + $_COOKIE[$this->getSignedRequestCookieName()]); + } + } + return $this->signedRequest; + } + + /** + * Get the UID of the connected user, or 0 + * if the Facebook user is not connected. + * + * @return string the UID if available. + */ + public function getUser() { + if ($this->user !== null) { + // we've already determined this and cached the value. + return $this->user; + } + + return $this->user = $this->getUserFromAvailableData(); + } + + /** + * Determines the connected user by first examining any signed + * requests, then considering an authorization code, and then + * falling back to any persistent store storing the user. + * + * @return integer The id of the connected Facebook user, + * or 0 if no such user exists. + */ + protected function getUserFromAvailableData() { + // if a signed request is supplied, then it solely determines + // who the user is. + $signed_request = $this->getSignedRequest(); + if ($signed_request) { + if (array_key_exists('user_id', $signed_request)) { + $user = $signed_request['user_id']; + + if($user != $this->getPersistentData('user_id')){ + $this->clearAllPersistentData(); + } + + $this->setPersistentData('user_id', $signed_request['user_id']); + return $user; + } + + // if the signed request didn't present a user id, then invalidate + // all entries in any persistent store. + $this->clearAllPersistentData(); + return 0; + } + + $user = $this->getPersistentData('user_id', $default = 0); + $persisted_access_token = $this->getPersistentData('access_token'); + + // use access_token to fetch user id if we have a user access_token, or if + // the cached access token has changed. + $access_token = $this->getAccessToken(); + if ($access_token && + $access_token != $this->getApplicationAccessToken() && + !($user && $persisted_access_token == $access_token)) { + $user = $this->getUserFromAccessToken(); + if ($user) { + $this->setPersistentData('user_id', $user); + } else { + $this->clearAllPersistentData(); + } + } + + return $user; + } + + /** + * Get a Login URL for use with redirects. By default, full page redirect is + * assumed. If you are using the generated URL with a window.open() call in + * JavaScript, you can pass in display=popup as part of the $params. + * + * The parameters: + * - redirect_uri: the url to go to after a successful login + * - scope: comma separated list of requested extended perms + * + * @param array $params Provide custom parameters + * @return string The URL for the login flow + */ + public function getLoginUrl($params=array()) { + $this->establishCSRFTokenState(); + $currentUrl = $this->getCurrentUrl(); + + // if 'scope' is passed as an array, convert to comma separated list + $scopeParams = isset($params['scope']) ? $params['scope'] : null; + if ($scopeParams && is_array($scopeParams)) { + $params['scope'] = implode(',', $scopeParams); + } + + return $this->getUrl( + 'www', + 'dialog/oauth', + array_merge(array( + 'client_id' => $this->getAppId(), + 'redirect_uri' => $currentUrl, // possibly overwritten + 'state' => $this->state), + $params)); + } + + /** + * Get a Logout URL suitable for use with redirects. + * + * The parameters: + * - next: the url to go to after a successful logout + * + * @param array $params Provide custom parameters + * @return string The URL for the logout flow + */ + public function getLogoutUrl($params=array()) { + return $this->getUrl( + 'www', + 'logout.php', + array_merge(array( + 'next' => $this->getCurrentUrl(), + 'access_token' => $this->getUserAccessToken(), + ), $params) + ); + } + + /** + * Get a login status URL to fetch the status from Facebook. + * + * The parameters: + * - ok_session: the URL to go to if a session is found + * - no_session: the URL to go to if the user is not connected + * - no_user: the URL to go to if the user is not signed into facebook + * + * @param array $params Provide custom parameters + * @return string The URL for the logout flow + */ + public function getLoginStatusUrl($params=array()) { + return $this->getUrl( + 'www', + 'extern/login_status.php', + array_merge(array( + 'api_key' => $this->getAppId(), + 'no_session' => $this->getCurrentUrl(), + 'no_user' => $this->getCurrentUrl(), + 'ok_session' => $this->getCurrentUrl(), + 'session_version' => 3, + ), $params) + ); + } + + /** + * Make an API call. + * + * @return mixed The decoded response + */ + public function api(/* polymorphic */) { + $args = func_get_args(); + if (is_array($args[0])) { + return $this->_restserver($args[0]); + } else { + return call_user_func_array(array($this, '_graph'), $args); + } + } + + /** + * Constructs and returns the name of the cookie that + * potentially houses the signed request for the app user. + * The cookie is not set by the BaseFacebook class, but + * it may be set by the JavaScript SDK. + * + * @return string the name of the cookie that would house + * the signed request value. + */ + protected function getSignedRequestCookieName() { + return 'fbsr_'.$this->getAppId(); + } + + /** + * Constructs and returns the name of the coookie that potentially contain + * metadata. The cookie is not set by the BaseFacebook class, but it may be + * set by the JavaScript SDK. + * + * @return string the name of the cookie that would house metadata. + */ + protected function getMetadataCookieName() { + return 'fbm_'.$this->getAppId(); + } + + /** + * Get the authorization code from the query parameters, if it exists, + * and otherwise return false to signal no authorization code was + * discoverable. + * + * @return mixed The authorization code, or false if the authorization + * code could not be determined. + */ + protected function getCode() { + if (isset($_REQUEST['code'])) { + if ($this->state !== null && + isset($_REQUEST['state']) && + $this->state === $_REQUEST['state']) { + + // CSRF state has done its job, so clear it + $this->state = null; + $this->clearPersistentData('state'); + return $_REQUEST['code']; + } else { + self::errorLog('CSRF state token does not match one provided.'); + return false; + } + } + + return false; + } + + /** + * Retrieves the UID with the understanding that + * $this->accessToken has already been set and is + * seemingly legitimate. It relies on Facebook's Graph API + * to retrieve user information and then extract + * the user ID. + * + * @return integer Returns the UID of the Facebook user, or 0 + * if the Facebook user could not be determined. + */ + protected function getUserFromAccessToken() { + try { + $user_info = $this->api('/me'); + return $user_info['id']; + } catch (FacebookApiException $e) { + return 0; + } + } + + /** + * Returns the access token that should be used for logged out + * users when no authorization code is available. + * + * @return string The application access token, useful for gathering + * public information about users and applications. + */ + protected function getApplicationAccessToken() { + return $this->appId.'|'.$this->appSecret; + } + + /** + * Lays down a CSRF state token for this process. + * + * @return void + */ + protected function establishCSRFTokenState() { + if ($this->state === null) { + $this->state = md5(uniqid(mt_rand(), true)); + $this->setPersistentData('state', $this->state); + } + } + + /** + * Retrieves an access token for the given authorization code + * (previously generated from www.facebook.com on behalf of + * a specific user). The authorization code is sent to graph.facebook.com + * and a legitimate access token is generated provided the access token + * and the user for which it was generated all match, and the user is + * either logged in to Facebook or has granted an offline access permission. + * + * @param string $code An authorization code. + * @return mixed An access token exchanged for the authorization code, or + * false if an access token could not be generated. + */ + protected function getAccessTokenFromCode($code, $redirect_uri = null) { + if (empty($code)) { + return false; + } + + if ($redirect_uri === null) { + $redirect_uri = $this->getCurrentUrl(); + } + + try { + // need to circumvent json_decode by calling _oauthRequest + // directly, since response isn't JSON format. + $access_token_response = + $this->_oauthRequest( + $this->getUrl('graph', '/oauth/access_token'), + $params = array('client_id' => $this->getAppId(), + 'client_secret' => $this->getAppSecret(), + 'redirect_uri' => $redirect_uri, + 'code' => $code)); + } catch (FacebookApiException $e) { + // most likely that user very recently revoked authorization. + // In any event, we don't have an access token, so say so. + return false; + } + + if (empty($access_token_response)) { + return false; + } + + $response_params = array(); + parse_str($access_token_response, $response_params); + if (!isset($response_params['access_token'])) { + return false; + } + + return $response_params['access_token']; + } + + /** + * Invoke the old restserver.php endpoint. + * + * @param array $params Method call object + * + * @return mixed The decoded response object + * @throws FacebookApiException + */ + protected function _restserver($params) { + // generic application level parameters + $params['api_key'] = $this->getAppId(); + $params['format'] = 'json-strings'; + + $result = json_decode($this->_oauthRequest( + $this->getApiUrl($params['method']), + $params + ), true); + + // results are returned, errors are thrown + if (is_array($result) && isset($result['error_code'])) { + $this->throwAPIException($result); + // @codeCoverageIgnoreStart + } + // @codeCoverageIgnoreEnd + + $method = strtolower($params['method']); + if ($method === 'auth.expiresession' || + $method === 'auth.revokeauthorization') { + $this->destroySession(); + } + + return $result; + } + + /** + * Return true if this is video post. + * + * @param string $path The path + * @param string $method The http method (default 'GET') + * + * @return boolean true if this is video post + */ + protected function isVideoPost($path, $method = 'GET') { + if ($method == 'POST' && preg_match("/^(\/)(.+)(\/)(videos)$/", $path)) { + return true; + } + return false; + } + + /** + * Invoke the Graph API. + * + * @param string $path The path (required) + * @param string $method The http method (default 'GET') + * @param array $params The query/post data + * + * @return mixed The decoded response object + * @throws FacebookApiException + */ + protected function _graph($path, $method = 'GET', $params = array()) { + if (is_array($method) && empty($params)) { + $params = $method; + $method = 'GET'; + } + $params['method'] = $method; // method override as we always do a POST + + if ($this->isVideoPost($path, $method)) { + $domainKey = 'graph_video'; + } else { + $domainKey = 'graph'; + } + + $result = json_decode($this->_oauthRequest( + $this->getUrl($domainKey, $path), + $params + ), true); + + // results are returned, errors are thrown + if (is_array($result) && isset($result['error'])) { + $this->throwAPIException($result); + // @codeCoverageIgnoreStart + } + // @codeCoverageIgnoreEnd + + return $result; + } + + /** + * Make a OAuth Request. + * + * @param string $url The path (required) + * @param array $params The query/post data + * + * @return string The decoded response object + * @throws FacebookApiException + */ + protected function _oauthRequest($url, $params) { + if (!isset($params['access_token'])) { + $params['access_token'] = $this->getAccessToken(); + } + + // json_encode all params values that are not strings + foreach ($params as $key => $value) { + if (!is_string($value)) { + $params[$key] = json_encode($value); + } + } + + return $this->makeRequest($url, $params); + } + + /** + * Makes an HTTP request. This method can be overridden by subclasses if + * developers want to do fancier things or use something other than curl to + * make the request. + * + * @param string $url The URL to make the request to + * @param array $params The parameters to use for the POST body + * @param CurlHandler $ch Initialized curl handle + * + * @return string The response text + */ + protected function makeRequest($url, $params, $ch=null) { + if (!$ch) { + $ch = curl_init(); + } + + $opts = self::$CURL_OPTS; + if ($this->getFileUploadSupport()) { + $opts[CURLOPT_POSTFIELDS] = $params; + } else { + $opts[CURLOPT_POSTFIELDS] = http_build_query($params, null, '&'); + } + $opts[CURLOPT_URL] = $url; + + // disable the 'Expect: 100-continue' behaviour. This causes CURL to wait + // for 2 seconds if the server does not support this header. + if (isset($opts[CURLOPT_HTTPHEADER])) { + $existing_headers = $opts[CURLOPT_HTTPHEADER]; + $existing_headers[] = 'Expect:'; + $opts[CURLOPT_HTTPHEADER] = $existing_headers; + } else { + $opts[CURLOPT_HTTPHEADER] = array('Expect:'); + } + + curl_setopt_array($ch, $opts); + curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/fb_ca_chain_bundle.crt'); + $result = curl_exec($ch); + +// if (curl_errno($ch) == 60) { // CURLE_SSL_CACERT +// self::errorLog('Invalid or no certificate authority found, '. +// 'using bundled information'); +// curl_setopt($ch, CURLOPT_CAINFO, +// dirname(__FILE__) . '/fb_ca_chain_bundle.crt'); +// $result = curl_exec($ch); +// } + + // With dual stacked DNS responses, it's possible for a server to + // have IPv6 enabled but not have IPv6 connectivity. If this is + // the case, curl will try IPv4 first and if that fails, then it will + // fall back to IPv6 and the error EHOSTUNREACH is returned by the + // operating system. + if ($result === false && empty($opts[CURLOPT_IPRESOLVE])) { + $matches = array(); + $regex = '/Failed to connect to ([^:].*): Network is unreachable/'; + if (preg_match($regex, curl_error($ch), $matches)) { + if (strlen(@inet_pton($matches[1])) === 16) { + self::errorLog('Invalid IPv6 configuration on server, '. + 'Please disable or get native IPv6 on your server.'); + self::$CURL_OPTS[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4; + curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + $result = curl_exec($ch); + } + } + } + + if ($result === false) { + $e = new FacebookApiException(array( + 'error_code' => curl_errno($ch), + 'error' => array( + 'message' => curl_error($ch), + 'type' => 'CurlException', + ), + )); + curl_close($ch); + throw $e; + } + curl_close($ch); + return $result; + } + + /** + * Parses a signed_request and validates the signature. + * + * @param string $signed_request A signed token + * @return array The payload inside it or null if the sig is wrong + */ + protected function parseSignedRequest($signed_request) { + list($encoded_sig, $payload) = explode('.', $signed_request, 2); + + // decode the data + $sig = self::base64UrlDecode($encoded_sig); + $data = json_decode(self::base64UrlDecode($payload), true); + + if (strtoupper($data['algorithm']) !== self::SIGNED_REQUEST_ALGORITHM) { + self::errorLog( + 'Unknown algorithm. Expected ' . self::SIGNED_REQUEST_ALGORITHM); + return null; + } + + // check sig + $expected_sig = hash_hmac('sha256', $payload, + $this->getAppSecret(), $raw = true); + if ($sig !== $expected_sig) { + self::errorLog('Bad Signed JSON signature!'); + return null; + } + + return $data; + } + + /** + * Makes a signed_request blob using the given data. + * + * @param array The data array. + * @return string The signed request. + */ + protected function makeSignedRequest($data) { + if (!is_array($data)) { + throw new InvalidArgumentException( + 'makeSignedRequest expects an array. Got: ' . print_r($data, true)); + } + $data['algorithm'] = self::SIGNED_REQUEST_ALGORITHM; + $data['issued_at'] = time(); + $json = json_encode($data); + $b64 = self::base64UrlEncode($json); + $raw_sig = hash_hmac('sha256', $b64, $this->getAppSecret(), $raw = true); + $sig = self::base64UrlEncode($raw_sig); + return $sig.'.'.$b64; + } + + /** + * Build the URL for api given parameters. + * + * @param $method String the method name. + * @return string The URL for the given parameters + */ + protected function getApiUrl($method) { + static $READ_ONLY_CALLS = + array('admin.getallocation' => 1, + 'admin.getappproperties' => 1, + 'admin.getbannedusers' => 1, + 'admin.getlivestreamvialink' => 1, + 'admin.getmetrics' => 1, + 'admin.getrestrictioninfo' => 1, + 'application.getpublicinfo' => 1, + 'auth.getapppublickey' => 1, + 'auth.getsession' => 1, + 'auth.getsignedpublicsessiondata' => 1, + 'comments.get' => 1, + 'connect.getunconnectedfriendscount' => 1, + 'dashboard.getactivity' => 1, + 'dashboard.getcount' => 1, + 'dashboard.getglobalnews' => 1, + 'dashboard.getnews' => 1, + 'dashboard.multigetcount' => 1, + 'dashboard.multigetnews' => 1, + 'data.getcookies' => 1, + 'events.get' => 1, + 'events.getmembers' => 1, + 'fbml.getcustomtags' => 1, + 'feed.getappfriendstories' => 1, + 'feed.getregisteredtemplatebundlebyid' => 1, + 'feed.getregisteredtemplatebundles' => 1, + 'fql.multiquery' => 1, + 'fql.query' => 1, + 'friends.arefriends' => 1, + 'friends.get' => 1, + 'friends.getappusers' => 1, + 'friends.getlists' => 1, + 'friends.getmutualfriends' => 1, + 'gifts.get' => 1, + 'groups.get' => 1, + 'groups.getmembers' => 1, + 'intl.gettranslations' => 1, + 'links.get' => 1, + 'notes.get' => 1, + 'notifications.get' => 1, + 'pages.getinfo' => 1, + 'pages.isadmin' => 1, + 'pages.isappadded' => 1, + 'pages.isfan' => 1, + 'permissions.checkavailableapiaccess' => 1, + 'permissions.checkgrantedapiaccess' => 1, + 'photos.get' => 1, + 'photos.getalbums' => 1, + 'photos.gettags' => 1, + 'profile.getinfo' => 1, + 'profile.getinfooptions' => 1, + 'stream.get' => 1, + 'stream.getcomments' => 1, + 'stream.getfilters' => 1, + 'users.getinfo' => 1, + 'users.getloggedinuser' => 1, + 'users.getstandardinfo' => 1, + 'users.hasapppermission' => 1, + 'users.isappuser' => 1, + 'users.isverified' => 1, + 'video.getuploadlimits' => 1); + $name = 'api'; + if (isset($READ_ONLY_CALLS[strtolower($method)])) { + $name = 'api_read'; + } else if (strtolower($method) == 'video.upload') { + $name = 'api_video'; + } + return self::getUrl($name, 'restserver.php'); + } + + /** + * Build the URL for given domain alias, path and parameters. + * + * @param $name string The name of the domain + * @param $path string Optional path (without a leading slash) + * @param $params array Optional query parameters + * + * @return string The URL for the given parameters + */ + protected function getUrl($name, $path='', $params=array()) { + $url = self::$DOMAIN_MAP[$name]; + if ($path) { + if ($path[0] === '/') { + $path = substr($path, 1); + } + $url .= $path; + } + if ($params) { + $url .= '?' . http_build_query($params, null, '&'); + } + + return $url; + } + + protected function getHttpHost() { + if ($this->trustForwarded && isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { + return $_SERVER['HTTP_X_FORWARDED_HOST']; + } + return $_SERVER['HTTP_HOST']; + } + + protected function getHttpProtocol() { + if ($this->trustForwarded && isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { + if ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { + return 'https'; + } + return 'http'; + } + /*apache + variants specific way of checking for https*/ + if (isset($_SERVER['HTTPS']) && + ($_SERVER['HTTPS'] === 'on' || $_SERVER['HTTPS'] == 1)) { + return 'https'; + } + /*nginx way of checking for https*/ + if (isset($_SERVER['SERVER_PORT']) && + ($_SERVER['SERVER_PORT'] === '443')) { + return 'https'; + } + return 'http'; + } + + /** + * Get the base domain used for the cookie. + */ + protected function getBaseDomain() { + // The base domain is stored in the metadata cookie if not we fallback + // to the current hostname + $metadata = $this->getMetadataCookie(); + if (array_key_exists('base_domain', $metadata) && + !empty($metadata['base_domain'])) { + return trim($metadata['base_domain'], '.'); + } + return $this->getHttpHost(); + } + + /** + + /** + * Returns the Current URL, stripping it of known FB parameters that should + * not persist. + * + * @return string The current URL + */ + protected function getCurrentUrl() { + $protocol = $this->getHttpProtocol() . '://'; + $host = $this->getHttpHost(); + $currentUrl = $protocol.$host.$_SERVER['REQUEST_URI']; + $parts = parse_url($currentUrl); + + $query = ''; + if (!empty($parts['query'])) { + // drop known fb params + $params = explode('&', $parts['query']); + $retained_params = array(); + foreach ($params as $param) { + if ($this->shouldRetainParam($param)) { + $retained_params[] = $param; + } + } + + if (!empty($retained_params)) { + $query = '?'.implode($retained_params, '&'); + } + } + + // use port if non default + $port = + isset($parts['port']) && + (($protocol === 'http://' && $parts['port'] !== 80) || + ($protocol === 'https://' && $parts['port'] !== 443)) + ? ':' . $parts['port'] : ''; + + // rebuild + return $protocol . $parts['host'] . $port . $parts['path'] . $query; + } + + /** + * Returns true if and only if the key or key/value pair should + * be retained as part of the query string. This amounts to + * a brute-force search of the very small list of Facebook-specific + * params that should be stripped out. + * + * @param string $param A key or key/value pair within a URL's query (e.g. + * 'foo=a', 'foo=', or 'foo'. + * + * @return boolean + */ + protected function shouldRetainParam($param) { + foreach (self::$DROP_QUERY_PARAMS as $drop_query_param) { + if (strpos($param, $drop_query_param.'=') === 0) { + return false; + } + } + + return true; + } + + /** + * Analyzes the supplied result to see if it was thrown + * because the access token is no longer valid. If that is + * the case, then we destroy the session. + * + * @param $result array A record storing the error message returned + * by a failed API call. + */ + protected function throwAPIException($result) { + $e = new FacebookApiException($result); + switch ($e->getType()) { + // OAuth 2.0 Draft 00 style + case 'OAuthException': + // OAuth 2.0 Draft 10 style + case 'invalid_token': + // REST server errors are just Exceptions + case 'Exception': + $message = $e->getMessage(); + if ((strpos($message, 'Error validating access token') !== false) || + (strpos($message, 'Invalid OAuth access token') !== false) || + (strpos($message, 'An active access token must be used') !== false) + ) { + $this->destroySession(); + } + break; + } + + throw $e; + } + + + /** + * Prints to the error log if you aren't in command line mode. + * + * @param string $msg Log message + */ + protected static function errorLog($msg) { + // disable error log if we are running in a CLI environment + // @codeCoverageIgnoreStart + if (php_sapi_name() != 'cli') { + error_log($msg); + } + // uncomment this if you want to see the errors on the page + // print 'error_log: '.$msg."\n"; + // @codeCoverageIgnoreEnd + } + + /** + * Base64 encoding that doesn't need to be urlencode()ed. + * Exactly the same as base64_encode except it uses + * - instead of + + * _ instead of / + * No padded = + * + * @param string $input base64UrlEncoded string + * @return string + */ + protected static function base64UrlDecode($input) { + return base64_decode(strtr($input, '-_', '+/')); + } + + /** + * Base64 encoding that doesn't need to be urlencode()ed. + * Exactly the same as base64_encode except it uses + * - instead of + + * _ instead of / + * + * @param string $input string + * @return string base64Url encoded string + */ + protected static function base64UrlEncode($input) { + $str = strtr(base64_encode($input), '+/', '-_'); + $str = str_replace('=', '', $str); + return $str; + } + + /** + * Destroy the current session + */ + public function destroySession() { + $this->accessToken = null; + $this->signedRequest = null; + $this->user = null; + $this->clearAllPersistentData(); + + // Javascript sets a cookie that will be used in getSignedRequest that we + // need to clear if we can + $cookie_name = $this->getSignedRequestCookieName(); + if (array_key_exists($cookie_name, $_COOKIE)) { + unset($_COOKIE[$cookie_name]); + if (!headers_sent()) { + $base_domain = $this->getBaseDomain(); + setcookie($cookie_name, '', 1, '/', '.'.$base_domain); + } else { + // @codeCoverageIgnoreStart + self::errorLog( + 'There exists a cookie that we wanted to clear that we couldn\'t '. + 'clear because headers was already sent. Make sure to do the first '. + 'API call before outputing anything.' + ); + // @codeCoverageIgnoreEnd + } + } + } + + /** + * Parses the metadata cookie that our Javascript API set + * + * @return an array mapping key to value + */ + protected function getMetadataCookie() { + $cookie_name = $this->getMetadataCookieName(); + if (!array_key_exists($cookie_name, $_COOKIE)) { + return array(); + } + + // The cookie value can be wrapped in "-characters so remove them + $cookie_value = trim($_COOKIE[$cookie_name], '"'); + + if (empty($cookie_value)) { + return array(); + } + + $parts = explode('&', $cookie_value); + $metadata = array(); + foreach ($parts as $part) { + $pair = explode('=', $part, 2); + if (!empty($pair[0])) { + $metadata[urldecode($pair[0])] = + (count($pair) > 1) ? urldecode($pair[1]) : ''; + } + } + + return $metadata; + } + + protected static function isAllowedDomain($big, $small) { + if ($big === $small) { + return true; + } + return self::endsWith($big, '.'.$small); + } + + protected static function endsWith($big, $small) { + $len = strlen($small); + if ($len === 0) { + return true; + } + return substr($big, -$len) === $small; + } + + /** + * Each of the following four methods should be overridden in + * a concrete subclass, as they are in the provided Facebook class. + * The Facebook class uses PHP sessions to provide a primitive + * persistent store, but another subclass--one that you implement-- + * might use a database, memcache, or an in-memory cache. + * + * @see Facebook + */ + + /** + * Stores the given ($key, $value) pair, so that future calls to + * getPersistentData($key) return $value. This call may be in another request. + * + * @param string $key + * @param array $value + * + * @return void + */ + abstract protected function setPersistentData($key, $value); + + /** + * Get the data for $key, persisted by BaseFacebook::setPersistentData() + * + * @param string $key The key of the data to retrieve + * @param boolean $default The default value to return if $key is not found + * + * @return mixed + */ + abstract protected function getPersistentData($key, $default = false); + + /** + * Clear the data with $key from the persistent storage + * + * @param string $key + * @return void + */ + abstract protected function clearPersistentData($key); + + /** + * Clear all data from the persistent storage + * + * @return void + */ + abstract protected function clearAllPersistentData(); +} diff --git a/rainloop/v/1.2.5.406/app/libraries/facebook/facebook.php b/rainloop/v/1.2.5.406/app/libraries/facebook/facebook.php new file mode 100644 index 000000000..f838245d0 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/facebook/facebook.php @@ -0,0 +1,119 @@ +rlUserHash = ''; + $this->rlAccount = null; + $this->rlStorageProvaider = null; + + if (!empty($config['rlStorageProvaider'])) + { + $this->rlStorageProvaider = $config['rlStorageProvaider']; + } + + if (!empty($config['rlAccount'])) + { + $this->rlAccount = $config['rlAccount']; + } + + if (!empty($config['rlUserHash'])) + { + $this->rlUserHash = (string) $config['rlUserHash']; + } + + if (!class_exists('\\RainLoop\\Providers\\Storage\\Enumerations\\StorageType') || '' === $this->rlUserHash) + { + $this->rlStorageProvaider = null; + } + + parent::__construct($config); + } + + public function UserLogout() + { + $this->clearAllPersistentData(); + } + + protected function setPersistentData($key, $value) + { + if (!in_array($key, self::$kSupportedKeys)) + { + self::errorLog('Unsupported key passed to setPersistentData.'); + return; + } + + $session_var_name = $this->constructSessionVariableName($key); + if ($this->rlStorageProvaider) + { + $this->rlStorageProvaider->Put( + $this->rlAccount ? $this->rlAccount : null, + $this->rlAccount ? \RainLoop\Providers\Storage\Enumerations\StorageType::USER : + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + $session_var_name, $value); + } + } + + protected function getPersistentData($key, $default = false) + { + if (!in_array($key, self::$kSupportedKeys)) + { + self::errorLog('Unsupported key passed to getPersistentData.'); + return $default; + } + + $session_var_name = $this->constructSessionVariableName($key); + if ($this->rlStorageProvaider) + { + return $this->rlStorageProvaider->Get( + $this->rlAccount ? $this->rlAccount : null, + $this->rlAccount ? \RainLoop\Providers\Storage\Enumerations\StorageType::USER : + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + $session_var_name, $default); + } + } + + protected function clearPersistentData($key) + { + if (!in_array($key, self::$kSupportedKeys)) + { + self::errorLog('Unsupported key passed to clearPersistentData.'); + return; + } + + $session_var_name = $this->constructSessionVariableName($key); + if ($this->rlStorageProvaider) + { + $this->rlStorageProvaider->Clear( + $this->rlAccount ? $this->rlAccount : null, + $this->rlAccount ? \RainLoop\Providers\Storage\Enumerations\StorageType::USER : + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + $session_var_name); + } + } + + protected function clearAllPersistentData() + { + foreach (self::$kSupportedKeys as $key) + { + $this->clearPersistentData($key); + } + } + + protected function constructSessionVariableName($key) + { + $parts = array('fb', $this->getAppId(), $key, md5($this->rlUserHash)); + return implode('_', $parts); + } +} diff --git a/rainloop/v/1.2.5.406/app/libraries/facebook/fb_ca_chain_bundle.crt b/rainloop/v/1.2.5.406/app/libraries/facebook/fb_ca_chain_bundle.crt new file mode 100644 index 000000000..969239ff6 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/facebook/fb_ca_chain_bundle.crt @@ -0,0 +1,3920 @@ +## +## ca-bundle.crt -- Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Thu Oct 18 19:05:59 2012 +## +## This is a bundle of X.509 certificates of public Certificate Authorities +## (CA). These were automatically extracted from Mozilla's root certificates +## file (certdata.txt). This file can be found in the mozilla source tree: +## http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1 +## +## It contains the certificates in PEM format and therefore +## can be directly used with curl / libcurl / php_curl, or with +## an Apache+mod_ssl webserver for SSL client authentication. +## Just configure this file as the SSLCACertificateFile. +## + +# @(#) $RCSfile: certdata.txt,v $ $Revision: 1.86 $ $Date: 2012/10/18 16:26:52 $ + +GTE CyberTrust Global Root +========================== +-----BEGIN CERTIFICATE----- +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg +Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG +A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz +MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL +Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0 +IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u +sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql +HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID +AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW +M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF +NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +-----END CERTIFICATE----- + +Thawte Server CA +================ +-----BEGIN CERTIFICATE----- +MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs +dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UE +AxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5j +b20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNV +BAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29u +c3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcG +A1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0 +ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl +/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg7 +1CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzAR +MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9J +GubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZ +GCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc= +-----END CERTIFICATE----- + +Thawte Premium Server CA +======================== +-----BEGIN CERTIFICATE----- +MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs +dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE +AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl +ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT +AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU +VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2 +aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ +cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2 +aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh +Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/ +qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm +SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf +8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t +UCemDaYj+bvLpgcUQg== +-----END CERTIFICATE----- + +Equifax Secure CA +================= +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE +ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT +B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR +fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW +8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG +A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE +CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG +A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS +spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB +Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961 +zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB +BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95 +70+sB3c4 +-----END CERTIFICATE----- + +Digital Signature Trust Co. Global CA 1 +======================================= +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE +ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMTAeFw05ODEy +MTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs +IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJE +NySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2i +o74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo +BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0 +dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw +IoAPMTk5ODEyMTAxODEwMjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQY +MBaAFGp5fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i+DAM +BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB +ACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lNQseSJqBcNJo4cvj9axY+IO6CizEq +kzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4 +RbyhkwS7hp86W0N6w4pl +-----END CERTIFICATE----- + +Digital Signature Trust Co. Global CA 3 +======================================= +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE +ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMjAeFw05ODEy +MDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs +IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGOD +VvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JS +xhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo +BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0 +dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw +IoAPMTk5ODEyMDkxOTE3MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQY +MBaAFB6CTShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5WzAM +BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB +AEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHRxdf0CiUPPXiBng+xZ8SQTGPdXqfi +up/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVLB3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1 +mPnHfxsb1gYgAlihw6ID +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority +======================================================= +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMx +FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVow +XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz +IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94 +f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol +hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBAgUAA4GBALtMEivPLCYA +TxQT3ab7/AoRhIzzKBxnki98tsX63/Dolbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59Ah +WM1pF+NEHJwZRDmJXNycAA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2Omuf +Tqj/ZA1k +-----END CERTIFICATE----- + +Verisign Class 1 Public Primary Certification Authority - G2 +============================================================ +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz +dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz +dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgd +k4xWArzZbxpvUjZudVYKVdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIq +WpDBucSmFc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQIDAQAB +MA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0Jh9ZrbWB85a7FkCMM +XErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2uluIncrKTdcu1OofdPvAbT6shkdHvC +lUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68DzFc6PLZ +-----END CERTIFICATE----- + +Verisign Class 2 Public Primary Certification Authority - G2 +============================================================ +-----BEGIN CERTIFICATE----- +MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1h +cnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNp +Z24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1 +c3QgTmV0d29yazAeFw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1h +cnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNp +Z24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1 +c3QgTmV0d29yazCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjx +nNuX6Zr8wgQGE75fUsjMHiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRC +wiNPStjwDqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cCAwEA +ATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9jinb3/7aHmZuovCfTK +1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAXrXfMSTWqz9iP0b63GJZHc2pUIjRk +LbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnInjBJ7xUS0rg== +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority - G2 +============================================================ +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz +dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz +dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCO +FoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71 +lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQAB +MA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01UbSuvDV1Ai2TT +1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7iF6YM40AIOw7n60RzKprxaZLvcRTD +Oaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpYoJ2daZH9 +-----END CERTIFICATE----- + +GlobalSign Root CA +================== +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx +GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds +b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD +VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa +DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc +THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb +Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP +c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX +gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF +AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj +Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG +j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH +hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC +X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +GlobalSign Root CA - R2 +======================= +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6 +ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp +s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN +S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL +TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C +ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i +YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN +BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp +9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu +01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7 +9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +ValiCert Class 1 VA +=================== +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp +b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh +bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIy +MjM0OFoXDTE5MDYyNTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 +d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEg +UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 +LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIi +GQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCm +DuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0LBwG +lN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLWI8sogTLDAHkY7FkX +icnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPwnXS3qT6gpf+2SQMT2iLM7XGCK5nP +Orf1LXLI +-----END CERTIFICATE----- + +ValiCert Class 2 VA +=================== +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp +b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh +bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw +MTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 +d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIg +UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 +LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVC +CSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7Rf +ZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZ +SWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbV +UjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8 +W9ViH0Pd +-----END CERTIFICATE----- + +RSA Root Certificate 1 +====================== +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp +b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh +bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw +MjIzM1oXDTE5MDYyNjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 +d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMg +UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 +LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td +3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89H +BFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliEZwgs +3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJn0WuPIqpsHEzXcjF +V9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/APhmcGcwTTYJBtYze4D1gCCAPRX5r +on+jjBXu +-----END CERTIFICATE----- + +Verisign Class 1 Public Primary Certification Authority - G3 +============================================================ +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy +dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAN2E1Lm0+afY8wR4nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/E +bRrsC+MO8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjVojYJ +rKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjbPG7PoBMAGrgnoeS+ +Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP26KbqxzcSXKMpHgLZ2x87tNcPVkeB +FQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vrn5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA +q2aN17O6x5q25lXQBfGfMY1aqtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/N +y9Sn2WCVhDr4wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 +ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrspSCAaWihT37h +a88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4E1Z5T21Q6huwtVexN2ZYI/Pc +D98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== +-----END CERTIFICATE----- + +Verisign Class 2 Public Primary Certification Authority - G3 +============================================================ +-----BEGIN CERTIFICATE----- +MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29y +azE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ug +b25seTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1 +c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y +aXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEArwoNwtUs22e5LeWUJ92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6 +tW8UvxDOJxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUYwZF7 +C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9okoqQHgiBVrKtaaNS +0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjNqWm6o+sdDZykIKbBoMXRRkwXbdKs +Zj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/ESrg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0 +JhU8wI1NQ0kdvekhktdmnLfexbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf +0xwLRtxyID+u7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU +sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RIsH/7NiXaldDx +JBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTPcjnhsUPgKM+351psE2tJs//j +GHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority - G3 +============================================================ +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy +dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1 +EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc +cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw +EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj +055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA +ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f +j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0 +xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa +t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- + +Verisign Class 4 Public Primary Certification Authority - G3 +============================================================ +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy +dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS +tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM +8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW +Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX +Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA +j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt +mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm +fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd +RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG +UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== +-----END CERTIFICATE----- + +Entrust.net Secure Server CA +============================ +-----BEGIN CERTIFICATE----- +MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMCVVMxFDASBgNV +BAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5uZXQvQ1BTIGluY29ycC4gYnkg +cmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRl +ZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eTAeFw05OTA1MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIG +A1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBi +eSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1p +dGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQ +aO2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5 +gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OCAdcw +ggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHboIHYpIHVMIHSMQsw +CQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5l +dC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF +bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu +dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0MFqBDzIwMTkw +NTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0Bow +HQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAaMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA +BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyN +Ewr75Ji174z4xRAN95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9 +n9cd2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= +-----END CERTIFICATE----- + +Entrust.net Premium 2048 Secure Server CA +========================================= +-----BEGIN CERTIFICATE----- +MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u +ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp +bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx +NzUwNTFaFw0xOTEyMjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 +d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u +ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL +Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr +hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW +nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi +VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo3QwcjARBglghkgBhvhC +AQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGAvtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdER +gL7YibkIozH5oSQJFrlwMB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0B +AQUFAAOCAQEAWUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo +oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQh7A6tcOdBTcS +o8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18f3v/rxzP5tsHrV7bhZ3QKw0z +2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfNB/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjX +OP/swNlQ8C5LWK5Gb9Auw2DaclVyvUxFnmG6v4SBkgPR0ml8xQ== +-----END CERTIFICATE----- + +Baltimore CyberTrust Root +========================= +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE +ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li +ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC +SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs +dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME +uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB +UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C +G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 +XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr +l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI +VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB +BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh +cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 +hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa +Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H +RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +Equifax Secure Global eBusiness CA +================================== +-----BEGIN CERTIFICATE----- +MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +RXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNp +bmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMx +HDAaBgNVBAoTE0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEds +b2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRV +PEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzN +qfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxn +hcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j +BBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hs +MA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okEN +I7SS+RkAZ70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIY +NMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV +-----END CERTIFICATE----- + +Equifax Secure eBusiness CA 1 +============================= +-----BEGIN CERTIFICATE----- +MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +RXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENB +LTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UE +ChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNz +IENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ +1MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBuWqDZQu4a +IZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKwEnv+j6YDAgMBAAGjZjBk +MBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEp4MlIR21kW +Nl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQF +AAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5 +lSE/9dR+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+ +KpYrtWKmpj29f5JZzVoqgrI3eQ== +-----END CERTIFICATE----- + +Equifax Secure eBusiness CA 2 +============================= +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEXMBUGA1UE +ChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0y +MB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoT +DkVxdWlmYXggU2VjdXJlMSYwJAYDVQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn +2Z0GvxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/BPO3QSQ5 +BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0CAwEAAaOCAQkwggEFMHAG +A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUx +JjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoG +A1UdEAQTMBGBDzIwMTkwNjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9e +uSBIplBqy/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQFMAMB +Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAAyGgq3oThr1 +jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia +78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUm +V+GRMOrN +-----END CERTIFICATE----- + +AddTrust Low-Value Services Root +================================ +-----BEGIN CERTIFICATE----- +MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU +cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw +CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO +ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6 +54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr +oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1 +Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui +GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w +HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT +RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw +HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt +ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph +iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY +eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr +mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj +ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= +-----END CERTIFICATE----- + +AddTrust External Root +====================== +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD +VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw +NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU +cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg +Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821 ++iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw +Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo +aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy +2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7 +7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL +VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk +VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB +IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl +j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355 +e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u +G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE----- + +AddTrust Public Services Root +============================= +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU +cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ +BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l +dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu +nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i +d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG +Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw +HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G +A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G +A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4 +JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL ++YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao +GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9 +Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H +EufOX1362KqxMy3ZdvJOOjMMK7MtkAY= +-----END CERTIFICATE----- + +AddTrust Qualified Certificates Root +==================================== +-----BEGIN CERTIFICATE----- +MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU +cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx +CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ +IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx +64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3 +KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o +L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR +wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU +MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE +BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y +azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG +GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X +dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze +RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB +iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE= +-----END CERTIFICATE----- + +Entrust Root Certification Authority +==================================== +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw +b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG +A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 +MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu +MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu +Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz +A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww +Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 +j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN +rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 +MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH +hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM +Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa +v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS +W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 +tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +RSA Security 2048 v3 +==================== +-----BEGIN CERTIFICATE----- +MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYDVQQK +ExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAy +MjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAb +BgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7 +Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgb +WhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iH +KrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP ++Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4E +FgQUB8NRMKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmY +v/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj +0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwj +VAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395 +nzIlQnQFgCi/vcEkllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA +pKnXwiJPZ9d37CAFYd4= +-----END CERTIFICATE----- + +GeoTrust Global CA +================== +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw +MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j +LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo +BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet +8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc +T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU +vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk +DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q +zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4 +d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2 +mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p +XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm +Mw== +-----END CERTIFICATE----- + +GeoTrust Global CA 2 +==================== +-----BEGIN CERTIFICATE----- +MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw +MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j +LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/ +NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k +LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA +Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b +HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH +K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7 +srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh +ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL +OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC +x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF +H4z1Ir+rzoPz4iIprn2DQKi6bA== +-----END CERTIFICATE----- + +GeoTrust Universal CA +===================== +-----BEGIN CERTIFICATE----- +MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1 +MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu +Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t +JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e +RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs +7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d +8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V +qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga +Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB +Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu +KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08 +ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0 +XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB +hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc +aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2 +qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL +oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK +xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF +KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2 +DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK +xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU +p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI +P/rmMuGNG2+k5o7Y+SlIis5z/iw= +-----END CERTIFICATE----- + +GeoTrust Universal CA 2 +======================= +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0 +MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg +SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0 +DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17 +j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q +JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a +QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2 +WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP +20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn +ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC +SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG +8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2 ++/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E +BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z +dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ +4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+ +mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq +A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg +Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP +pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d +FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp +gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm +X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS +-----END CERTIFICATE----- + +UTN-USER First-Network Applications +=================================== +-----BEGIN CERTIFICATE----- +MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCBozELMAkGA1UE +BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl +IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzAp +BgNVBAMTIlVUTi1VU0VSRmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5 +WhcNMTkwNzA5MTg1NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5T +YWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3QtTmV0d29yayBB +cHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz+5Gh5DZVhawGNFug +mliy+LUPBXeDrjKxdpJo7CNKyXY/45y2N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4Cj +DUeJT1FxL+78P/m4FoCHiZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXu +Ozr0hAReYFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1axwi +P8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6gyN7igEL66S/ozjIE +j3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8w +HQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPhahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9j +cmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0G +CSqGSIb3DQEBBQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y +IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6LzsQCv4AdRWOOTK +RIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4ZSfP1FMa8Kxun08FDAOBp4Qp +xFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qMYEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAq +DbUMo2s/rn9X9R+WfN9v3YIwLGUbQErNaLly7HF27FSOH4UMAWr6pjisH8SE +-----END CERTIFICATE----- + +America Online Root Certification Authority 1 +============================================= +-----BEGIN CERTIFICATE----- +MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkG +A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg +T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lkhsmj76CG +v2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym1BW32J/X3HGrfpq/m44z +DyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsWOqMFf6Dch9Wc/HKpoH145LcxVR5lu9Rh +sCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP +8c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Z +o/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQB8itEf +GDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkFZu90821fnZmv9ov761KyBZiibyrF +VL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft +3OJvx8Fi8eNy1gTIdGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43g +Kd8hdIaC2y+CMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds +sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 +-----END CERTIFICATE----- + +America Online Root Certification Authority 2 +============================================= +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkG +A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg +T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC206B89en +fHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFciKtZHgVdEglZTvYYUAQv8 +f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2JxhP7JsowtS013wMPgwr38oE18aO6lhO +qKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JN +RvCAOVIyD+OEsnpD8l7eXz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0 +gBe4lL8BPeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67Xnfn +6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEqZ8A9W6Wa6897Gqid +FEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZo2C7HK2JNDJiuEMhBnIMoVxtRsX6 +Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnj +B453cMor9H124HhnAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3Op +aaEg5+31IqEjFNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmnxPBUlgtk87FY +T15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2LHo1YGwRgJfMqZJS5ivmae2p ++DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzcccobGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXg +JXUjhx5c3LqdsKyzadsXg8n33gy8CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//Zoy +zH1kUQ7rVyZ2OuMeIjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgO +ZtMADjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2FAjgQ5ANh +1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUXOm/9riW99XJZZLF0Kjhf +GEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPbAZO1XB4Y3WRayhgoPmMEEf0cjQAPuDff +Z4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQlZvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuP +cX/9XhmgD0uRuMRUvAawRY8mkaKO/qk= +-----END CERTIFICATE----- + +Visa eCommerce Root +=================== +-----BEGIN CERTIFICATE----- +MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG +EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug +QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2 +WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm +VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv +bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL +F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b +RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0 +TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI +/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs +GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG +MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc +CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW +YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz +zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu +YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt +398znM/jra6O1I7mT1GvFpLgXPYHDw== +-----END CERTIFICATE----- + +Certum Root CA +============== +-----BEGIN CERTIFICATE----- +MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK +ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla +Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u +by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x +wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL +kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ +89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K +Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P +NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+ +GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg +GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/ +0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS +qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw== +-----END CERTIFICATE----- + +Comodo AAA Services root +======================== +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw +MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl +c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV +BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG +C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs +i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW +Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH +Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK +Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f +BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl +cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz +LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm +7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z +8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C +12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +Comodo Secure Services root +=========================== +-----BEGIN CERTIFICATE----- +MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw +MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu +Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi +BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP +9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc +rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC +oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V +p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E +FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj +YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm +aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm +4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj +Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL +DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw +pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H +RR3B7Hzs/Sk= +-----END CERTIFICATE----- + +Comodo Trusted Services root +============================ +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw +MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h +bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw +IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7 +3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y +/9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6 +juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS +ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud +DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp +ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl +cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw +uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 +pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA +BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l +R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O +9y5Xt5hwXsjEeLBi +-----END CERTIFICATE----- + +QuoVadis Root CA +================ +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE +ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz +MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp +cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD +EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk +J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL +F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL +YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen +AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w +PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y +ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7 +MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj +YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs +ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW +Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu +BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw +FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6 +tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo +fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul +LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x +gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi +5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi +5nrQNiOKSnQ2+Q== +-----END CERTIFICATE----- + +QuoVadis Root CA 2 +================== +-----BEGIN CERTIFICATE----- +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 1 Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG +U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAxMDQwNjEwNDkxM1oXDTIxMDQw +NjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh +IENsYXNzMSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H88 +7dF+2rDNbS82rDTG29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9 +EJUkoVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk3w0LBUXl +0fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBLqdReLjVQCfOAl/QMF645 +2F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIINnvmLVz5MxxftLItyM19yejhW1ebZrgUa +HXVFsculJRwSVzb9IjcCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZT +iFIwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE9 +28Jj2VuXZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0HDjxV +yhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VOTzF2nBBhjrZTOqMR +vq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2UvkVrCqIexVmiUefkl98HVrhq4uz2P +qYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4wzMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9Z +IRlXvVWa +-----END CERTIFICATE----- + +Sonera Class 2 Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG +U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw +NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh +IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3 +/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT +dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG +f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P +tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH +nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT +XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt +0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI +cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph +Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx +EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH +llpwrN9M +-----END CERTIFICATE----- + +Staat der Nederlanden Root CA +============================= +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE +ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g +Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w +HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh +bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt +vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P +jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca +C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth +vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6 +22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV +HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v +dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN +BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR +EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw +MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y +nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR +iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== +-----END CERTIFICATE----- + +TDC Internet Root CA +==================== +-----BEGIN CERTIFICATE----- +MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJESzEVMBMGA1UE +ChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTAeFw0wMTA0MDUx +NjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNVBAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJu +ZXQxHTAbBgNVBAsTFFREQyBJbnRlcm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxLhAvJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20j +xsNuZp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a0vnRrEvL +znWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc14izbSysseLlJ28TQx5yc +5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGNeGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6 +otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcDR0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZI +AYb4QgEBBAQDAgAHMGUGA1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMM +VERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxMEQ1JM +MTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3WjALBgNVHQ8EBAMC +AQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAwHQYDVR0OBBYEFGxkAcf9hW2syNqe +UAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJKoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0G +CSqGSIb3DQEBBQUAA4IBAQBOQ8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540m +gwV5dOy0uaOXwTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ +2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm899qNLPg7kbWzb +O0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0jUNAE4z9mQNUecYu6oah9jrU +Cbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38aQNiuJkFBT1reBK9sG9l +-----END CERTIFICATE----- + +TDC OCES Root CA +================ +-----BEGIN CERTIFICATE----- +MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJESzEMMAoGA1UE +ChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEwODM5MzBaFw0zNzAyMTEwOTA5 +MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNUREMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuH +nEz9pPPEXyG9VhDr2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0 +zY0s2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItUGBxIYXvV +iGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKjdGqPqcNiKXEx5TukYBde +dObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+rTpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO +3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB +5DCB4TCB3gYIKoFQgSkBAQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5k +ay9yZXBvc2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRlciBm +cmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEuMS4xLiBDZXJ0aWZp +Y2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEuMS4x +LjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1UdHwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEM +MAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYm +aHR0cDovL2NybC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy +MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZJ2cdUBVLc647 ++RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqGSIb2fQdBAAQQMA4bCFY2LjA6 +NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACromJkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4 +A9G28kNBKWKnctj7fAXmMXAnVBhOinxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYsc +A+UYyAFMP8uXBV2YcaaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9 +AOoBmbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQYqbsFbS1 +AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9BKNDLdr8C2LqL19iUw== +-----END CERTIFICATE----- + +UTN DATACorp SGC Root CA +======================== +-----BEGIN CERTIFICATE----- +MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE +BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl +IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ +BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa +MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w +HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy +dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys +raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo +wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA +9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv +33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud +DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9 +BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD +LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3 +DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft +Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0 +I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx +EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP +DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI +-----END CERTIFICATE----- + +UTN USERFirst Email Root CA +=========================== +-----BEGIN CERTIFICATE----- +MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCBrjELMAkGA1UE +BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl +IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0 +BgNVBAMTLVVUTi1VU0VSRmlyc3QtQ2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05 +OTA3MDkxNzI4NTBaFw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQx +FzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsx +ITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UEAxMtVVROLVVTRVJGaXJz +dC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWlsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3BYHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIx +B8dOtINknS4p1aJkxIW9hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8 +om+rWV6lL8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLmSGHG +TPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM1tZUOt4KpLoDd7Nl +yP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws6wIDAQABo4G5MIG2MAsGA1UdDwQE +AwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNV +HR8EUTBPME2gS6BJhkdodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGll +bnRBdXRoZW50aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH +AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u7mFVbwQ+zzne +xRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0xtcgBEXkzYABurorbs6q15L+ +5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQrfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarV +NZ1yQAOJujEdxRBoUp7fooXFXAimeOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZ +w7JHpsIyYdfHb0gkUSeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ= +-----END CERTIFICATE----- + +UTN USERFirst Hardware Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE +BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl +IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd +BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx +OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0 +eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz +ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI +wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd +tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8 +i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf +Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw +gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF +lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF +UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF +BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW +XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2 +lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn +iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67 +nfhmqA== +-----END CERTIFICATE----- + +UTN USERFirst Object Root CA +============================ +-----BEGIN CERTIFICATE----- +MIIEZjCCA06gAwIBAgIQRL4Mi1AAJLQR0zYt4LNfGzANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UE +BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl +IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAb +BgNVBAMTFFVUTi1VU0VSRmlyc3QtT2JqZWN0MB4XDTk5MDcwOTE4MzEyMFoXDTE5MDcwOTE4NDAz +NlowgZUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkx +HjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3dy51c2Vy +dHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdDCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAM6qgT+jo2F4qjEAVZURnicPHxzfOpuCaDDASmEd8S8O+r5596Uj71VR +loTN2+O5bj4x2AogZ8f02b+U60cEPgLOKqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQ +w5ujm9M89RKZd7G3CeBo5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbHd2pBnqcP1/vu +lBe3/IW+pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh2JU022R5KP+6LhHC5ehbkkj7 +RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzTbafc8H9vg2XiaquHhnUCAwEAAaOBrzCBrDAL +BgNVHQ8EBAMCAcYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU2u1kdBScFDyr3ZmpvVsoTYs8 +ydgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmly +c3QtT2JqZWN0LmNybDApBgNVHSUEIjAgBggrBgEFBQcDAwYIKwYBBQUHAwgGCisGAQQBgjcKAwQw +DQYJKoZIhvcNAQEFBQADggEBAAgfUrE3RHjb/c652pWWmKpVZIC1WkDdIaXFwfNfLEzIR1pp6ujw +NTX00CXzyKakh0q9G7FzCL3Uw8q2NbtZhncxzaeAFK4T7/yxSPlrJSUtUbYsbUXBmMiKVl0+7kNO +PmsnjtA6S4ULX9Ptaqd1y9Fahy85dRNacrACgZ++8A+EVCBibGnU4U3GDZlDAQ0Slox4nb9QorFE +qmrPF3rPbw/U+CRVX/A0FklmPlBGyWNxODFiuGK581OtbLUrohKqGU8J2l7nk8aOFAj+8DCAGKCG +hU3IfdeLA/5u1fedFqySLKAj5ZyRUh+U3xeUc8OzwcFxBSAAeL0TUh2oPs0AH8g= +-----END CERTIFICATE----- + +Camerfirma Chambers of Commerce Root +==================================== +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe +QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i +ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx +NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp +cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn +MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC +AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU +xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH +NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW +DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV +d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud +EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v +cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P +AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh +bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD +VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz +aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi +fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD +L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN +UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n +ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1 +erfutGWaIZDgqtCYvDi1czyL+Nw= +-----END CERTIFICATE----- + +Camerfirma Global Chambersign Root +================================== +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe +QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i +ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx +NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt +YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg +MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw +ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J +1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O +by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl +6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c +8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/ +BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j +aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B +Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj +aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y +ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh +bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA +PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y +gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ +PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4 +IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes +t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== +-----END CERTIFICATE----- + +NetLock Qualified (Class QA) Root +================================= +-----BEGIN CERTIFICATE----- +MIIG0TCCBbmgAwIBAgIBezANBgkqhkiG9w0BAQUFADCByTELMAkGA1UEBhMCSFUxETAPBgNVBAcT +CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV +BAsTEVRhbnVzaXR2YW55a2lhZG9rMUIwQAYDVQQDEzlOZXRMb2NrIE1pbm9zaXRldHQgS296amVn +eXpvaSAoQ2xhc3MgUUEpIFRhbnVzaXR2YW55a2lhZG8xHjAcBgkqhkiG9w0BCQEWD2luZm9AbmV0 +bG9jay5odTAeFw0wMzAzMzAwMTQ3MTFaFw0yMjEyMTUwMTQ3MTFaMIHJMQswCQYDVQQGEwJIVTER +MA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNhZ2kgS2Z0 +LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxQjBABgNVBAMTOU5ldExvY2sgTWlub3NpdGV0 +dCBLb3pqZWd5em9pIChDbGFzcyBRQSkgVGFudXNpdHZhbnlraWFkbzEeMBwGCSqGSIb3DQEJARYP +aW5mb0BuZXRsb2NrLmh1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx1Ilstg91IRV +CacbvWy5FPSKAtt2/GoqeKvld/Bu4IwjZ9ulZJm53QE+b+8tmjwi8F3JV6BVQX/yQ15YglMxZc4e +8ia6AFQer7C8HORSjKAyr7c3sVNnaHRnUPYtLmTeriZ539+Zhqurf4XsoPuAzPS4DB6TRWO53Lhb +m+1bOdRfYrCnjnxmOCyqsQhjF2d9zL2z8cM/z1A57dEZgxXbhxInlrfa6uWdvLrqOU+L73Sa58XQ +0uqGURzk/mQIKAR5BevKxXEOC++r6uwSEaEYBTJp0QwsGj0lmT+1fMptsK6ZmfoIYOcZwvK9UdPM +0wKswREMgM6r3JSda6M5UzrWhQIDAMV9o4ICwDCCArwwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV +HQ8BAf8EBAMCAQYwggJ1BglghkgBhvhCAQ0EggJmFoICYkZJR1lFTEVNISBFemVuIHRhbnVzaXR2 +YW55IGEgTmV0TG9jayBLZnQuIE1pbm9zaXRldHQgU3pvbGdhbHRhdGFzaSBTemFiYWx5emF0YWJh +biBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBBIG1pbm9zaXRldHQgZWxla3Ryb25p +a3VzIGFsYWlyYXMgam9naGF0YXMgZXJ2ZW55ZXN1bGVzZW5laywgdmFsYW1pbnQgZWxmb2dhZGFz +YW5hayBmZWx0ZXRlbGUgYSBNaW5vc2l0ZXR0IFN6b2xnYWx0YXRhc2kgU3phYmFseXphdGJhbiwg +YXogQWx0YWxhbm9zIFN6ZXJ6b2Rlc2kgRmVsdGV0ZWxla2JlbiBlbG9pcnQgZWxsZW5vcnplc2kg +ZWxqYXJhcyBtZWd0ZXRlbGUuIEEgZG9rdW1lbnR1bW9rIG1lZ3RhbGFsaGF0b2sgYSBodHRwczov +L3d3dy5uZXRsb2NrLmh1L2RvY3MvIGNpbWVuIHZhZ3kga2VyaGV0b2sgYXogaW5mb0BuZXRsb2Nr +Lm5ldCBlLW1haWwgY2ltZW4uIFdBUk5JTkchIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0 +aGlzIGNlcnRpZmljYXRlIGFyZSBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIFF1YWxpZmllZCBDUFMg +YXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3Lm5ldGxvY2suaHUvZG9jcy8gb3IgYnkgZS1tYWlsIGF0 +IGluZm9AbmV0bG9jay5uZXQwHQYDVR0OBBYEFAlqYhaSsFq7VQ7LdTI6MuWyIckoMA0GCSqGSIb3 +DQEBBQUAA4IBAQCRalCc23iBmz+LQuM7/KbD7kPgz/PigDVJRXYC4uMvBcXxKufAQTPGtpvQMznN +wNuhrWw3AkxYQTvyl5LGSKjN5Yo5iWH5Upfpvfb5lHTocQ68d4bDBsxafEp+NFAwLvt/MpqNPfMg +W/hqyobzMUwsWYACff44yTB1HLdV47yfuqhthCgFdbOLDcCRVCHnpgu0mfVRQdzNo0ci2ccBgcTc +R08m6h/t280NmPSjnLRzMkqWmf68f8glWPhY83ZmiVSkpj7EUFy6iRiCdUgh0k8T6GB+B3bbELVR +5qq5aKrN9p2QdRLqOBrKROi3macqaJVmlaut74nLYKkGEsaUR+ko +-----END CERTIFICATE----- + +NetLock Notary (Class A) Root +============================= +-----BEGIN CERTIFICATE----- +MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI +EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 +dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j +ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX +DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH +EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD +VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz +cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM +D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ +z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC +/tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7 +tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6 +4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG +A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC +Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv +bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu +IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn +LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0 +ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz +IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh +IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu +b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh +bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg +Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp +bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5 +ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP +ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB +CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr +KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM +8CgHrTwXZoi1/baI +-----END CERTIFICATE----- + +NetLock Business (Class B) Root +=============================== +-----BEGIN CERTIFICATE----- +MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUxETAPBgNVBAcT +CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV +BAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQDEylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikg +VGFudXNpdHZhbnlraWFkbzAeFw05OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYD +VQQGEwJIVTERMA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRv +bnNhZ2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5ldExvY2sg +VXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB +iQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2S +o/1bXHQawEfKOml2mrriRBf8TKPV/riXiK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr +1nGTLbO/CVRY7QbrqHvcQ7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV +HQ8BAf8EBAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZ +RUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRh +dGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQuIEEgaGl0 +ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRv +c2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUg +YXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh +c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBz +Oi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6ZXNA +bmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhl +IHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2 +YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBj +cHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06sPgzTEdM +43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXan3BukxowOR0w2y7jfLKR +stE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKSNitjrFgBazMpUIaD8QFI +-----END CERTIFICATE----- + +NetLock Express (Class C) Root +============================== +-----BEGIN CERTIFICATE----- +MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUxETAPBgNVBAcT +CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV +BAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQDEytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBD +KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJ +BgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 +dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMrTmV0TG9j +ayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzANBgkqhkiG9w0BAQEFAAOB +jQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNAOoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3Z +W3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63 +euyucYT2BDMIJTLrdKwWRMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQw +DgYDVR0PAQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEWggJN +RklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0YWxhbm9zIFN6b2xn +YWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBB +IGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBOZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1i +aXp0b3NpdGFzYSB2ZWRpLiBBIGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0 +ZWxlIGF6IGVsb2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs +ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25sYXBqYW4gYSBo +dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kga2VyaGV0byBheiBlbGxlbm9y +emVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4gSU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5k +IHRoZSB1c2Ugb2YgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQ +UyBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwg +YXQgY3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmYta3UzbM2 +xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2gpO0u9f38vf5NNwgMvOOW +gyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4Fp1hBWeAyNDYpQcCNJgEjTME1A== +-----END CERTIFICATE----- + +XRamp Global CA Root +==================== +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE +BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj +dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx +HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg +U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu +IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx +foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE +zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs +AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry +xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap +oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC +AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc +/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n +nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz +8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +Go Daddy Class 2 CA +=================== +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY +VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG +A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g +RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD +ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv +2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 +qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j +YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY +vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O +BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o +atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu +MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim +PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt +I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI +Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b +vZ8= +-----END CERTIFICATE----- + +Starfield Class 2 CA +==================== +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc +U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo +MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG +A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG +SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY +bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ +JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm +epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN +F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF +MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f +hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo +bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs +afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM +PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD +KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 +QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +StartCom Certification Authority +================================ +-----BEGIN CERTIFICATE----- +MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu +ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 +NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk +LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg +U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y +o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ +Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d +eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt +2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z +6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ +osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ +untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc +UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT +37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE +FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0 +Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj +YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH +AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw +Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg +U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5 +LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh +cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT +dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC +AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh +3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm +vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk +fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3 +fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ +EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq +yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl +1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/ +lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro +g14= +-----END CERTIFICATE----- + +Taiwan GRCA +=========== +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG +EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X +DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv +dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN +w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5 +BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O +1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO +htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov +J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7 +Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t +B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB +O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8 +lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV +HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2 +09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ +TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj +Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2 +Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU +D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz +DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk +Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk +7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ +CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy ++fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS +-----END CERTIFICATE----- + +Firmaprofesional Root CA +======================== +-----BEGIN CERTIFICATE----- +MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMxIjAgBgNVBAcT +GUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1dG9yaWRhZCBkZSBDZXJ0aWZp +Y2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FA +ZmlybWFwcm9mZXNpb25hbC5jb20wHhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTEL +MAkGA1UEBhMCRVMxIjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMT +OUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2 +ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20wggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5uCp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5V +j1H5WuretXDE7aTt/6MNbg9kUDGvASdYrv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJH +lShbz++AbOCQl4oBPB3zhxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf +3H5idPayBQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcLiam8 +NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcbAgMBAAGjgZ8wgZww +KgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lvbmFsLmNvbTASBgNVHRMBAf8ECDAG +AQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQAD +ggEBAEdz/o0nVPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq +u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36mhoEyIwOdyPdf +wUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzflZKG+TQyTmAyX9odtsz/ny4Cm +7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBpQWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YG +VM+h4k0460tQtcsm9MracEpqoeJ5quGnM/b9Sh/22WA= +-----END CERTIFICATE----- + +Wells Fargo Root CA +=================== +-----BEGIN CERTIFICATE----- +MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCVVMxFDASBgNV +BAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN +MDAxMDExMTY0MTI4WhcNMjEwMTE0MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dl +bGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEv +MC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n135zHCLielTWi5MbqNQ1mX +x3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHESxP9cMIlrCL1dQu3U+SlK93OvRw6esP3 +E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4OJgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5 +OEL8pahbSCOz6+MlsoCultQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4j +sNtlAHCEAQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMBAAGj +YTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcBCzAyMDAGCCsGAQUF +BwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRwb2xpY3kwDQYJKoZIhvcNAQEFBQAD +ggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrv +m+0fazbuSCUlFLZWohDo7qd/0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0R +OhPs7fpvcmR7nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx +x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ33ZwmVxwQ023 +tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s= +-----END CERTIFICATE----- + +Swisscom Root CA 1 +================== +-----BEGIN CERTIFICATE----- +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 Platinum CA - G2 +========================== +-----BEGIN CERTIFICATE----- +MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCQ0gxFTAT +BgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWduIFBsYXRpbnVtIENBIC0gRzIw +HhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAwWjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMM +U3dpc3NTaWduIEFHMSMwIQYDVQQDExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu +669yIIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2HtnIuJpX+UF +eNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+6ixuEFGSzH7VozPY1kne +WCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5objM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIo +j5+saCB9bzuohTEJfwvH6GXp43gOCWcwizSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/6 +8++QHkwFix7qepF6w9fl+zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34T +aNhxKFrYzt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaPpZjy +domyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtFKwH3HBqi7Ri6Cr2D ++m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuWae5ogObnmLo2t/5u7Su9IPhlGdpV +CX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMBAAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCv +zAeHFUdvOMW0ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW +IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUAA4ICAQAIhab1 +Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0uMoI3LQwnkAHFmtllXcBrqS3 +NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4 +U99REJNi54Av4tHgvI42Rncz7Lj7jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8 +KV2LwUvJ4ooTHbG/u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl +9x8DYSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1puEa+S1B +aYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXaicYwu+uPyyIIoK6q8QNs +OktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbGDI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSY +Mdp08YSTcU1f+2BY0fvEwW2JorsgH51xkcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAci +IfNAChs0B0QTwoRqjt8ZWr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g== +-----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----- + +S-TRUST Authentication and Encryption Root CA 2005 PN +===================================================== +-----BEGIN CERTIFICATE----- +MIIEezCCA2OgAwIBAgIQNxkY5lNUfBq1uMtZWts1tzANBgkqhkiG9w0BAQUFADCBrjELMAkGA1UE +BhMCREUxIDAeBgNVBAgTF0JhZGVuLVd1ZXJ0dGVtYmVyZyAoQlcpMRIwEAYDVQQHEwlTdHV0dGdh +cnQxKTAnBgNVBAoTIERldXRzY2hlciBTcGFya2Fzc2VuIFZlcmxhZyBHbWJIMT4wPAYDVQQDEzVT +LVRSVVNUIEF1dGhlbnRpY2F0aW9uIGFuZCBFbmNyeXB0aW9uIFJvb3QgQ0EgMjAwNTpQTjAeFw0w +NTA2MjIwMDAwMDBaFw0zMDA2MjEyMzU5NTlaMIGuMQswCQYDVQQGEwJERTEgMB4GA1UECBMXQmFk +ZW4tV3VlcnR0ZW1iZXJnIChCVykxEjAQBgNVBAcTCVN0dXR0Z2FydDEpMCcGA1UEChMgRGV1dHNj +aGVyIFNwYXJrYXNzZW4gVmVybGFnIEdtYkgxPjA8BgNVBAMTNVMtVFJVU1QgQXV0aGVudGljYXRp +b24gYW5kIEVuY3J5cHRpb24gUm9vdCBDQSAyMDA1OlBOMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEA2bVKwdMz6tNGs9HiTNL1toPQb9UY6ZOvJ44TzbUlNlA0EmQpoVXhOmCTnijJ4/Ob +4QSwI7+Vio5bG0F/WsPoTUzVJBY+h0jUJ67m91MduwwA7z5hca2/OnpYH5Q9XIHV1W/fuJvS9eXL +g3KSwlOyggLrra1fFi2SU3bxibYs9cEv4KdKb6AwajLrmnQDaHgTncovmwsdvs91DSaXm8f1Xgqf +eN+zvOyauu9VjxuapgdjKRdZYgkqeQd3peDRF2npW932kKvimAoA0SVtnteFhy+S8dF2g08LOlk3 +KC8zpxdQ1iALCvQm+Z845y2kuJuJja2tyWp9iRe79n+Ag3rm7QIDAQABo4GSMIGPMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMCkGA1UdEQQiMCCkHjAcMRowGAYDVQQDExFTVFJv +bmxpbmUxLTIwNDgtNTAdBgNVHQ4EFgQUD8oeXHngovMpttKFswtKtWXsa1IwHwYDVR0jBBgwFoAU +D8oeXHngovMpttKFswtKtWXsa1IwDQYJKoZIhvcNAQEFBQADggEBAK8B8O0ZPCjoTVy7pWMciDMD +pwCHpB8gq9Yc4wYfl35UvbfRssnV2oDsF9eK9XvCAPbpEW+EoFolMeKJ+aQAPzFoLtU96G7m1R08 +P7K9n3frndOMusDXtk3sU5wPBG7qNWdX4wple5A64U8+wwCSersFiXOMy6ZNwPv2AtawB6MDwidA +nwzkhYItr5pCHdDHjfhA7p0GVxzZotiAFP7hYy0yh9WUUpY6RsZxlj33mA6ykaqP2vROJAA5Veit +F7nTNCtKqUDMFypVZUF0Qn71wK/Ik63yGFs9iQzbRzkk+OBM8h+wPQrKBU6JIRrjKpms/H+h8Q8b +Hz2eBIPdltkdOpQ= +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA +========================= +-----BEGIN CERTIFICATE----- +MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE +BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL +EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0 +MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz +dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT +GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG +d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N +oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc +QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ +PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb +MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG +IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD +VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3 +LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A +dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn +AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA +4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg +AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA +egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6 +Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO +PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv +c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h +cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw +IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT +WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV +MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER +MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp +Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal +HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT +nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE +aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a +86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK +yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB +S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= +-----END CERTIFICATE----- + +Certigna +======== +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw +EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 +MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI +Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q +XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH +GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p +ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg +DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf +Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ +tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ +BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J +SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA +hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ +ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu +PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY +1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +AC Ra\xC3\xADz Certic\xC3\xA1mara S.A. +====================================== +-----BEGIN CERTIFICATE----- +MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNVBAYT +AkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRpZmljYWNpw7NuIERpZ2l0YWwg +LSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwaQUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4w +HhcNMDYxMTI3MjA0NjI5WhcNMzAwNDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+ +U29jaWVkYWQgQ2FtZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJh +IFMuQS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeGqentLhM0R7LQcNzJPNCN +yu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzLfDe3fezTf3MZsGqy2IiKLUV0qPezuMDU +2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQY5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU3 +4ojC2I+GdV75LaeHM/J4Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP +2yYe68yQ54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+bMMCm +8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48jilSH5L887uvDdUhf +HjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++EjYfDIJss2yKHzMI+ko6Kh3VOz3vCa +Mh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/ztA/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK +5lw1omdMEWux+IBkAC1vImHFrEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1b +czwmPS9KvqfJpxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE +AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCBlTCBkgYEVR0g +ADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFyYS5jb20vZHBjLzBaBggrBgEF +BQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW507WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2Ug +cHVlZGVuIGVuY29udHJhciBlbiBsYSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEf +AygPU3zmpFmps4p6xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuX +EpBcunvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/Jre7Ir5v +/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dpezy4ydV/NgIlqmjCMRW3 +MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42gzmRkBDI8ck1fj+404HGIGQatlDCIaR4 +3NAvO2STdPCWkPHv+wlaNECW8DYSwaN0jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wk +eZBWN7PGKX6jD/EpOe9+XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f +/RWmnkJDW2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/RL5h +RqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35rMDOhYil/SrnhLecU +Iw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxkBYn8eNZcLCZDqQ== +-----END CERTIFICATE----- + +TC TrustCenter Class 2 CA II +============================ +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy +IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw +MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 +c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE +AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw +IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2 +xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ +Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u +SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB +7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 +Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU +cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i +SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u +TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G +dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ +KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj +TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP +JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk +vQ== +-----END CERTIFICATE----- + +TC TrustCenter Class 3 CA II +============================ +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy +IENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYw +MTEyMTQ0MTU3WhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 +c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UE +AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJWHt4bNwcwIi9v8Qbxq63W +yKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+QVl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo +6SI7dYnWRBpl8huXJh0obazovVkdKyT21oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZ +uV3bOx4a+9P/FRQI2AlqukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk +2ZyqBwi1Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NXXAek0CSnwPIA1DCB +7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 +Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU +cnVzdENlbnRlciUyMENsYXNzJTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i +SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u +TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlNirTzwppVMXzE +O2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8TtXqluJucsG7Kv5sbviRmEb8 +yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9 +IJqDnxrcOfHFcqMRA/07QlIp2+gB95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal +092Y+tTmBvTwtiBjS+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc +5A== +-----END CERTIFICATE----- + +TC TrustCenter Universal CA I +============================= +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy +IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN +MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg +VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw +JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC +qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv +xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw +ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O +gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j +BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG +1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy +vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3 +ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT +ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a +7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY +-----END CERTIFICATE----- + +Deutsche Telekom Root CA 2 +========================== +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT +RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG +A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5 +MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G +A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS +b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5 +bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI +KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY +AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK +Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV +jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV +HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr +E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy +zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8 +rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G +dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU +Cm26OWMohpLzGITY+9HPBVZkVw== +-----END CERTIFICATE----- + +ComSign CA +========== +-----BEGIN CERTIFICATE----- +MIIDkzCCAnugAwIBAgIQFBOWgxRVjOp7Y+X8NId3RDANBgkqhkiG9w0BAQUFADA0MRMwEQYDVQQD +EwpDb21TaWduIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0wNDAzMjQxMTMy +MThaFw0yOTAzMTkxNTAyMThaMDQxEzARBgNVBAMTCkNvbVNpZ24gQ0ExEDAOBgNVBAoTB0NvbVNp +Z24xCzAJBgNVBAYTAklMMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8ORUaSvTx49q +ROR+WCf4C9DklBKK8Rs4OC8fMZwG1Cyn3gsqrhqg455qv588x26i+YtkbDqthVVRVKU4VbirgwTy +P2Q298CNQ0NqZtH3FyrV7zb6MBBC11PN+fozc0yz6YQgitZBJzXkOPqUm7h65HkfM/sb2CEJKHxN +GGleZIp6GZPKfuzzcuc3B1hZKKxC+cX/zT/npfo4sdAMx9lSGlPWgcxCejVb7Us6eva1jsz/D3zk +YDaHL63woSV9/9JLEYhwVKZBqGdTUkJe5DSe5L6j7KpiXd3DTKaCQeQzC6zJMw9kglcq/QytNuEM +rkvF7zuZ2SOzW120V+x0cAwqTwIDAQABo4GgMIGdMAwGA1UdEwQFMAMBAf8wPQYDVR0fBDYwNDAy +oDCgLoYsaHR0cDovL2ZlZGlyLmNvbXNpZ24uY28uaWwvY3JsL0NvbVNpZ25DQS5jcmwwDgYDVR0P +AQH/BAQDAgGGMB8GA1UdIwQYMBaAFEsBmz5WGmU2dst7l6qSBe4y5ygxMB0GA1UdDgQWBBRLAZs+ +VhplNnbLe5eqkgXuMucoMTANBgkqhkiG9w0BAQUFAAOCAQEA0Nmlfv4pYEWdfoPPbrxHbvUanlR2 +QnG0PFg/LUAlQvaBnPGJEMgOqnhPOAlXsDzACPw1jvFIUY0McXS6hMTXcpuEfDhOZAYnKuGntewI +mbQKDdSFc8gS4TXt8QUxHXOZDOuWyt3T5oWq8Ir7dcHyCTxlZWTzTNity4hp8+SDtwy9F1qWF8pb +/627HOkthIDYIb6FUtnUdLlphbpN7Sgy6/lhSuTENh4Z3G+EER+V9YMoGKgzkkMn3V0TBEVPh9VG +zT2ouvDzuFYkRes3x+F2T3I5GN9+dHLHcy056mDmrRGiVod7w2ia/viMcKjfZTL0pECMocJEAw6U +AGegcQCCSA== +-----END CERTIFICATE----- + +ComSign Secured CA +================== +-----BEGIN CERTIFICATE----- +MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE +AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w +NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD +QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs +49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH +7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB +kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1 +9guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw +AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t +U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA +j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC +AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a +BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp +FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP +51qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz +OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== +-----END CERTIFICATE----- + +Cybertrust Global Root +====================== +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li +ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4 +MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD +ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA ++Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW +0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL +AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin +89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT +8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2 +MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G +A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO +lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi +5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2 +hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T +X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----END CERTIFICATE----- + +ePKI Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG +EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx +MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq +MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs +IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi +lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv +qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX +12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O +WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ +ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao +lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ +vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi +Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi +MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 +1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq +KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV +xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP +NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r +GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE +xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx +gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy +sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD +BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3 +============================================================================================================================= +-----BEGIN CERTIFICATE----- +MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH +DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q +aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry +b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV +BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg +S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4 +MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl +IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF +n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl +IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft +dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl +cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO +Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1 +xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR +6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL +hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd +BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4 +N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT +y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh +LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M +dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI= +-----END CERTIFICATE----- + +Buypass Class 2 CA 1 +==================== +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAxMB4XDTA2 +MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh +c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7M +cXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLXl18xoS83 +0r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVBHfCuuCkslFJgNJQ72uA4 +0Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/R +uFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0P +AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV +1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt +7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2 +fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w +wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho +-----END CERTIFICATE----- + +Buypass Class 3 CA 1 +==================== +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1 +MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh +c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx +ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0 +n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia +AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c +1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P +AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7 +pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA +EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5 +htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj +el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 +-----END CERTIFICATE----- + +EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 +========================================================================== +-----BEGIN CERTIFICATE----- +MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNVBAMML0VCRyBF +bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMTcwNQYDVQQKDC5FQkcg +QmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXptZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAe +Fw0wNjA4MTcwMDIxMDlaFw0xNjA4MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25p +ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2lt +IFRla25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h4fuXd7hxlugTlkaDT7by +X3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAktiHq6yOU/im/+4mRDGSaBUorzAzu8T2b +gmmkTPiab+ci2hC6X5L8GCcKqKpE+i4stPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfr +eYteIAbTdgtsApWjluTLdlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZ +TqNGFav4c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8UmTDGy +Y5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z+kI2sSXFCjEmN1Zn +uqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0OLna9XvNRiYuoP1Vzv9s6xiQFlpJI +qkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMWOeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vm +ExH8nYQKE3vwO9D8owrXieqWfo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0 +Nokb+Clsi7n2l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgwFoAU587GT/wW +Z5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+8ygjdsZs93/mQJ7ANtyVDR2t +FcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgm +zJNSroIBk5DKd8pNSe/iWtkqvTDOTLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64k +XPBfrAowzIpAoHMEwfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqT +bCmYIai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJnxk1Gj7sU +RT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4QDgZxGhBM/nV+/x5XOULK +1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9qKd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt +2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11thie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQ +Y9iJSrSq3RZj9W6+YKH47ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9 +AahH3eU7QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT +-----END CERTIFICATE----- + +certSIGN ROOT CA +================ +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD +VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa +Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE +CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I +JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH +rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 +ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD +0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 +AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B +Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB +AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 +SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 +x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt +vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz +TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +CNNIC ROOT +========== +-----BEGIN CERTIFICATE----- +MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE +ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw +OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD +o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz +VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT +VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or +czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK +y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC +wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S +lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5 +Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM +O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8 +BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2 +G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m +mxE= +-----END CERTIFICATE----- + +ApplicationCA - Japanese Government +=================================== +-----BEGIN CERTIFICATE----- +MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT +SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw +MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl +cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4 +fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN +wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE +jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu +nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU +WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV +BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD +vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs +o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g +/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD +io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW +dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL +rosot4LKGAfmt1t06SAZf7IbiVQ= +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G3 +============================================= +-----BEGIN CERTIFICATE----- +MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE +BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0 +IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz +NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo +YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT +LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j +K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE +c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C +IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu +dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr +2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9 +cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE +Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD +AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s +t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt +-----END CERTIFICATE----- + +thawte Primary Root CA - G2 +=========================== +-----BEGIN CERTIFICATE----- +MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC +VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu +IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg +Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV +MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG +b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt +IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS +LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5 +8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU +mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN +G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K +rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== +-----END CERTIFICATE----- + +thawte Primary Root CA - G3 +=========================== +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE +BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 +aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w +ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh +d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD +VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG +A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At +P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC ++BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY +7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW +vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ +KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK +A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu +t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC +8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm +er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A= +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G2 +============================================= +-----BEGIN CERTIFICATE----- +MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu +Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1 +OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg +MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl +b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG +BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc +KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+ +EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m +ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2 +npaqBA+K +-----END CERTIFICATE----- + +VeriSign Universal Root Certification Authority +=============================================== +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE +BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO +ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk +IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj +1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP +MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72 +9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I +AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR +tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G +CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O +a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud +DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3 +Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx +Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx +P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P +wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4 +mJO37M2CYfE45k+XmCpajQ== +-----END CERTIFICATE----- + +VeriSign Class 3 Public Primary Certification Authority - G4 +============================================================ +-----BEGIN CERTIFICATE----- +MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC +VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3 +b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz +ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU +cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo +b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8 +Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz +rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw +HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u +Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD +A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx +AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== +-----END CERTIFICATE----- + +NetLock Arany (Class Gold) Főtanúsítvány +============================================ +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G +A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 +dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB +cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx +MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO +ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 +c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu +0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw +/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk +H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw +fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 +neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW +qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta +YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna +NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu +dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +Staat der Nederlanden Root CA - G2 +================================== +-----BEGIN CERTIFICATE----- +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 1 Public Primary Certification Authority +======================================================= +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx +FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow +XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAx +IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0fzGVuDLDQ +VoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHiTkVWaR94AoDa3EeRKbs2 +yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFgVKTk8d6Pa +XCUDfGD67gmZPCcQcMgMCeazh88K4hiWNWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n +0a3hUKw8fGJLj7qE1xIVGx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZ +RjXZ+Hxb +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority +======================================================= +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx +FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow +XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz +IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94 +f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol +hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBABByUqkFFBky +CEHwxWsKzH4PIRnN5GfcX6kb5sroc50i2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWX +bj9T/UWZYB2oK0z5XqcJ2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/ +D/xwzoiQ +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER +MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv +c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE +BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt +U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA +fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG +0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA +pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm +1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC +AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf +QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE +FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o +lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX +I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 +yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi +LXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi +=================================================== +-----BEGIN CERTIFICATE----- +MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG +EwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE8MDoGA1UEAxMz +ZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3 +MDEwNDExMzI0OFoXDTE3MDEwNDExMzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0 +cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9u +aWsgU2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdUMZTe1RK6UxYC6lhj71vY +8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlTL/jDj/6z/P2douNffb7tC+Bg62nsM+3Y +jfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAI +JjjcJRFHLfO6IxClv7wC90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk +9Ok0oSy1c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/BAQD +AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoEVtstxNulMA0GCSqG +SIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLPqk/CaOv/gKlR6D1id4k9CnU58W5d +F4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwq +D2fK/A+JYZ1lpTzlvBNbCNvj/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4 +Vwpm+Vganf2XKWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq +fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX +-----END CERTIFICATE----- + +GlobalSign Root CA - R3 +======================= +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt +iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ +0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 +rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl +OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 +xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 +lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 +EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E +bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 +YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r +kpeDMdmztcpHWD9f +-----END CERTIFICATE----- + +TC TrustCenter Universal CA III +=============================== +-----BEGIN CERTIFICATE----- +MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy +IFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAe +Fw0wOTA5MDkwODE1MjdaFw0yOTEyMzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNU +QyBUcnVzdENlbnRlciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0Ex +KDAmBgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF5+cvAqBNLaT6hdqbJYUt +QCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYvDIRlzg9uwliT6CwLOunBjvvya8o84pxO +juT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8vzArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+Eut +CHnNaYlAJ/Uqwa1D7KRTyGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1 +M4BDj5yjdipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBhMB8G +A1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI4jANBgkqhkiG9w0BAQUFAAOCAQEA +g8ev6n9NCjw5sWi+e22JLumzCecYV42FmhfzdkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+ +KGwWaODIl0YgoGhnYIg5IFHYaAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhK +BgePxLcHsU0GDeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV +CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPHLQNjO9Po5KIq +woIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg== +-----END CERTIFICATE----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +========================================================= +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw +QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB +NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD +Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P +B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY +7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH +ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI +plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX +MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX +LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK +bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU +vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud +EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH +DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA +bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx +ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx +51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk +R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP +T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f +Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl +osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR +crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR +saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD +KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi +6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +Izenpe.com +========== +-----BEGIN CERTIFICATE----- +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----- + +Actalis Authentication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM +BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE +AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky +MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz +IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ +wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa +by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6 +zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f +YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2 +oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l +EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7 +hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8 +EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5 +jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY +iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI +WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0 +JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx +K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+ +Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC +4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo +2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz +lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem +OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9 +vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----END CERTIFICATE----- + +Trustis FPS Root CA +=================== +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG +EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290 +IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV +BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ +RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk +H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa +cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt +o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA +AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd +BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c +GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC +yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P +8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV +l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl +iB6XzCGcKQENZetX2fNXlrtIzYE= +-----END CERTIFICATE----- + +StartCom Certification Authority +================================ +-----BEGIN CERTIFICATE----- +MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu +ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 +NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk +LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg +U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y +o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ +Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d +eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt +2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z +6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ +osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ +untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc +UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT +37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ +Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0 +dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu +c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv +bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0 +aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t +L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG +cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5 +fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm +N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN +Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T +tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX +e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA +2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs +HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE +JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib +D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8= +-----END CERTIFICATE----- + +StartCom Certification Authority G2 +=================================== +-----BEGIN CERTIFICATE----- +MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE +ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O +o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG +4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi +Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul +Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs +O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H +vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L +nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS +FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa +z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ +KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K +2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk +J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+ +JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG +/+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc +nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld +blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc +l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm +7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm +obp573PYtlNXLfbQ4ddI +-----END CERTIFICATE----- + +Buypass Class 2 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X +DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 +g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn +9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b +/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU +CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff +awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI +zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn +Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX +Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs +M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI +osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S +aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd +DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD +LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 +oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC +wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS +CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN +rJgWVqA= +-----END CERTIFICATE----- + +Buypass Class 3 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X +DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH +sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR +5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh +7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ +ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH +2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV +/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ +RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA +Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq +j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G +uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG +Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 +ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 +KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz +6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug +UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe +eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi +Cp/HuZc= +-----END CERTIFICATE----- + +TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı +====================================================== +-----BEGIN CERTIFICATE----- +MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOcUktUUlVTVCBF +bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP +MA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg +QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4X +DTA3MTIyNTE4MzcxOVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxl +a3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMCVFIxDzAN +BgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp +bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEFyYWzEsWsgMjAwNzCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9N +YvDdE3ePYakqtdTyuTFYKTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQv +KUmi8wUG+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveGHtya +KhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6PIzdezKKqdfcYbwnT +rqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M733WB2+Y8a+xwXrXgTW4qhe04MsC +AwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHkYb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/s +Px+EnWVUXKgWAkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I +aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5mxRZNTZPz/OO +Xl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsaXRik7r4EW5nVcV9VZWRi1aKb +BFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZqxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAK +poRq0Tl9 +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 3 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx +MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK +9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU +NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF +iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W +0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr +AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb +fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT +ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h +P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== +-----END CERTIFICATE----- + +EE Certification Centre Root CA +=============================== +-----BEGIN CERTIFICATE----- +MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG +EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy +dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw +MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB +UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy +ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM +TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2 +rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw +93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN +P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ +MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF +BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj +xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM +lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u +uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU +3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM +dcGWxZ0= +-----END CERTIFICATE----- diff --git a/rainloop/v/1.2.5.406/app/libraries/lessphp/LICENSE b/rainloop/v/1.2.5.406/app/libraries/lessphp/LICENSE new file mode 100644 index 000000000..b2338b1c8 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/lessphp/LICENSE @@ -0,0 +1,660 @@ +For ease of distribution, lessphp 0.2.0 is under a dual license. +You are free to pick which one suits your needs. + + + + +MIT LICENSE + + + + +Copyright (c) 2010 Leaf Corcoran, http://leafo.net/lessphp + +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. + + + + +GPL VERSION 3 + + + + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + diff --git a/rainloop/v/1.2.5.406/app/libraries/lessphp/README.md b/rainloop/v/1.2.5.406/app/libraries/lessphp/README.md new file mode 100644 index 000000000..0085e19d9 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/lessphp/README.md @@ -0,0 +1,96 @@ +# lessphp v0.3.9 +### + +[![Build Status](https://secure.travis-ci.org/leafo/lessphp.png)](http://travis-ci.org/leafo/lessphp) + +`lessphp` is a compiler for LESS written in PHP. The documentation is great, +so check it out: . + +Here's a quick tutorial: + +### How to use in your PHP project + +The only file required is `lessc.inc.php`, so copy that to your include directory. + +The typical flow of **lessphp** is to create a new instance of `lessc`, +configure it how you like, then tell it to compile something using one built in +compile methods. + +The `compile` method compiles a string of LESS code to CSS. + +```php +compile(".block { padding: 3 + 4px }"); +``` + +The `compileFile` method reads and compiles a file. It will either return the +result or write it to the path specified by an optional second argument. + +```php +compileFile("input.less"); +``` + +The `compileChecked` method is like `compileFile`, but it only compiles if the output +file doesn't exist or it's older than the input file: + +```php +checkedCompile("input.less", "output.css"); +``` + +If there any problem compiling your code, an exception is thrown with a helpful message: + +```php +compile("invalid LESS } {"); +} catch (exception $e) { + echo "fatal error: " . $e->getMessage(); +} +``` + +The `lessc` object can be configured through an assortment of instance methods. +Some possible configuration options include [changing the output format][1], +[setting variables from PHP][2], and [controlling the preservation of +comments][3], writing [custom functions][4] and much more. It's all described +in [the documentation][0]. + + + [0]: http://leafo.net/lessphp/docs/ + [1]: http://leafo.net/lessphp/docs/#output_formatting + [2]: http://leafo.net/lessphp/docs/#setting_variables_from_php + [3]: http://leafo.net/lessphp/docs/#preserving_comments + [4]: http://leafo.net/lessphp/docs/#custom_functions + + +### How to use from the command line + +An additional script has been included to use the compiler from the command +line. In the simplest invocation, you specify an input file and the compiled +css is written to standard out: + + $ plessc input.less > output.css + +Using the -r flag, you can specify LESS code directly as an argument or, if +the argument is left off, from standard in: + + $ plessc -r "my less code here" + +Finally, by using the -w flag you can watch a specified input file and have it +compile as needed to the output file: + + $ plessc -w input-file output-file + +Errors from watch mode are written to standard out. + +The -f flag sets the [output formatter][1]. For example, to compress the +output run this: + + $ plessc -f=compressed myfile.less + +For more help, run `plessc --help` + diff --git a/rainloop/v/1.2.5.406/app/libraries/lessphp/ctype.php b/rainloop/v/1.2.5.406/app/libraries/lessphp/ctype.php new file mode 100644 index 000000000..5464168e7 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/lessphp/ctype.php @@ -0,0 +1,32 @@ + + * Licensed under MIT or GPLv3, see LICENSE + */ + + +/** + * The less compiler and parser. + * + * Converting LESS to CSS is a three stage process. The incoming file is parsed + * by `lessc_parser` into a syntax tree, then it is compiled into another tree + * representing the CSS structure by `lessc`. The CSS tree is fed into a + * formatter, like `lessc_formatter` which then outputs CSS as a string. + * + * During the first compile, all values are *reduced*, which means that their + * types are brought to the lowest form before being dump as strings. This + * handles math equations, variable dereferences, and the like. + * + * The `parse` function of `lessc` is the entry point. + * + * In summary: + * + * The `lessc` class creates an intstance of the parser, feeds it LESS code, + * then transforms the resulting tree to a CSS tree. This class also holds the + * evaluation context, such as all available mixins and variables at any given + * time. + * + * The `lessc_parser` class is only concerned with parsing its input. + * + * The `lessc_formatter` takes a CSS tree, and dumps it to a formatted string, + * handling things like indentation. + */ +class lessc { + static public $VERSION = "v0.3.9"; + static protected $TRUE = array("keyword", "true"); + static protected $FALSE = array("keyword", "false"); + + protected $libFunctions = array(); + protected $registeredVars = array(); + protected $preserveComments = false; + + public $vPrefix = '@'; // prefix of abstract properties + public $mPrefix = '$'; // prefix of abstract blocks + public $parentSelector = '&'; + + public $importDisabled = false; + public $importDir = ''; + + protected $numberPrecision = null; + + // set to the parser that generated the current line when compiling + // so we know how to create error messages + protected $sourceParser = null; + protected $sourceLoc = null; + + static public $defaultValue = array("keyword", ""); + + static protected $nextImportId = 0; // uniquely identify imports + + // attempts to find the path of an import url, returns null for css files + protected function findImport($url) { + foreach ((array)$this->importDir as $dir) { + $full = $dir.(substr($dir, -1) != '/' ? '/' : '').$url; + if ($this->fileExists($file = $full.'.less') || $this->fileExists($file = $full)) { + return $file; + } + } + + return null; + } + + protected function fileExists($name) { + return is_file($name); + } + + static public function compressList($items, $delim) { + if (!isset($items[1]) && isset($items[0])) return $items[0]; + else return array('list', $delim, $items); + } + + static public function preg_quote($what) { + return preg_quote($what, '/'); + } + + protected function tryImport($importPath, $parentBlock, $out) { + if ($importPath[0] == "function" && $importPath[1] == "url") { + $importPath = $this->flattenList($importPath[2]); + } + + $str = $this->coerceString($importPath); + if ($str === null) return false; + + $url = $this->compileValue($this->lib_e($str)); + + // don't import if it ends in css + if (substr_compare($url, '.css', -4, 4) === 0) return false; + + $realPath = $this->findImport($url); + if ($realPath === null) return false; + + if ($this->importDisabled) { + return array(false, "/* import disabled */"); + } + + $this->addParsedFile($realPath); + $parser = $this->makeParser($realPath); + $root = $parser->parse(file_get_contents($realPath)); + + // set the parents of all the block props + foreach ($root->props as $prop) { + if ($prop[0] == "block") { + $prop[1]->parent = $parentBlock; + } + } + + // copy mixins into scope, set their parents + // bring blocks from import into current block + // TODO: need to mark the source parser these came from this file + foreach ($root->children as $childName => $child) { + if (isset($parentBlock->children[$childName])) { + $parentBlock->children[$childName] = array_merge( + $parentBlock->children[$childName], + $child); + } else { + $parentBlock->children[$childName] = $child; + } + } + + $pi = pathinfo($realPath); + $dir = $pi["dirname"]; + + list($top, $bottom) = $this->sortProps($root->props, true); + $this->compileImportedProps($top, $parentBlock, $out, $parser, $dir); + + return array(true, $bottom, $parser, $dir); + } + + protected function compileImportedProps($props, $block, $out, $sourceParser, $importDir) { + $oldSourceParser = $this->sourceParser; + + $oldImport = $this->importDir; + + // TODO: this is because the importDir api is stupid + $this->importDir = (array)$this->importDir; + array_unshift($this->importDir, $importDir); + + foreach ($props as $prop) { + $this->compileProp($prop, $block, $out); + } + + $this->importDir = $oldImport; + $this->sourceParser = $oldSourceParser; + } + + /** + * Recursively compiles a block. + * + * A block is analogous to a CSS block in most cases. A single LESS document + * is encapsulated in a block when parsed, but it does not have parent tags + * so all of it's children appear on the root level when compiled. + * + * Blocks are made up of props and children. + * + * Props are property instructions, array tuples which describe an action + * to be taken, eg. write a property, set a variable, mixin a block. + * + * The children of a block are just all the blocks that are defined within. + * This is used to look up mixins when performing a mixin. + * + * Compiling the block involves pushing a fresh environment on the stack, + * and iterating through the props, compiling each one. + * + * See lessc::compileProp() + * + */ + protected function compileBlock($block) { + switch ($block->type) { + case "root": + $this->compileRoot($block); + break; + case null: + $this->compileCSSBlock($block); + break; + case "media": + $this->compileMedia($block); + break; + case "directive": + $name = "@" . $block->name; + if (!empty($block->value)) { + $name .= " " . $this->compileValue($this->reduce($block->value)); + } + + $this->compileNestedBlock($block, array($name)); + break; + default: + $this->throwError("unknown block type: $block->type\n"); + } + } + + protected function compileCSSBlock($block) { + $env = $this->pushEnv(); + + $selectors = $this->compileSelectors($block->tags); + $env->selectors = $this->multiplySelectors($selectors); + $out = $this->makeOutputBlock(null, $env->selectors); + + $this->scope->children[] = $out; + $this->compileProps($block, $out); + + $block->scope = $env; // mixins carry scope with them! + $this->popEnv(); + } + + protected function compileMedia($media) { + $env = $this->pushEnv($media); + $parentScope = $this->mediaParent($this->scope); + + $query = $this->compileMediaQuery($this->multiplyMedia($env)); + + $this->scope = $this->makeOutputBlock($media->type, array($query)); + $parentScope->children[] = $this->scope; + + $this->compileProps($media, $this->scope); + + if (count($this->scope->lines) > 0) { + $orphanSelelectors = $this->findClosestSelectors(); + if (!is_null($orphanSelelectors)) { + $orphan = $this->makeOutputBlock(null, $orphanSelelectors); + $orphan->lines = $this->scope->lines; + array_unshift($this->scope->children, $orphan); + $this->scope->lines = array(); + } + } + + $this->scope = $this->scope->parent; + $this->popEnv(); + } + + protected function mediaParent($scope) { + while (!empty($scope->parent)) { + if (!empty($scope->type) && $scope->type != "media") { + break; + } + $scope = $scope->parent; + } + + return $scope; + } + + protected function compileNestedBlock($block, $selectors) { + $this->pushEnv($block); + $this->scope = $this->makeOutputBlock($block->type, $selectors); + $this->scope->parent->children[] = $this->scope; + + $this->compileProps($block, $this->scope); + + $this->scope = $this->scope->parent; + $this->popEnv(); + } + + protected function compileRoot($root) { + $this->pushEnv(); + $this->scope = $this->makeOutputBlock($root->type); + $this->compileProps($root, $this->scope); + $this->popEnv(); + } + + protected function compileProps($block, $out) { + foreach ($this->sortProps($block->props) as $prop) { + $this->compileProp($prop, $block, $out); + } + } + + protected function sortProps($props, $split = false) { + $vars = array(); + $imports = array(); + $other = array(); + + foreach ($props as $prop) { + switch ($prop[0]) { + case "assign": + if (isset($prop[1][0]) && $prop[1][0] == $this->vPrefix) { + $vars[] = $prop; + } else { + $other[] = $prop; + } + break; + case "import": + $id = self::$nextImportId++; + $prop[] = $id; + $imports[] = $prop; + $other[] = array("import_mixin", $id); + break; + default: + $other[] = $prop; + } + } + + if ($split) { + return array(array_merge($vars, $imports), $other); + } else { + return array_merge($vars, $imports, $other); + } + } + + protected function compileMediaQuery($queries) { + $compiledQueries = array(); + foreach ($queries as $query) { + $parts = array(); + foreach ($query as $q) { + switch ($q[0]) { + case "mediaType": + $parts[] = implode(" ", array_slice($q, 1)); + break; + case "mediaExp": + if (isset($q[2])) { + $parts[] = "($q[1]: " . + $this->compileValue($this->reduce($q[2])) . ")"; + } else { + $parts[] = "($q[1])"; + } + break; + case "variable": + $parts[] = $this->compileValue($this->reduce($q)); + break; + } + } + + if (count($parts) > 0) { + $compiledQueries[] = implode(" and ", $parts); + } + } + + $out = "@media"; + if (!empty($parts)) { + $out .= " " . + implode($this->formatter->selectorSeparator, $compiledQueries); + } + return $out; + } + + protected function multiplyMedia($env, $childQueries = null) { + if (is_null($env) || + !empty($env->block->type) && $env->block->type != "media") + { + return $childQueries; + } + + // plain old block, skip + if (empty($env->block->type)) { + return $this->multiplyMedia($env->parent, $childQueries); + } + + $out = array(); + $queries = $env->block->queries; + if (is_null($childQueries)) { + $out = $queries; + } else { + foreach ($queries as $parent) { + foreach ($childQueries as $child) { + $out[] = array_merge($parent, $child); + } + } + } + + return $this->multiplyMedia($env->parent, $out); + } + + protected function expandParentSelectors(&$tag, $replace) { + $parts = explode("$&$", $tag); + $count = 0; + foreach ($parts as &$part) { + $part = str_replace($this->parentSelector, $replace, $part, $c); + $count += $c; + } + $tag = implode($this->parentSelector, $parts); + return $count; + } + + protected function findClosestSelectors() { + $env = $this->env; + $selectors = null; + while ($env !== null) { + if (isset($env->selectors)) { + $selectors = $env->selectors; + break; + } + $env = $env->parent; + } + + return $selectors; + } + + + // multiply $selectors against the nearest selectors in env + protected function multiplySelectors($selectors) { + // find parent selectors + + $parentSelectors = $this->findClosestSelectors(); + if (is_null($parentSelectors)) { + // kill parent reference in top level selector + foreach ($selectors as &$s) { + $this->expandParentSelectors($s, ""); + } + + return $selectors; + } + + $out = array(); + foreach ($parentSelectors as $parent) { + foreach ($selectors as $child) { + $count = $this->expandParentSelectors($child, $parent); + + // don't prepend the parent tag if & was used + if ($count > 0) { + $out[] = trim($child); + } else { + $out[] = trim($parent . ' ' . $child); + } + } + } + + return $out; + } + + // reduces selector expressions + protected function compileSelectors($selectors) { + $out = array(); + + foreach ($selectors as $s) { + if (is_array($s)) { + list(, $value) = $s; + $out[] = trim($this->compileValue($this->reduce($value))); + } else { + $out[] = $s; + } + } + + return $out; + } + + protected function eq($left, $right) { + return $left == $right; + } + + protected function patternMatch($block, $callingArgs) { + // match the guards if it has them + // any one of the groups must have all its guards pass for a match + if (!empty($block->guards)) { + $groupPassed = false; + foreach ($block->guards as $guardGroup) { + foreach ($guardGroup as $guard) { + $this->pushEnv(); + $this->zipSetArgs($block->args, $callingArgs); + + $negate = false; + if ($guard[0] == "negate") { + $guard = $guard[1]; + $negate = true; + } + + $passed = $this->reduce($guard) == self::$TRUE; + if ($negate) $passed = !$passed; + + $this->popEnv(); + + if ($passed) { + $groupPassed = true; + } else { + $groupPassed = false; + break; + } + } + + if ($groupPassed) break; + } + + if (!$groupPassed) { + return false; + } + } + + $numCalling = count($callingArgs); + + if (empty($block->args)) { + return $block->isVararg || $numCalling == 0; + } + + $i = -1; // no args + // try to match by arity or by argument literal + foreach ($block->args as $i => $arg) { + switch ($arg[0]) { + case "lit": + if (empty($callingArgs[$i]) || !$this->eq($arg[1], $callingArgs[$i])) { + return false; + } + break; + case "arg": + // no arg and no default value + if (!isset($callingArgs[$i]) && !isset($arg[2])) { + return false; + } + break; + case "rest": + $i--; // rest can be empty + break 2; + } + } + + if ($block->isVararg) { + return true; // not having enough is handled above + } else { + $numMatched = $i + 1; + // greater than becuase default values always match + return $numMatched >= $numCalling; + } + } + + protected function patternMatchAll($blocks, $callingArgs) { + $matches = null; + foreach ($blocks as $block) { + if ($this->patternMatch($block, $callingArgs)) { + $matches[] = $block; + } + } + + return $matches; + } + + // attempt to find blocks matched by path and args + protected function findBlocks($searchIn, $path, $args, $seen=array()) { + if ($searchIn == null) return null; + if (isset($seen[$searchIn->id])) return null; + $seen[$searchIn->id] = true; + + $name = $path[0]; + + if (isset($searchIn->children[$name])) { + $blocks = $searchIn->children[$name]; + if (count($path) == 1) { + $matches = $this->patternMatchAll($blocks, $args); + if (!empty($matches)) { + // This will return all blocks that match in the closest + // scope that has any matching block, like lessjs + return $matches; + } + } else { + $matches = array(); + foreach ($blocks as $subBlock) { + $subMatches = $this->findBlocks($subBlock, + array_slice($path, 1), $args, $seen); + + if (!is_null($subMatches)) { + foreach ($subMatches as $sm) { + $matches[] = $sm; + } + } + } + + return count($matches) > 0 ? $matches : null; + } + } + + if ($searchIn->parent === $searchIn) return null; + return $this->findBlocks($searchIn->parent, $path, $args, $seen); + } + + // sets all argument names in $args to either the default value + // or the one passed in through $values + protected function zipSetArgs($args, $values) { + $i = 0; + $assignedValues = array(); + foreach ($args as $a) { + if ($a[0] == "arg") { + if ($i < count($values) && !is_null($values[$i])) { + $value = $values[$i]; + } elseif (isset($a[2])) { + $value = $a[2]; + } else $value = null; + + $value = $this->reduce($value); + $this->set($a[1], $value); + $assignedValues[] = $value; + } + $i++; + } + + // check for a rest + $last = end($args); + if ($last[0] == "rest") { + $rest = array_slice($values, count($args) - 1); + $this->set($last[1], $this->reduce(array("list", " ", $rest))); + } + + $this->env->arguments = $assignedValues; + } + + // compile a prop and update $lines or $blocks appropriately + protected function compileProp($prop, $block, $out) { + // set error position context + $this->sourceLoc = isset($prop[-1]) ? $prop[-1] : -1; + + switch ($prop[0]) { + case 'assign': + list(, $name, $value) = $prop; + if ($name[0] == $this->vPrefix) { + $this->set($name, $value); + } else { + $out->lines[] = $this->formatter->property($name, + $this->compileValue($this->reduce($value))); + } + break; + case 'block': + list(, $child) = $prop; + $this->compileBlock($child); + break; + case 'mixin': + list(, $path, $args, $suffix) = $prop; + + $args = array_map(array($this, "reduce"), (array)$args); + $mixins = $this->findBlocks($block, $path, $args); + + if ($mixins === null) { + // fwrite(STDERR,"failed to find block: ".implode(" > ", $path)."\n"); + break; // throw error here?? + } + + foreach ($mixins as $mixin) { + $haveScope = false; + if (isset($mixin->parent->scope)) { + $haveScope = true; + $mixinParentEnv = $this->pushEnv(); + $mixinParentEnv->storeParent = $mixin->parent->scope; + } + + $haveArgs = false; + if (isset($mixin->args)) { + $haveArgs = true; + $this->pushEnv(); + $this->zipSetArgs($mixin->args, $args); + } + + $oldParent = $mixin->parent; + if ($mixin != $block) $mixin->parent = $block; + + foreach ($this->sortProps($mixin->props) as $subProp) { + if ($suffix !== null && + $subProp[0] == "assign" && + is_string($subProp[1]) && + $subProp[1]{0} != $this->vPrefix) + { + $subProp[2] = array( + 'list', ' ', + array($subProp[2], array('keyword', $suffix)) + ); + } + + $this->compileProp($subProp, $mixin, $out); + } + + $mixin->parent = $oldParent; + + if ($haveArgs) $this->popEnv(); + if ($haveScope) $this->popEnv(); + } + + break; + case 'raw': + $out->lines[] = $prop[1]; + break; + case "directive": + list(, $name, $value) = $prop; + $out->lines[] = "@$name " . $this->compileValue($this->reduce($value)).';'; + break; + case "comment": + $out->lines[] = $prop[1]; + break; + case "import"; + list(, $importPath, $importId) = $prop; + $importPath = $this->reduce($importPath); + + if (!isset($this->env->imports)) { + $this->env->imports = array(); + } + + $result = $this->tryImport($importPath, $block, $out); + + $this->env->imports[$importId] = $result === false ? + array(false, "@import " . $this->compileValue($importPath).";") : + $result; + + break; + case "import_mixin": + list(,$importId) = $prop; + $import = $this->env->imports[$importId]; + if ($import[0] === false) { + $out->lines[] = $import[1]; + } else { + list(, $bottom, $parser, $importDir) = $import; + $this->compileImportedProps($bottom, $block, $out, $parser, $importDir); + } + + break; + default: + $this->throwError("unknown op: {$prop[0]}\n"); + } + } + + + /** + * Compiles a primitive value into a CSS property value. + * + * Values in lessphp are typed by being wrapped in arrays, their format is + * typically: + * + * array(type, contents [, additional_contents]*) + * + * The input is expected to be reduced. This function will not work on + * things like expressions and variables. + */ + protected function compileValue($value) { + switch ($value[0]) { + case 'list': + // [1] - delimiter + // [2] - array of values + return implode($value[1], array_map(array($this, 'compileValue'), $value[2])); + case 'raw_color': + if (!empty($this->formatter->compressColors)) { + return $this->compileValue($this->coerceColor($value)); + } + return $value[1]; + case 'keyword': + // [1] - the keyword + return $value[1]; + case 'number': + list(, $num, $unit) = $value; + // [1] - the number + // [2] - the unit + if ($this->numberPrecision !== null) { + $num = round($num, $this->numberPrecision); + } + return $num . $unit; + case 'string': + // [1] - contents of string (includes quotes) + list(, $delim, $content) = $value; + foreach ($content as &$part) { + if (is_array($part)) { + $part = $this->compileValue($part); + } + } + return $delim . implode($content) . $delim; + case 'color': + // [1] - red component (either number or a %) + // [2] - green component + // [3] - blue component + // [4] - optional alpha component + list(, $r, $g, $b) = $value; + $r = round($r); + $g = round($g); + $b = round($b); + + if (count($value) == 5 && $value[4] != 1) { // rgba + return 'rgba('.$r.','.$g.','.$b.','.$value[4].')'; + } + + $h = sprintf("#%02x%02x%02x", $r, $g, $b); + + if (!empty($this->formatter->compressColors)) { + // Converting hex color to short notation (e.g. #003399 to #039) + if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) { + $h = '#' . $h[1] . $h[3] . $h[5]; + } + } + + return $h; + + case 'function': + list(, $name, $args) = $value; + return $name.'('.$this->compileValue($args).')'; + default: // assumed to be unit + $this->throwError("unknown value type: $value[0]"); + } + } + + protected function lib_isnumber($value) { + return $this->toBool($value[0] == "number"); + } + + protected function lib_isstring($value) { + return $this->toBool($value[0] == "string"); + } + + protected function lib_iscolor($value) { + return $this->toBool($this->coerceColor($value)); + } + + protected function lib_iskeyword($value) { + return $this->toBool($value[0] == "keyword"); + } + + protected function lib_ispixel($value) { + return $this->toBool($value[0] == "number" && $value[2] == "px"); + } + + protected function lib_ispercentage($value) { + return $this->toBool($value[0] == "number" && $value[2] == "%"); + } + + protected function lib_isem($value) { + return $this->toBool($value[0] == "number" && $value[2] == "em"); + } + + protected function lib_isrem($value) { + return $this->toBool($value[0] == "number" && $value[2] == "rem"); + } + + protected function lib_rgbahex($color) { + $color = $this->coerceColor($color); + if (is_null($color)) + $this->throwError("color expected for rgbahex"); + + return sprintf("#%02x%02x%02x%02x", + isset($color[4]) ? $color[4]*255 : 255, + $color[1],$color[2], $color[3]); + } + + protected function lib_argb($color){ + return $this->lib_rgbahex($color); + } + + // utility func to unquote a string + protected function lib_e($arg) { + switch ($arg[0]) { + case "list": + $items = $arg[2]; + if (isset($items[0])) { + return $this->lib_e($items[0]); + } + return self::$defaultValue; + case "string": + $arg[1] = ""; + return $arg; + case "keyword": + return $arg; + default: + return array("keyword", $this->compileValue($arg)); + } + } + + protected function lib__sprintf($args) { + if ($args[0] != "list") return $args; + $values = $args[2]; + $string = array_shift($values); + $template = $this->compileValue($this->lib_e($string)); + + $i = 0; + if (preg_match_all('/%[dsa]/', $template, $m)) { + foreach ($m[0] as $match) { + $val = isset($values[$i]) ? + $this->reduce($values[$i]) : array('keyword', ''); + + // lessjs compat, renders fully expanded color, not raw color + if ($color = $this->coerceColor($val)) { + $val = $color; + } + + $i++; + $rep = $this->compileValue($this->lib_e($val)); + $template = preg_replace('/'.self::preg_quote($match).'/', + $rep, $template, 1); + } + } + + $d = $string[0] == "string" ? $string[1] : '"'; + return array("string", $d, array($template)); + } + + protected function lib_floor($arg) { + $value = $this->assertNumber($arg); + return array("number", floor($value), $arg[2]); + } + + protected function lib_ceil($arg) { + $value = $this->assertNumber($arg); + return array("number", ceil($value), $arg[2]); + } + + protected function lib_round($arg) { + $value = $this->assertNumber($arg); + return array("number", round($value), $arg[2]); + } + + protected function lib_unit($arg) { + if ($arg[0] == "list") { + list($number, $newUnit) = $arg[2]; + return array("number", $this->assertNumber($number), + $this->compileValue($this->lib_e($newUnit))); + } else { + return array("number", $this->assertNumber($arg), ""); + } + } + + /** + * Helper function to get arguments for color manipulation functions. + * takes a list that contains a color like thing and a percentage + */ + protected function colorArgs($args) { + if ($args[0] != 'list' || count($args[2]) < 2) { + return array(array('color', 0, 0, 0), 0); + } + list($color, $delta) = $args[2]; + $color = $this->assertColor($color); + $delta = floatval($delta[1]); + + return array($color, $delta); + } + + protected function lib_darken($args) { + list($color, $delta) = $this->colorArgs($args); + + $hsl = $this->toHSL($color); + $hsl[3] = $this->clamp($hsl[3] - $delta, 100); + return $this->toRGB($hsl); + } + + protected function lib_lighten($args) { + list($color, $delta) = $this->colorArgs($args); + + $hsl = $this->toHSL($color); + $hsl[3] = $this->clamp($hsl[3] + $delta, 100); + return $this->toRGB($hsl); + } + + protected function lib_saturate($args) { + list($color, $delta) = $this->colorArgs($args); + + $hsl = $this->toHSL($color); + $hsl[2] = $this->clamp($hsl[2] + $delta, 100); + return $this->toRGB($hsl); + } + + protected function lib_desaturate($args) { + list($color, $delta) = $this->colorArgs($args); + + $hsl = $this->toHSL($color); + $hsl[2] = $this->clamp($hsl[2] - $delta, 100); + return $this->toRGB($hsl); + } + + protected function lib_spin($args) { + list($color, $delta) = $this->colorArgs($args); + + $hsl = $this->toHSL($color); + + $hsl[1] = $hsl[1] + $delta % 360; + if ($hsl[1] < 0) $hsl[1] += 360; + + return $this->toRGB($hsl); + } + + protected function lib_fadeout($args) { + list($color, $delta) = $this->colorArgs($args); + $color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) - $delta/100); + return $color; + } + + protected function lib_fadein($args) { + list($color, $delta) = $this->colorArgs($args); + $color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) + $delta/100); + return $color; + } + + protected function lib_hue($color) { + $hsl = $this->toHSL($this->assertColor($color)); + return round($hsl[1]); + } + + protected function lib_saturation($color) { + $hsl = $this->toHSL($this->assertColor($color)); + return round($hsl[2]); + } + + protected function lib_lightness($color) { + $hsl = $this->toHSL($this->assertColor($color)); + return round($hsl[3]); + } + + // get the alpha of a color + // defaults to 1 for non-colors or colors without an alpha + protected function lib_alpha($value) { + if (!is_null($color = $this->coerceColor($value))) { + return isset($color[4]) ? $color[4] : 1; + } + } + + // set the alpha of the color + protected function lib_fade($args) { + list($color, $alpha) = $this->colorArgs($args); + $color[4] = $this->clamp($alpha / 100.0); + return $color; + } + + protected function lib_percentage($arg) { + $num = $this->assertNumber($arg); + return array("number", $num*100, "%"); + } + + // mixes two colors by weight + // mix(@color1, @color2, @weight); + // http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#mix-instance_method + protected function lib_mix($args) { + if ($args[0] != "list" || count($args[2]) < 3) + $this->throwError("mix expects (color1, color2, weight)"); + + list($first, $second, $weight) = $args[2]; + $first = $this->assertColor($first); + $second = $this->assertColor($second); + + $first_a = $this->lib_alpha($first); + $second_a = $this->lib_alpha($second); + $weight = $weight[1] / 100.0; + + $w = $weight * 2 - 1; + $a = $first_a - $second_a; + + $w1 = (($w * $a == -1 ? $w : ($w + $a)/(1 + $w * $a)) + 1) / 2.0; + $w2 = 1.0 - $w1; + + $new = array('color', + $w1 * $first[1] + $w2 * $second[1], + $w1 * $first[2] + $w2 * $second[2], + $w1 * $first[3] + $w2 * $second[3], + ); + + if ($first_a != 1.0 || $second_a != 1.0) { + $new[] = $first_a * $weight + $second_a * ($weight - 1); + } + + return $this->fixColor($new); + } + + protected function lib_contrast($args) { + if ($args[0] != 'list' || count($args[2]) < 3) { + return array(array('color', 0, 0, 0), 0); + } + + list($inputColor, $darkColor, $lightColor) = $args[2]; + + $inputColor = $this->assertColor($inputColor); + $darkColor = $this->assertColor($darkColor); + $lightColor = $this->assertColor($lightColor); + $hsl = $this->toHSL($inputColor); + + if ($hsl[3] > 50) { + return $darkColor; + } + + return $lightColor; + } + + protected function assertColor($value, $error = "expected color value") { + $color = $this->coerceColor($value); + if (is_null($color)) $this->throwError($error); + return $color; + } + + protected function assertNumber($value, $error = "expecting number") { + if ($value[0] == "number") return $value[1]; + $this->throwError($error); + } + + protected function toHSL($color) { + if ($color[0] == 'hsl') return $color; + + $r = $color[1] / 255; + $g = $color[2] / 255; + $b = $color[3] / 255; + + $min = min($r, $g, $b); + $max = max($r, $g, $b); + + $L = ($min + $max) / 2; + if ($min == $max) { + $S = $H = 0; + } else { + if ($L < 0.5) + $S = ($max - $min)/($max + $min); + else + $S = ($max - $min)/(2.0 - $max - $min); + + if ($r == $max) $H = ($g - $b)/($max - $min); + elseif ($g == $max) $H = 2.0 + ($b - $r)/($max - $min); + elseif ($b == $max) $H = 4.0 + ($r - $g)/($max - $min); + + } + + $out = array('hsl', + ($H < 0 ? $H + 6 : $H)*60, + $S*100, + $L*100, + ); + + if (count($color) > 4) $out[] = $color[4]; // copy alpha + return $out; + } + + protected function toRGB_helper($comp, $temp1, $temp2) { + if ($comp < 0) $comp += 1.0; + elseif ($comp > 1) $comp -= 1.0; + + if (6 * $comp < 1) return $temp1 + ($temp2 - $temp1) * 6 * $comp; + if (2 * $comp < 1) return $temp2; + if (3 * $comp < 2) return $temp1 + ($temp2 - $temp1)*((2/3) - $comp) * 6; + + return $temp1; + } + + /** + * Converts a hsl array into a color value in rgb. + * Expects H to be in range of 0 to 360, S and L in 0 to 100 + */ + protected function toRGB($color) { + if ($color[0] == 'color') return $color; + + $H = $color[1] / 360; + $S = $color[2] / 100; + $L = $color[3] / 100; + + if ($S == 0) { + $r = $g = $b = $L; + } else { + $temp2 = $L < 0.5 ? + $L*(1.0 + $S) : + $L + $S - $L * $S; + + $temp1 = 2.0 * $L - $temp2; + + $r = $this->toRGB_helper($H + 1/3, $temp1, $temp2); + $g = $this->toRGB_helper($H, $temp1, $temp2); + $b = $this->toRGB_helper($H - 1/3, $temp1, $temp2); + } + + // $out = array('color', round($r*255), round($g*255), round($b*255)); + $out = array('color', $r*255, $g*255, $b*255); + if (count($color) > 4) $out[] = $color[4]; // copy alpha + return $out; + } + + protected function clamp($v, $max = 1, $min = 0) { + return min($max, max($min, $v)); + } + + /** + * Convert the rgb, rgba, hsl color literals of function type + * as returned by the parser into values of color type. + */ + protected function funcToColor($func) { + $fname = $func[1]; + if ($func[2][0] != 'list') return false; // need a list of arguments + $rawComponents = $func[2][2]; + + if ($fname == 'hsl' || $fname == 'hsla') { + $hsl = array('hsl'); + $i = 0; + foreach ($rawComponents as $c) { + $val = $this->reduce($c); + $val = isset($val[1]) ? floatval($val[1]) : 0; + + if ($i == 0) $clamp = 360; + elseif ($i < 3) $clamp = 100; + else $clamp = 1; + + $hsl[] = $this->clamp($val, $clamp); + $i++; + } + + while (count($hsl) < 4) $hsl[] = 0; + return $this->toRGB($hsl); + + } elseif ($fname == 'rgb' || $fname == 'rgba') { + $components = array(); + $i = 1; + foreach ($rawComponents as $c) { + $c = $this->reduce($c); + if ($i < 4) { + if ($c[0] == "number" && $c[2] == "%") { + $components[] = 255 * ($c[1] / 100); + } else { + $components[] = floatval($c[1]); + } + } elseif ($i == 4) { + if ($c[0] == "number" && $c[2] == "%") { + $components[] = 1.0 * ($c[1] / 100); + } else { + $components[] = floatval($c[1]); + } + } else break; + + $i++; + } + while (count($components) < 3) $components[] = 0; + array_unshift($components, 'color'); + return $this->fixColor($components); + } + + return false; + } + + protected function reduce($value, $forExpression = false) { + switch ($value[0]) { + case "interpolate": + $reduced = $this->reduce($value[1]); + $var = $this->compileValue($reduced); + $res = $this->reduce(array("variable", $this->vPrefix . $var)); + + if (empty($value[2])) $res = $this->lib_e($res); + + return $res; + case "variable": + $key = $value[1]; + if (is_array($key)) { + $key = $this->reduce($key); + $key = $this->vPrefix . $this->compileValue($this->lib_e($key)); + } + + $seen =& $this->env->seenNames; + + if (!empty($seen[$key])) { + $this->throwError("infinite loop detected: $key"); + } + + $seen[$key] = true; + $out = $this->reduce($this->get($key, self::$defaultValue)); + $seen[$key] = false; + return $out; + case "list": + foreach ($value[2] as &$item) { + $item = $this->reduce($item, $forExpression); + } + return $value; + case "expression": + return $this->evaluate($value); + case "string": + foreach ($value[2] as &$part) { + if (is_array($part)) { + $strip = $part[0] == "variable"; + $part = $this->reduce($part); + if ($strip) $part = $this->lib_e($part); + } + } + return $value; + case "escape": + list(,$inner) = $value; + return $this->lib_e($this->reduce($inner)); + case "function": + $color = $this->funcToColor($value); + if ($color) return $color; + + list(, $name, $args) = $value; + if ($name == "%") $name = "_sprintf"; + $f = isset($this->libFunctions[$name]) ? + $this->libFunctions[$name] : array($this, 'lib_'.$name); + + if (is_callable($f)) { + if ($args[0] == 'list') + $args = self::compressList($args[2], $args[1]); + + $ret = call_user_func($f, $this->reduce($args, true), $this); + + if (is_null($ret)) { + return array("string", "", array( + $name, "(", $args, ")" + )); + } + + // convert to a typed value if the result is a php primitive + if (is_numeric($ret)) $ret = array('number', $ret, ""); + elseif (!is_array($ret)) $ret = array('keyword', $ret); + + return $ret; + } + + // plain function, reduce args + $value[2] = $this->reduce($value[2]); + return $value; + case "unary": + list(, $op, $exp) = $value; + $exp = $this->reduce($exp); + + if ($exp[0] == "number") { + switch ($op) { + case "+": + return $exp; + case "-": + $exp[1] *= -1; + return $exp; + } + } + return array("string", "", array($op, $exp)); + } + + if ($forExpression) { + switch ($value[0]) { + case "keyword": + if ($color = $this->coerceColor($value)) { + return $color; + } + break; + case "raw_color": + return $this->coerceColor($value); + } + } + + return $value; + } + + + // coerce a value for use in color operation + protected function coerceColor($value) { + switch($value[0]) { + case 'color': return $value; + case 'raw_color': + $c = array("color", 0, 0, 0); + $colorStr = substr($value[1], 1); + $num = hexdec($colorStr); + $width = strlen($colorStr) == 3 ? 16 : 256; + + for ($i = 3; $i > 0; $i--) { // 3 2 1 + $t = $num % $width; + $num /= $width; + + $c[$i] = $t * (256/$width) + $t * floor(16/$width); + } + + return $c; + case 'keyword': + $name = $value[1]; + if (isset(self::$cssColors[$name])) { + $rgba = explode(',', self::$cssColors[$name]); + + if(isset($rgba[3])) + return array('color', $rgba[0], $rgba[1], $rgba[2], $rgba[3]); + + return array('color', $rgba[0], $rgba[1], $rgba[2]); + } + return null; + } + } + + // make something string like into a string + protected function coerceString($value) { + switch ($value[0]) { + case "string": + return $value; + case "keyword": + return array("string", "", array($value[1])); + } + return null; + } + + // turn list of length 1 into value type + protected function flattenList($value) { + if ($value[0] == "list" && count($value[2]) == 1) { + return $this->flattenList($value[2][0]); + } + return $value; + } + + protected function toBool($a) { + if ($a) return self::$TRUE; + else return self::$FALSE; + } + + // evaluate an expression + protected function evaluate($exp) { + list(, $op, $left, $right, $whiteBefore, $whiteAfter) = $exp; + + $left = $this->reduce($left, true); + $right = $this->reduce($right, true); + + if ($leftColor = $this->coerceColor($left)) { + $left = $leftColor; + } + + if ($rightColor = $this->coerceColor($right)) { + $right = $rightColor; + } + + $ltype = $left[0]; + $rtype = $right[0]; + + // operators that work on all types + if ($op == "and") { + return $this->toBool($left == self::$TRUE && $right == self::$TRUE); + } + + if ($op == "=") { + return $this->toBool($this->eq($left, $right) ); + } + + if ($op == "+" && !is_null($str = $this->stringConcatenate($left, $right))) { + return $str; + } + + // type based operators + $fname = "op_${ltype}_${rtype}"; + if (is_callable(array($this, $fname))) { + $out = $this->$fname($op, $left, $right); + if (!is_null($out)) return $out; + } + + // make the expression look it did before being parsed + $paddedOp = $op; + if ($whiteBefore) $paddedOp = " " . $paddedOp; + if ($whiteAfter) $paddedOp .= " "; + + return array("string", "", array($left, $paddedOp, $right)); + } + + protected function stringConcatenate($left, $right) { + if ($strLeft = $this->coerceString($left)) { + if ($right[0] == "string") { + $right[1] = ""; + } + $strLeft[2][] = $right; + return $strLeft; + } + + if ($strRight = $this->coerceString($right)) { + array_unshift($strRight[2], $left); + return $strRight; + } + } + + + // make sure a color's components don't go out of bounds + protected function fixColor($c) { + foreach (range(1, 3) as $i) { + if ($c[$i] < 0) $c[$i] = 0; + if ($c[$i] > 255) $c[$i] = 255; + } + + return $c; + } + + protected function op_number_color($op, $lft, $rgt) { + if ($op == '+' || $op == '*') { + return $this->op_color_number($op, $rgt, $lft); + } + } + + protected function op_color_number($op, $lft, $rgt) { + if ($rgt[0] == '%') $rgt[1] /= 100; + + return $this->op_color_color($op, $lft, + array_fill(1, count($lft) - 1, $rgt[1])); + } + + protected function op_color_color($op, $left, $right) { + $out = array('color'); + $max = count($left) > count($right) ? count($left) : count($right); + foreach (range(1, $max - 1) as $i) { + $lval = isset($left[$i]) ? $left[$i] : 0; + $rval = isset($right[$i]) ? $right[$i] : 0; + switch ($op) { + case '+': + $out[] = $lval + $rval; + break; + case '-': + $out[] = $lval - $rval; + break; + case '*': + $out[] = $lval * $rval; + break; + case '%': + $out[] = $lval % $rval; + break; + case '/': + if ($rval == 0) $this->throwError("evaluate error: can't divide by zero"); + $out[] = $lval / $rval; + break; + default: + $this->throwError('evaluate error: color op number failed on op '.$op); + } + } + return $this->fixColor($out); + } + + function lib_red($color){ + $color = $this->coerceColor($color); + if (is_null($color)) { + $this->throwError('color expected for red()'); + } + + return $color[1]; + } + + function lib_green($color){ + $color = $this->coerceColor($color); + if (is_null($color)) { + $this->throwError('color expected for green()'); + } + + return $color[2]; + } + + function lib_blue($color){ + $color = $this->coerceColor($color); + if (is_null($color)) { + $this->throwError('color expected for blue()'); + } + + return $color[3]; + } + + + // operator on two numbers + protected function op_number_number($op, $left, $right) { + $unit = empty($left[2]) ? $right[2] : $left[2]; + + $value = 0; + switch ($op) { + case '+': + $value = $left[1] + $right[1]; + break; + case '*': + $value = $left[1] * $right[1]; + break; + case '-': + $value = $left[1] - $right[1]; + break; + case '%': + $value = $left[1] % $right[1]; + break; + case '/': + if ($right[1] == 0) $this->throwError('parse error: divide by zero'); + $value = $left[1] / $right[1]; + break; + case '<': + return $this->toBool($left[1] < $right[1]); + case '>': + return $this->toBool($left[1] > $right[1]); + case '>=': + return $this->toBool($left[1] >= $right[1]); + case '=<': + return $this->toBool($left[1] <= $right[1]); + default: + $this->throwError('parse error: unknown number operator: '.$op); + } + + return array("number", $value, $unit); + } + + + /* environment functions */ + + protected function makeOutputBlock($type, $selectors = null) { + $b = new stdclass; + $b->lines = array(); + $b->children = array(); + $b->selectors = $selectors; + $b->type = $type; + $b->parent = $this->scope; + return $b; + } + + // the state of execution + protected function pushEnv($block = null) { + $e = new stdclass; + $e->parent = $this->env; + $e->store = array(); + $e->block = $block; + + $this->env = $e; + return $e; + } + + // pop something off the stack + protected function popEnv() { + $old = $this->env; + $this->env = $this->env->parent; + return $old; + } + + // set something in the current env + protected function set($name, $value) { + $this->env->store[$name] = $value; + } + + + // get the highest occurrence entry for a name + protected function get($name, $default=null) { + $current = $this->env; + + $isArguments = $name == $this->vPrefix . 'arguments'; + while ($current) { + if ($isArguments && isset($current->arguments)) { + return array('list', ' ', $current->arguments); + } + + if (isset($current->store[$name])) + return $current->store[$name]; + else { + $current = isset($current->storeParent) ? + $current->storeParent : $current->parent; + } + } + + return $default; + } + + // inject array of unparsed strings into environment as variables + protected function injectVariables($args) { + $this->pushEnv(); + $parser = new lessc_parser($this, __METHOD__); + foreach ($args as $name => $strValue) { + if ($name{0} != '@') $name = '@'.$name; + $parser->count = 0; + $parser->buffer = (string)$strValue; + if (!$parser->propertyValue($value)) { + throw new Exception("failed to parse passed in variable $name: $strValue"); + } + + $this->set($name, $value); + } + } + + /** + * Initialize any static state, can initialize parser for a file + * $opts isn't used yet + */ + public function __construct($fname = null) { + if ($fname !== null) { + // used for deprecated parse method + $this->_parseFile = $fname; + } + } + + public function compile($string, $name = null) { + $locale = setlocale(LC_NUMERIC, 0); + setlocale(LC_NUMERIC, "C"); + + $this->parser = $this->makeParser($name); + $root = $this->parser->parse($string); + + $this->env = null; + $this->scope = null; + + $this->formatter = $this->newFormatter(); + + if (!empty($this->registeredVars)) { + $this->injectVariables($this->registeredVars); + } + + $this->sourceParser = $this->parser; // used for error messages + $this->compileBlock($root); + + ob_start(); + $this->formatter->block($this->scope); + $out = ob_get_clean(); + setlocale(LC_NUMERIC, $locale); + return $out; + } + + public function compileFile($fname, $outFname = null) { + if (!is_readable($fname)) { + throw new Exception('load error: failed to find '.$fname); + } + + $pi = pathinfo($fname); + + $oldImport = $this->importDir; + + $this->importDir = (array)$this->importDir; + $this->importDir[] = $pi['dirname'].'/'; + + $this->allParsedFiles = array(); + $this->addParsedFile($fname); + + $out = $this->compile(file_get_contents($fname), $fname); + + $this->importDir = $oldImport; + + if ($outFname !== null) { + return file_put_contents($outFname, $out); + } + + return $out; + } + + // compile only if changed input has changed or output doesn't exist + public function checkedCompile($in, $out) { + if (!is_file($out) || filemtime($in) > filemtime($out)) { + $this->compileFile($in, $out); + return true; + } + return false; + } + + /** + * Execute lessphp on a .less file or a lessphp cache structure + * + * The lessphp cache structure contains information about a specific + * less file having been parsed. It can be used as a hint for future + * calls to determine whether or not a rebuild is required. + * + * The cache structure contains two important keys that may be used + * externally: + * + * compiled: The final compiled CSS + * updated: The time (in seconds) the CSS was last compiled + * + * The cache structure is a plain-ol' PHP associative array and can + * be serialized and unserialized without a hitch. + * + * @param mixed $in Input + * @param bool $force Force rebuild? + * @return array lessphp cache structure + */ + public function cachedCompile($in, $force = false) { + // assume no root + $root = null; + + if (is_string($in)) { + $root = $in; + } elseif (is_array($in) and isset($in['root'])) { + if ($force or ! isset($in['files'])) { + // If we are forcing a recompile or if for some reason the + // structure does not contain any file information we should + // specify the root to trigger a rebuild. + $root = $in['root']; + } elseif (isset($in['files']) and is_array($in['files'])) { + foreach ($in['files'] as $fname => $ftime ) { + if (!file_exists($fname) or filemtime($fname) > $ftime) { + // One of the files we knew about previously has changed + // so we should look at our incoming root again. + $root = $in['root']; + break; + } + } + } + } else { + // TODO: Throw an exception? We got neither a string nor something + // that looks like a compatible lessphp cache structure. + return null; + } + + if ($root !== null) { + // If we have a root value which means we should rebuild. + $out = array(); + $out['root'] = $root; + $out['compiled'] = $this->compileFile($root); + $out['files'] = $this->allParsedFiles(); + $out['updated'] = time(); + return $out; + } else { + // No changes, pass back the structure + // we were given initially. + return $in; + } + + } + + // parse and compile buffer + // This is deprecated + public function parse($str = null, $initialVariables = null) { + if (is_array($str)) { + $initialVariables = $str; + $str = null; + } + + $oldVars = $this->registeredVars; + if ($initialVariables !== null) { + $this->setVariables($initialVariables); + } + + if ($str == null) { + if (empty($this->_parseFile)) { + throw new exception("nothing to parse"); + } + + $out = $this->compileFile($this->_parseFile); + } else { + $out = $this->compile($str); + } + + $this->registeredVars = $oldVars; + return $out; + } + + protected function makeParser($name) { + $parser = new lessc_parser($this, $name); + $parser->writeComments = $this->preserveComments; + + return $parser; + } + + public function setFormatter($name) { + $this->formatterName = $name; + } + + protected function newFormatter() { + $className = "lessc_formatter_lessjs"; + if (!empty($this->formatterName)) { + if (!is_string($this->formatterName)) + return $this->formatterName; + $className = "lessc_formatter_$this->formatterName"; + } + + return new $className; + } + + public function setPreserveComments($preserve) { + $this->preserveComments = $preserve; + } + + public function registerFunction($name, $func) { + $this->libFunctions[$name] = $func; + } + + public function unregisterFunction($name) { + unset($this->libFunctions[$name]); + } + + public function setVariables($variables) { + $this->registeredVars = array_merge($this->registeredVars, $variables); + } + + public function unsetVariable($name) { + unset($this->registeredVars[$name]); + } + + public function setImportDir($dirs) { + $this->importDir = (array)$dirs; + } + + public function addImportDir($dir) { + $this->importDir = (array)$this->importDir; + $this->importDir[] = $dir; + } + + public function allParsedFiles() { + return $this->allParsedFiles; + } + + protected function addParsedFile($file) { + $this->allParsedFiles[realpath($file)] = filemtime($file); + } + + /** + * Uses the current value of $this->count to show line and line number + */ + protected function throwError($msg = null) { + if ($this->sourceLoc >= 0) { + $this->sourceParser->throwError($msg, $this->sourceLoc); + } + throw new exception($msg); + } + + // compile file $in to file $out if $in is newer than $out + // returns true when it compiles, false otherwise + public static function ccompile($in, $out, $less = null) { + if ($less === null) { + $less = new self; + } + return $less->checkedCompile($in, $out); + } + + public static function cexecute($in, $force = false, $less = null) { + if ($less === null) { + $less = new self; + } + return $less->cachedCompile($in, $force); + } + + static protected $cssColors = array( + 'aliceblue' => '240,248,255', + 'antiquewhite' => '250,235,215', + 'aqua' => '0,255,255', + 'aquamarine' => '127,255,212', + 'azure' => '240,255,255', + 'beige' => '245,245,220', + 'bisque' => '255,228,196', + 'black' => '0,0,0', + 'blanchedalmond' => '255,235,205', + 'blue' => '0,0,255', + 'blueviolet' => '138,43,226', + 'brown' => '165,42,42', + 'burlywood' => '222,184,135', + 'cadetblue' => '95,158,160', + 'chartreuse' => '127,255,0', + 'chocolate' => '210,105,30', + 'coral' => '255,127,80', + 'cornflowerblue' => '100,149,237', + 'cornsilk' => '255,248,220', + 'crimson' => '220,20,60', + 'cyan' => '0,255,255', + 'darkblue' => '0,0,139', + 'darkcyan' => '0,139,139', + 'darkgoldenrod' => '184,134,11', + 'darkgray' => '169,169,169', + 'darkgreen' => '0,100,0', + 'darkgrey' => '169,169,169', + 'darkkhaki' => '189,183,107', + 'darkmagenta' => '139,0,139', + 'darkolivegreen' => '85,107,47', + 'darkorange' => '255,140,0', + 'darkorchid' => '153,50,204', + 'darkred' => '139,0,0', + 'darksalmon' => '233,150,122', + 'darkseagreen' => '143,188,143', + 'darkslateblue' => '72,61,139', + 'darkslategray' => '47,79,79', + 'darkslategrey' => '47,79,79', + 'darkturquoise' => '0,206,209', + 'darkviolet' => '148,0,211', + 'deeppink' => '255,20,147', + 'deepskyblue' => '0,191,255', + 'dimgray' => '105,105,105', + 'dimgrey' => '105,105,105', + 'dodgerblue' => '30,144,255', + 'firebrick' => '178,34,34', + 'floralwhite' => '255,250,240', + 'forestgreen' => '34,139,34', + 'fuchsia' => '255,0,255', + 'gainsboro' => '220,220,220', + 'ghostwhite' => '248,248,255', + 'gold' => '255,215,0', + 'goldenrod' => '218,165,32', + 'gray' => '128,128,128', + 'green' => '0,128,0', + 'greenyellow' => '173,255,47', + 'grey' => '128,128,128', + 'honeydew' => '240,255,240', + 'hotpink' => '255,105,180', + 'indianred' => '205,92,92', + 'indigo' => '75,0,130', + 'ivory' => '255,255,240', + 'khaki' => '240,230,140', + 'lavender' => '230,230,250', + 'lavenderblush' => '255,240,245', + 'lawngreen' => '124,252,0', + 'lemonchiffon' => '255,250,205', + 'lightblue' => '173,216,230', + 'lightcoral' => '240,128,128', + 'lightcyan' => '224,255,255', + 'lightgoldenrodyellow' => '250,250,210', + 'lightgray' => '211,211,211', + 'lightgreen' => '144,238,144', + 'lightgrey' => '211,211,211', + 'lightpink' => '255,182,193', + 'lightsalmon' => '255,160,122', + 'lightseagreen' => '32,178,170', + 'lightskyblue' => '135,206,250', + 'lightslategray' => '119,136,153', + 'lightslategrey' => '119,136,153', + 'lightsteelblue' => '176,196,222', + 'lightyellow' => '255,255,224', + 'lime' => '0,255,0', + 'limegreen' => '50,205,50', + 'linen' => '250,240,230', + 'magenta' => '255,0,255', + 'maroon' => '128,0,0', + 'mediumaquamarine' => '102,205,170', + 'mediumblue' => '0,0,205', + 'mediumorchid' => '186,85,211', + 'mediumpurple' => '147,112,219', + 'mediumseagreen' => '60,179,113', + 'mediumslateblue' => '123,104,238', + 'mediumspringgreen' => '0,250,154', + 'mediumturquoise' => '72,209,204', + 'mediumvioletred' => '199,21,133', + 'midnightblue' => '25,25,112', + 'mintcream' => '245,255,250', + 'mistyrose' => '255,228,225', + 'moccasin' => '255,228,181', + 'navajowhite' => '255,222,173', + 'navy' => '0,0,128', + 'oldlace' => '253,245,230', + 'olive' => '128,128,0', + 'olivedrab' => '107,142,35', + 'orange' => '255,165,0', + 'orangered' => '255,69,0', + 'orchid' => '218,112,214', + 'palegoldenrod' => '238,232,170', + 'palegreen' => '152,251,152', + 'paleturquoise' => '175,238,238', + 'palevioletred' => '219,112,147', + 'papayawhip' => '255,239,213', + 'peachpuff' => '255,218,185', + 'peru' => '205,133,63', + 'pink' => '255,192,203', + 'plum' => '221,160,221', + 'powderblue' => '176,224,230', + 'purple' => '128,0,128', + 'red' => '255,0,0', + 'rosybrown' => '188,143,143', + 'royalblue' => '65,105,225', + 'saddlebrown' => '139,69,19', + 'salmon' => '250,128,114', + 'sandybrown' => '244,164,96', + 'seagreen' => '46,139,87', + 'seashell' => '255,245,238', + 'sienna' => '160,82,45', + 'silver' => '192,192,192', + 'skyblue' => '135,206,235', + 'slateblue' => '106,90,205', + 'slategray' => '112,128,144', + 'slategrey' => '112,128,144', + 'snow' => '255,250,250', + 'springgreen' => '0,255,127', + 'steelblue' => '70,130,180', + 'tan' => '210,180,140', + 'teal' => '0,128,128', + 'thistle' => '216,191,216', + 'tomato' => '255,99,71', + 'transparent' => '0,0,0,0', + 'turquoise' => '64,224,208', + 'violet' => '238,130,238', + 'wheat' => '245,222,179', + 'white' => '255,255,255', + 'whitesmoke' => '245,245,245', + 'yellow' => '255,255,0', + 'yellowgreen' => '154,205,50' + ); +} + +// responsible for taking a string of LESS code and converting it into a +// syntax tree +class lessc_parser { + static protected $nextBlockId = 0; // used to uniquely identify blocks + + static protected $precedence = array( + '=<' => 0, + '>=' => 0, + '=' => 0, + '<' => 0, + '>' => 0, + + '+' => 1, + '-' => 1, + '*' => 2, + '/' => 2, + '%' => 2, + ); + + static protected $whitePattern; + static protected $commentMulti; + + static protected $commentSingle = "//"; + static protected $commentMultiLeft = "/*"; + static protected $commentMultiRight = "*/"; + + // regex string to match any of the operators + static protected $operatorString; + + // these properties will supress division unless it's inside parenthases + static protected $supressDivisionProps = + array('/border-radius$/i', '/^font$/i'); + + protected $blockDirectives = array("font-face", "keyframes", "page", "-moz-document"); + protected $lineDirectives = array("charset"); + + /** + * if we are in parens we can be more liberal with whitespace around + * operators because it must evaluate to a single value and thus is less + * ambiguous. + * + * Consider: + * property1: 10 -5; // is two numbers, 10 and -5 + * property2: (10 -5); // should evaluate to 5 + */ + protected $inParens = false; + + // caches preg escaped literals + static protected $literalCache = array(); + + public function __construct($lessc, $sourceName = null) { + $this->eatWhiteDefault = true; + // reference to less needed for vPrefix, mPrefix, and parentSelector + $this->lessc = $lessc; + + $this->sourceName = $sourceName; // name used for error messages + + $this->writeComments = false; + + if (!self::$operatorString) { + self::$operatorString = + '('.implode('|', array_map(array('lessc', 'preg_quote'), + array_keys(self::$precedence))).')'; + + $commentSingle = lessc::preg_quote(self::$commentSingle); + $commentMultiLeft = lessc::preg_quote(self::$commentMultiLeft); + $commentMultiRight = lessc::preg_quote(self::$commentMultiRight); + + self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight; + self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais'; + } + } + + public function parse($buffer) { + $this->count = 0; + $this->line = 1; + + $this->env = null; // block stack + $this->buffer = $this->writeComments ? $buffer : $this->removeComments($buffer); + $this->pushSpecialBlock("root"); + $this->eatWhiteDefault = true; + $this->seenComments = array(); + + // trim whitespace on head + // if (preg_match('/^\s+/', $this->buffer, $m)) { + // $this->line += substr_count($m[0], "\n"); + // $this->buffer = ltrim($this->buffer); + // } + $this->whitespace(); + + // parse the entire file + $lastCount = $this->count; + while (false !== $this->parseChunk()); + + if ($this->count != strlen($this->buffer)) + $this->throwError(); + + // TODO report where the block was opened + if (!is_null($this->env->parent)) + throw new exception('parse error: unclosed block'); + + return $this->env; + } + + /** + * Parse a single chunk off the head of the buffer and append it to the + * current parse environment. + * Returns false when the buffer is empty, or when there is an error. + * + * This function is called repeatedly until the entire document is + * parsed. + * + * This parser is most similar to a recursive descent parser. Single + * functions represent discrete grammatical rules for the language, and + * they are able to capture the text that represents those rules. + * + * Consider the function lessc::keyword(). (all parse functions are + * structured the same) + * + * The function takes a single reference argument. When calling the + * function it will attempt to match a keyword on the head of the buffer. + * If it is successful, it will place the keyword in the referenced + * argument, advance the position in the buffer, and return true. If it + * fails then it won't advance the buffer and it will return false. + * + * All of these parse functions are powered by lessc::match(), which behaves + * the same way, but takes a literal regular expression. Sometimes it is + * more convenient to use match instead of creating a new function. + * + * Because of the format of the functions, to parse an entire string of + * grammatical rules, you can chain them together using &&. + * + * But, if some of the rules in the chain succeed before one fails, then + * the buffer position will be left at an invalid state. In order to + * avoid this, lessc::seek() is used to remember and set buffer positions. + * + * Before parsing a chain, use $s = $this->seek() to remember the current + * position into $s. Then if a chain fails, use $this->seek($s) to + * go back where we started. + */ + protected function parseChunk() { + if (empty($this->buffer)) return false; + $s = $this->seek(); + + // setting a property + if ($this->keyword($key) && $this->assign() && + $this->propertyValue($value, $key) && $this->end()) + { + $this->append(array('assign', $key, $value), $s); + return true; + } else { + $this->seek($s); + } + + + // look for special css blocks + if ($this->literal('@', false)) { + $this->count--; + + // media + if ($this->literal('@media')) { + if (($this->mediaQueryList($mediaQueries) || true) + && $this->literal('{')) + { + $media = $this->pushSpecialBlock("media"); + $media->queries = is_null($mediaQueries) ? array() : $mediaQueries; + return true; + } else { + $this->seek($s); + return false; + } + } + + if ($this->literal("@", false) && $this->keyword($dirName)) { + if ($this->isDirective($dirName, $this->blockDirectives)) { + if (($this->openString("{", $dirValue, null, array(";")) || true) && + $this->literal("{")) + { + $dir = $this->pushSpecialBlock("directive"); + $dir->name = $dirName; + if (isset($dirValue)) $dir->value = $dirValue; + return true; + } + } elseif ($this->isDirective($dirName, $this->lineDirectives)) { + if ($this->propertyValue($dirValue) && $this->end()) { + $this->append(array("directive", $dirName, $dirValue)); + return true; + } + } + } + + $this->seek($s); + } + + // setting a variable + if ($this->variable($var) && $this->assign() && + $this->propertyValue($value) && $this->end()) + { + $this->append(array('assign', $var, $value), $s); + return true; + } else { + $this->seek($s); + } + + if ($this->import($importValue)) { + $this->append($importValue, $s); + return true; + } + + // opening parametric mixin + if ($this->tag($tag, true) && $this->argumentDef($args, $isVararg) && + ($this->guards($guards) || true) && + $this->literal('{')) + { + $block = $this->pushBlock($this->fixTags(array($tag))); + $block->args = $args; + $block->isVararg = $isVararg; + if (!empty($guards)) $block->guards = $guards; + return true; + } else { + $this->seek($s); + } + + // opening a simple block + if ($this->tags($tags) && $this->literal('{')) { + $tags = $this->fixTags($tags); + $this->pushBlock($tags); + return true; + } else { + $this->seek($s); + } + + // closing a block + if ($this->literal('}', false)) { + try { + $block = $this->pop(); + } catch (exception $e) { + $this->seek($s); + $this->throwError($e->getMessage()); + } + + $hidden = false; + if (is_null($block->type)) { + $hidden = true; + if (!isset($block->args)) { + foreach ($block->tags as $tag) { + if (!is_string($tag) || $tag{0} != $this->lessc->mPrefix) { + $hidden = false; + break; + } + } + } + + foreach ($block->tags as $tag) { + if (is_string($tag)) { + $this->env->children[$tag][] = $block; + } + } + } + + if (!$hidden) { + $this->append(array('block', $block), $s); + } + + // this is done here so comments aren't bundled into he block that + // was just closed + $this->whitespace(); + return true; + } + + // mixin + if ($this->mixinTags($tags) && + ($this->argumentValues($argv) || true) && + ($this->keyword($suffix) || true) && $this->end()) + { + $tags = $this->fixTags($tags); + $this->append(array('mixin', $tags, $argv, $suffix), $s); + return true; + } else { + $this->seek($s); + } + + // spare ; + if ($this->literal(';')) return true; + + return false; // got nothing, throw error + } + + protected function isDirective($dirname, $directives) { + // TODO: cache pattern in parser + $pattern = implode("|", + array_map(array("lessc", "preg_quote"), $directives)); + $pattern = '/^(-[a-z-]+-)?(' . $pattern . ')$/i'; + + return preg_match($pattern, $dirname); + } + + protected function fixTags($tags) { + // move @ tags out of variable namespace + foreach ($tags as &$tag) { + if ($tag{0} == $this->lessc->vPrefix) + $tag[0] = $this->lessc->mPrefix; + } + return $tags; + } + + // a list of expressions + protected function expressionList(&$exps) { + $values = array(); + + while ($this->expression($exp)) { + $values[] = $exp; + } + + if (count($values) == 0) return false; + + $exps = lessc::compressList($values, ' '); + return true; + } + + /** + * Attempt to consume an expression. + * @link http://en.wikipedia.org/wiki/Operator-precedence_parser#Pseudo-code + */ + protected function expression(&$out) { + if ($this->value($lhs)) { + $out = $this->expHelper($lhs, 0); + + // look for / shorthand + if (!empty($this->env->supressedDivision)) { + unset($this->env->supressedDivision); + $s = $this->seek(); + if ($this->literal("/") && $this->value($rhs)) { + $out = array("list", "", + array($out, array("keyword", "/"), $rhs)); + } else { + $this->seek($s); + } + } + + return true; + } + return false; + } + + /** + * recursively parse infix equation with $lhs at precedence $minP + */ + protected function expHelper($lhs, $minP) { + $this->inExp = true; + $ss = $this->seek(); + + while (true) { + $whiteBefore = isset($this->buffer[$this->count - 1]) && + ctype_space($this->buffer[$this->count - 1]); + + // If there is whitespace before the operator, then we require + // whitespace after the operator for it to be an expression + $needWhite = $whiteBefore && !$this->inParens; + + if ($this->match(self::$operatorString.($needWhite ? '\s' : ''), $m) && self::$precedence[$m[1]] >= $minP) { + if (!$this->inParens && isset($this->env->currentProperty) && $m[1] == "/" && empty($this->env->supressedDivision)) { + foreach (self::$supressDivisionProps as $pattern) { + if (preg_match($pattern, $this->env->currentProperty)) { + $this->env->supressedDivision = true; + break 2; + } + } + } + + + $whiteAfter = isset($this->buffer[$this->count - 1]) && + ctype_space($this->buffer[$this->count - 1]); + + if (!$this->value($rhs)) break; + + // peek for next operator to see what to do with rhs + if ($this->peek(self::$operatorString, $next) && self::$precedence[$next[1]] > self::$precedence[$m[1]]) { + $rhs = $this->expHelper($rhs, self::$precedence[$next[1]]); + } + + $lhs = array('expression', $m[1], $lhs, $rhs, $whiteBefore, $whiteAfter); + $ss = $this->seek(); + + continue; + } + + break; + } + + $this->seek($ss); + + return $lhs; + } + + // consume a list of values for a property + public function propertyValue(&$value, $keyName = null) { + $values = array(); + + if ($keyName !== null) $this->env->currentProperty = $keyName; + + $s = null; + while ($this->expressionList($v)) { + $values[] = $v; + $s = $this->seek(); + if (!$this->literal(',')) break; + } + + if ($s) $this->seek($s); + + if ($keyName !== null) unset($this->env->currentProperty); + + if (count($values) == 0) return false; + + $value = lessc::compressList($values, ', '); + return true; + } + + protected function parenValue(&$out) { + $s = $this->seek(); + + // speed shortcut + if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "(") { + return false; + } + + $inParens = $this->inParens; + if ($this->literal("(") && + ($this->inParens = true) && $this->expression($exp) && + $this->literal(")")) + { + $out = $exp; + $this->inParens = $inParens; + return true; + } else { + $this->inParens = $inParens; + $this->seek($s); + } + + return false; + } + + // a single value + protected function value(&$value) { + $s = $this->seek(); + + // speed shortcut + if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "-") { + // negation + if ($this->literal("-", false) && + (($this->variable($inner) && $inner = array("variable", $inner)) || + $this->unit($inner) || + $this->parenValue($inner))) + { + $value = array("unary", "-", $inner); + return true; + } else { + $this->seek($s); + } + } + + if ($this->parenValue($value)) return true; + if ($this->unit($value)) return true; + if ($this->color($value)) return true; + if ($this->func($value)) return true; + if ($this->string($value)) return true; + + if ($this->keyword($word)) { + $value = array('keyword', $word); + return true; + } + + // try a variable + if ($this->variable($var)) { + $value = array('variable', $var); + return true; + } + + // unquote string (should this work on any type? + if ($this->literal("~") && $this->string($str)) { + $value = array("escape", $str); + return true; + } else { + $this->seek($s); + } + + // css hack: \0 + if ($this->literal('\\') && $this->match('([0-9]+)', $m)) { + $value = array('keyword', '\\'.$m[1]); + return true; + } else { + $this->seek($s); + } + + return false; + } + + // an import statement + protected function import(&$out) { + $s = $this->seek(); + if (!$this->literal('@import')) return false; + + // @import "something.css" media; + // @import url("something.css") media; + // @import url(something.css) media; + + if ($this->propertyValue($value)) { + $out = array("import", $value); + return true; + } + } + + protected function mediaQueryList(&$out) { + if ($this->genericList($list, "mediaQuery", ",", false)) { + $out = $list[2]; + return true; + } + return false; + } + + protected function mediaQuery(&$out) { + $s = $this->seek(); + + $expressions = null; + $parts = array(); + + if (($this->literal("only") && ($only = true) || $this->literal("not") && ($not = true) || true) && $this->keyword($mediaType)) { + $prop = array("mediaType"); + if (isset($only)) $prop[] = "only"; + if (isset($not)) $prop[] = "not"; + $prop[] = $mediaType; + $parts[] = $prop; + } else { + $this->seek($s); + } + + + if (!empty($mediaType) && !$this->literal("and")) { + // ~ + } else { + $this->genericList($expressions, "mediaExpression", "and", false); + if (is_array($expressions)) $parts = array_merge($parts, $expressions[2]); + } + + if (count($parts) == 0) { + $this->seek($s); + return false; + } + + $out = $parts; + return true; + } + + protected function mediaExpression(&$out) { + $s = $this->seek(); + $value = null; + if ($this->literal("(") && + $this->keyword($feature) && + ($this->literal(":") && $this->expression($value) || true) && + $this->literal(")")) + { + $out = array("mediaExp", $feature); + if ($value) $out[] = $value; + return true; + } elseif ($this->variable($variable)) { + $out = array('variable', $variable); + return true; + } + + $this->seek($s); + return false; + } + + // an unbounded string stopped by $end + protected function openString($end, &$out, $nestingOpen=null, $rejectStrs = null) { + $oldWhite = $this->eatWhiteDefault; + $this->eatWhiteDefault = false; + + $stop = array("'", '"', "@{", $end); + $stop = array_map(array("lessc", "preg_quote"), $stop); + // $stop[] = self::$commentMulti; + + if (!is_null($rejectStrs)) { + $stop = array_merge($stop, $rejectStrs); + } + + $patt = '(.*?)('.implode("|", $stop).')'; + + $nestingLevel = 0; + + $content = array(); + while ($this->match($patt, $m, false)) { + if (!empty($m[1])) { + $content[] = $m[1]; + if ($nestingOpen) { + $nestingLevel += substr_count($m[1], $nestingOpen); + } + } + + $tok = $m[2]; + + $this->count-= strlen($tok); + if ($tok == $end) { + if ($nestingLevel == 0) { + break; + } else { + $nestingLevel--; + } + } + + if (($tok == "'" || $tok == '"') && $this->string($str)) { + $content[] = $str; + continue; + } + + if ($tok == "@{" && $this->interpolation($inter)) { + $content[] = $inter; + continue; + } + + if (!empty($rejectStrs) && in_array($tok, $rejectStrs)) { + $ount = null; + break; + } + + $content[] = $tok; + $this->count+= strlen($tok); + } + + $this->eatWhiteDefault = $oldWhite; + + if (count($content) == 0) return false; + + // trim the end + if (is_string(end($content))) { + $content[count($content) - 1] = rtrim(end($content)); + } + + $out = array("string", "", $content); + return true; + } + + protected function string(&$out) { + $s = $this->seek(); + if ($this->literal('"', false)) { + $delim = '"'; + } elseif ($this->literal("'", false)) { + $delim = "'"; + } else { + return false; + } + + $content = array(); + + // look for either ending delim , escape, or string interpolation + $patt = '([^\n]*?)(@\{|\\\\|' . + lessc::preg_quote($delim).')'; + + $oldWhite = $this->eatWhiteDefault; + $this->eatWhiteDefault = false; + + while ($this->match($patt, $m, false)) { + $content[] = $m[1]; + if ($m[2] == "@{") { + $this->count -= strlen($m[2]); + if ($this->interpolation($inter, false)) { + $content[] = $inter; + } else { + $this->count += strlen($m[2]); + $content[] = "@{"; // ignore it + } + } elseif ($m[2] == '\\') { + $content[] = $m[2]; + if ($this->literal($delim, false)) { + $content[] = $delim; + } + } else { + $this->count -= strlen($delim); + break; // delim + } + } + + $this->eatWhiteDefault = $oldWhite; + + if ($this->literal($delim)) { + $out = array("string", $delim, $content); + return true; + } + + $this->seek($s); + return false; + } + + protected function interpolation(&$out) { + $oldWhite = $this->eatWhiteDefault; + $this->eatWhiteDefault = true; + + $s = $this->seek(); + if ($this->literal("@{") && + $this->openString("}", $interp, null, array("'", '"', ";")) && + $this->literal("}", false)) + { + $out = array("interpolate", $interp); + $this->eatWhiteDefault = $oldWhite; + if ($this->eatWhiteDefault) $this->whitespace(); + return true; + } + + $this->eatWhiteDefault = $oldWhite; + $this->seek($s); + return false; + } + + protected function unit(&$unit) { + // speed shortcut + if (isset($this->buffer[$this->count])) { + $char = $this->buffer[$this->count]; + if (!ctype_digit($char) && $char != ".") return false; + } + + if ($this->match('([0-9]+(?:\.[0-9]*)?|\.[0-9]+)([%a-zA-Z]+)?', $m)) { + $unit = array("number", $m[1], empty($m[2]) ? "" : $m[2]); + return true; + } + return false; + } + + // a # color + protected function color(&$out) { + if ($this->match('(#(?:[0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{3}))', $m)) { + if (strlen($m[1]) > 7) { + $out = array("string", "", array($m[1])); + } else { + $out = array("raw_color", $m[1]); + } + return true; + } + + return false; + } + + // consume a list of property values delimited by ; and wrapped in () + protected function argumentValues(&$args, $delim = ',') { + $s = $this->seek(); + if (!$this->literal('(')) return false; + + $values = array(); + while (true) { + if ($this->expressionList($value)) $values[] = $value; + if (!$this->literal($delim)) break; + else { + if ($value == null) $values[] = null; + $value = null; + } + } + + if (!$this->literal(')')) { + $this->seek($s); + return false; + } + + $args = $values; + return true; + } + + // consume an argument definition list surrounded by () + // each argument is a variable name with optional value + // or at the end a ... or a variable named followed by ... + protected function argumentDef(&$args, &$isVararg, $delim = ',') { + $s = $this->seek(); + if (!$this->literal('(')) return false; + + $values = array(); + + $isVararg = false; + while (true) { + if ($this->literal("...")) { + $isVararg = true; + break; + } + + if ($this->variable($vname)) { + $arg = array("arg", $vname); + $ss = $this->seek(); + if ($this->assign() && $this->expressionList($value)) { + $arg[] = $value; + } else { + $this->seek($ss); + if ($this->literal("...")) { + $arg[0] = "rest"; + $isVararg = true; + } + } + $values[] = $arg; + if ($isVararg) break; + continue; + } + + if ($this->value($literal)) { + $values[] = array("lit", $literal); + } + + if (!$this->literal($delim)) break; + } + + if (!$this->literal(')')) { + $this->seek($s); + return false; + } + + $args = $values; + + return true; + } + + // consume a list of tags + // this accepts a hanging delimiter + protected function tags(&$tags, $simple = false, $delim = ',') { + $tags = array(); + while ($this->tag($tt, $simple)) { + $tags[] = $tt; + if (!$this->literal($delim)) break; + } + if (count($tags) == 0) return false; + + return true; + } + + // list of tags of specifying mixin path + // optionally separated by > (lazy, accepts extra >) + protected function mixinTags(&$tags) { + $s = $this->seek(); + $tags = array(); + while ($this->tag($tt, true)) { + $tags[] = $tt; + $this->literal(">"); + } + + if (count($tags) == 0) return false; + + return true; + } + + // a bracketed value (contained within in a tag definition) + protected function tagBracket(&$value) { + // speed shortcut + if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "[") { + return false; + } + + $s = $this->seek(); + if ($this->literal('[') && $this->to(']', $c, true) && $this->literal(']', false)) { + $value = '['.$c.']'; + // whitespace? + if ($this->whitespace()) $value .= " "; + + // escape parent selector, (yuck) + $value = str_replace($this->lessc->parentSelector, "$&$", $value); + return true; + } + + $this->seek($s); + return false; + } + + protected function tagExpression(&$value) { + $s = $this->seek(); + if ($this->literal("(") && $this->expression($exp) && $this->literal(")")) { + $value = array('exp', $exp); + return true; + } + + $this->seek($s); + return false; + } + + // a space separated list of selectors + protected function tag(&$tag, $simple = false) { + if ($simple) + $chars = '^@,:;{}\][>\(\) "\''; + else + $chars = '^@,;{}["\''; + + $s = $this->seek(); + + if (!$simple && $this->tagExpression($tag)) { + return true; + } + + $hasExpression = false; + $parts = array(); + while ($this->tagBracket($first)) $parts[] = $first; + + $oldWhite = $this->eatWhiteDefault; + $this->eatWhiteDefault = false; + + while (true) { + if ($this->match('(['.$chars.'0-9]['.$chars.']*)', $m)) { + $parts[] = $m[1]; + if ($simple) break; + + while ($this->tagBracket($brack)) { + $parts[] = $brack; + } + continue; + } + + if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "@") { + if ($this->interpolation($interp)) { + $hasExpression = true; + $interp[2] = true; // don't unescape + $parts[] = $interp; + continue; + } + + if ($this->literal("@")) { + $parts[] = "@"; + continue; + } + } + + if ($this->unit($unit)) { // for keyframes + $parts[] = $unit[1]; + $parts[] = $unit[2]; + continue; + } + + break; + } + + $this->eatWhiteDefault = $oldWhite; + if (!$parts) { + $this->seek($s); + return false; + } + + if ($hasExpression) { + $tag = array("exp", array("string", "", $parts)); + } else { + $tag = trim(implode($parts)); + } + + $this->whitespace(); + return true; + } + + // a css function + protected function func(&$func) { + $s = $this->seek(); + + if ($this->match('(%|[\w\-_][\w\-_:\.]+|[\w_])', $m) && $this->literal('(')) { + $fname = $m[1]; + + $sPreArgs = $this->seek(); + + $args = array(); + while (true) { + $ss = $this->seek(); + // this ugly nonsense is for ie filter properties + if ($this->keyword($name) && $this->literal('=') && $this->expressionList($value)) { + $args[] = array("string", "", array($name, "=", $value)); + } else { + $this->seek($ss); + if ($this->expressionList($value)) { + $args[] = $value; + } + } + + if (!$this->literal(',')) break; + } + $args = array('list', ',', $args); + + if ($this->literal(')')) { + $func = array('function', $fname, $args); + return true; + } elseif ($fname == 'url') { + // couldn't parse and in url? treat as string + $this->seek($sPreArgs); + if ($this->openString(")", $string) && $this->literal(")")) { + $func = array('function', $fname, $string); + return true; + } + } + } + + $this->seek($s); + return false; + } + + // consume a less variable + protected function variable(&$name) { + $s = $this->seek(); + if ($this->literal($this->lessc->vPrefix, false) && + ($this->variable($sub) || $this->keyword($name))) + { + if (!empty($sub)) { + $name = array('variable', $sub); + } else { + $name = $this->lessc->vPrefix.$name; + } + return true; + } + + $name = null; + $this->seek($s); + return false; + } + + /** + * Consume an assignment operator + * Can optionally take a name that will be set to the current property name + */ + protected function assign($name = null) { + if ($name) $this->currentProperty = $name; + return $this->literal(':') || $this->literal('='); + } + + // consume a keyword + protected function keyword(&$word) { + if ($this->match('([\w_\-\*!"][\w\-_"]*)', $m)) { + $word = $m[1]; + return true; + } + return false; + } + + // consume an end of statement delimiter + protected function end() { + if ($this->literal(';')) { + return true; + } elseif ($this->count == strlen($this->buffer) || $this->buffer{$this->count} == '}') { + // if there is end of file or a closing block next then we don't need a ; + return true; + } + return false; + } + + protected function guards(&$guards) { + $s = $this->seek(); + + if (!$this->literal("when")) { + $this->seek($s); + return false; + } + + $guards = array(); + + while ($this->guardGroup($g)) { + $guards[] = $g; + if (!$this->literal(",")) break; + } + + if (count($guards) == 0) { + $guards = null; + $this->seek($s); + return false; + } + + return true; + } + + // a bunch of guards that are and'd together + // TODO rename to guardGroup + protected function guardGroup(&$guardGroup) { + $s = $this->seek(); + $guardGroup = array(); + while ($this->guard($guard)) { + $guardGroup[] = $guard; + if (!$this->literal("and")) break; + } + + if (count($guardGroup) == 0) { + $guardGroup = null; + $this->seek($s); + return false; + } + + return true; + } + + protected function guard(&$guard) { + $s = $this->seek(); + $negate = $this->literal("not"); + + if ($this->literal("(") && $this->expression($exp) && $this->literal(")")) { + $guard = $exp; + if ($negate) $guard = array("negate", $guard); + return true; + } + + $this->seek($s); + return false; + } + + /* raw parsing functions */ + + protected function literal($what, $eatWhitespace = null) { + if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault; + + // shortcut on single letter + if (!isset($what[1]) && isset($this->buffer[$this->count])) { + if ($this->buffer[$this->count] == $what) { + if (!$eatWhitespace) { + $this->count++; + return true; + } + // goes below... + } else { + return false; + } + } + + if (!isset(self::$literalCache[$what])) { + self::$literalCache[$what] = lessc::preg_quote($what); + } + + return $this->match(self::$literalCache[$what], $m, $eatWhitespace); + } + + protected function genericList(&$out, $parseItem, $delim="", $flatten=true) { + $s = $this->seek(); + $items = array(); + while ($this->$parseItem($value)) { + $items[] = $value; + if ($delim) { + if (!$this->literal($delim)) break; + } + } + + if (count($items) == 0) { + $this->seek($s); + return false; + } + + if ($flatten && count($items) == 1) { + $out = $items[0]; + } else { + $out = array("list", $delim, $items); + } + + return true; + } + + + // advance counter to next occurrence of $what + // $until - don't include $what in advance + // $allowNewline, if string, will be used as valid char set + protected function to($what, &$out, $until = false, $allowNewline = false) { + if (is_string($allowNewline)) { + $validChars = $allowNewline; + } else { + $validChars = $allowNewline ? "." : "[^\n]"; + } + if (!$this->match('('.$validChars.'*?)'.lessc::preg_quote($what), $m, !$until)) return false; + if ($until) $this->count -= strlen($what); // give back $what + $out = $m[1]; + return true; + } + + // try to match something on head of buffer + protected function match($regex, &$out, $eatWhitespace = null) { + if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault; + + $r = '/'.$regex.($eatWhitespace && !$this->writeComments ? '\s*' : '').'/Ais'; + if (preg_match($r, $this->buffer, $out, null, $this->count)) { + $this->count += strlen($out[0]); + if ($eatWhitespace && $this->writeComments) $this->whitespace(); + return true; + } + return false; + } + + // match some whitespace + protected function whitespace() { + if ($this->writeComments) { + $gotWhite = false; + while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) { + if (isset($m[1]) && empty($this->commentsSeen[$this->count])) { + $this->append(array("comment", $m[1])); + $this->commentsSeen[$this->count] = true; + } + $this->count += strlen($m[0]); + $gotWhite = true; + } + return $gotWhite; + } else { + $this->match("", $m); + return strlen($m[0]) > 0; + } + } + + // match something without consuming it + protected function peek($regex, &$out = null, $from=null) { + if (is_null($from)) $from = $this->count; + $r = '/'.$regex.'/Ais'; + $result = preg_match($r, $this->buffer, $out, null, $from); + + return $result; + } + + // seek to a spot in the buffer or return where we are on no argument + protected function seek($where = null) { + if ($where === null) return $this->count; + else $this->count = $where; + return true; + } + + /* misc functions */ + + public function throwError($msg = "parse error", $count = null) { + $count = is_null($count) ? $this->count : $count; + + $line = $this->line + + substr_count(substr($this->buffer, 0, $count), "\n"); + + if (!empty($this->sourceName)) { + $loc = "$this->sourceName on line $line"; + } else { + $loc = "line: $line"; + } + + // TODO this depends on $this->count + if ($this->peek("(.*?)(\n|$)", $m, $count)) { + throw new exception("$msg: failed at `$m[1]` $loc"); + } else { + throw new exception("$msg: $loc"); + } + } + + protected function pushBlock($selectors=null, $type=null) { + $b = new stdclass; + $b->parent = $this->env; + + $b->type = $type; + $b->id = self::$nextBlockId++; + + $b->isVararg = false; // TODO: kill me from here + $b->tags = $selectors; + + $b->props = array(); + $b->children = array(); + + $this->env = $b; + return $b; + } + + // push a block that doesn't multiply tags + protected function pushSpecialBlock($type) { + return $this->pushBlock(null, $type); + } + + // append a property to the current block + protected function append($prop, $pos = null) { + if ($pos !== null) $prop[-1] = $pos; + $this->env->props[] = $prop; + } + + // pop something off the stack + protected function pop() { + $old = $this->env; + $this->env = $this->env->parent; + return $old; + } + + // remove comments from $text + // todo: make it work for all functions, not just url + protected function removeComments($text) { + $look = array( + 'url(', '//', '/*', '"', "'" + ); + + $out = ''; + $min = null; + while (true) { + // find the next item + foreach ($look as $token) { + $pos = strpos($text, $token); + if ($pos !== false) { + if (!isset($min) || $pos < $min[1]) $min = array($token, $pos); + } + } + + if (is_null($min)) break; + + $count = $min[1]; + $skip = 0; + $newlines = 0; + switch ($min[0]) { + case 'url(': + if (preg_match('/url\(.*?\)/', $text, $m, 0, $count)) + $count += strlen($m[0]) - strlen($min[0]); + break; + case '"': + case "'": + if (preg_match('/'.$min[0].'.*?'.$min[0].'/', $text, $m, 0, $count)) + $count += strlen($m[0]) - 1; + break; + case '//': + $skip = strpos($text, "\n", $count); + if ($skip === false) $skip = strlen($text) - $count; + else $skip -= $count; + break; + case '/*': + if (preg_match('/\/\*.*?\*\//s', $text, $m, 0, $count)) { + $skip = strlen($m[0]); + $newlines = substr_count($m[0], "\n"); + } + break; + } + + if ($skip == 0) $count += strlen($min[0]); + + $out .= substr($text, 0, $count).str_repeat("\n", $newlines); + $text = substr($text, $count + $skip); + + $min = null; + } + + return $out.$text; + } + +} + +class lessc_formatter_classic { + public $indentChar = " "; + + public $break = "\n"; + public $open = " {"; + public $close = "}"; + public $selectorSeparator = ", "; + public $assignSeparator = ":"; + + public $openSingle = " { "; + public $closeSingle = " }"; + + public $disableSingle = false; + public $breakSelectors = false; + + public $compressColors = false; + + public function __construct() { + $this->indentLevel = 0; + } + + public function indentStr($n = 0) { + return str_repeat($this->indentChar, max($this->indentLevel + $n, 0)); + } + + public function property($name, $value) { + return $name . $this->assignSeparator . $value . ";"; + } + + protected function isEmpty($block) { + if (empty($block->lines)) { + foreach ($block->children as $child) { + if (!$this->isEmpty($child)) return false; + } + + return true; + } + return false; + } + + public function block($block) { + if ($this->isEmpty($block)) return; + + $inner = $pre = $this->indentStr(); + + $isSingle = !$this->disableSingle && + is_null($block->type) && count($block->lines) == 1; + + if (!empty($block->selectors)) { + $this->indentLevel++; + + if ($this->breakSelectors) { + $selectorSeparator = $this->selectorSeparator . $this->break . $pre; + } else { + $selectorSeparator = $this->selectorSeparator; + } + + echo $pre . + implode($selectorSeparator, $block->selectors); + if ($isSingle) { + echo $this->openSingle; + $inner = ""; + } else { + echo $this->open . $this->break; + $inner = $this->indentStr(); + } + + } + + if (!empty($block->lines)) { + $glue = $this->break.$inner; + echo $inner . implode($glue, $block->lines); + if (!$isSingle && !empty($block->children)) { + echo $this->break; + } + } + + foreach ($block->children as $child) { + $this->block($child); + } + + if (!empty($block->selectors)) { + if (!$isSingle && empty($block->children)) echo $this->break; + + if ($isSingle) { + echo $this->closeSingle . $this->break; + } else { + echo $pre . $this->close . $this->break; + } + + $this->indentLevel--; + } + } +} + +class lessc_formatter_compressed extends lessc_formatter_classic { + public $disableSingle = true; + public $open = "{"; + public $selectorSeparator = ","; + public $assignSeparator = ":"; + public $break = ""; + public $compressColors = true; + + public function indentStr($n = 0) { + return ""; + } +} + +class lessc_formatter_lessjs extends lessc_formatter_classic { + public $disableSingle = true; + public $breakSelectors = true; + public $assignSeparator = ": "; + public $selectorSeparator = ","; +} + + diff --git a/rainloop/v/1.2.5.406/app/libraries/pclzip/gnu-lgpl.txt b/rainloop/v/1.2.5.406/app/libraries/pclzip/gnu-lgpl.txt new file mode 100644 index 000000000..cbee875ba --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/pclzip/gnu-lgpl.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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 with +this License. + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/rainloop/v/1.2.5.406/app/libraries/pclzip/pclzip.lib.php b/rainloop/v/1.2.5.406/app/libraries/pclzip/pclzip.lib.php new file mode 100644 index 000000000..fca7fc5bf --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/pclzip/pclzip.lib.php @@ -0,0 +1,5693 @@ +zipname = $p_zipname; + $this->zip_fd = 0; + $this->magic_quotes_status = -1; + + // ----- Return + return; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // create($p_filelist, $p_add_dir="", $p_remove_dir="") + // create($p_filelist, $p_option, $p_option_value, ...) + // Description : + // This method supports two different synopsis. The first one is historical. + // This method creates a Zip Archive. The Zip file is created in the + // filesystem. The files and directories indicated in $p_filelist + // are added in the archive. See the parameters description for the + // supported format of $p_filelist. + // When a directory is in the list, the directory and its content is added + // in the archive. + // In this synopsis, the function takes an optional variable list of + // options. See bellow the supported options. + // Parameters : + // $p_filelist : An array containing file or directory names, or + // a string containing one filename or one directory name, or + // a string containing a list of filenames and/or directory + // names separated by spaces. + // $p_add_dir : A path to add before the real path of the archived file, + // in order to have it memorized in the archive. + // $p_remove_dir : A path to remove from the real path of the file to archive, + // in order to have a shorter path memorized in the archive. + // When $p_add_dir and $p_remove_dir are set, $p_remove_dir + // is removed first, before $p_add_dir is added. + // Options : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_COMMENT : + // PCLZIP_CB_PRE_ADD : + // PCLZIP_CB_POST_ADD : + // Return Values : + // 0 on failure, + // The list of the added files, with a status of the add action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function create($p_filelist) + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Set default values + $v_options = array(); + $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Look for arguments + if ($v_size > 1) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Remove from the options list the first argument + array_shift($v_arg_list); + $v_size--; + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_ADD => 'optional', + PCLZIP_CB_POST_ADD => 'optional', + PCLZIP_OPT_NO_COMPRESSION => 'optional', + PCLZIP_OPT_COMMENT => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + //, PCLZIP_OPT_CRYPT => 'optional' + )); + if ($v_result != 1) { + return 0; + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1]; + } + else if ($v_size > 2) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, + "Invalid number / type of arguments"); + return 0; + } + } + } + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Init + $v_string_list = array(); + $v_att_list = array(); + $v_filedescr_list = array(); + $p_result_list = array(); + + // ----- Look if the $p_filelist is really an array + if (is_array($p_filelist)) { + + // ----- Look if the first element is also an array + // This will mean that this is a file description entry + if (isset($p_filelist[0]) && is_array($p_filelist[0])) { + $v_att_list = $p_filelist; + } + + // ----- The list is a list of string names + else { + $v_string_list = $p_filelist; + } + } + + // ----- Look if the $p_filelist is a string + else if (is_string($p_filelist)) { + // ----- Create a list from the string + $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist); + } + + // ----- Invalid variable type for $p_filelist + else { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist"); + return 0; + } + + // ----- Reformat the string list + if (sizeof($v_string_list) != 0) { + foreach ($v_string_list as $v_string) { + if ($v_string != '') { + $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string; + } + else { + } + } + } + + // ----- For each file in the list check the attributes + $v_supported_attributes + = array ( PCLZIP_ATT_FILE_NAME => 'mandatory' + ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional' + ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional' + ,PCLZIP_ATT_FILE_MTIME => 'optional' + ,PCLZIP_ATT_FILE_CONTENT => 'optional' + ,PCLZIP_ATT_FILE_COMMENT => 'optional' + ); + foreach ($v_att_list as $v_entry) { + $v_result = $this->privFileDescrParseAtt($v_entry, + $v_filedescr_list[], + $v_options, + $v_supported_attributes); + if ($v_result != 1) { + return 0; + } + } + + // ----- Expand the filelist (expand directories) + $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Call the create fct + $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Return + return $p_result_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // add($p_filelist, $p_add_dir="", $p_remove_dir="") + // add($p_filelist, $p_option, $p_option_value, ...) + // Description : + // This method supports two synopsis. The first one is historical. + // This methods add the list of files in an existing archive. + // If a file with the same name already exists, it is added at the end of the + // archive, the first one is still present. + // If the archive does not exist, it is created. + // Parameters : + // $p_filelist : An array containing file or directory names, or + // a string containing one filename or one directory name, or + // a string containing a list of filenames and/or directory + // names separated by spaces. + // $p_add_dir : A path to add before the real path of the archived file, + // in order to have it memorized in the archive. + // $p_remove_dir : A path to remove from the real path of the file to archive, + // in order to have a shorter path memorized in the archive. + // When $p_add_dir and $p_remove_dir are set, $p_remove_dir + // is removed first, before $p_add_dir is added. + // Options : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_COMMENT : + // PCLZIP_OPT_ADD_COMMENT : + // PCLZIP_OPT_PREPEND_COMMENT : + // PCLZIP_CB_PRE_ADD : + // PCLZIP_CB_POST_ADD : + // Return Values : + // 0 on failure, + // The list of the added files, with a status of the add action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function add($p_filelist) + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Set default values + $v_options = array(); + $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Look for arguments + if ($v_size > 1) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Remove form the options list the first argument + array_shift($v_arg_list); + $v_size--; + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_ADD => 'optional', + PCLZIP_CB_POST_ADD => 'optional', + PCLZIP_OPT_NO_COMPRESSION => 'optional', + PCLZIP_OPT_COMMENT => 'optional', + PCLZIP_OPT_ADD_COMMENT => 'optional', + PCLZIP_OPT_PREPEND_COMMENT => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + //, PCLZIP_OPT_CRYPT => 'optional' + )); + if ($v_result != 1) { + return 0; + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1]; + } + else if ($v_size > 2) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); + + // ----- Return + return 0; + } + } + } + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Init + $v_string_list = array(); + $v_att_list = array(); + $v_filedescr_list = array(); + $p_result_list = array(); + + // ----- Look if the $p_filelist is really an array + if (is_array($p_filelist)) { + + // ----- Look if the first element is also an array + // This will mean that this is a file description entry + if (isset($p_filelist[0]) && is_array($p_filelist[0])) { + $v_att_list = $p_filelist; + } + + // ----- The list is a list of string names + else { + $v_string_list = $p_filelist; + } + } + + // ----- Look if the $p_filelist is a string + else if (is_string($p_filelist)) { + // ----- Create a list from the string + $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist); + } + + // ----- Invalid variable type for $p_filelist + else { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist"); + return 0; + } + + // ----- Reformat the string list + if (sizeof($v_string_list) != 0) { + foreach ($v_string_list as $v_string) { + $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string; + } + } + + // ----- For each file in the list check the attributes + $v_supported_attributes + = array ( PCLZIP_ATT_FILE_NAME => 'mandatory' + ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional' + ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional' + ,PCLZIP_ATT_FILE_MTIME => 'optional' + ,PCLZIP_ATT_FILE_CONTENT => 'optional' + ,PCLZIP_ATT_FILE_COMMENT => 'optional' + ); + foreach ($v_att_list as $v_entry) { + $v_result = $this->privFileDescrParseAtt($v_entry, + $v_filedescr_list[], + $v_options, + $v_supported_attributes); + if ($v_result != 1) { + return 0; + } + } + + // ----- Expand the filelist (expand directories) + $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Call the create fct + $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Return + return $p_result_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : listContent() + // Description : + // This public method, gives the list of the files and directories, with their + // properties. + // The properties of each entries in the list are (used also in other functions) : + // filename : Name of the file. For a create or add action it is the filename + // given by the user. For an extract function it is the filename + // of the extracted file. + // stored_filename : Name of the file / directory stored in the archive. + // size : Size of the stored file. + // compressed_size : Size of the file's data compressed in the archive + // (without the headers overhead) + // mtime : Last known modification date of the file (UNIX timestamp) + // comment : Comment associated with the file + // folder : true | false + // index : index of the file in the archive + // status : status of the action (depending of the action) : + // Values are : + // ok : OK ! + // filtered : the file / dir is not extracted (filtered by user) + // already_a_directory : the file can not be extracted because a + // directory with the same name already exists + // write_protected : the file can not be extracted because a file + // with the same name already exists and is + // write protected + // newer_exist : the file was not extracted because a newer file exists + // path_creation_fail : the file is not extracted because the folder + // does not exist and can not be created + // write_error : the file was not extracted because there was a + // error while writing the file + // read_error : the file was not extracted because there was a error + // while reading the file + // invalid_header : the file was not extracted because of an archive + // format error (bad file header) + // Note that each time a method can continue operating when there + // is an action error on a file, the error is only logged in the file status. + // Return Values : + // 0 on an unrecoverable failure, + // The list of the files in the archive. + // -------------------------------------------------------------------------------- + function listContent() + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Call the extracting fct + $p_list = array(); + if (($v_result = $this->privList($p_list)) != 1) + { + unset($p_list); + return(0); + } + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // extract($p_path="./", $p_remove_path="") + // extract([$p_option, $p_option_value, ...]) + // Description : + // This method supports two synopsis. The first one is historical. + // This method extract all the files / directories from the archive to the + // folder indicated in $p_path. + // If you want to ignore the 'root' part of path of the memorized files + // you can indicate this in the optional $p_remove_path parameter. + // By default, if a newer file with the same name already exists, the + // file is not extracted. + // + // If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions + // are used, the path indicated in PCLZIP_OPT_ADD_PATH is append + // at the end of the path value of PCLZIP_OPT_PATH. + // Parameters : + // $p_path : Path where the files and directories are to be extracted + // $p_remove_path : First part ('root' part) of the memorized path + // (if any similar) to remove while extracting. + // Options : + // PCLZIP_OPT_PATH : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_CB_PRE_EXTRACT : + // PCLZIP_CB_POST_EXTRACT : + // Return Values : + // 0 or a negative value on failure, + // The list of the extracted files, with a status of the action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function extract() + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Set default values + $v_options = array(); +// $v_path = "./"; + $v_path = ''; + $v_remove_path = ""; + $v_remove_all_path = false; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Default values for option + $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; + + // ----- Look for arguments + if ($v_size > 0) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_PATH => 'optional', + PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_EXTRACT => 'optional', + PCLZIP_CB_POST_EXTRACT => 'optional', + PCLZIP_OPT_SET_CHMOD => 'optional', + PCLZIP_OPT_BY_NAME => 'optional', + PCLZIP_OPT_BY_EREG => 'optional', + PCLZIP_OPT_BY_PREG => 'optional', + PCLZIP_OPT_BY_INDEX => 'optional', + PCLZIP_OPT_EXTRACT_AS_STRING => 'optional', + PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional', + PCLZIP_OPT_REPLACE_NEWER => 'optional' + ,PCLZIP_OPT_STOP_ON_ERROR => 'optional' + ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + )); + if ($v_result != 1) { + return 0; + } + + // ----- Set the arguments + if (isset($v_options[PCLZIP_OPT_PATH])) { + $v_path = $v_options[PCLZIP_OPT_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) { + $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { + $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH]; + } + if (isset($v_options[PCLZIP_OPT_ADD_PATH])) { + // ----- Check for '/' in last path char + if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) { + $v_path .= '/'; + } + $v_path .= $v_options[PCLZIP_OPT_ADD_PATH]; + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_path = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_remove_path = $v_arg_list[1]; + } + else if ($v_size > 2) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); + + // ----- Return + return 0; + } + } + } + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Trace + + // ----- Call the extracting fct + $p_list = array(); + $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, + $v_remove_all_path, $v_options); + if ($v_result < 1) { + unset($p_list); + return(0); + } + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + + // -------------------------------------------------------------------------------- + // Function : + // extractByIndex($p_index, $p_path="./", $p_remove_path="") + // extractByIndex($p_index, [$p_option, $p_option_value, ...]) + // Description : + // This method supports two synopsis. The first one is historical. + // This method is doing a partial extract of the archive. + // The extracted files or folders are identified by their index in the + // archive (from 0 to n). + // Note that if the index identify a folder, only the folder entry is + // extracted, not all the files included in the archive. + // Parameters : + // $p_index : A single index (integer) or a string of indexes of files to + // extract. The form of the string is "0,4-6,8-12" with only numbers + // and '-' for range or ',' to separate ranges. No spaces or ';' + // are allowed. + // $p_path : Path where the files and directories are to be extracted + // $p_remove_path : First part ('root' part) of the memorized path + // (if any similar) to remove while extracting. + // Options : + // PCLZIP_OPT_PATH : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and + // not as files. + // The resulting content is in a new field 'content' in the file + // structure. + // This option must be used alone (any other options are ignored). + // PCLZIP_CB_PRE_EXTRACT : + // PCLZIP_CB_POST_EXTRACT : + // Return Values : + // 0 on failure, + // The list of the extracted files, with a status of the action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + //function extractByIndex($p_index, options...) + function extractByIndex($p_index) + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Set default values + $v_options = array(); +// $v_path = "./"; + $v_path = ''; + $v_remove_path = ""; + $v_remove_all_path = false; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Default values for option + $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; + + // ----- Look for arguments + if ($v_size > 1) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Remove form the options list the first argument + array_shift($v_arg_list); + $v_size--; + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_PATH => 'optional', + PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_EXTRACT_AS_STRING => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_EXTRACT => 'optional', + PCLZIP_CB_POST_EXTRACT => 'optional', + PCLZIP_OPT_SET_CHMOD => 'optional', + PCLZIP_OPT_REPLACE_NEWER => 'optional' + ,PCLZIP_OPT_STOP_ON_ERROR => 'optional' + ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + )); + if ($v_result != 1) { + return 0; + } + + // ----- Set the arguments + if (isset($v_options[PCLZIP_OPT_PATH])) { + $v_path = $v_options[PCLZIP_OPT_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) { + $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { + $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH]; + } + if (isset($v_options[PCLZIP_OPT_ADD_PATH])) { + // ----- Check for '/' in last path char + if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) { + $v_path .= '/'; + } + $v_path .= $v_options[PCLZIP_OPT_ADD_PATH]; + } + if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) { + $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; + } + else { + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_path = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_remove_path = $v_arg_list[1]; + } + else if ($v_size > 2) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); + + // ----- Return + return 0; + } + } + } + + // ----- Trace + + // ----- Trick + // Here I want to reuse extractByRule(), so I need to parse the $p_index + // with privParseOptions() + $v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index); + $v_options_trick = array(); + $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick, + array (PCLZIP_OPT_BY_INDEX => 'optional' )); + if ($v_result != 1) { + return 0; + } + $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX]; + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Call the extracting fct + if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) { + return(0); + } + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // delete([$p_option, $p_option_value, ...]) + // Description : + // This method removes files from the archive. + // If no parameters are given, then all the archive is emptied. + // Parameters : + // None or optional arguments. + // Options : + // PCLZIP_OPT_BY_INDEX : + // PCLZIP_OPT_BY_NAME : + // PCLZIP_OPT_BY_EREG : + // PCLZIP_OPT_BY_PREG : + // Return Values : + // 0 on failure, + // The list of the files which are still present in the archive. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function delete() + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Set default values + $v_options = array(); + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Look for arguments + if ($v_size > 0) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_BY_NAME => 'optional', + PCLZIP_OPT_BY_EREG => 'optional', + PCLZIP_OPT_BY_PREG => 'optional', + PCLZIP_OPT_BY_INDEX => 'optional' )); + if ($v_result != 1) { + return 0; + } + } + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Call the delete fct + $v_list = array(); + if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) { + $this->privSwapBackMagicQuotes(); + unset($v_list); + return(0); + } + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : deleteByIndex() + // Description : + // ***** Deprecated ***** + // delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered. + // -------------------------------------------------------------------------------- + function deleteByIndex($p_index) + { + + $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index); + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : properties() + // Description : + // This method gives the properties of the archive. + // The properties are : + // nb : Number of files in the archive + // comment : Comment associated with the archive file + // status : not_exist, ok + // Parameters : + // None + // Return Values : + // 0 on failure, + // An array with the archive properties. + // -------------------------------------------------------------------------------- + function properties() + { + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + $this->privSwapBackMagicQuotes(); + return(0); + } + + // ----- Default properties + $v_prop = array(); + $v_prop['comment'] = ''; + $v_prop['nb'] = 0; + $v_prop['status'] = 'not_exist'; + + // ----- Look if file exists + if (@is_file($this->zipname)) + { + // ----- Open the zip file + if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) + { + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode'); + + // ----- Return + return 0; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privSwapBackMagicQuotes(); + return 0; + } + + // ----- Close the zip file + $this->privCloseFd(); + + // ----- Set the user attributes + $v_prop['comment'] = $v_central_dir['comment']; + $v_prop['nb'] = $v_central_dir['entries']; + $v_prop['status'] = 'ok'; + } + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_prop; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : duplicate() + // Description : + // This method creates an archive by copying the content of an other one. If + // the archive already exist, it is replaced by the new one without any warning. + // Parameters : + // $p_archive : The filename of a valid archive, or + // a valid PclZip object. + // Return Values : + // 1 on success. + // 0 or a negative value on error (error code). + // -------------------------------------------------------------------------------- + function duplicate($p_archive) + { + $v_result = 1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Look if the $p_archive is a PclZip object + if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip')) + { + + // ----- Duplicate the archive + $v_result = $this->privDuplicate($p_archive->zipname); + } + + // ----- Look if the $p_archive is a string (so a filename) + else if (is_string($p_archive)) + { + + // ----- Check that $p_archive is a valid zip file + // TBC : Should also check the archive format + if (!is_file($p_archive)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'"); + $v_result = PCLZIP_ERR_MISSING_FILE; + } + else { + // ----- Duplicate the archive + $v_result = $this->privDuplicate($p_archive); + } + } + + // ----- Invalid variable + else + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add"); + $v_result = PCLZIP_ERR_INVALID_PARAMETER; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : merge() + // Description : + // This method merge the $p_archive_to_add archive at the end of the current + // one ($this). + // If the archive ($this) does not exist, the merge becomes a duplicate. + // If the $p_archive_to_add archive does not exist, the merge is a success. + // Parameters : + // $p_archive_to_add : It can be directly the filename of a valid zip archive, + // or a PclZip object archive. + // Return Values : + // 1 on success, + // 0 or negative values on error (see below). + // -------------------------------------------------------------------------------- + function merge($p_archive_to_add) + { + $v_result = 1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Look if the $p_archive_to_add is a PclZip object + if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip')) + { + + // ----- Merge the archive + $v_result = $this->privMerge($p_archive_to_add); + } + + // ----- Look if the $p_archive_to_add is a string (so a filename) + else if (is_string($p_archive_to_add)) + { + + // ----- Create a temporary archive + $v_object_archive = new PclZip($p_archive_to_add); + + // ----- Merge the archive + $v_result = $this->privMerge($v_object_archive); + } + + // ----- Invalid variable + else + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add"); + $v_result = PCLZIP_ERR_INVALID_PARAMETER; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + + + // -------------------------------------------------------------------------------- + // Function : errorCode() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorCode() + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + return(PclErrorCode()); + } + else { + return($this->error_code); + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : errorName() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorName($p_with_code=false) + { + $v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR', + PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL', + PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL', + PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER', + PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE', + PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG', + PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP', + PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE', + PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL', + PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION', + PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT', + PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL', + PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL', + PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM', + PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', + PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE', + PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE', + PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', + PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION' + ,PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE' + ,PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION' + ); + + if (isset($v_name[$this->error_code])) { + $v_value = $v_name[$this->error_code]; + } + else { + $v_value = 'NoName'; + } + + if ($p_with_code) { + return($v_value.' ('.$this->error_code.')'); + } + else { + return($v_value); + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : errorInfo() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorInfo($p_full=false) + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + return(PclErrorString()); + } + else { + if ($p_full) { + return($this->errorName(true)." : ".$this->error_string); + } + else { + return($this->error_string." [code ".$this->error_code."]"); + } + } + } + // -------------------------------------------------------------------------------- + + +// -------------------------------------------------------------------------------- +// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS ***** +// ***** ***** +// ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY ***** +// -------------------------------------------------------------------------------- + + + + // -------------------------------------------------------------------------------- + // Function : privCheckFormat() + // Description : + // This method check that the archive exists and is a valid zip archive. + // Several level of check exists. (futur) + // Parameters : + // $p_level : Level of check. Default 0. + // 0 : Check the first bytes (magic codes) (default value)) + // 1 : 0 + Check the central directory (futur) + // 2 : 1 + Check each file header (futur) + // Return Values : + // true on success, + // false on error, the error code is set. + // -------------------------------------------------------------------------------- + function privCheckFormat($p_level=0) + { + $v_result = true; + + // ----- Reset the file system cache + clearstatcache(); + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Look if the file exits + if (!is_file($this->zipname)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'"); + return(false); + } + + // ----- Check that the file is readeable + if (!is_readable($this->zipname)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'"); + return(false); + } + + // ----- Check the magic code + // TBC + + // ----- Check the central header + // TBC + + // ----- Check each file header + // TBC + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privParseOptions() + // Description : + // This internal methods reads the variable list of arguments ($p_options_list, + // $p_size) and generate an array with the options and values ($v_result_list). + // $v_requested_options contains the options that can be present and those that + // must be present. + // $v_requested_options is an array, with the option value as key, and 'optional', + // or 'mandatory' as value. + // Parameters : + // See above. + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false) + { + $v_result=1; + + // ----- Read the options + $i=0; + while ($i<$p_size) { + + // ----- Check if the option is supported + if (!isset($v_requested_options[$p_options_list[$i]])) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for next option + switch ($p_options_list[$i]) { + // ----- Look for options that request a path value + case PCLZIP_OPT_PATH : + case PCLZIP_OPT_REMOVE_PATH : + case PCLZIP_OPT_ADD_PATH : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE); + $i++; + break; + + case PCLZIP_OPT_TEMP_FILE_THRESHOLD : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + return PclZip::errorCode(); + } + + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'"); + return PclZip::errorCode(); + } + + // ----- Check the value + $v_value = $p_options_list[$i+1]; + if ((!is_integer($v_value)) || ($v_value<0)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + return PclZip::errorCode(); + } + + // ----- Get the value (and convert it in bytes) + $v_result_list[$p_options_list[$i]] = $v_value*1048576; + $i++; + break; + + case PCLZIP_OPT_TEMP_FILE_ON : + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'"); + return PclZip::errorCode(); + } + + $v_result_list[$p_options_list[$i]] = true; + break; + + case PCLZIP_OPT_TEMP_FILE_OFF : + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_ON])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'"); + return PclZip::errorCode(); + } + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'"); + return PclZip::errorCode(); + } + + $v_result_list[$p_options_list[$i]] = true; + break; + + case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if ( is_string($p_options_list[$i+1]) + && ($p_options_list[$i+1] != '')) { + $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE); + $i++; + } + else { + } + break; + + // ----- Look for options that request an array of string for value + case PCLZIP_OPT_BY_NAME : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if (is_string($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1]; + } + else if (is_array($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + $i++; + break; + + // ----- Look for options that request an EREG or PREG expression + case PCLZIP_OPT_BY_EREG : + // ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG + // to PCLZIP_OPT_BY_PREG + $p_options_list[$i] = PCLZIP_OPT_BY_PREG; + case PCLZIP_OPT_BY_PREG : + //case PCLZIP_OPT_CRYPT : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if (is_string($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + $i++; + break; + + // ----- Look for options that takes a string + case PCLZIP_OPT_COMMENT : + case PCLZIP_OPT_ADD_COMMENT : + case PCLZIP_OPT_PREPEND_COMMENT : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, + "Missing parameter value for option '" + .PclZipUtilOptionText($p_options_list[$i]) + ."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if (is_string($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, + "Wrong parameter value for option '" + .PclZipUtilOptionText($p_options_list[$i]) + ."'"); + + // ----- Return + return PclZip::errorCode(); + } + $i++; + break; + + // ----- Look for options that request an array of index + case PCLZIP_OPT_BY_INDEX : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_work_list = array(); + if (is_string($p_options_list[$i+1])) { + + // ----- Remove spaces + $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', ''); + + // ----- Parse items + $v_work_list = explode(",", $p_options_list[$i+1]); + } + else if (is_integer($p_options_list[$i+1])) { + $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1]; + } + else if (is_array($p_options_list[$i+1])) { + $v_work_list = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Reduce the index list + // each index item in the list must be a couple with a start and + // an end value : [0,3], [5-5], [8-10], ... + // ----- Check the format of each item + $v_sort_flag=false; + $v_sort_value=0; + for ($j=0; $j= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + $i++; + break; + + // ----- Look for options that request a call-back + case PCLZIP_CB_PRE_EXTRACT : + case PCLZIP_CB_POST_EXTRACT : + case PCLZIP_CB_PRE_ADD : + case PCLZIP_CB_POST_ADD : + /* for futur use + case PCLZIP_CB_PRE_DELETE : + case PCLZIP_CB_POST_DELETE : + case PCLZIP_CB_PRE_LIST : + case PCLZIP_CB_POST_LIST : + */ + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_function_name = $p_options_list[$i+1]; + + // ----- Check that the value is a valid existing function + if (!function_exists($v_function_name)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Set the attribute + $v_result_list[$p_options_list[$i]] = $v_function_name; + $i++; + break; + + default : + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, + "Unknown parameter '" + .$p_options_list[$i]."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Next options + $i++; + } + + // ----- Look for mandatory options + if ($v_requested_options !== false) { + for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) { + // ----- Look for mandatory option + if ($v_requested_options[$key] == 'mandatory') { + // ----- Look if present + if (!isset($v_result_list[$key])) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")"); + + // ----- Return + return PclZip::errorCode(); + } + } + } + } + + // ----- Look for default values + if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) { + + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privOptionDefaultThreshold() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privOptionDefaultThreshold(&$p_options) + { + $v_result=1; + + if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) + || isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) { + return $v_result; + } + + // ----- Get 'memory_limit' configuration value + $v_memory_limit = ini_get('memory_limit'); + $v_memory_limit = trim($v_memory_limit); + $last = strtolower(substr($v_memory_limit, -1)); + + if($last == 'g') + //$v_memory_limit = $v_memory_limit*1024*1024*1024; + $v_memory_limit = $v_memory_limit*1073741824; + if($last == 'm') + //$v_memory_limit = $v_memory_limit*1024*1024; + $v_memory_limit = $v_memory_limit*1048576; + if($last == 'k') + $v_memory_limit = $v_memory_limit*1024; + + $p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit*PCLZIP_TEMPORARY_FILE_RATIO); + + + // ----- Sanity check : No threshold if value lower than 1M + if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) { + unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privFileDescrParseAtt() + // Description : + // Parameters : + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false) + { + $v_result=1; + + // ----- For each file in the list check the attributes + foreach ($p_file_list as $v_key => $v_value) { + + // ----- Check if the option is supported + if (!isset($v_requested_options[$v_key])) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for attribute + switch ($v_key) { + case PCLZIP_ATT_FILE_NAME : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['filename'] = PclZipUtilPathReduction($v_value); + + if ($p_filedescr['filename'] == '') { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + break; + + case PCLZIP_ATT_FILE_NEW_SHORT_NAME : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value); + + if ($p_filedescr['new_short_name'] == '') { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + break; + + case PCLZIP_ATT_FILE_NEW_FULL_NAME : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value); + + if ($p_filedescr['new_full_name'] == '') { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + break; + + // ----- Look for options that takes a string + case PCLZIP_ATT_FILE_COMMENT : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['comment'] = $v_value; + break; + + case PCLZIP_ATT_FILE_MTIME : + if (!is_integer($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['mtime'] = $v_value; + break; + + case PCLZIP_ATT_FILE_CONTENT : + $p_filedescr['content'] = $v_value; + break; + + default : + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, + "Unknown parameter '".$v_key."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for mandatory options + if ($v_requested_options !== false) { + for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) { + // ----- Look for mandatory option + if ($v_requested_options[$key] == 'mandatory') { + // ----- Look if present + if (!isset($p_file_list[$key])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")"); + return PclZip::errorCode(); + } + } + } + } + + // end foreach + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privFileDescrExpand() + // Description : + // This method look for each item of the list to see if its a file, a folder + // or a string to be added as file. For any other type of files (link, other) + // just ignore the item. + // Then prepare the information that will be stored for that file. + // When its a folder, expand the folder with all the files that are in that + // folder (recursively). + // Parameters : + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privFileDescrExpand(&$p_filedescr_list, &$p_options) + { + $v_result=1; + + // ----- Create a result list + $v_result_list = array(); + + // ----- Look each entry + for ($i=0; $iprivCalculateStoredFilename($v_descr, $p_options); + + // ----- Add the descriptor in result list + $v_result_list[sizeof($v_result_list)] = $v_descr; + + // ----- Look for folder + if ($v_descr['type'] == 'folder') { + // ----- List of items in folder + $v_dirlist_descr = array(); + $v_dirlist_nb = 0; + if ($v_folder_handler = @opendir($v_descr['filename'])) { + while (($v_item_handler = @readdir($v_folder_handler)) !== false) { + + // ----- Skip '.' and '..' + if (($v_item_handler == '.') || ($v_item_handler == '..')) { + continue; + } + + // ----- Compose the full filename + $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler; + + // ----- Look for different stored filename + // Because the name of the folder was changed, the name of the + // files/sub-folders also change + if (($v_descr['stored_filename'] != $v_descr['filename']) + && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))) { + if ($v_descr['stored_filename'] != '') { + $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler; + } + else { + $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler; + } + } + + $v_dirlist_nb++; + } + + @closedir($v_folder_handler); + } + else { + // TBC : unable to open folder in read mode + } + + // ----- Expand each element of the list + if ($v_dirlist_nb != 0) { + // ----- Expand + if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) { + return $v_result; + } + + // ----- Concat the resulting list + $v_result_list = array_merge($v_result_list, $v_dirlist_descr); + } + else { + } + + // ----- Free local array + unset($v_dirlist_descr); + } + } + + // ----- Get the result list + $p_filedescr_list = $v_result_list; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCreate() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privCreate($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + $v_list_detail = array(); + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Open the file in write mode + if (($v_result = $this->privOpenFd('wb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Add the list of files + $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options); + + // ----- Close + $this->privCloseFd(); + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAdd() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAdd($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + $v_list_detail = array(); + + // ----- Look if the archive exists or is empty + if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0)) + { + + // ----- Do a create + $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options); + + // ----- Return + return $v_result; + } + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('rb')) != 1) + { + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Go to beginning of File + @rewind($this->zip_fd); + + // ----- Creates a temporay file + $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; + + // ----- Open the temporary file in write mode + if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) + { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Copy the files from the archive to the temporary file + // TBC : Here I should better append the file and go back to erase the central dir + $v_size = $v_central_dir['offset']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($this->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Swap the file descriptor + // Here is a trick : I swap the temporary fd with the zip fd, in order to use + // the following methods on the temporary fil and not the real archive + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Add the files + $v_header_list = array(); + if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) + { + fclose($v_zip_temp_fd); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($this->zip_fd); + + // ----- Copy the block of file headers from the old archive + $v_size = $v_central_dir['size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($v_zip_temp_fd, $v_read_size); + @fwrite($this->zip_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Create the Central Dir files header + for ($i=0, $v_count=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) { + fclose($v_zip_temp_fd); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + $v_count++; + } + + // ----- Transform the header to a 'usable' info + $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); + } + + // ----- Zip file comment + $v_comment = $v_central_dir['comment']; + if (isset($p_options[PCLZIP_OPT_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_COMMENT]; + } + if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) { + $v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT]; + } + if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment; + } + + // ----- Calculate the size of the central header + $v_size = @ftell($this->zip_fd)-$v_offset; + + // ----- Create the central dir footer + if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1) + { + // ----- Reset the file list + unset($v_header_list); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + + // ----- Swap back the file descriptor + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Close + $this->privCloseFd(); + + // ----- Close the temporary file + @fclose($v_zip_temp_fd); + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Delete the zip file + // TBC : I should test the result ... + @unlink($this->zipname); + + // ----- Rename the temporary file + // TBC : I should test the result ... + //@rename($v_zip_temp_name, $this->zipname); + PclZipUtilRename($v_zip_temp_name, $this->zipname); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privOpenFd() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privOpenFd($p_mode) + { + $v_result=1; + + // ----- Look if already open + if ($this->zip_fd != 0) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Open the zip file + if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCloseFd() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privCloseFd() + { + $v_result=1; + + if ($this->zip_fd != 0) + @fclose($this->zip_fd); + $this->zip_fd = 0; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddList() + // Description : + // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is + // different from the real path of the file. This is usefull if you want to have PclTar + // running in any directory, and memorize relative path from an other directory. + // Parameters : + // $p_list : An array containing the file or directory names to add in the tar + // $p_result_list : list of added files with their properties (specially the status field) + // $p_add_dir : Path to add in the filename path archived + // $p_remove_dir : Path to remove in the filename path archived + // Return Values : + // -------------------------------------------------------------------------------- +// function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options) + function privAddList($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + + // ----- Add the files + $v_header_list = array(); + if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($this->zip_fd); + + // ----- Create the Central Dir files header + for ($i=0,$v_count=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) { + // ----- Return + return $v_result; + } + $v_count++; + } + + // ----- Transform the header to a 'usable' info + $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); + } + + // ----- Zip file comment + $v_comment = ''; + if (isset($p_options[PCLZIP_OPT_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_COMMENT]; + } + + // ----- Calculate the size of the central header + $v_size = @ftell($this->zip_fd)-$v_offset; + + // ----- Create the central dir footer + if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1) + { + // ----- Reset the file list + unset($v_header_list); + + // ----- Return + return $v_result; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddFileList() + // Description : + // Parameters : + // $p_filedescr_list : An array containing the file description + // or directory names to add in the zip + // $p_result_list : list of added files with their properties (specially the status field) + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + $v_header = array(); + + // ----- Recuperate the current number of elt in list + $v_nb = sizeof($p_result_list); + + // ----- Loop on the files + for ($j=0; ($jprivAddFile($p_filedescr_list[$j], $v_header, + $p_options); + if ($v_result != 1) { + return $v_result; + } + + // ----- Store the file infos + $p_result_list[$v_nb++] = $v_header; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFile($p_filedescr, &$p_header, &$p_options) + { + $v_result=1; + + // ----- Working variable + $p_filename = $p_filedescr['filename']; + + // TBC : Already done in the fileAtt check ... ? + if ($p_filename == "") { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for a stored different filename + /* TBC : Removed + if (isset($p_filedescr['stored_filename'])) { + $v_stored_filename = $p_filedescr['stored_filename']; + } + else { + $v_stored_filename = $p_filedescr['stored_filename']; + } + */ + + // ----- Set the file properties + clearstatcache(); + $p_header['version'] = 20; + $p_header['version_extracted'] = 10; + $p_header['flag'] = 0; + $p_header['compression'] = 0; + $p_header['crc'] = 0; + $p_header['compressed_size'] = 0; + $p_header['filename_len'] = strlen($p_filename); + $p_header['extra_len'] = 0; + $p_header['disk'] = 0; + $p_header['internal'] = 0; + $p_header['offset'] = 0; + $p_header['filename'] = $p_filename; +// TBC : Removed $p_header['stored_filename'] = $v_stored_filename; + $p_header['stored_filename'] = $p_filedescr['stored_filename']; + $p_header['extra'] = ''; + $p_header['status'] = 'ok'; + $p_header['index'] = -1; + + // ----- Look for regular file + if ($p_filedescr['type']=='file') { + $p_header['external'] = 0x00000000; + $p_header['size'] = filesize($p_filename); + } + + // ----- Look for regular folder + else if ($p_filedescr['type']=='folder') { + $p_header['external'] = 0x00000010; + $p_header['mtime'] = filemtime($p_filename); + $p_header['size'] = filesize($p_filename); + } + + // ----- Look for virtual file + else if ($p_filedescr['type'] == 'virtual_file') { + $p_header['external'] = 0x00000000; + $p_header['size'] = strlen($p_filedescr['content']); + } + + + // ----- Look for filetime + if (isset($p_filedescr['mtime'])) { + $p_header['mtime'] = $p_filedescr['mtime']; + } + else if ($p_filedescr['type'] == 'virtual_file') { + $p_header['mtime'] = time(); + } + else { + $p_header['mtime'] = filemtime($p_filename); + } + + // ------ Look for file comment + if (isset($p_filedescr['comment'])) { + $p_header['comment_len'] = strlen($p_filedescr['comment']); + $p_header['comment'] = $p_filedescr['comment']; + } + else { + $p_header['comment_len'] = 0; + $p_header['comment'] = ''; + } + + // ----- Look for pre-add callback + if (isset($p_options[PCLZIP_CB_PRE_ADD])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_header, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_PRE_ADD](PCLZIP_CB_PRE_ADD, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_header['status'] = "skipped"; + $v_result = 1; + } + + // ----- Update the informations + // Only some fields can be modified + if ($p_header['stored_filename'] != $v_local_header['stored_filename']) { + $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']); + } + } + + // ----- Look for empty stored filename + if ($p_header['stored_filename'] == "") { + $p_header['status'] = "filtered"; + } + + // ----- Check the path length + if (strlen($p_header['stored_filename']) > 0xFF) { + $p_header['status'] = 'filename_too_long'; + } + + // ----- Look if no error, or file not skipped + if ($p_header['status'] == 'ok') { + + // ----- Look for a file + if ($p_filedescr['type'] == 'file') { + // ----- Look for using temporary file to zip + if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) + && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON]) + || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) + && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])) ) ) { + $v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options); + if ($v_result < PCLZIP_ERR_NO_ERROR) { + return $v_result; + } + } + + // ----- Use "in memory" zip algo + else { + + // ----- Open the source file + if (($v_file = @fopen($p_filename, "rb")) == 0) { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode"); + return PclZip::errorCode(); + } + + // ----- Read the file content + $v_content = @fread($v_file, $p_header['size']); + + // ----- Close the file + @fclose($v_file); + + // ----- Calculate the CRC + $p_header['crc'] = @crc32($v_content); + + // ----- Look for no compression + if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) { + // ----- Set header parameters + $p_header['compressed_size'] = $p_header['size']; + $p_header['compression'] = 0; + } + + // ----- Look for normal compression + else { + // ----- Compress the content + $v_content = @gzdeflate($v_content); + + // ----- Set header parameters + $p_header['compressed_size'] = strlen($v_content); + $p_header['compression'] = 8; + } + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { + @fclose($v_file); + return $v_result; + } + + // ----- Write the compressed (or not) content + @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']); + + } + + } + + // ----- Look for a virtual file (a file from string) + else if ($p_filedescr['type'] == 'virtual_file') { + + $v_content = $p_filedescr['content']; + + // ----- Calculate the CRC + $p_header['crc'] = @crc32($v_content); + + // ----- Look for no compression + if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) { + // ----- Set header parameters + $p_header['compressed_size'] = $p_header['size']; + $p_header['compression'] = 0; + } + + // ----- Look for normal compression + else { + // ----- Compress the content + $v_content = @gzdeflate($v_content); + + // ----- Set header parameters + $p_header['compressed_size'] = strlen($v_content); + $p_header['compression'] = 8; + } + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { + @fclose($v_file); + return $v_result; + } + + // ----- Write the compressed (or not) content + @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']); + } + + // ----- Look for a directory + else if ($p_filedescr['type'] == 'folder') { + // ----- Look for directory last '/' + if (@substr($p_header['stored_filename'], -1) != '/') { + $p_header['stored_filename'] .= '/'; + } + + // ----- Set the file properties + $p_header['size'] = 0; + //$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked + $p_header['external'] = 0x00000010; // Value for a folder : to be checked + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) + { + return $v_result; + } + } + } + + // ----- Look for post-add callback + if (isset($p_options[PCLZIP_CB_POST_ADD])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_header, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_POST_ADD](PCLZIP_CB_POST_ADD, $v_local_header); + if ($v_result == 0) { + // ----- Ignored + $v_result = 1; + } + + // ----- Update the informations + // Nothing can be modified + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddFileUsingTempFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options) + { + $v_result=PCLZIP_ERR_NO_ERROR; + + // ----- Working variable + $p_filename = $p_filedescr['filename']; + + + // ----- Open the source file + if (($v_file = @fopen($p_filename, "rb")) == 0) { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode"); + return PclZip::errorCode(); + } + + // ----- Creates a compressed temporary file + $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz'; + if (($v_file_compressed = @gzopen($v_gzip_temp_name, "wb")) == 0) { + fclose($v_file); + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode'); + return PclZip::errorCode(); + } + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = filesize($p_filename); + while ($v_size != 0) { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($v_file, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @gzputs($v_file_compressed, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Close the file + @fclose($v_file); + @gzclose($v_file_compressed); + + // ----- Check the minimum file size + if (filesize($v_gzip_temp_name) < 18) { + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes'); + return PclZip::errorCode(); + } + + // ----- Extract the compressed attributes + if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); + return PclZip::errorCode(); + } + + // ----- Read the gzip file header + $v_binary_data = @fread($v_file_compressed, 10); + $v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data); + + // ----- Check some parameters + $v_data_header['os'] = bin2hex($v_data_header['os']); + + // ----- Read the gzip file footer + @fseek($v_file_compressed, filesize($v_gzip_temp_name)-8); + $v_binary_data = @fread($v_file_compressed, 8); + $v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data); + + // ----- Set the attributes + $p_header['compression'] = ord($v_data_header['cm']); + //$p_header['mtime'] = $v_data_header['mtime']; + $p_header['crc'] = $v_data_footer['crc']; + $p_header['compressed_size'] = filesize($v_gzip_temp_name)-18; + + // ----- Close the file + @fclose($v_file_compressed); + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { + return $v_result; + } + + // ----- Add the compressed data + if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) + { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); + return PclZip::errorCode(); + } + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + fseek($v_file_compressed, 10); + $v_size = $p_header['compressed_size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($v_file_compressed, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($this->zip_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Close the file + @fclose($v_file_compressed); + + // ----- Unlink the temporary file + @unlink($v_gzip_temp_name); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCalculateStoredFilename() + // Description : + // Based on file descriptor properties and global options, this method + // calculate the filename that will be stored in the archive. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privCalculateStoredFilename(&$p_filedescr, &$p_options) + { + $v_result=1; + + // ----- Working variables + $p_filename = $p_filedescr['filename']; + if (isset($p_options[PCLZIP_OPT_ADD_PATH])) { + $p_add_dir = $p_options[PCLZIP_OPT_ADD_PATH]; + } + else { + $p_add_dir = ''; + } + if (isset($p_options[PCLZIP_OPT_REMOVE_PATH])) { + $p_remove_dir = $p_options[PCLZIP_OPT_REMOVE_PATH]; + } + else { + $p_remove_dir = ''; + } + if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { + $p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH]; + } + else { + $p_remove_all_dir = 0; + } + + + // ----- Look for full name change + if (isset($p_filedescr['new_full_name'])) { + // ----- Remove drive letter if any + $v_stored_filename = PclZipUtilTranslateWinPath($p_filedescr['new_full_name']); + } + + // ----- Look for path and/or short name change + else { + + // ----- Look for short name change + // Its when we cahnge just the filename but not the path + if (isset($p_filedescr['new_short_name'])) { + $v_path_info = pathinfo($p_filename); + $v_dir = ''; + if ($v_path_info['dirname'] != '') { + $v_dir = $v_path_info['dirname'].'/'; + } + $v_stored_filename = $v_dir.$p_filedescr['new_short_name']; + } + else { + // ----- Calculate the stored filename + $v_stored_filename = $p_filename; + } + + // ----- Look for all path to remove + if ($p_remove_all_dir) { + $v_stored_filename = basename($p_filename); + } + // ----- Look for partial path remove + else if ($p_remove_dir != "") { + if (substr($p_remove_dir, -1) != '/') + $p_remove_dir .= "/"; + + if ( (substr($p_filename, 0, 2) == "./") + || (substr($p_remove_dir, 0, 2) == "./")) { + + if ( (substr($p_filename, 0, 2) == "./") + && (substr($p_remove_dir, 0, 2) != "./")) { + $p_remove_dir = "./".$p_remove_dir; + } + if ( (substr($p_filename, 0, 2) != "./") + && (substr($p_remove_dir, 0, 2) == "./")) { + $p_remove_dir = substr($p_remove_dir, 2); + } + } + + $v_compare = PclZipUtilPathInclusion($p_remove_dir, + $v_stored_filename); + if ($v_compare > 0) { + if ($v_compare == 2) { + $v_stored_filename = ""; + } + else { + $v_stored_filename = substr($v_stored_filename, + strlen($p_remove_dir)); + } + } + } + + // ----- Remove drive letter if any + $v_stored_filename = PclZipUtilTranslateWinPath($v_stored_filename); + + // ----- Look for path to add + if ($p_add_dir != "") { + if (substr($p_add_dir, -1) == "/") + $v_stored_filename = $p_add_dir.$v_stored_filename; + else + $v_stored_filename = $p_add_dir."/".$v_stored_filename; + } + } + + // ----- Filename (reduce the path of stored name) + $v_stored_filename = PclZipUtilPathReduction($v_stored_filename); + $p_filedescr['stored_filename'] = $v_stored_filename; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privWriteFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteFileHeader(&$p_header) + { + $v_result=1; + + // ----- Store the offset position of the file + $p_header['offset'] = ftell($this->zip_fd); + + // ----- Transform UNIX mtime to DOS format mdate/mtime + $v_date = getdate($p_header['mtime']); + $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; + $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; + + // ----- Packed data + $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50, + $p_header['version_extracted'], $p_header['flag'], + $p_header['compression'], $v_mtime, $v_mdate, + $p_header['crc'], $p_header['compressed_size'], + $p_header['size'], + strlen($p_header['stored_filename']), + $p_header['extra_len']); + + // ----- Write the first 148 bytes of the header in the archive + fputs($this->zip_fd, $v_binary_data, 30); + + // ----- Write the variable fields + if (strlen($p_header['stored_filename']) != 0) + { + fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); + } + if ($p_header['extra_len'] != 0) + { + fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privWriteCentralFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteCentralFileHeader(&$p_header) + { + $v_result=1; + + // TBC + //for(reset($p_header); $key = key($p_header); next($p_header)) { + //} + + // ----- Transform UNIX mtime to DOS format mdate/mtime + $v_date = getdate($p_header['mtime']); + $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; + $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; + + + // ----- Packed data + $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50, + $p_header['version'], $p_header['version_extracted'], + $p_header['flag'], $p_header['compression'], + $v_mtime, $v_mdate, $p_header['crc'], + $p_header['compressed_size'], $p_header['size'], + strlen($p_header['stored_filename']), + $p_header['extra_len'], $p_header['comment_len'], + $p_header['disk'], $p_header['internal'], + $p_header['external'], $p_header['offset']); + + // ----- Write the 42 bytes of the header in the zip file + fputs($this->zip_fd, $v_binary_data, 46); + + // ----- Write the variable fields + if (strlen($p_header['stored_filename']) != 0) + { + fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); + } + if ($p_header['extra_len'] != 0) + { + fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']); + } + if ($p_header['comment_len'] != 0) + { + fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privWriteCentralHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment) + { + $v_result=1; + + // ----- Packed data + $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries, + $p_nb_entries, $p_size, + $p_offset, strlen($p_comment)); + + // ----- Write the 22 bytes of the header in the zip file + fputs($this->zip_fd, $v_binary_data, 22); + + // ----- Write the variable fields + if (strlen($p_comment) != 0) + { + fputs($this->zip_fd, $p_comment, strlen($p_comment)); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privList() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privList(&$p_list) + { + $v_result=1; + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Open the zip file + if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) + { + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Go to beginning of Central Dir + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_central_dir['offset'])) + { + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read each entry + for ($i=0; $i<$v_central_dir['entries']; $i++) + { + // ----- Read the file header + if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) + { + $this->privSwapBackMagicQuotes(); + return $v_result; + } + $v_header['index'] = $i; + + // ----- Get the only interesting attributes + $this->privConvertHeader2FileInfo($v_header, $p_list[$i]); + unset($v_header); + } + + // ----- Close the zip file + $this->privCloseFd(); + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privConvertHeader2FileInfo() + // Description : + // This function takes the file informations from the central directory + // entries and extract the interesting parameters that will be given back. + // The resulting file infos are set in the array $p_info + // $p_info['filename'] : Filename with full path. Given by user (add), + // extracted in the filesystem (extract). + // $p_info['stored_filename'] : Stored filename in the archive. + // $p_info['size'] = Size of the file. + // $p_info['compressed_size'] = Compressed size of the file. + // $p_info['mtime'] = Last modification date of the file. + // $p_info['comment'] = Comment associated with the file. + // $p_info['folder'] = true/false : indicates if the entry is a folder or not. + // $p_info['status'] = status of the action on the file. + // $p_info['crc'] = CRC of the file content. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privConvertHeader2FileInfo($p_header, &$p_info) + { + $v_result=1; + + // ----- Get the interesting attributes + $v_temp_path = PclZipUtilPathReduction($p_header['filename']); + $p_info['filename'] = $v_temp_path; + $v_temp_path = PclZipUtilPathReduction($p_header['stored_filename']); + $p_info['stored_filename'] = $v_temp_path; + $p_info['size'] = $p_header['size']; + $p_info['compressed_size'] = $p_header['compressed_size']; + $p_info['mtime'] = $p_header['mtime']; + $p_info['comment'] = $p_header['comment']; + $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010); + $p_info['index'] = $p_header['index']; + $p_info['status'] = $p_header['status']; + $p_info['crc'] = $p_header['crc']; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractByRule() + // Description : + // Extract a file or directory depending of rules (by index, by name, ...) + // Parameters : + // $p_file_list : An array where will be placed the properties of each + // extracted file + // $p_path : Path to add while writing the extracted files + // $p_remove_path : Path to remove (from the file memorized path) while writing the + // extracted files. If the path does not match the file path, + // the file is extracted with its memorized path. + // $p_remove_path does not apply to 'list' mode. + // $p_path and $p_remove_path are commulative. + // Return Values : + // 1 on success,0 or less on error (see error code list) + // -------------------------------------------------------------------------------- + function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options) + { + $v_result=1; + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Check the path + if ( ($p_path == "") + || ( (substr($p_path, 0, 1) != "/") + && (substr($p_path, 0, 3) != "../") + && (substr($p_path,1,2)!=":/"))) + $p_path = "./".$p_path; + + // ----- Reduce the path last (and duplicated) '/' + if (($p_path != "./") && ($p_path != "/")) + { + // ----- Look for the path end '/' + while (substr($p_path, -1) == "/") + { + $p_path = substr($p_path, 0, strlen($p_path)-1); + } + } + + // ----- Look for path to remove format (should end by /) + if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/')) + { + $p_remove_path .= '/'; + } + $p_remove_path_size = strlen($p_remove_path); + + // ----- Open the zip file + if (($v_result = $this->privOpenFd('rb')) != 1) + { + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Start at beginning of Central Dir + $v_pos_entry = $v_central_dir['offset']; + + // ----- Read each entry + $j_start = 0; + for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) + { + + // ----- Read next Central dir entry + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_pos_entry)) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the file header + $v_header = array(); + if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Store the index + $v_header['index'] = $i; + + // ----- Store the file position + $v_pos_entry = ftell($this->zip_fd); + + // ----- Look for the specific extract rules + $v_extract = false; + + // ----- Look for extract by name rule + if ( (isset($p_options[PCLZIP_OPT_BY_NAME])) + && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) { + + // ----- Look if the filename is in the list + for ($j=0; ($j strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) + && (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) { + $v_extract = true; + } + } + // ----- Look for a filename + elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) { + $v_extract = true; + } + } + } + + // ----- Look for extract by ereg rule + // ereg() is deprecated with PHP 5.3 + /* + else if ( (isset($p_options[PCLZIP_OPT_BY_EREG])) + && ($p_options[PCLZIP_OPT_BY_EREG] != "")) { + + if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) { + $v_extract = true; + } + } + */ + + // ----- Look for extract by preg rule + else if ( (isset($p_options[PCLZIP_OPT_BY_PREG])) + && ($p_options[PCLZIP_OPT_BY_PREG] != "")) { + + if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) { + $v_extract = true; + } + } + + // ----- Look for extract by index rule + else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX])) + && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) { + + // ----- Look if the index is in the list + for ($j=$j_start; ($j=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) { + $v_extract = true; + } + if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) { + $j_start = $j+1; + } + + if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) { + break; + } + } + } + + // ----- Look for no rule, which means extract all the archive + else { + $v_extract = true; + } + + // ----- Check compression method + if ( ($v_extract) + && ( ($v_header['compression'] != 8) + && ($v_header['compression'] != 0))) { + $v_header['status'] = 'unsupported_compression'; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + $this->privSwapBackMagicQuotes(); + + PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION, + "Filename '".$v_header['stored_filename']."' is " + ."compressed by an unsupported compression " + ."method (".$v_header['compression'].") "); + + return PclZip::errorCode(); + } + } + + // ----- Check encrypted files + if (($v_extract) && (($v_header['flag'] & 1) == 1)) { + $v_header['status'] = 'unsupported_encryption'; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + $this->privSwapBackMagicQuotes(); + + PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, + "Unsupported encryption for " + ." filename '".$v_header['stored_filename'] + ."'"); + + return PclZip::errorCode(); + } + } + + // ----- Look for real extraction + if (($v_extract) && ($v_header['status'] != 'ok')) { + $v_result = $this->privConvertHeader2FileInfo($v_header, + $p_file_list[$v_nb_extracted++]); + if ($v_result != 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + $v_extract = false; + } + + // ----- Look for real extraction + if ($v_extract) + { + + // ----- Go to the file position + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_header['offset'])) + { + // ----- Close the zip file + $this->privCloseFd(); + + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for extraction as string + if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) { + + $v_string = ''; + + // ----- Extracting the file + $v_result1 = $this->privExtractFileAsString($v_header, $v_string, $p_options); + if ($v_result1 < 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result1; + } + + // ----- Get the only interesting attributes + if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Set the file content + $p_file_list[$v_nb_extracted]['content'] = $v_string; + + // ----- Next extracted file + $v_nb_extracted++; + + // ----- Look for user callback abort + if ($v_result1 == 2) { + break; + } + } + // ----- Look for extraction in standard output + elseif ( (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) + && ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) { + // ----- Extracting the file in standard output + $v_result1 = $this->privExtractFileInOutput($v_header, $p_options); + if ($v_result1 < 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result1; + } + + // ----- Get the only interesting attributes + if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Look for user callback abort + if ($v_result1 == 2) { + break; + } + } + // ----- Look for normal extraction + else { + // ----- Extracting the file + $v_result1 = $this->privExtractFile($v_header, + $p_path, $p_remove_path, + $p_remove_all_path, + $p_options); + if ($v_result1 < 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result1; + } + + // ----- Get the only interesting attributes + if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Look for user callback abort + if ($v_result1 == 2) { + break; + } + } + } + } + + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFile() + // Description : + // Parameters : + // Return Values : + // + // 1 : ... ? + // PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback + // -------------------------------------------------------------------------------- + function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options) + { + $v_result=1; + + // ----- Read the file header + if (($v_result = $this->privReadFileHeader($v_header)) != 1) + { + // ----- Return + return $v_result; + } + + + // ----- Check that the file header is coherent with $p_entry info + if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { + // TBC + } + + // ----- Look for all path to remove + if ($p_remove_all_path == true) { + // ----- Look for folder entry that not need to be extracted + if (($p_entry['external']&0x00000010)==0x00000010) { + + $p_entry['status'] = "filtered"; + + return $v_result; + } + + // ----- Get the basename of the path + $p_entry['filename'] = basename($p_entry['filename']); + } + + // ----- Look for path to remove + else if ($p_remove_path != "") + { + if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2) + { + + // ----- Change the file status + $p_entry['status'] = "filtered"; + + // ----- Return + return $v_result; + } + + $p_remove_path_size = strlen($p_remove_path); + if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path) + { + + // ----- Remove the path + $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size); + + } + } + + // ----- Add the path + if ($p_path != '') { + $p_entry['filename'] = $p_path."/".$p_entry['filename']; + } + + // ----- Check a base_dir_restriction + if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) { + $v_inclusion + = PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION], + $p_entry['filename']); + if ($v_inclusion == 0) { + + PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION, + "Filename '".$p_entry['filename']."' is " + ."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION"); + + return PclZip::errorCode(); + } + } + + // ----- Look for pre-extract callback + if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_entry['status'] = "skipped"; + $v_result = 1; + } + + // ----- Look for abort result + if ($v_result == 2) { + // ----- This status is internal and will be changed in 'skipped' + $p_entry['status'] = "aborted"; + $v_result = PCLZIP_ERR_USER_ABORTED; + } + + // ----- Update the informations + // Only some fields can be modified + $p_entry['filename'] = $v_local_header['filename']; + } + + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Look for specific actions while the file exist + if (file_exists($p_entry['filename'])) + { + + // ----- Look if file is a directory + if (is_dir($p_entry['filename'])) + { + + // ----- Change the file status + $p_entry['status'] = "already_a_directory"; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + // For historical reason first PclZip implementation does not stop + // when this kind of error occurs. + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY, + "Filename '".$p_entry['filename']."' is " + ."already used by an existing directory"); + + return PclZip::errorCode(); + } + } + // ----- Look if file is write protected + else if (!is_writeable($p_entry['filename'])) + { + + // ----- Change the file status + $p_entry['status'] = "write_protected"; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + // For historical reason first PclZip implementation does not stop + // when this kind of error occurs. + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, + "Filename '".$p_entry['filename']."' exists " + ."and is write protected"); + + return PclZip::errorCode(); + } + } + + // ----- Look if the extracted file is older + else if (filemtime($p_entry['filename']) > $p_entry['mtime']) + { + // ----- Change the file status + if ( (isset($p_options[PCLZIP_OPT_REPLACE_NEWER])) + && ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) { + } + else { + $p_entry['status'] = "newer_exist"; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + // For historical reason first PclZip implementation does not stop + // when this kind of error occurs. + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, + "Newer version of '".$p_entry['filename']."' exists " + ."and option PCLZIP_OPT_REPLACE_NEWER is not selected"); + + return PclZip::errorCode(); + } + } + } + else { + } + } + + // ----- Check the directory availability and create it if necessary + else { + if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/')) + $v_dir_to_check = $p_entry['filename']; + else if (!strstr($p_entry['filename'], "/")) + $v_dir_to_check = ""; + else + $v_dir_to_check = dirname($p_entry['filename']); + + if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) { + + // ----- Change the file status + $p_entry['status'] = "path_creation_fail"; + + // ----- Return + //return $v_result; + $v_result = 1; + } + } + } + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Do the extraction (if not a folder) + if (!(($p_entry['external']&0x00000010)==0x00000010)) + { + // ----- Look for not compressed file + if ($p_entry['compression'] == 0) { + + // ----- Opening destination file + if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) + { + + // ----- Change the file status + $p_entry['status'] = "write_error"; + + // ----- Return + return $v_result; + } + + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = $p_entry['compressed_size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($this->zip_fd, $v_read_size); + /* Try to speed up the code + $v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($v_dest_file, $v_binary_data, $v_read_size); + */ + @fwrite($v_dest_file, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Closing the destination file + fclose($v_dest_file); + + // ----- Change the file mtime + touch($p_entry['filename'], $p_entry['mtime']); + + + } + else { + // ----- TBC + // Need to be finished + if (($p_entry['flag'] & 1) == 1) { + PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, 'File \''.$p_entry['filename'].'\' is encrypted. Encrypted files are not supported.'); + return PclZip::errorCode(); + } + + + // ----- Look for using temporary file to unzip + if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) + && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON]) + || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) + && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])) ) ) { + $v_result = $this->privExtractFileUsingTempFile($p_entry, $p_options); + if ($v_result < PCLZIP_ERR_NO_ERROR) { + return $v_result; + } + } + + // ----- Look for extract in memory + else { + + + // ----- Read the compressed file in a buffer (one shot) + $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Decompress the file + $v_file_content = @gzinflate($v_buffer); + unset($v_buffer); + if ($v_file_content === FALSE) { + + // ----- Change the file status + // TBC + $p_entry['status'] = "error"; + + return $v_result; + } + + // ----- Opening destination file + if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { + + // ----- Change the file status + $p_entry['status'] = "write_error"; + + return $v_result; + } + + // ----- Write the uncompressed data + @fwrite($v_dest_file, $v_file_content, $p_entry['size']); + unset($v_file_content); + + // ----- Closing the destination file + @fclose($v_dest_file); + + } + + // ----- Change the file mtime + @touch($p_entry['filename'], $p_entry['mtime']); + } + + // ----- Look for chmod option + if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) { + + // ----- Change the mode of the file + @chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]); + } + + } + } + + // ----- Change abort status + if ($p_entry['status'] == "aborted") { + $p_entry['status'] = "skipped"; + } + + // ----- Look for post-extract callback + elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); + + // ----- Look for abort result + if ($v_result == 2) { + $v_result = PCLZIP_ERR_USER_ABORTED; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFileUsingTempFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileUsingTempFile(&$p_entry, &$p_options) + { + $v_result=1; + + // ----- Creates a temporary file + $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz'; + if (($v_dest_file = @fopen($v_gzip_temp_name, "wb")) == 0) { + fclose($v_file); + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode'); + return PclZip::errorCode(); + } + + + // ----- Write gz file format header + $v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3)); + @fwrite($v_dest_file, $v_binary_data, 10); + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = $p_entry['compressed_size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($this->zip_fd, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($v_dest_file, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Write gz file format footer + $v_binary_data = pack('VV', $p_entry['crc'], $p_entry['size']); + @fwrite($v_dest_file, $v_binary_data, 8); + + // ----- Close the temporary file + @fclose($v_dest_file); + + // ----- Opening destination file + if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { + $p_entry['status'] = "write_error"; + return $v_result; + } + + // ----- Open the temporary gz file + if (($v_src_file = @gzopen($v_gzip_temp_name, 'rb')) == 0) { + @fclose($v_dest_file); + $p_entry['status'] = "read_error"; + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); + return PclZip::errorCode(); + } + + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = $p_entry['size']; + while ($v_size != 0) { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @gzread($v_src_file, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($v_dest_file, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + @fclose($v_dest_file); + @gzclose($v_src_file); + + // ----- Delete the temporary file + @unlink($v_gzip_temp_name); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFileInOutput() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileInOutput(&$p_entry, &$p_options) + { + $v_result=1; + + // ----- Read the file header + if (($v_result = $this->privReadFileHeader($v_header)) != 1) { + return $v_result; + } + + + // ----- Check that the file header is coherent with $p_entry info + if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { + // TBC + } + + // ----- Look for pre-extract callback + if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_entry['status'] = "skipped"; + $v_result = 1; + } + + // ----- Look for abort result + if ($v_result == 2) { + // ----- This status is internal and will be changed in 'skipped' + $p_entry['status'] = "aborted"; + $v_result = PCLZIP_ERR_USER_ABORTED; + } + + // ----- Update the informations + // Only some fields can be modified + $p_entry['filename'] = $v_local_header['filename']; + } + + // ----- Trace + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Do the extraction (if not a folder) + if (!(($p_entry['external']&0x00000010)==0x00000010)) { + // ----- Look for not compressed file + if ($p_entry['compressed_size'] == $p_entry['size']) { + + // ----- Read the file in a buffer (one shot) + $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Send the file to the output + echo $v_buffer; + unset($v_buffer); + } + else { + + // ----- Read the compressed file in a buffer (one shot) + $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Decompress the file + $v_file_content = gzinflate($v_buffer); + unset($v_buffer); + + // ----- Send the file to the output + echo $v_file_content; + unset($v_file_content); + } + } + } + + // ----- Change abort status + if ($p_entry['status'] == "aborted") { + $p_entry['status'] = "skipped"; + } + + // ----- Look for post-extract callback + elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); + + // ----- Look for abort result + if ($v_result == 2) { + $v_result = PCLZIP_ERR_USER_ABORTED; + } + } + + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFileAsString() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileAsString(&$p_entry, &$p_string, &$p_options) + { + $v_result=1; + + // ----- Read the file header + $v_header = array(); + if (($v_result = $this->privReadFileHeader($v_header)) != 1) + { + // ----- Return + return $v_result; + } + + + // ----- Check that the file header is coherent with $p_entry info + if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { + // TBC + } + + // ----- Look for pre-extract callback + if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_entry['status'] = "skipped"; + $v_result = 1; + } + + // ----- Look for abort result + if ($v_result == 2) { + // ----- This status is internal and will be changed in 'skipped' + $p_entry['status'] = "aborted"; + $v_result = PCLZIP_ERR_USER_ABORTED; + } + + // ----- Update the informations + // Only some fields can be modified + $p_entry['filename'] = $v_local_header['filename']; + } + + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Do the extraction (if not a folder) + if (!(($p_entry['external']&0x00000010)==0x00000010)) { + // ----- Look for not compressed file + // if ($p_entry['compressed_size'] == $p_entry['size']) + if ($p_entry['compression'] == 0) { + + // ----- Reading the file + $p_string = @fread($this->zip_fd, $p_entry['compressed_size']); + } + else { + + // ----- Reading the file + $v_data = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Decompress the file + if (($p_string = @gzinflate($v_data)) === FALSE) { + // TBC + } + } + + // ----- Trace + } + else { + // TBC : error : can not extract a folder in a string + } + + } + + // ----- Change abort status + if ($p_entry['status'] == "aborted") { + $p_entry['status'] = "skipped"; + } + + // ----- Look for post-extract callback + elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Swap the content to header + $v_local_header['content'] = $p_string; + $p_string = ''; + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); + + // ----- Swap back the content to header + $p_string = $v_local_header['content']; + unset($v_local_header['content']); + + // ----- Look for abort result + if ($v_result == 2) { + $v_result = PCLZIP_ERR_USER_ABORTED; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privReadFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadFileHeader(&$p_header) + { + $v_result=1; + + // ----- Read the 4 bytes signature + $v_binary_data = @fread($this->zip_fd, 4); + $v_data = unpack('Vid', $v_binary_data); + + // ----- Check signature + if ($v_data['id'] != 0x04034b50) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the first 42 bytes of the header + $v_binary_data = fread($this->zip_fd, 26); + + // ----- Look for invalid block size + if (strlen($v_binary_data) != 26) + { + $p_header['filename'] = ""; + $p_header['status'] = "invalid_header"; + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data)); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Extract the values + $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data); + + // ----- Get filename + $p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']); + + // ----- Get extra_fields + if ($v_data['extra_len'] != 0) { + $p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']); + } + else { + $p_header['extra'] = ''; + } + + // ----- Extract properties + $p_header['version_extracted'] = $v_data['version']; + $p_header['compression'] = $v_data['compression']; + $p_header['size'] = $v_data['size']; + $p_header['compressed_size'] = $v_data['compressed_size']; + $p_header['crc'] = $v_data['crc']; + $p_header['flag'] = $v_data['flag']; + $p_header['filename_len'] = $v_data['filename_len']; + + // ----- Recuperate date in UNIX format + $p_header['mdate'] = $v_data['mdate']; + $p_header['mtime'] = $v_data['mtime']; + if ($p_header['mdate'] && $p_header['mtime']) + { + // ----- Extract time + $v_hour = ($p_header['mtime'] & 0xF800) >> 11; + $v_minute = ($p_header['mtime'] & 0x07E0) >> 5; + $v_seconde = ($p_header['mtime'] & 0x001F)*2; + + // ----- Extract date + $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; + $v_month = ($p_header['mdate'] & 0x01E0) >> 5; + $v_day = $p_header['mdate'] & 0x001F; + + // ----- Get UNIX date format + $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); + + } + else + { + $p_header['mtime'] = time(); + } + + // TBC + //for(reset($v_data); $key = key($v_data); next($v_data)) { + //} + + // ----- Set the stored filename + $p_header['stored_filename'] = $p_header['filename']; + + // ----- Set the status field + $p_header['status'] = "ok"; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privReadCentralFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadCentralFileHeader(&$p_header) + { + $v_result=1; + + // ----- Read the 4 bytes signature + $v_binary_data = @fread($this->zip_fd, 4); + $v_data = unpack('Vid', $v_binary_data); + + // ----- Check signature + if ($v_data['id'] != 0x02014b50) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the first 42 bytes of the header + $v_binary_data = fread($this->zip_fd, 42); + + // ----- Look for invalid block size + if (strlen($v_binary_data) != 42) + { + $p_header['filename'] = ""; + $p_header['status'] = "invalid_header"; + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data)); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Extract the values + $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data); + + // ----- Get filename + if ($p_header['filename_len'] != 0) + $p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']); + else + $p_header['filename'] = ''; + + // ----- Get extra + if ($p_header['extra_len'] != 0) + $p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']); + else + $p_header['extra'] = ''; + + // ----- Get comment + if ($p_header['comment_len'] != 0) + $p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']); + else + $p_header['comment'] = ''; + + // ----- Extract properties + + // ----- Recuperate date in UNIX format + //if ($p_header['mdate'] && $p_header['mtime']) + // TBC : bug : this was ignoring time with 0/0/0 + if (1) + { + // ----- Extract time + $v_hour = ($p_header['mtime'] & 0xF800) >> 11; + $v_minute = ($p_header['mtime'] & 0x07E0) >> 5; + $v_seconde = ($p_header['mtime'] & 0x001F)*2; + + // ----- Extract date + $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; + $v_month = ($p_header['mdate'] & 0x01E0) >> 5; + $v_day = $p_header['mdate'] & 0x001F; + + // ----- Get UNIX date format + $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); + + } + else + { + $p_header['mtime'] = time(); + } + + // ----- Set the stored filename + $p_header['stored_filename'] = $p_header['filename']; + + // ----- Set default status to ok + $p_header['status'] = 'ok'; + + // ----- Look if it is a directory + if (substr($p_header['filename'], -1) == '/') { + //$p_header['external'] = 0x41FF0010; + $p_header['external'] = 0x00000010; + } + + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCheckFileHeaders() + // Description : + // Parameters : + // Return Values : + // 1 on success, + // 0 on error; + // -------------------------------------------------------------------------------- + function privCheckFileHeaders(&$p_local_header, &$p_central_header) + { + $v_result=1; + + // ----- Check the static values + // TBC + if ($p_local_header['filename'] != $p_central_header['filename']) { + } + if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) { + } + if ($p_local_header['flag'] != $p_central_header['flag']) { + } + if ($p_local_header['compression'] != $p_central_header['compression']) { + } + if ($p_local_header['mtime'] != $p_central_header['mtime']) { + } + if ($p_local_header['filename_len'] != $p_central_header['filename_len']) { + } + + // ----- Look for flag bit 3 + if (($p_local_header['flag'] & 8) == 8) { + $p_local_header['size'] = $p_central_header['size']; + $p_local_header['compressed_size'] = $p_central_header['compressed_size']; + $p_local_header['crc'] = $p_central_header['crc']; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privReadEndCentralDir() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadEndCentralDir(&$p_central_dir) + { + $v_result=1; + + // ----- Go to the end of the zip file + $v_size = filesize($this->zipname); + @fseek($this->zip_fd, $v_size); + if (@ftell($this->zip_fd) != $v_size) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\''); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- First try : look if this is an archive with no commentaries (most of the time) + // in this case the end of central dir is at 22 bytes of the file end + $v_found = 0; + if ($v_size > 26) { + @fseek($this->zip_fd, $v_size-22); + if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22)) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\''); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read for bytes + $v_binary_data = @fread($this->zip_fd, 4); + $v_data = @unpack('Vid', $v_binary_data); + + // ----- Check signature + if ($v_data['id'] == 0x06054b50) { + $v_found = 1; + } + + $v_pos = ftell($this->zip_fd); + } + + // ----- Go back to the maximum possible size of the Central Dir End Record + if (!$v_found) { + $v_maximum_size = 65557; // 0xFFFF + 22; + if ($v_maximum_size > $v_size) + $v_maximum_size = $v_size; + @fseek($this->zip_fd, $v_size-$v_maximum_size); + if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size)) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\''); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read byte per byte in order to find the signature + $v_pos = ftell($this->zip_fd); + $v_bytes = 0x00000000; + while ($v_pos < $v_size) + { + // ----- Read a byte + $v_byte = @fread($this->zip_fd, 1); + + // ----- Add the byte + //$v_bytes = ($v_bytes << 8) | Ord($v_byte); + // Note we mask the old value down such that once shifted we can never end up with more than a 32bit number + // Otherwise on systems where we have 64bit integers the check below for the magic number will fail. + $v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte); + + // ----- Compare the bytes + if ($v_bytes == 0x504b0506) + { + $v_pos++; + break; + } + + $v_pos++; + } + + // ----- Look if not found end of central dir + if ($v_pos == $v_size) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature"); + + // ----- Return + return PclZip::errorCode(); + } + } + + // ----- Read the first 18 bytes of the header + $v_binary_data = fread($this->zip_fd, 18); + + // ----- Look for invalid block size + if (strlen($v_binary_data) != 18) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data)); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Extract the values + $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data); + + // ----- Check the global size + if (($v_pos + $v_data['comment_size'] + 18) != $v_size) { + + // ----- Removed in release 2.2 see readme file + // The check of the file size is a little too strict. + // Some bugs where found when a zip is encrypted/decrypted with 'crypt'. + // While decrypted, zip has training 0 bytes + if (0) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, + 'The central dir is not at the end of the archive.' + .' Some trailing bytes exists after the archive.'); + + // ----- Return + return PclZip::errorCode(); + } + } + + // ----- Get comment + if ($v_data['comment_size'] != 0) { + $p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']); + } + else + $p_central_dir['comment'] = ''; + + $p_central_dir['entries'] = $v_data['entries']; + $p_central_dir['disk_entries'] = $v_data['disk_entries']; + $p_central_dir['offset'] = $v_data['offset']; + $p_central_dir['size'] = $v_data['size']; + $p_central_dir['disk'] = $v_data['disk']; + $p_central_dir['disk_start'] = $v_data['disk_start']; + + // TBC + //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) { + //} + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDeleteByRule() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDeleteByRule(&$p_result_list, &$p_options) + { + $v_result=1; + $v_list_detail = array(); + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('rb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privCloseFd(); + return $v_result; + } + + // ----- Go to beginning of File + @rewind($this->zip_fd); + + // ----- Scan all the files + // ----- Start at beginning of Central Dir + $v_pos_entry = $v_central_dir['offset']; + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_pos_entry)) + { + // ----- Close the zip file + $this->privCloseFd(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read each entry + $v_header_list = array(); + $j_start = 0; + for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) + { + + // ----- Read the file header + $v_header_list[$v_nb_extracted] = array(); + if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + + return $v_result; + } + + + // ----- Store the index + $v_header_list[$v_nb_extracted]['index'] = $i; + + // ----- Look for the specific extract rules + $v_found = false; + + // ----- Look for extract by name rule + if ( (isset($p_options[PCLZIP_OPT_BY_NAME])) + && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) { + + // ----- Look if the filename is in the list + for ($j=0; ($j strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) + && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) { + $v_found = true; + } + elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */ + && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) { + $v_found = true; + } + } + // ----- Look for a filename + elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) { + $v_found = true; + } + } + } + + // ----- Look for extract by ereg rule + // ereg() is deprecated with PHP 5.3 + /* + else if ( (isset($p_options[PCLZIP_OPT_BY_EREG])) + && ($p_options[PCLZIP_OPT_BY_EREG] != "")) { + + if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) { + $v_found = true; + } + } + */ + + // ----- Look for extract by preg rule + else if ( (isset($p_options[PCLZIP_OPT_BY_PREG])) + && ($p_options[PCLZIP_OPT_BY_PREG] != "")) { + + if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) { + $v_found = true; + } + } + + // ----- Look for extract by index rule + else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX])) + && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) { + + // ----- Look if the index is in the list + for ($j=$j_start; ($j=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) { + $v_found = true; + } + if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) { + $j_start = $j+1; + } + + if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) { + break; + } + } + } + else { + $v_found = true; + } + + // ----- Look for deletion + if ($v_found) + { + unset($v_header_list[$v_nb_extracted]); + } + else + { + $v_nb_extracted++; + } + } + + // ----- Look if something need to be deleted + if ($v_nb_extracted > 0) { + + // ----- Creates a temporay file + $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; + + // ----- Creates a temporary zip archive + $v_temp_zip = new PclZip($v_zip_temp_name); + + // ----- Open the temporary zip file in write mode + if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) { + $this->privCloseFd(); + + // ----- Return + return $v_result; + } + + // ----- Look which file need to be kept + for ($i=0; $izip_fd); + if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the file header + $v_local_header = array(); + if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Check that local file header is same as central file header + if ($this->privCheckFileHeaders($v_local_header, + $v_header_list[$i]) != 1) { + // TBC + } + unset($v_local_header); + + // ----- Write the file header + if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Read/write the data block + if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($v_temp_zip->zip_fd); + + // ----- Re-Create the Central Dir files header + for ($i=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) { + $v_temp_zip->privCloseFd(); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Transform the header to a 'usable' info + $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); + } + + + // ----- Zip file comment + $v_comment = ''; + if (isset($p_options[PCLZIP_OPT_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_COMMENT]; + } + + // ----- Calculate the size of the central header + $v_size = @ftell($v_temp_zip->zip_fd)-$v_offset; + + // ----- Create the central dir footer + if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) { + // ----- Reset the file list + unset($v_header_list); + $v_temp_zip->privCloseFd(); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Close + $v_temp_zip->privCloseFd(); + $this->privCloseFd(); + + // ----- Delete the zip file + // TBC : I should test the result ... + @unlink($this->zipname); + + // ----- Rename the temporary file + // TBC : I should test the result ... + //@rename($v_zip_temp_name, $this->zipname); + PclZipUtilRename($v_zip_temp_name, $this->zipname); + + // ----- Destroy the temporary archive + unset($v_temp_zip); + } + + // ----- Remove every files : reset the file + else if ($v_central_dir['entries'] != 0) { + $this->privCloseFd(); + + if (($v_result = $this->privOpenFd('wb')) != 1) { + return $v_result; + } + + if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) { + return $v_result; + } + + $this->privCloseFd(); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDirCheck() + // Description : + // Check if a directory exists, if not it creates it and all the parents directory + // which may be useful. + // Parameters : + // $p_dir : Directory path to check. + // Return Values : + // 1 : OK + // -1 : Unable to create directory + // -------------------------------------------------------------------------------- + function privDirCheck($p_dir, $p_is_dir=false) + { + $v_result = 1; + + + // ----- Remove the final '/' + if (($p_is_dir) && (substr($p_dir, -1)=='/')) + { + $p_dir = substr($p_dir, 0, strlen($p_dir)-1); + } + + // ----- Check the directory availability + if ((is_dir($p_dir)) || ($p_dir == "")) + { + return 1; + } + + // ----- Extract parent directory + $p_parent_dir = dirname($p_dir); + + // ----- Just a check + if ($p_parent_dir != $p_dir) + { + // ----- Look for parent directory + if ($p_parent_dir != "") + { + if (($v_result = $this->privDirCheck($p_parent_dir)) != 1) + { + return $v_result; + } + } + } + + // ----- Create the directory + if (!@mkdir($p_dir, 0777)) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privMerge() + // Description : + // If $p_archive_to_add does not exist, the function exit with a success result. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privMerge(&$p_archive_to_add) + { + $v_result=1; + + // ----- Look if the archive_to_add exists + if (!is_file($p_archive_to_add->zipname)) + { + + // ----- Nothing to merge, so merge is a success + $v_result = 1; + + // ----- Return + return $v_result; + } + + // ----- Look if the archive exists + if (!is_file($this->zipname)) + { + + // ----- Do a duplicate + $v_result = $this->privDuplicate($p_archive_to_add->zipname); + + // ----- Return + return $v_result; + } + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('rb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privCloseFd(); + return $v_result; + } + + // ----- Go to beginning of File + @rewind($this->zip_fd); + + // ----- Open the archive_to_add file + if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1) + { + $this->privCloseFd(); + + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir_to_add = array(); + if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1) + { + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + + return $v_result; + } + + // ----- Go to beginning of File + @rewind($p_archive_to_add->zip_fd); + + // ----- Creates a temporay file + $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; + + // ----- Open the temporary file in write mode + if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) + { + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Copy the files from the archive to the temporary file + // TBC : Here I should better append the file and go back to erase the central dir + $v_size = $v_central_dir['offset']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($this->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Copy the files from the archive_to_add into the temporary file + $v_size = $v_central_dir_to_add['offset']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($v_zip_temp_fd); + + // ----- Copy the block of file headers from the old archive + $v_size = $v_central_dir['size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($this->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Copy the block of file headers from the archive_to_add + $v_size = $v_central_dir_to_add['size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Merge the file comments + $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment']; + + // ----- Calculate the size of the (new) central header + $v_size = @ftell($v_zip_temp_fd)-$v_offset; + + // ----- Swap the file descriptor + // Here is a trick : I swap the temporary fd with the zip fd, in order to use + // the following methods on the temporary fil and not the real archive fd + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Create the central dir footer + if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1) + { + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + @fclose($v_zip_temp_fd); + $this->zip_fd = null; + + // ----- Reset the file list + unset($v_header_list); + + // ----- Return + return $v_result; + } + + // ----- Swap back the file descriptor + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Close + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + + // ----- Close the temporary file + @fclose($v_zip_temp_fd); + + // ----- Delete the zip file + // TBC : I should test the result ... + @unlink($this->zipname); + + // ----- Rename the temporary file + // TBC : I should test the result ... + //@rename($v_zip_temp_name, $this->zipname); + PclZipUtilRename($v_zip_temp_name, $this->zipname); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDuplicate() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDuplicate($p_archive_filename) + { + $v_result=1; + + // ----- Look if the $p_archive_filename exists + if (!is_file($p_archive_filename)) + { + + // ----- Nothing to duplicate, so duplicate is a success. + $v_result = 1; + + // ----- Return + return $v_result; + } + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('wb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Open the temporary file in write mode + if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0) + { + $this->privCloseFd(); + + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Copy the files from the archive to the temporary file + // TBC : Here I should better append the file and go back to erase the central dir + $v_size = filesize($p_archive_filename); + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($v_zip_temp_fd, $v_read_size); + @fwrite($this->zip_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Close + $this->privCloseFd(); + + // ----- Close the temporary file + @fclose($v_zip_temp_fd); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privErrorLog() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privErrorLog($p_error_code=0, $p_error_string='') + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + PclError($p_error_code, $p_error_string); + } + else { + $this->error_code = $p_error_code; + $this->error_string = $p_error_string; + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privErrorReset() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privErrorReset() + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + PclErrorReset(); + } + else { + $this->error_code = 0; + $this->error_string = ''; + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDisableMagicQuotes() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDisableMagicQuotes() + { + $v_result=1; + + // ----- Look if function exists + if ( (!function_exists("get_magic_quotes_runtime")) + || (!function_exists("set_magic_quotes_runtime"))) { + return $v_result; + } + + // ----- Look if already done + if ($this->magic_quotes_status != -1) { + return $v_result; + } + + // ----- Get and memorize the magic_quote value + $this->magic_quotes_status = @get_magic_quotes_runtime(); + + // ----- Disable magic_quotes + if ($this->magic_quotes_status == 1) { + @set_magic_quotes_runtime(0); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privSwapBackMagicQuotes() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privSwapBackMagicQuotes() + { + $v_result=1; + + // ----- Look if function exists + if ( (!function_exists("get_magic_quotes_runtime")) + || (!function_exists("set_magic_quotes_runtime"))) { + return $v_result; + } + + // ----- Look if something to do + if ($this->magic_quotes_status != -1) { + return $v_result; + } + + // ----- Swap back magic_quotes + if ($this->magic_quotes_status == 1) { + @set_magic_quotes_runtime($this->magic_quotes_status); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + } + // End of class + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilPathReduction() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function PclZipUtilPathReduction($p_dir) + { + $v_result = ""; + + // ----- Look for not empty path + if ($p_dir != "") { + // ----- Explode path by directory names + $v_list = explode("/", $p_dir); + + // ----- Study directories from last to first + $v_skip = 0; + for ($i=sizeof($v_list)-1; $i>=0; $i--) { + // ----- Look for current path + if ($v_list[$i] == ".") { + // ----- Ignore this directory + // Should be the first $i=0, but no check is done + } + else if ($v_list[$i] == "..") { + $v_skip++; + } + else if ($v_list[$i] == "") { + // ----- First '/' i.e. root slash + if ($i == 0) { + $v_result = "/".$v_result; + if ($v_skip > 0) { + // ----- It is an invalid path, so the path is not modified + // TBC + $v_result = $p_dir; + $v_skip = 0; + } + } + // ----- Last '/' i.e. indicates a directory + else if ($i == (sizeof($v_list)-1)) { + $v_result = $v_list[$i]; + } + // ----- Double '/' inside the path + else { + // ----- Ignore only the double '//' in path, + // but not the first and last '/' + } + } + else { + // ----- Look for item to skip + if ($v_skip > 0) { + $v_skip--; + } + else { + $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:""); + } + } + } + + // ----- Look for skip + if ($v_skip > 0) { + while ($v_skip > 0) { + $v_result = '../'.$v_result; + $v_skip--; + } + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilPathInclusion() + // Description : + // This function indicates if the path $p_path is under the $p_dir tree. Or, + // said in an other way, if the file or sub-dir $p_path is inside the dir + // $p_dir. + // The function indicates also if the path is exactly the same as the dir. + // This function supports path with duplicated '/' like '//', but does not + // support '.' or '..' statements. + // Parameters : + // Return Values : + // 0 if $p_path is not inside directory $p_dir + // 1 if $p_path is inside directory $p_dir + // 2 if $p_path is exactly the same as $p_dir + // -------------------------------------------------------------------------------- + function PclZipUtilPathInclusion($p_dir, $p_path) + { + $v_result = 1; + + // ----- Look for path beginning by ./ + if ( ($p_dir == '.') + || ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) { + $p_dir = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1); + } + if ( ($p_path == '.') + || ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) { + $p_path = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1); + } + + // ----- Explode dir and path by directory separator + $v_list_dir = explode("/", $p_dir); + $v_list_dir_size = sizeof($v_list_dir); + $v_list_path = explode("/", $p_path); + $v_list_path_size = sizeof($v_list_path); + + // ----- Study directories paths + $i = 0; + $j = 0; + while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) { + + // ----- Look for empty dir (path reduction) + if ($v_list_dir[$i] == '') { + $i++; + continue; + } + if ($v_list_path[$j] == '') { + $j++; + continue; + } + + // ----- Compare the items + if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) { + $v_result = 0; + } + + // ----- Next items + $i++; + $j++; + } + + // ----- Look if everything seems to be the same + if ($v_result) { + // ----- Skip all the empty items + while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++; + while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++; + + if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) { + // ----- There are exactly the same + $v_result = 2; + } + else if ($i < $v_list_dir_size) { + // ----- The path is shorter than the dir + $v_result = 0; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilCopyBlock() + // Description : + // Parameters : + // $p_mode : read/write compression mode + // 0 : src & dest normal + // 1 : src gzip, dest normal + // 2 : src normal, dest gzip + // 3 : src & dest gzip + // Return Values : + // -------------------------------------------------------------------------------- + function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0) + { + $v_result = 1; + + if ($p_mode==0) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($p_src, $v_read_size); + @fwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + else if ($p_mode==1) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @gzread($p_src, $v_read_size); + @fwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + else if ($p_mode==2) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($p_src, $v_read_size); + @gzwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + else if ($p_mode==3) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @gzread($p_src, $v_read_size); + @gzwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilRename() + // Description : + // This function tries to do a simple rename() function. If it fails, it + // tries to copy the $p_src file in a new $p_dest file and then unlink the + // first one. + // Parameters : + // $p_src : Old filename + // $p_dest : New filename + // Return Values : + // 1 on success, 0 on failure. + // -------------------------------------------------------------------------------- + function PclZipUtilRename($p_src, $p_dest) + { + $v_result = 1; + + // ----- Try to rename the files + if (!@rename($p_src, $p_dest)) { + + // ----- Try to copy & unlink the src + if (!@copy($p_src, $p_dest)) { + $v_result = 0; + } + else if (!@unlink($p_src)) { + $v_result = 0; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilOptionText() + // Description : + // Translate option value in text. Mainly for debug purpose. + // Parameters : + // $p_option : the option value. + // Return Values : + // The option text value. + // -------------------------------------------------------------------------------- + function PclZipUtilOptionText($p_option) + { + + $v_list = get_defined_constants(); + for (reset($v_list); $v_key = key($v_list); next($v_list)) { + $v_prefix = substr($v_key, 0, 10); + if (( ($v_prefix == 'PCLZIP_OPT') + || ($v_prefix == 'PCLZIP_CB_') + || ($v_prefix == 'PCLZIP_ATT')) + && ($v_list[$v_key] == $p_option)) { + return $v_key; + } + } + + $v_result = 'Unknown'; + + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilTranslateWinPath() + // Description : + // Translate windows path by replacing '\' by '/' and optionally removing + // drive letter. + // Parameters : + // $p_path : path to translate. + // $p_remove_disk_letter : true | false + // Return Values : + // The path translated. + // -------------------------------------------------------------------------------- + function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true) + { + if (stristr(php_uname(), 'windows')) { + // ----- Look for potential disk letter + if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) { + $p_path = substr($p_path, $v_position+1); + } + // ----- Change potential windows directory separator + if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) { + $p_path = strtr($p_path, '\\', '/'); + } + } + return $p_path; + } + // -------------------------------------------------------------------------------- + + diff --git a/rainloop/v/1.2.5.406/app/libraries/pclzip/readme.txt b/rainloop/v/1.2.5.406/app/libraries/pclzip/readme.txt new file mode 100644 index 000000000..6ed883947 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/pclzip/readme.txt @@ -0,0 +1,421 @@ +// -------------------------------------------------------------------------------- +// PclZip 2.8.2 - readme.txt +// -------------------------------------------------------------------------------- +// License GNU/LGPL - August 2009 +// Vincent Blavet - vincent@phpconcept.net +// http://www.phpconcept.net +// -------------------------------------------------------------------------------- +// $Id: readme.txt,v 1.60 2009/09/30 20:35:21 vblavet Exp $ +// -------------------------------------------------------------------------------- + + + +0 - Sommaire +============ + 1 - Introduction + 2 - What's new + 3 - Corrected bugs + 4 - Known bugs or limitations + 5 - License + 6 - Warning + 7 - Documentation + 8 - Author + 9 - Contribute + +1 - Introduction +================ + + PclZip is a library that allow you to manage a Zip archive. + + Full documentation about PclZip can be found here : http://www.phpconcept.net/pclzip + +2 - What's new +============== + + Version 2.8.2 : + - PCLZIP_CB_PRE_EXTRACT and PCLZIP_CB_POST_EXTRACT are now supported with + extraction as a string (PCLZIP_OPT_EXTRACT_AS_STRING). The string + can also be modified in the post-extract call back. + **Bugs correction : + - PCLZIP_OPT_REMOVE_ALL_PATH was not working correctly + - Remove use of eval() and do direct call to callback functions + - Correct support of 64bits systems (Thanks to WordPress team) + + Version 2.8.1 : + - Move option PCLZIP_OPT_BY_EREG to PCLZIP_OPT_BY_PREG because ereg() is + deprecated in PHP 5.3. When using option PCLZIP_OPT_BY_EREG, PclZip will + automatically replace it by PCLZIP_OPT_BY_PREG. + + Version 2.8 : + - Improve extraction of zip archive for large files by using temporary files + This feature is working like the one defined in r2.7. + Options are renamed : PCLZIP_OPT_TEMP_FILE_ON, PCLZIP_OPT_TEMP_FILE_OFF, + PCLZIP_OPT_TEMP_FILE_THRESHOLD + - Add a ratio constant PCLZIP_TEMPORARY_FILE_RATIO to configure the auto + sense of temporary file use. + - Bug correction : Reduce filepath in returned file list to remove ennoying + './/' preambule in file path. + + Version 2.7 : + - Improve creation of zip archive for large files : + PclZip will now autosense the configured memory and use temporary files + when large file is suspected. + This feature can also ne triggered by manual options in create() and add() + methods. 'PCLZIP_OPT_ADD_TEMP_FILE_ON' force the use of temporary files, + 'PCLZIP_OPT_ADD_TEMP_FILE_OFF' disable the autosense technic, + 'PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD' allow for configuration of a size + threshold to use temporary files. + Using "temporary files" rather than "memory" might take more time, but + might give the ability to zip very large files : + Tested on my win laptop with a 88Mo file : + Zip "in-memory" : 18sec (max_execution_time=30, memory_limit=180Mo) + Zip "tmporary-files" : 23sec (max_execution_time=30, memory_limit=30Mo) + - Replace use of mktime() by time() to limit the E_STRICT error messages. + - Bug correction : When adding files with full windows path (drive letter) + PclZip is now working. Before, if the drive letter is not the default + path, PclZip was not able to add the file. + + Version 2.6 : + - Code optimisation + - New attributes PCLZIP_ATT_FILE_COMMENT gives the ability to + add a comment for a specific file. (Don't really know if this is usefull) + - New attribute PCLZIP_ATT_FILE_CONTENT gives the ability to add a string + as a file. + - New attribute PCLZIP_ATT_FILE_MTIME modify the timestamp associated with + a file. + - Correct a bug. Files archived with a timestamp with 0h0m0s were extracted + with current time + - Add CRC value in the informations returned back for each file after an + action. + - Add missing closedir() statement. + - When adding a folder, and removing the path of this folder, files were + incorrectly added with a '/' at the beginning. Which means files are + related to root in unix systems. Corrected. + - Add conditional if before constant definition. This will allow users + to redefine constants without changing the file, and then improve + upgrade of pclzip code for new versions. + + Version 2.5 : + - Introduce the ability to add file/folder with individual properties (file descriptor). + This gives for example the ability to change the filename of a zipped file. + . Able to add files individually + . Able to change full name + . Able to change short name + . Compatible with global options + - New attributes : PCLZIP_ATT_FILE_NAME, PCLZIP_ATT_FILE_NEW_SHORT_NAME, PCLZIP_ATT_FILE_NEW_FULL_NAME + - New error code : PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE + - Add a security control feature. PclZip can extract any file in any folder + of a system. People may use this to upload a zip file and try to override + a system file. The PCLZIP_OPT_EXTRACT_DIR_RESTRICTION will give the + ability to forgive any directory transversal behavior. + - New PCLZIP_OPT_EXTRACT_DIR_RESTRICTION : check extraction path + - New error code : PCLZIP_ERR_DIRECTORY_RESTRICTION + - Modification in PclZipUtilPathInclusion() : dir and path beginning with ./ will be prepend + by current path (getcwd()) + + Version 2.4 : + - Code improvment : try to speed up the code by removing unusefull call to pack() + - Correct bug in delete() : delete() should be called with no argument. This was not + the case in 2.3. This is corrected in 2.4. + - Correct a bug in path_inclusion function. When the path has several '../../', the + result was bad. + - Add a check for magic_quotes_runtime configuration. If enabled, PclZip will + disable it while working and det it back to its original value. + This resolve a lots of bad formated archive errors. + - Bug correction : PclZip now correctly unzip file in some specific situation, + when compressed content has same size as uncompressed content. + - Bug correction : When selecting option 'PCLZIP_OPT_REMOVE_ALL_PATH', + directories are not any more created. + - Code improvment : correct unclosed opendir(), better handling of . and .. in + loops. + + + Version 2.3 : + - Correct a bug with PHP5 : affecting the value 0xFE49FFE0 to a variable does not + give the same result in PHP4 and PHP5 .... + + Version 2.2 : + - Try development of PCLZIP_OPT_CRYPT ..... + However this becomes to a stop. To crypt/decrypt I need to multiply 2 long integers, + the result (greater than a long) is not supported by PHP. Even the use of bcmath + functions does not help. I did not find yet a solution ...; + - Add missing '/' at end of directory entries + - Check is a file is encrypted or not. Returns status 'unsupported_encryption' and/or + error code PCLZIP_ERR_UNSUPPORTED_ENCRYPTION. + - Corrected : Bad "version need to extract" field in local file header + - Add private method privCheckFileHeaders() in order to check local and central + file headers. PclZip is now supporting purpose bit flag bit 3. Purpose bit flag bit 3 gives + the ability to have a local file header without size, compressed size and crc filled. + - Add a generic status 'error' for file status + - Add control of compression type. PclZip only support deflate compression method. + Before v2.2, PclZip does not check the compression method used in an archive while + extracting. With v2.2 PclZip returns a new error status for a file using an unsupported + compression method. New status is "unsupported_compression". New error code is + PCLZIP_ERR_UNSUPPORTED_COMPRESSION. + - Add optional attribute PCLZIP_OPT_STOP_ON_ERROR. This will stop the extract of files + when errors like 'a folder with same name exists' or 'a newer file exists' or + 'a write protected file' exists, rather than set a status for the concerning file + and resume the extract of the zip. + - Add optional attribute PCLZIP_OPT_REPLACE_NEWER. This will force, during an extract' the + replacement of the file, even if a newer version of the file exists. + Note that today if a file with the same name already exists but is older it will be + replaced by the extracted one. + - Improve PclZipUtilOption() + - Support of zip archive with trailing bytes. Before 2.2, PclZip checks that the central + directory structure is the last data in the archive. Crypt encryption/decryption of + zip archive put trailing 0 bytes after decryption. PclZip is now supporting this. + + Version 2.1 : + - Add the ability to abort the extraction by using a user callback function. + The user can now return the value '2' in its callback which indicates to stop the + extraction. For a pre call-back extract is stopped before the extration of the current + file. For a post call back, the extraction is stopped after. + - Add the ability to extract a file (or several files) directly in the standard output. + This is done by the new parameter PCLZIP_OPT_EXTRACT_IN_OUTPUT with method extract(). + - Add support for parameters PCLZIP_OPT_COMMENT, PCLZIP_OPT_ADD_COMMENT, + PCLZIP_OPT_PREPEND_COMMENT. This will create, replace, add, or prepend comments + in the zip archive. + - When merging two archives, the comments are not any more lost, but merged, with a + blank space separator. + - Corrected bug : Files are not deleted when all files are asked to be deleted. + - Corrected bug : Folders with name '0' made PclZip to abort the create or add feature. + + + Version 2.0 : + ***** Warning : Some new features may break the backward compatibility for your scripts. + Please carefully read the readme file. + - Add the ability to delete by Index, name and regular expression. This feature is + performed by the method delete(), which uses the optional parameters + PCLZIP_OPT_BY_INDEX, PCLZIP_OPT_BY_NAME, PCLZIP_OPT_BY_EREG or PCLZIP_OPT_BY_PREG. + - Add the ability to extract by regular expression. To extract by regexp you must use the method + extract(), with the option PCLZIP_OPT_BY_EREG or PCLZIP_OPT_BY_PREG + (depending if you want to use ereg() or preg_match() syntax) followed by the + regular expression pattern. + - Add the ability to extract by index, directly with the extract() method. This is a + code improvment of the extractByIndex() method. + - Add the ability to extract by name. To extract by name you must use the method + extract(), with the option PCLZIP_OPT_BY_NAME followed by the filename to + extract or an array of filenames to extract. To extract all a folder, use the folder + name rather than the filename with a '/' at the end. + - Add the ability to add files without compression. This is done with a new attribute + which is PCLZIP_OPT_NO_COMPRESSION. + - Add the attribute PCLZIP_OPT_EXTRACT_AS_STRING, which allow to extract a file directly + in a string without using any file (or temporary file). + - Add constant PCLZIP_SEPARATOR for static configuration of filename separators in a single string. + The default separator is now a comma (,) and not any more a blank space. + THIS BREAK THE BACKWARD COMPATIBILITY : Please check if this may have an impact with + your script. + - Improve algorythm performance by removing the use of temporary files when adding or + extracting files in an archive. + - Add (correct) detection of empty filename zipping. This can occurs when the removed + path is the same + as a zipped dir. The dir is not zipped (['status'] = filtered), only its content. + - Add better support for windows paths (thanks for help from manus@manusfreedom.com). + - Corrected bug : When the archive file already exists with size=0, the add() method + fails. Corrected in 2.0. + - Remove the use of OS_WINDOWS constant. Use php_uname() function rather. + - Control the order of index ranges in extract by index feature. + - Change the internal management of folders (better handling of internal flag). + + + Version 1.3 : + - Removing the double include check. This is now done by include_once() and require_once() + PHP directives. + - Changing the error handling mecanism : Remove the use of an external error library. + The former PclError...() functions are replaced by internal equivalent methods. + By changing the environment variable PCLZIP_ERROR_EXTERNAL you can still use the former library. + Introducing the use of constants for error codes rather than integer values. This will help + in futur improvment. + Introduction of error handling functions like errorCode(), errorName() and errorInfo(). + - Remove the deprecated use of calling function with arguments passed by reference. + - Add the calling of extract(), extractByIndex(), create() and add() functions + with variable options rather than fixed arguments. + - Add the ability to remove all the file path while extracting or adding, + without any need to specify the path to remove. + This is available for extract(), extractByIndex(), create() and add() functionS by using + the new variable options parameters : + - PCLZIP_OPT_REMOVE_ALL_PATH : by indicating this option while calling the fct. + - Ability to change the mode of a file after the extraction (chmod()). + This is available for extract() and extractByIndex() functionS by using + the new variable options parameters. + - PCLZIP_OPT_SET_CHMOD : by setting the value of this option. + - Ability to definition call-back options. These call-back will be called during the adding, + or the extracting of file (extract(), extractByIndex(), create() and add() functions) : + - PCLZIP_CB_PRE_EXTRACT : will be called before each extraction of a file. The user + can trigerred the change the filename of the extracted file. The user can triggered the + skip of the extraction. This is adding a 'skipped' status in the file list result value. + - PCLZIP_CB_POST_EXTRACT : will be called after each extraction of a file. + Nothing can be triggered from that point. + - PCLZIP_CB_PRE_ADD : will be called before each add of a file. The user + can trigerred the change the stored filename of the added file. The user can triggered the + skip of the add. This is adding a 'skipped' status in the file list result value. + - PCLZIP_CB_POST_ADD : will be called after each add of a file. + Nothing can be triggered from that point. + - Two status are added in the file list returned as function result : skipped & filename_too_long + 'skipped' is used when a call-back function ask for skipping the file. + 'filename_too_long' is used while adding a file with a too long filename to archive (the file is + not added) + - Adding the function PclZipUtilPathInclusion(), that check the inclusion of a path into + a directory. + - Add a check of the presence of the archive file before some actions (like list, ...) + - Add the initialisation of field "index" in header array. This means that by + default index will be -1 when not explicitly set by the methods. + + Version 1.2 : + - Adding a duplicate function. + - Adding a merge function. The merge function is a "quick merge" function, + it just append the content of an archive at the end of the first one. There + is no check for duplicate files or more recent files. + - Improve the search of the central directory end. + + Version 1.1.2 : + + - Changing the license of PclZip. PclZip is now released under the GNU / LGPL license + (see License section). + - Adding the optional support of a static temporary directory. You will need to configure + the constant PCLZIP_TEMPORARY_DIR if you want to use this feature. + - Improving the rename() function. In some cases rename() does not work (different + Filesystems), so it will be replaced by a copy() + unlink() functions. + + Version 1.1.1 : + + - Maintenance release, no new feature. + + Version 1.1 : + + - New method Add() : adding files in the archive + - New method ExtractByIndex() : partial extract of the archive, files are identified by + their index in the archive + - New method DeleteByIndex() : delete some files/folder entries from the archive, + files are identified by their index in the archive. + - Adding a test of the zlib extension presence. If not present abort the script. + + Version 1.0.1 : + + - No new feature + + +3 - Corrected bugs +================== + + Corrected in Version 2.0 : + - Corrected : During an extraction, if a call-back fucntion is used and try to skip + a file, all the extraction process is stopped. + + Corrected in Version 1.3 : + - Corrected : Support of static synopsis for method extract() is broken. + - Corrected : invalid size of archive content field (0xFF) should be (0xFFFF). + - Corrected : When an extract is done with a remove_path parameter, the entry for + the directory with exactly the same path is not skipped/filtered. + - Corrected : extractByIndex() and deleteByIndex() were not managing index in the + right way. For example indexes '1,3-5,11' will only extract files 1 and 11. This + is due to a sort of the index resulting table that puts 11 before 3-5 (sort on + string and not interger). The sort is temporarilly removed, this means that + you must provide a sorted list of index ranges. + + Corrected in Version 1.2 : + + - Nothing. + + Corrected in Version 1.1.2 : + + - Corrected : Winzip is unable to delete or add new files in a PclZip created archives. + + Corrected in Version 1.1.1 : + + - Corrected : When archived file is not compressed (0% compression), the + extract method fails. + + Corrected in Version 1.1 : + + - Corrected : Adding a complete tree of folder may result in a bad archive + creation. + + Corrected in Version 1.0.1 : + + - Corrected : Error while compressing files greater than PCLZIP_READ_BLOCK_SIZE (default=1024). + + +4 - Known bugs or limitations +============================= + + Please publish bugs reports in SourceForge : + http://sourceforge.net/tracker/?group_id=40254&atid=427564 + + In Version 2.x : + - PclZip does only support file uncompressed or compressed with deflate (compression method 8) + - PclZip does not support password protected zip archive + - Some concern were seen when changing mtime of a file while archiving. + Seems to be linked to Daylight Saving Time (PclTest_changing_mtime). + + In Version 1.2 : + + - merge() methods does not check for duplicate files or last date of modifications. + + In Version 1.1 : + + - Limitation : Using 'extract' fields in the file header in the zip archive is not supported. + - WinZip is unable to delete a single file in a PclZip created archive. It is also unable to + add a file in a PclZip created archive. (Corrected in v.1.2) + + In Version 1.0.1 : + + - Adding a complete tree of folder may result in a bad archive + creation. (Corrected in V.1.1). + - Path given to methods must be in the unix format (/) and not the Windows format (\). + Workaround : Use only / directory separators. + - PclZip is using temporary files that are sometime the name of the file with a .tmp or .gz + added suffix. Files with these names may already exist and may be overwritten. + Workaround : none. + - PclZip does not check if the zlib extension is present. If it is absent, the zip + file is not created and the lib abort without warning. + Workaround : enable the zlib extension on the php install + + In Version 1.0 : + + - Error while compressing files greater than PCLZIP_READ_BLOCK_SIZE (default=1024). + (Corrected in v.1.0.1) + - Limitation : Multi-disk zip archive are not supported. + + +5 - License +=========== + + Since version 1.1.2, PclZip Library is released under GNU/LGPL license. + This library is free, so you can use it at no cost. + + HOWEVER, if you release a script, an application, a library or any kind of + code using PclZip library (or a part of it), YOU MUST : + - Indicate in the documentation (or a readme file), that your work + uses PclZip Library, and make a reference to the author and the web site + http://www.phpconcept.net + - Gives the ability to the final user to update the PclZip libary. + + I will also appreciate that you send me a mail (vincent@phpconcept.net), just to + be aware that someone is using PclZip. + + For more information about GNU/LGPL license : http://www.gnu.org + +6 - Warning +================= + + This library and the associated files are non commercial, non professional work. + It should not have unexpected results. However if any damage is caused by this software + the author can not be responsible. + The use of this software is at the risk of the user. + +7 - Documentation +================= + PclZip User Manuel is available in English on PhpConcept : http://www.phpconcept.net/pclzip/man/en/index.php + A Russian translation was done by Feskov Kuzma : http://php.russofile.ru/ru/authors/unsort/zip/ + +8 - Author +========== + + This software was written by Vincent Blavet (vincent@phpconcept.net) on its leasure time. + +9 - Contribute +============== + If you want to contribute to the development of PclZip, please contact vincent@phpconcept.net. + If you can help in financing PhpConcept hosting service, please go to + http://www.phpconcept.net/soutien.php diff --git a/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/LICENSE b/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + 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: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) 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 + + (d) 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 + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/README.md b/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/README.md new file mode 100644 index 000000000..7d45323cf --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/README.md @@ -0,0 +1,211 @@ +# tmhOAuth + +An OAuth 1.0A library written in PHP by @themattharris, specifically for use +with the Twitter API. + +**Disclaimer**: This project is a work in progress. Please use the issue tracker +to report any enhancements or issues you encounter. + +## Goals + +- Support OAuth 1.0A +- Use Authorisation headers instead of query string or POST parameters +- Allow uploading of images +- Provide enough information to assist with debugging + +## Dependencies + +The library has been tested with PHP 5.3+ and relies on CURL and hash_hmac. The +vast majority of hosting providers include these libraries and run with PHP 5.1+. + +The code makes use of hash_hmac, which was introduced in PHP 5.1.2. If your version +of PHP is lower than this you should ask your hosting provider for an update. + +## A note about security and SSL + +Version 0.60 hardened the security of the library and defaulted `curl_ssl_verifypeer` to `true`. +As some hosting providers do not provide the most current certificate root file +it is now included in this repository. If the version is out of date OR you prefer +to download the certificate roots yourself, you can get them +from: http://curl.haxx.se/ca/cacert.pem + +Before upgrading the version of tmhOAuth that you use, be sure to verify the SSL +handling works on your server by running the `examples/verify_ssl.php` script. + +## Usage + +This will be built out later but for the moment review the examples repository + for ways the library can be +used. Each example contains instructions on how to use it. + +## Notes for users of previous versions + +If you previously used version 0.4 be aware the utility functions +have now been broken into their own file. Before you use version 0.5+ in your app +test locally to ensure your code doesn't need tmhUtilities included. + +If you used custom HTTP request headers when they were defined as `'key: value'` strings +you should now define them as `'key' => 'value'` pairs. + +Versions prior to 0.7.3 collapsed headers with the same value into one +$tmhOAuth->response['headers'] key. Since 0.7.3 headers with the same key will use an array +to store their values. + +## Change History +### 0.7.5 - 20 Februrary 2013 +- tidying up of composer.json. (Issue #112) Props: ceeram + +### 0.7.4 - 19 Februrary 2013 +- corrections to composer.json to support packagists requirements. (Issue #110) + +### 0.7.3 - 18 Februrary 2013 +- add support for making requests with the host header being different to the request host. +- ensure headers with the same key do not overwrite each other in $tmhOAuth->response['headers']. +- removed examples submodule in favor of examples including tmhOAuth, rather than tmhOAuth including examples +- made it so that if param values are sent to $tmhOAuth->request as an array (key -> array()) then $tmhOAuth->prepare_params will now implode them using ',' +- fixed composer. (Issue #99). Props: rasa +- fixed PHPDoc. (Issue #47). Props: trante +- instead of void, $tmhOAuth->curlit now returns 0 if 'prevent_request' is set + +### 0.7.2 - 01 November 2012 +- use DIRECTORY_SEPARATOR for multi-environment support. (Issue #80) Props: whallz +- tidied up the curlHeader function to use explode instead of substr and store the keys in the format they are returned from the API +- removed content-length hack as it isn't needed if CURLOPT_POSTFIELDS is initialized on all POSTs +- removed the expects header hack as Twitter no longer requires it to be there +- introduce composer.json. (Issues #39, #77, #85) Props: akandels, conradkleinespel, dguyon, kud, philsturgeon, willdurand +- added support for specifying custom headers when using $tmhOAuth->request. (Issue #98) + +### 0.7.1 - 27 October 2012 +- set content-length to 0 explictly to avoid a bug between libcurl and Twitter. (Issue #94) +- allow initialization without a configuration array (default config to array()) +- prevent ->url allowing double slashes in paths + +### 0.7.0 - 04 September 2012 +- changed version numbers to x.y.z format +- stronger method scoping (public and private) +- Typo fix in depenencies. (Issue #42) Props: tantek +- Only lowercase the host and scheme, and not path, in prepare_url. (Issue #56) Props: uzyn +- Fixed a number of PHP warnings by changing some tmhUtilty methods to static. (Issue #52) Props: DrayChou +- Raw headers and response body are now available as `$tmhOAuth->response['raw']` +- Moved the examples to their own repository +- Removed the `noexamples` branch as master does not contain examples anymore +- Introduced `$tmhOAuth->config['timezone']` and set `date_default_timezone_set`. (Issue #70) Props: iamctodd + +### 0.621 - 12 March 2012 +- Ensure `$_SERVER['HTTPS']` isset before checking it's value. Props: kud + +### 0.62 - 01 March 2012 +- Fix array merging bug. Props: julien-c +- use is_callable instead of function_exists: Props: samwierema +- Allow options to be specified for the entify function. Props: davidcroda +- protocol was not inferred correctly for https when ['HTTPS'] == 'on'. Props: ospector +- Switched to https for twitter.com display URLs +- Improved the search results example + +### 0.61 - 16 January 2012 +- Removed trailing ?> from tmhOAuth.php and tmhUtilities.php to meet the Zend Framework's coding practices. Props: reedy +- Fixed bug where CURLOPT_SSL_VERIFYHOST was defaulted to true when it should have been defaulted to 2. Props: kevinsmcarthur + +### 0.60 - 29 December 2011 +- Changed any use of implode to the preferred format of implode($glue, $pieces). Props: reedy +- Moved oauth_verifier to the authorization header as shown in example of RFC 5849. Props: spacenick +- added curl error and error number values to the $tmhOAuth->response object +- added an example script for testing the SSL connection to twitter.com with the new SSL configuration of tmhOAuth +- added a function to generate the useragent depending on whether SSL is on or not +- defaulted CURLOPT_SSL_VERIFYPEER to true +- added CURLOPT_SSL_VERIFYHOST and defaulted it to true +- added the most current cacert.pem file from http://curl.haxx.se/ca/cacert.pem and configured curl to use it + +### 0.58 - 29 December 2011 +- Rearranged some configuration variables around to make commenting easier +- Standarised on lowercase booleans + +### 0.57 - 11 December 2011 +- Fixed prevent_request so OAuth Echo requests work again. +- Added a TwitPic OAuth Echo example + +### 0.56 - 29 September 2011 +- Fixed version reference in the UserAgent +- Updated tmhUtilities::entify with support for media +- Updated tmhUtilities::entify with support for multibyte characters. Props: andersonshatch + +### 0.55 - 29 September 2011 +- Added support for content encoding. Defaults to whatever localhost supports. Props: yusuke + +### 0.54 - 29 September 2011 +- User-Agent is now configurable and includes the current version number of the script +- Updated the Streaming examples to use SSL + +### 0.53 - 15 July 2011 +- Fixed issue where headers were being duplicated if the library was called more than once. +- Updated examples to fit the new location of access tokens and secrets on dev.twitter.com +- Added Photo Tweet example + +### 0.52 - 06 July 2011 +- Fixed issue where the preference for include_time in create_nonce was being ignored + +### 0.51 - 06 July 2011 +- Use isset instead of suppress errors. Props: funkatron +- Added example of using the Search API +- Added example of using friends/ids and users/lookup to get details of a users friends +- Added example of the authorize OAuth webflow + +### 0.5 - 29 March 2011 +- Moved utility functions out of the main class and into the tmhUtilities class. +- Added the ability to send OAuth parameters as part of the querystring or POST body. +- Section 3.4.1.2 says the url must be lowercase so prepare URL now does this. +- Added a convenience method for accessing the safe_encode/decode transforms. +- Updated the examples to use the new utilities library. +- Added examples for sitestreams and userstreams. +- Added a more advanced streaming API example. + +### 0.4 - 03 March 2011 +- Fixed handling of parameters when using DELETE. Thanks to yusuke for reporting +- Fixed php_self to handle port numbers other than 80/443. Props: yusuke +- Updated function pr to use pre only when not running in CLI mode +- Add support for proxy servers. Props juanchorossi +- Function request now returns the HTTP status code. Props: kronenthaler +- Documentation fixes for xAuth. Props: 140dev +- Some minor code formatting changes + +### 0.3 - 28 September 2010 +- Moved entities rendering into the library + +### 0.2 - 17 September 2010 +- Added support for the Streaming API + +### 0.14 - 17 September 2010 +- Fixed authorisation header for use with OAuth Echo + +### 0.13 - 17 September 2010 +- Added use_ssl configuration parameter +- Fixed config array typo +- Removed v from the config +- Remove protocol from the host (configured by use_ssl) +- Added include for easier debugging + +### 0.12 - 17 September 2010 + +- Moved curl options to config +- Added the ability for curl to follow redirects, default false + +### 0.11 - 17 September 2010 + +- Fixed a bug in the GET requests + +### 0.1 - 26 August 2010 + +- Initial beta version + +## Community + +License: Apache 2 (see [included LICENSE file](https://github.com/themattharris/tmhOAuth/blob/master/LICENSE)) + +Follow [@tmhOAuth](https://twitter.com/intent/follow?screen_name=tmhOAuth) to receive updates on releases, or ask for support +Follow me on Twitter: [@themattharris](https://twitter.com/intent/follow?screen_name=themattharris) +Check out the Twitter Developer Resources: + +## To Do + +- Add good behavior logic to the Streaming API handler - i.e. on disconnect back off +- Async Curl support \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/cacert.pem b/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/cacert.pem new file mode 100644 index 000000000..334fb26ad --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/cacert.pem @@ -0,0 +1,3376 @@ +## +## ca-bundle.crt -- Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Thu Nov 3 19:04:19 2011 +## +## 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.80 $ $Date: 2011/11/03 15:11:58 $ + +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----- + +Verisign Class 4 Public Primary Certification Authority - G2 +============================================================ +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz +dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz +dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4 +xBewRNzjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH +qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwIDAQAB +MA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwjcSGIL4LcY/oCRaxF +WdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0ycyfYaT5DdPauxYma51N86Xv2S/PB +ZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRPT8qAkbYp +-----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----- + +TC TrustCenter, Germany, Class 2 CA +=================================== +-----BEGIN CERTIFICATE----- +MIIDXDCCAsWgAwIBAgICA+owDQYJKoZIhvcNAQEEBQAwgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig +U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVzdENlbnRlciBD +bGFzcyAyIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAeFw05 +ODAzMDkxMTU5NTlaFw0xMTAxMDExMTU5NTlaMIG8MQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RDZW50ZXIgZm9yIFNlY3Vy +aXR5IGluIERhdGEgTmV0d29ya3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3Mg +MiBDQTEpMCcGCSqGSIb3DQEJARYaY2VydGlmaWNhdGVAdHJ1c3RjZW50ZXIuZGUwgZ8wDQYJKoZI +hvcNAQEBBQADgY0AMIGJAoGBANo46O0yAClxgwENv4wB3NrGrTmkqYov1YtcaF9QxmL1Zr3KkSLs +qh1R1z2zUbKDTl3LSbDwTFXlay3HhQswHJJOgtTKAu33b77c4OMUuAVT8pr0VotanoWT0bSCVq5N +u6hLVxa8/vhYnvgpjbB7zXjJT6yLZwzxnPv8V5tXXE8NAgMBAAGjazBpMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgGGMDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3LnRydXN0Y2VudGVy +LmRlL2d1aWRlbGluZXMwEQYJYIZIAYb4QgEBBAQDAgAHMA0GCSqGSIb3DQEBBAUAA4GBAIRS+yjf +/x91AbwBvgRWl2p0QiQxg/lGsQaKic+WLDO/jLVfenKhhQbOhvgFjuj5Jcrag4wGrOs2bYWRNAQ2 +9ELw+HkuCkhcq8xRT3h2oNmsGb0q0WkEKJHKNhAngFdb0lz1wlurZIFjdFH0l7/NEij3TWZ/p/Ac +ASZ4smZHcFFk +-----END CERTIFICATE----- + +TC TrustCenter, Germany, Class 3 CA +=================================== +-----BEGIN CERTIFICATE----- +MIIDXDCCAsWgAwIBAgICA+swDQYJKoZIhvcNAQEEBQAwgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig +U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVzdENlbnRlciBD +bGFzcyAzIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAeFw05 +ODAzMDkxMTU5NTlaFw0xMTAxMDExMTU5NTlaMIG8MQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RDZW50ZXIgZm9yIFNlY3Vy +aXR5IGluIERhdGEgTmV0d29ya3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3Mg +MyBDQTEpMCcGCSqGSIb3DQEJARYaY2VydGlmaWNhdGVAdHJ1c3RjZW50ZXIuZGUwgZ8wDQYJKoZI +hvcNAQEBBQADgY0AMIGJAoGBALa0wTUFLg2N7KBAahwOJ6ZQkmtQGwfeLud2zODa/ISoXoxjaitN +2U4CdhHBC/KNecoAtvGwDtf7pBc9r6tpepYnv68zoZoqWarEtTcI8hKlMbZD9TKWcSgoq40oht+7 +7uMMfTDWw1Krj10nnGvAo+cFa1dJRLNu6mTP0o56UHd3AgMBAAGjazBpMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgGGMDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3LnRydXN0Y2VudGVy +LmRlL2d1aWRlbGluZXMwEQYJYIZIAYb4QgEBBAQDAgAHMA0GCSqGSIb3DQEBBAUAA4GBABY9xs3B +u4VxhUafPiCPUSiZ7C1FIWMjWwS7TJC4iJIETb19AaM/9uzO8d7+feXhPrvGq14L3T2WxMup1Pkm +5gZOngylerpuw3yCGdHHsbHD2w2Om0B8NwvxXej9H5CIpQ5ON2QhqE6NtJ/x3kit1VYYUimLRzQS +CdS7kjXvD9s0 +-----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----- \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/tmhOAuth.php b/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/tmhOAuth.php new file mode 100644 index 000000000..c4ad4e78a --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/tmhOAuth.php @@ -0,0 +1,724 @@ +params = array(); + $this->headers = array(); + $this->auto_fixed_time = false; + $this->buffer = null; + + // default configuration options + $this->config = array_merge( + array( + // leave 'user_agent' blank for default, otherwise set this to + // something that clearly identifies your app + 'user_agent' => '', + // default timezone for requests + 'timezone' => 'UTC', + + 'use_ssl' => true, + 'host' => 'api.twitter.com', + + 'consumer_key' => '', + 'consumer_secret' => '', + 'user_token' => '', + 'user_secret' => '', + 'force_nonce' => false, + 'nonce' => false, // used for checking signatures. leave as false for auto + 'force_timestamp' => false, + 'timestamp' => false, // used for checking signatures. leave as false for auto + + // oauth signing variables that are not dynamic + 'oauth_version' => '1.0', + 'oauth_signature_method' => 'HMAC-SHA1', + + // you probably don't want to change any of these curl values + 'curl_connecttimeout' => 30, + 'curl_timeout' => 10, + + // for security this should always be set to 2. + 'curl_ssl_verifyhost' => 2, + // for security this should always be set to true. + 'curl_ssl_verifypeer' => true, + + // you can get the latest cacert.pem from here http://curl.haxx.se/ca/cacert.pem + 'curl_cainfo' => dirname(__FILE__) . DIRECTORY_SEPARATOR . 'cacert.pem', + 'curl_capath' => dirname(__FILE__), + + 'curl_followlocation' => false, // whether to follow redirects or not + + // support for proxy servers + 'curl_proxy' => false, // really you don't want to use this if you are using streaming + 'curl_proxyuserpwd' => false, // format username:password for proxy, if required + 'curl_encoding' => '', // leave blank for all supported formats, else use gzip, deflate, identity + + // streaming API + 'is_streaming' => false, + 'streaming_eol' => "\r\n", + 'streaming_metrics_interval' => 60, + + // header or querystring. You should always use header! + // this is just to help me debug other developers implementations + 'as_header' => true, + 'debug' => false, + ), + $config + ); + $this->set_user_agent(); + date_default_timezone_set($this->config['timezone']); + } + + /** + * Sets the useragent for PHP to use + * If '$this->config['user_agent']' already has a value it is used instead of one + * being generated. + * + * @return void value is stored to the config array class variable + */ + private function set_user_agent() { + if (!empty($this->config['user_agent'])) + return; + + if ($this->config['curl_ssl_verifyhost'] && $this->config['curl_ssl_verifypeer']) { + $ssl = '+SSL'; + } else { + $ssl = '-SSL'; + } + + $ua = 'tmhOAuth ' . self::VERSION . $ssl . ' - //github.com/themattharris/tmhOAuth'; + $this->config['user_agent'] = $ua; + } + + /** + * Generates a random OAuth nonce. + * If 'force_nonce' is true a nonce is not generated and the value in the configuration will be retained. + * + * @param string $length how many characters the nonce should be before MD5 hashing. default 12 + * @param string $include_time whether to include time at the beginning of the nonce. default true + * @return void value is stored to the config array class variable + */ + private function create_nonce($length=12, $include_time=true) { + if ($this->config['force_nonce'] == false) { + $sequence = array_merge(range(0,9), range('A','Z'), range('a','z')); + $length = $length > count($sequence) ? count($sequence) : $length; + shuffle($sequence); + + $prefix = $include_time ? microtime() : ''; + $this->config['nonce'] = md5(substr($prefix . implode('', $sequence), 0, $length)); + } + } + + /** + * Generates a timestamp. + * If 'force_timestamp' is true a nonce is not generated and the value in the configuration will be retained. + * + * @return void value is stored to the config array class variable + */ + private function create_timestamp() { + $this->config['timestamp'] = ($this->config['force_timestamp'] == false ? time() : $this->config['timestamp']); + } + + /** + * Encodes the string or array passed in a way compatible with OAuth. + * If an array is passed each array value will will be encoded. + * + * @param mixed $data the scalar or array to encode + * @return $data encoded in a way compatible with OAuth + */ + private function safe_encode($data) { + if (is_array($data)) { + return array_map(array($this, 'safe_encode'), $data); + } else if (is_scalar($data)) { + return str_ireplace( + array('+', '%7E'), + array(' ', '~'), + rawurlencode($data) + ); + } else { + return ''; + } + } + + /** + * Decodes the string or array from it's URL encoded form + * If an array is passed each array value will will be decoded. + * + * @param mixed $data the scalar or array to decode + * @return string $data decoded from the URL encoded form + */ + private function safe_decode($data) { + if (is_array($data)) { + return array_map(array($this, 'safe_decode'), $data); + } else if (is_scalar($data)) { + return rawurldecode($data); + } else { + return ''; + } + } + + /** + * Returns an array of the standard OAuth parameters. + * + * @return array all required OAuth parameters, safely encoded + */ + private function get_defaults() { + $defaults = array( + 'oauth_version' => $this->config['oauth_version'], + 'oauth_nonce' => $this->config['nonce'], + 'oauth_timestamp' => $this->config['timestamp'], + 'oauth_consumer_key' => $this->config['consumer_key'], + 'oauth_signature_method' => $this->config['oauth_signature_method'], + ); + + // include the user token if it exists + if ( $this->config['user_token'] ) + $defaults['oauth_token'] = $this->config['user_token']; + + // safely encode + foreach ($defaults as $k => $v) { + $_defaults[$this->safe_encode($k)] = $this->safe_encode($v); + } + + return $_defaults; + } + + /** + * Extracts and decodes OAuth parameters from the passed string + * + * @param string $body the response body from an OAuth flow method + * @return array the response body safely decoded to an array of key => values + */ + public function extract_params($body) { + $kvs = explode('&', $body); + $decoded = array(); + foreach ($kvs as $kv) { + $kv = explode('=', $kv, 2); + $kv[0] = $this->safe_decode($kv[0]); + $kv[1] = $this->safe_decode($kv[1]); + $decoded[$kv[0]] = $kv[1]; + } + return $decoded; + } + + /** + * Prepares the HTTP method for use in the base string by converting it to + * uppercase. + * + * @param string $method an HTTP method such as GET or POST + * @return void value is stored to the class variable 'method' + */ + private function prepare_method($method) { + $this->method = strtoupper($method); + } + + /** + * Prepares the URL for use in the base string by ripping it apart and + * reconstructing it. + * + * Ref: 3.4.1.2 + * + * @param string $url the request URL + * @return void value is stored to the class variable 'url' + */ + private function prepare_url($url) { + $parts = parse_url($url); + + $port = isset($parts['port']) ? $parts['port'] : false; + $scheme = $parts['scheme']; + $host = $parts['host']; + $path = isset($parts['path']) ? $parts['path'] : false; + + $port or $port = ($scheme == 'https') ? '443' : '80'; + + if (($scheme == 'https' && $port != '443') + || ($scheme == 'http' && $port != '80')) { + $host = "$host:$port"; + } + + // the scheme and host MUST be lowercase + $this->url = strtolower("$scheme://$host"); + // but not the path + $this->url .= $path; + } + + /** + * Prepares all parameters for the base string and request. + * Multipart parameters are ignored as they are not defined in the specification, + * all other types of parameter are encoded for compatibility with OAuth. + * + * @param array $params the parameters for the request + * @return void prepared values are stored in the class variable 'signing_params' + */ + private function prepare_params($params) { + // do not encode multipart parameters, leave them alone + if ($this->config['multipart']) { + $this->request_params = $params; + $params = array(); + } + + // signing parameters are request parameters + OAuth default parameters + $this->signing_params = array_merge($this->get_defaults(), (array)$params); + + // Remove oauth_signature if present + // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.") + if (isset($this->signing_params['oauth_signature'])) { + unset($this->signing_params['oauth_signature']); + } + + // Parameters are sorted by name, using lexicographical byte value ordering. + // Ref: Spec: 9.1.1 (1) + uksort($this->signing_params, 'strcmp'); + + // encode. Also sort the signed parameters from the POST parameters + foreach ($this->signing_params as $k => $v) { + $k = $this->safe_encode($k); + + if (is_array($v)) + $v = implode(',', $v); + + $v = $this->safe_encode($v); + $_signing_params[$k] = $v; + $kv[] = "{$k}={$v}"; + } + + // auth params = the default oauth params which are present in our collection of signing params + $this->auth_params = array_intersect_key($this->get_defaults(), $_signing_params); + if (isset($_signing_params['oauth_callback'])) { + $this->auth_params['oauth_callback'] = $_signing_params['oauth_callback']; + unset($_signing_params['oauth_callback']); + } + + if (isset($_signing_params['oauth_verifier'])) { + $this->auth_params['oauth_verifier'] = $_signing_params['oauth_verifier']; + unset($_signing_params['oauth_verifier']); + } + + // request_params is already set if we're doing multipart, if not we need to set them now + if ( ! $this->config['multipart']) + $this->request_params = array_diff_key($_signing_params, $this->get_defaults()); + + // create the parameter part of the base string + $this->signing_params = implode('&', $kv); + } + + /** + * Prepares the OAuth signing key + * + * @return void prepared signing key is stored in the class variable 'signing_key' + */ + private function prepare_signing_key() { + $this->signing_key = $this->safe_encode($this->config['consumer_secret']) . '&' . $this->safe_encode($this->config['user_secret']); + } + + /** + * Prepare the base string. + * Ref: Spec: 9.1.3 ("Concatenate Request Elements") + * + * @return void prepared base string is stored in the class variable 'base_string' + */ + private function prepare_base_string() { + $url = $this->url; + + # if the host header is set we need to rewrite the basestring to use + # that, instead of the request host. otherwise the signature won't match + # on the server side + if (!empty($this->custom_headers['Host'])) { + $url = str_ireplace( + $this->config['host'], + $this->custom_headers['Host'], + $url + ); + } + + $base = array( + $this->method, + $url, + $this->signing_params + ); + $this->base_string = implode('&', $this->safe_encode($base)); + } + + /** + * Prepares the Authorization header + * + * @return void prepared authorization header is stored in the class variable headers['Authorization'] + */ + private function prepare_auth_header() { + unset($this->headers['Authorization']); + + uksort($this->auth_params, 'strcmp'); + if (!$this->config['as_header']) : + $this->request_params = array_merge($this->request_params, $this->auth_params); + return; + endif; + + foreach ($this->auth_params as $k => $v) { + $kv[] = "{$k}=\"{$v}\""; + } + $this->auth_header = 'OAuth ' . implode(', ', $kv); + $this->headers['Authorization'] = $this->auth_header; + } + + /** + * Signs the request and adds the OAuth signature. This runs all the request + * parameter preparation methods. + * + * @param string $method the HTTP method being used. e.g. POST, GET, HEAD etc + * @param string $url the request URL without query string parameters + * @param array $params the request parameters as an array of key=value pairs + * @param string $useauth whether to use authentication when making the request. + * @return void + */ + private function sign($method, $url, $params, $useauth) { + $this->prepare_method($method); + $this->prepare_url($url); + $this->prepare_params($params); + + // we don't sign anything is we're not using auth + if ($useauth) { + $this->prepare_base_string(); + $this->prepare_signing_key(); + + $this->auth_params['oauth_signature'] = $this->safe_encode( + base64_encode( + hash_hmac( + 'sha1', $this->base_string, $this->signing_key, true + ))); + + $this->prepare_auth_header(); + } + } + + /** + * Make an HTTP request using this library. This method doesn't return anything. + * Instead the response should be inspected directly. + * + * @param string $method the HTTP method being used. e.g. POST, GET, HEAD etc + * @param string $url the request URL without query string parameters + * @param array $params the request parameters as an array of key=value pairs. Default empty array + * @param string $useauth whether to use authentication when making the request. Default true + * @param string $multipart whether this request contains multipart data. Default false + * @param array $headers any custom headers to send with the request. Default empty array + * @return int the http response code for the request. 0 is returned if a connection could not be made + */ + public function request($method, $url, $params=array(), $useauth=true, $multipart=false, $headers=array()) { + // reset the request headers (we don't want to reuse them) + $this->headers = array(); + $this->custom_headers = $headers; + + $this->config['multipart'] = $multipart; + + $this->create_nonce(); + $this->create_timestamp(); + + $this->sign($method, $url, $params, $useauth); + + if (!empty($this->custom_headers)) + $this->headers = array_merge((array)$this->headers, (array)$this->custom_headers); + + return $this->curlit(); + } + + /** + * Make a long poll HTTP request using this library. This method is + * different to the other request methods as it isn't supposed to disconnect + * + * Using this method expects a callback which will receive the streaming + * responses. + * + * @param string $method the HTTP method being used. e.g. POST, GET, HEAD etc + * @param string $url the request URL without query string parameters + * @param array $params the request parameters as an array of key=value pairs + * @param string $callback the callback function to stream the buffer to. + * @return void + */ + public function streaming_request($method, $url, $params=array(), $callback='') { + if ( ! empty($callback) ) { + if ( ! is_callable($callback) ) { + return false; + } + $this->config['streaming_callback'] = $callback; + } + $this->metrics['start'] = time(); + $this->metrics['interval_start'] = $this->metrics['start']; + $this->metrics['tweets'] = 0; + $this->metrics['last_tweets'] = 0; + $this->metrics['bytes'] = 0; + $this->metrics['last_bytes'] = 0; + $this->config['is_streaming'] = true; + $this->request($method, $url, $params); + } + + /** + * Handles the updating of the current Streaming API metrics. + * + * @return array the metrics for the streaming api connection + */ + private function update_metrics() { + $now = time(); + if (($this->metrics['interval_start'] + $this->config['streaming_metrics_interval']) > $now) + return false; + + $this->metrics['tps'] = round( ($this->metrics['tweets'] - $this->metrics['last_tweets']) / $this->config['streaming_metrics_interval'], 2); + $this->metrics['bps'] = round( ($this->metrics['bytes'] - $this->metrics['last_bytes']) / $this->config['streaming_metrics_interval'], 2); + + $this->metrics['last_bytes'] = $this->metrics['bytes']; + $this->metrics['last_tweets'] = $this->metrics['tweets']; + $this->metrics['interval_start'] = $now; + return $this->metrics; + } + + /** + * Utility function to create the request URL in the requested format + * + * @param string $request the API method without extension + * @param string $format the format of the response. Default json. Set to an empty string to exclude the format + * @return string the concatenation of the host, API version, API method and format + */ + public function url($request, $format='json') { + $format = strlen($format) > 0 ? ".$format" : ''; + $proto = $this->config['use_ssl'] ? 'https:/' : 'http:/'; + + // backwards compatibility with v0.1 + if (isset($this->config['v'])) + $this->config['host'] = $this->config['host'] . '/' . $this->config['v']; + + $request = ltrim($request, '/'); + + $pos = strlen($request) - strlen($format); + if (substr($request, $pos) === $format) + $request = substr_replace($request, '', $pos); + + return implode('/', array( + $proto, + $this->config['host'], + $request . $format + )); + } + + /** + * Public access to the private safe decode/encode methods + * + * @param string $text the text to transform + * @param string $mode the transformation mode. either encode or decode + * @return string $text transformed by the given $mode + */ + public function transformText($text, $mode='encode') { + return $this->{"safe_$mode"}($text); + } + + /** + * Utility function to parse the returned curl headers and store them in the + * class array variable. + * + * @param object $ch curl handle + * @param string $header the response headers + * @return string the length of the header + */ + private function curlHeader($ch, $header) { + $this->response['raw'] .= $header; + + list($key, $value) = array_pad(explode(':', $header, 2), 2, null); + + $key = trim($key); + $value = trim($value); + + if ( ! isset($this->response['headers'][$key])) { + $this->response['headers'][$key] = $value; + } else { + if (!is_array($this->response['headers'][$key])) { + $this->response['headers'][$key] = array($this->response['headers'][$key]); + } + $this->response['headers'][$key][] = $value; + } + + return strlen($header); + } + + /** + * Utility function to parse the returned curl buffer and store them until + * an EOL is found. The buffer for curl is an undefined size so we need + * to collect the content until an EOL is found. + * + * This function calls the previously defined streaming callback method. + * + * @param object $ch curl handle + * @param string $data the current curl buffer + * @return int the length of the data string processed in this function + */ + private function curlWrite($ch, $data) { + $l = strlen($data); + if (strpos($data, $this->config['streaming_eol']) === false) { + $this->buffer .= $data; + return $l; + } + + $buffered = explode($this->config['streaming_eol'], $data); + $content = $this->buffer . $buffered[0]; + + $this->metrics['tweets']++; + $this->metrics['bytes'] += strlen($content); + + if ( ! is_callable($this->config['streaming_callback'])) + return 0; + + $metrics = $this->update_metrics(); + $stop = call_user_func( + $this->config['streaming_callback'], + $content, + strlen($content), + $metrics + ); + $this->buffer = $buffered[1]; + if ($stop) + return 0; + + return $l; + } + + /** + * Makes a curl request. Takes no parameters as all should have been prepared + * by the request method + * + * the response data is stored in the class variable 'response' + * + * @return int the http response code for the request. 0 is returned if a connection could not be made + */ + private function curlit() { + $this->response['raw'] = ''; + + // method handling + switch ($this->method) { + case 'POST': + break; + default: + // GET, DELETE request so convert the parameters to a querystring + if ( ! empty($this->request_params)) { + foreach ($this->request_params as $k => $v) { + // Multipart params haven't been encoded yet. + // Not sure why you would do a multipart GET but anyway, here's the support for it + if ($this->config['multipart']) { + $params[] = $this->safe_encode($k) . '=' . $this->safe_encode($v); + } else { + $params[] = $k . '=' . $v; + } + } + $qs = implode('&', $params); + $this->url = strlen($qs) > 0 ? $this->url . '?' . $qs : $this->url; + $this->request_params = array(); + } + break; + } + + // configure curl + $c = curl_init(); + curl_setopt_array($c, array( + CURLOPT_USERAGENT => $this->config['user_agent'], + CURLOPT_CONNECTTIMEOUT => $this->config['curl_connecttimeout'], + CURLOPT_TIMEOUT => $this->config['curl_timeout'], + CURLOPT_RETURNTRANSFER => true, + CURLOPT_SSL_VERIFYPEER => $this->config['curl_ssl_verifypeer'], + CURLOPT_SSL_VERIFYHOST => $this->config['curl_ssl_verifyhost'], + + CURLOPT_FOLLOWLOCATION => $this->config['curl_followlocation'], + CURLOPT_PROXY => $this->config['curl_proxy'], + CURLOPT_ENCODING => $this->config['curl_encoding'], + CURLOPT_URL => $this->url, + // process the headers + CURLOPT_HEADERFUNCTION => array($this, 'curlHeader'), + CURLOPT_HEADER => false, + CURLINFO_HEADER_OUT => true, + )); + + if ($this->config['curl_cainfo'] !== false) + curl_setopt($c, CURLOPT_CAINFO, $this->config['curl_cainfo']); + + if ($this->config['curl_capath'] !== false) + curl_setopt($c, CURLOPT_CAPATH, $this->config['curl_capath']); + + if ($this->config['curl_proxyuserpwd'] !== false) + curl_setopt($c, CURLOPT_PROXYUSERPWD, $this->config['curl_proxyuserpwd']); + + if ($this->config['is_streaming']) { + // process the body + $this->response['content-length'] = 0; + curl_setopt($c, CURLOPT_TIMEOUT, 0); + curl_setopt($c, CURLOPT_WRITEFUNCTION, array($this, 'curlWrite')); + } + + switch ($this->method) { + case 'GET': + break; + case 'POST': + curl_setopt($c, CURLOPT_POST, true); + curl_setopt($c, CURLOPT_POSTFIELDS, $this->request_params); + break; + default: + curl_setopt($c, CURLOPT_CUSTOMREQUEST, $this->method); + } + + if ( ! empty($this->request_params) ) { + // if not doing multipart we need to implode the parameters + if ( ! $this->config['multipart'] ) { + foreach ($this->request_params as $k => $v) { + $ps[] = "{$k}={$v}"; + } + $this->request_params = implode('&', $ps); + } + curl_setopt($c, CURLOPT_POSTFIELDS, $this->request_params); + } + + if ( ! empty($this->headers)) { + foreach ($this->headers as $k => $v) { + $headers[] = trim($k . ': ' . $v); + } + curl_setopt($c, CURLOPT_HTTPHEADER, $headers); + } + + if (isset($this->config['prevent_request']) && (true == $this->config['prevent_request'])) + return 0; + + // do it! + $response = curl_exec($c); + $code = curl_getinfo($c, CURLINFO_HTTP_CODE); + $info = curl_getinfo($c); + $error = curl_error($c); + $errno = curl_errno($c); + curl_close($c); + + // store the response + $this->response['code'] = $code; + $this->response['response'] = $response; + $this->response['info'] = $info; + $this->response['error'] = $error; + $this->response['errno'] = $errno; + + if (!isset($this->response['raw'])) { + $this->response['raw'] = ''; + } + $this->response['raw'] .= $response; + + return $code; + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/tmhUtilities.php b/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/tmhUtilities.php new file mode 100644 index 000000000..22277df35 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/libraries/tmhOAuth/tmhUtilities.php @@ -0,0 +1,280 @@ + 'UTF-8', + 'target' => '', + ); + + $opts = array_merge($default_opts, $options); + + $encoding = mb_internal_encoding(); + mb_internal_encoding($opts['encoding']); + + $keys = array(); + $is_retweet = false; + + if (isset($tweet['retweeted_status'])) { + $tweet = $tweet['retweeted_status']; + $is_retweet = true; + } + + if (!isset($tweet['entities'])) { + return $tweet['text']; + } + + $target = (!empty($opts['target'])) ? ' target="'.$opts['target'].'"' : ''; + + // prepare the entities + foreach ($tweet['entities'] as $type => $things) { + foreach ($things as $entity => $value) { + $tweet_link = "{$tweet['created_at']}"; + + switch ($type) { + case 'hashtags': + $href = "#{$value['text']}"; + break; + case 'user_mentions': + $href = "@{$value['screen_name']}"; + break; + case 'urls': + case 'media': + $url = empty($value['expanded_url']) ? $value['url'] : $value['expanded_url']; + $display = isset($value['display_url']) ? $value['display_url'] : str_replace('http://', '', $url); + // Not all pages are served in UTF-8 so you may need to do this ... + $display = urldecode(str_replace('%E2%80%A6', '…', urlencode($display))); + $href = "{$display}"; + break; + } + $keys[$value['indices']['0']] = mb_substr( + $tweet['text'], + $value['indices']['0'], + $value['indices']['1'] - $value['indices']['0'] + ); + $replacements[$value['indices']['0']] = $href; + } + } + + ksort($replacements); + $replacements = array_reverse($replacements, true); + $entified_tweet = $tweet['text']; + foreach ($replacements as $k => $v) { + $entified_tweet = mb_substr($entified_tweet, 0, $k).$v.mb_substr($entified_tweet, $k + strlen($keys[$k])); + } + $replacements = array( + 'replacements' => $replacements, + 'keys' => $keys + ); + + mb_internal_encoding($encoding); + return $entified_tweet; + } + + /** + * Returns the current URL. This is instead of PHP_SELF which is unsafe + * + * @param bool $dropqs whether to drop the querystring or not. Default true + * @return string the current URL + */ + public static function php_self($dropqs=true) { + $protocol = 'http'; + if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') { + $protocol = 'https'; + } elseif (isset($_SERVER['SERVER_PORT']) && ($_SERVER['SERVER_PORT'] == '443')) { + $protocol = 'https'; + } + + $url = sprintf('%s://%s%s', + $protocol, + $_SERVER['SERVER_NAME'], + $_SERVER['REQUEST_URI'] + ); + + $parts = parse_url($url); + + $port = $_SERVER['SERVER_PORT']; + $scheme = $parts['scheme']; + $host = $parts['host']; + $path = @$parts['path']; + $qs = @$parts['query']; + + $port or $port = ($scheme == 'https') ? '443' : '80'; + + if (($scheme == 'https' && $port != '443') + || ($scheme == 'http' && $port != '80')) { + $host = "$host:$port"; + } + $url = "$scheme://$host$path"; + if ( ! $dropqs) + return "{$url}?{$qs}"; + else + return $url; + } + + public static function is_cli() { + return (PHP_SAPI == 'cli' && empty($_SERVER['REMOTE_ADDR'])); + } + + /** + * Debug function for printing the content of an object + * + * @param mixes $obj + */ + public static function pr($obj) { + + if (!self::is_cli()) + echo '
';
+    if ( is_object($obj) )
+      print_r($obj);
+    elseif ( is_array($obj) )
+      print_r($obj);
+    else
+      echo $obj;
+    if (!self::is_cli())
+      echo '
'; + } + + /** + * Make an HTTP request using this library. This method is different to 'request' + * because on a 401 error it will retry the request. + * + * When a 401 error is returned it is possible the timestamp of the client is + * too different to that of the API server. In this situation it is recommended + * the request is retried with the OAuth timestamp set to the same as the API + * server. This method will automatically try that technique. + * + * This method doesn't return anything. Instead the response should be + * inspected directly. + * + * @param string $method the HTTP method being used. e.g. POST, GET, HEAD etc + * @param string $url the request URL without query string parameters + * @param array $params the request parameters as an array of key=value pairs + * @param string $useauth whether to use authentication when making the request. Default true. + * @param string $multipart whether this request contains multipart data. Default false + */ + public static function auto_fix_time_request($tmhOAuth, $method, $url, $params=array(), $useauth=true, $multipart=false) { + $tmhOAuth->request($method, $url, $params, $useauth, $multipart); + + // if we're not doing auth the timestamp isn't important + if ( ! $useauth) + return; + + // some error that isn't a 401 + if ($tmhOAuth->response['code'] != 401) + return; + + // some error that is a 401 but isn't because the OAuth token and signature are incorrect + // TODO: this check is horrid but helps avoid requesting twice when the username and password are wrong + if (stripos($tmhOAuth->response['response'], 'password') !== false) + return; + + // force the timestamp to be the same as the Twitter servers, and re-request + $tmhOAuth->auto_fixed_time = true; + $tmhOAuth->config['force_timestamp'] = true; + $tmhOAuth->config['timestamp'] = strtotime($tmhOAuth->response['headers']['date']); + return $tmhOAuth->request($method, $url, $params, $useauth, $multipart); + } + + /** + * Asks the user for input and returns the line they enter + * + * @param string $prompt the text to display to the user + * @return the text entered by the user + */ + public static function read_input($prompt) { + echo $prompt; + $handle = fopen("php://stdin","r"); + $data = fgets($handle); + return trim($data); + } + + /** + * Get a password from the shell. + * + * This function works on *nix systems only and requires shell_exec and stty. + * + * @param boolean $stars Wether or not to output stars for given characters + * @return string + * @url http://www.dasprids.de/blog/2008/08/22/getting-a-password-hidden-from-stdin-with-php-cli + */ + public static function read_password($prompt, $stars=false) { + echo $prompt; + $style = shell_exec('stty -g'); + + if ($stars === false) { + shell_exec('stty -echo'); + $password = rtrim(fgets(STDIN), "\n"); + } else { + shell_exec('stty -icanon -echo min 1 time 0'); + $password = ''; + while (true) : + $char = fgetc(STDIN); + if ($char === "\n") : + break; + elseif (ord($char) === 127) : + if (strlen($password) > 0) { + fwrite(STDOUT, "\x08 \x08"); + $password = substr($password, 0, -1); + } + else + fwrite(STDOUT, "*"); + $password .= $char; + endif; + endwhile; + } + + // Reset + shell_exec('stty ' . $style); + echo PHP_EOL; + return $password; + } + + /** + * Check if one string ends with another + * + * @param string $haystack the string to check inside of + * @param string $needle the string to check $haystack ends with + * @return true if $haystack ends with $needle, false otherwise + */ + public static function endswith($haystack, $needle) { + $haylen = strlen($haystack); + $needlelen = strlen($needle); + if ($needlelen > $haylen) + return false; + + return substr_compare($haystack, $needle, -$needlelen) === 0; + } +} \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/templates/BadBrowser.html b/rainloop/v/1.2.5.406/app/templates/BadBrowser.html new file mode 100644 index 000000000..b3be59f05 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/templates/BadBrowser.html @@ -0,0 +1,67 @@ + + + + + + + {{ErrorTitle}} + + + +
+ {{ErrorHeader}} +
+
+
+ {{ErrorDesc}} +
+ +
+ + \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/templates/Error.html b/rainloop/v/1.2.5.406/app/templates/Error.html new file mode 100644 index 000000000..3c9bf20bc --- /dev/null +++ b/rainloop/v/1.2.5.406/app/templates/Error.html @@ -0,0 +1,53 @@ + + + + + + + {{ErrorTitle}} + + + +
+ {{ErrorHeader}} +
+
+
+ {{ErrorDesc}} +
+
+
+ {{BackLink}} +
+
+ + \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/templates/Index.html b/rainloop/v/1.2.5.406/app/templates/Index.html new file mode 100644 index 000000000..7f947d914 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/templates/Index.html @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + +
RainLoop
+
+
+
+
+
+
+
+
+
+
+ + {{BaseTemplates}} + + +
+ + diff --git a/rainloop/v/1.2.5.406/app/templates/Themes/custom-values-dark.less b/rainloop/v/1.2.5.406/app/templates/Themes/custom-values-dark.less new file mode 100644 index 000000000..0b4733c28 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/templates/Themes/custom-values-dark.less @@ -0,0 +1,56 @@ + +// MAIN +@main-color: #333; +@main-background-color: #48525C; +@main-background-image: link; + +// LOADING +@loading-color: #ddd; +@loading-text-shadow: 0px 1px 0px rgba(0, 0, 0, 0.5); + +// LOGIN +@login-color: #eee; +@login-background-color: #2b333d; +@login-rgba-background-color: rgba(0,0,0,0.5); +@login-box-shadow: 0px 2px 10px rgba(0,0,0,0.5); +@login-border: none; +@login-border-radius: 7px; + +// MENU +@dropdown-menu-color: #333; +@dropdown-menu-background-color: #fff; +@dropdown-menu-hover-background-color: #48525C; +@dropdown-menu-hover-color: #eee; +@dropdown-menu-disable-color: #999; + +// FOLDERS +@folders-color: #fff; +@folders-disabled-color: #aaa; +@folders-selected-color: #fff; +@folders-selected-background-color: #2b333d; +@folders-selected-rgba-background-color: rgba(0,0,0,0.5); +@folders-hover-color: #fff; +@folders-hover-background-color: #2b333d; +@folders-hover-rgba-background-color: rgba(0,0,0,0.5); +@folders-drop-color: #fff; +@folders-drop-background-color: #2b333d; +@folders-drop-rgba-background-color: rgba(0,0,0,0.5); + +// SETTINGS +@settings-menu-color: #fff; +@settings-menu-disabled-color: #aaa; +@settings-menu-selected-color: #fff; +@settings-menu-selected-background-color: #2b333d; +@settings-menu-selected-rgba-background-color: rgba(0,0,0,0.5); +@settings-menu-hover-color: #fff; +@settings-menu-hover-background-color: #2b333d; +@settings-menu-hover-rgba-background-color: rgba(0,0,0,0.5); + +// MESSAGE LIST +@message-list-toolbar-background-color: #eee; +@message-list-toolbar-gradient-start: #f4f4f4; +@message-list-toolbar-gradient-end: #dfdfdf; + +// MESSAGE +@message-background-color: #fff; +@message-rgba-background-color: rgba(255,255,255,0.95); diff --git a/rainloop/v/1.2.5.406/app/templates/Themes/custom-values-light.less b/rainloop/v/1.2.5.406/app/templates/Themes/custom-values-light.less new file mode 100644 index 000000000..0061e6e61 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/templates/Themes/custom-values-light.less @@ -0,0 +1,55 @@ + +// MAIN +@main-color: #333; +@main-background-color: #eee; +@main-background-image: link; + +// LOADING +@loading-color: #000; + +// LOGIN +@login-color: #eee; +@login-background-color: #757575; +@login-rgba-background-color: rgba(0,0,0,0.5); +@login-box-shadow: none; +@login-border: none; +@login-border-radius: 7px; + +// MENU +@dropdown-menu-color: #333; +@dropdown-menu-background-color: #fff; +@dropdown-menu-hover-background-color: #757575; +@dropdown-menu-hover-color: #eee; +@dropdown-menu-disable-color: #999; + +// FOLDERS +@folders-color: #000; +@folders-disabled-color: #999; +@folders-selected-color: #eee; +@folders-selected-background-color: #757575; +@folders-selected-rgba-background-color: rgba(0,0,0,0.5); +@folders-hover-color: #eee; +@folders-hover-background-color: #757575; +@folders-hover-rgba-background-color: rgba(0,0,0,0.5); +@folders-drop-color: #eee; +@folders-drop-background-color: #757575; +@folders-drop-rgba-background-color: rgba(0,0,0,0.5); + +// SETTINGS +@settings-menu-color: #000; +@settings-menu-disabled-color: #999; +@settings-menu-selected-color: #eee; +@settings-menu-selected-background-color: #757575; +@settings-menu-selected-rgba-background-color: rgba(0,0,0,0.5); +@settings-menu-hover-color: #eee; +@settings-menu-hover-background-color: #757575; +@settings-menu-hover-rgba-background-color: rgba(0,0,0,0.5); + +// MESSAGE LIST +@message-list-toolbar-background-color: #eee; +@message-list-toolbar-gradient-start: #f4f4f4; +@message-list-toolbar-gradient-end: #dfdfdf; + +// MESSAGE +@message-background-color: #fff; +@message-rgba-background-color: rgba(255,255,255,0.95); \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/templates/Themes/template.less b/rainloop/v/1.2.5.406/app/templates/Themes/template.less new file mode 100644 index 000000000..28c1ade36 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/templates/Themes/template.less @@ -0,0 +1,148 @@ + +// mixins +++ +.thm-linear-gradient-mixin(@start, @end) when (iscolor(@start)) and (iscolor(@end)) { + background-color: mix(@start, @end, 60%) !important; + background-image: -moz-linear-gradient(top, @start, @end) !important; // FF 3.6+ + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@start), to(@end)) !important; // Safari 4+, Chrome 2+ + background-image: -webkit-linear-gradient(top, @start, @end) !important; // Safari 5.1+, Chrome 10+ + background-image: -o-linear-gradient(top, @start, @end !important); // Opera 11.10 + background-image: linear-gradient(to bottom, @start, @end) !important; // Standard, IE10 + background-repeat: repeat-x !important; + filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start),argb(@end))) !important; // IE9 and down +} + +.thm-border-radius(@radius) when (ispixel(@radius)) { + -webkit-border-radius: @radius !important; + -moz-border-radius: @radius !important; + border-radius: @radius !important; +} + +.thm-box-shadow(@shadow) { + -webkit-box-shadow: @shadow !important; + -moz-box-shadow: @shadow !important; + box-shadow: @shadow !important; +} +.thm-body-background-image(@value) when (isstring(@value)) { + background-image: url("@{base}@{value}") !important; +} +.thm-body-background-image(@value) when not (isstring(@value)) { + background-image: @value !important; +} +.thm-rgba-background-color(@simple, @rgba) when (@rgba = false) { + background-color: @simple !important; +} +.thm-rgba-background-color(@simple, @rgba) when not (@rgba = false) { + background-color: @simple !important; + background-color: @rgba !important; +} +// --- mixins + +.thm-body { + color: @main-color; + background-color: @main-background-color; + .thm-body-background-image(@main-background-image); +} + +.thm-loading { + color: @loading-color !important; + text-shadow: @loading-text-shadow !important; +} + +.thm-login { + color: @login-color !important; + border: @login-border !important; + .thm-rgba-background-color(@login-background-color, @login-rgba-background-color); + .thm-linear-gradient-mixin(@login-gradient-start, @login-gradient-end); + .thm-border-radius(@login-border-radius); + .thm-box-shadow(@login-box-shadow); + + .legend, .checkboxSignMe { + color: @login-color !important; + } +} + +.g-ui-menu { + color: @dropdown-menu-color !important; + background-color: @dropdown-menu-background-color !important; +} + +.g-ui-menu .e-item > .e-link { + color: @dropdown-menu-color !important; + background-color: @dropdown-menu-background-color !important; + + > i { + color: @dropdown-menu-color !important; + } +} + +.g-ui-menu .e-item > .e-link:hover { + color: @dropdown-menu-hover-color !important; + background-color: @dropdown-menu-hover-background-color !important; + + > i { + color: @dropdown-menu-hover-color !important; + } +} + +.g-ui-menu .e-item.disable > .e-link, .g-ui-menu .e-item.disable > .e-link:hover { + color: @dropdown-menu-disable-color !important; + background-color: @dropdown-menu-background-color !important; + + > i { + color: @dropdown-menu-disable-color !important; + } +} + +.thm-message-list-top-toolbar, .thm-message-list-bottom-toolbar { + .thm-rgba-background-color(@message-list-toolbar-background-color, @message-list-toolbar-rgba-background-color); + .thm-linear-gradient-mixin(@message-list-toolbar-gradient-start, @message-list-toolbar-gradient-end); +} + +.thm-folders .e-link { + + color: @folders-disabled-color !important; + + &.selectable { + color: @folders-color !important; + } + + &.selectable:hover { + color: @folders-hover-color !important; + .thm-rgba-background-color(@folders-hover-background-color, @folders-hover-rgba-background-color); + } + + &.selectable.selected { + color: @folders-selected-color !important; + .thm-rgba-background-color(@folders-selected-background-color, @folders-selected-rgba-background-color); + } + + &.selectable.droppableHover { + color: @folders-drop-color !important; + .thm-rgba-background-color(@folders-drop-background-color, @folders-drop-rgba-background-color); + } +} + +.thm-settings-menu .e-item { + + .e-link { + color: @settings-menu-disabled-color !important; + } + + &.selectable .e-link { + color: @settings-menu-color !important; + } + + &.selectable:hover .e-link { + .thm-rgba-background-color(@settings-menu-hover-background-color, @settings-menu-hover-rgba-background-color); + color: @settings-menu-hover-color !important; + } + + &.selectable.selected .e-link { + .thm-rgba-background-color(@settings-menu-selected-background-color, @settings-menu-selected-rgba-background-color); + color: @settings-menu-selected-color !important; + } +} + +.thm-message-view-background-color { + .thm-rgba-background-color(@message-background-color, @message-rgba-background-color); +} diff --git a/rainloop/v/1.2.5.406/app/templates/Themes/values.less b/rainloop/v/1.2.5.406/app/templates/Themes/values.less new file mode 100644 index 000000000..090756782 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/templates/Themes/values.less @@ -0,0 +1,59 @@ + +// MAIN +@main-color: #333; +@main-background-color: #e3e3e3; +@main-background-image: none; // "images/background.png" + +// LOADING +@loading-color: #000; // #ddd +@loading-text-shadow: none; // 0px 1px 0px rgba(0, 0, 0, 0.5); + +// LOGIN +@login-color: #555; +@login-background-color: #eee; +@login-rgba-background-color: false; // rgba(0,0,0,0.7) +@login-box-shadow: none; // 0px 2px 10px rgba(0,0,0,0.5) +@login-border: 1px solid #ccc; +@login-border-radius: 7px; +@login-gradient-start: none; // #f4f4f4 +@login-gradient-end: none; // #dfdfdf + +// MENU +@dropdown-menu-color: #333; +@dropdown-menu-background-color: #fff; +@dropdown-menu-hover-background-color: #444; +@dropdown-menu-hover-color: #eee; +@dropdown-menu-disable-color: #999; + +// FOLDERS +@folders-color: #333; +@folders-disabled-color: #666; +@folders-selected-color: #eee; +@folders-selected-background-color: #333; +@folders-selected-rgba-background-color: false; +@folders-hover-color: #eee; +@folders-hover-background-color: #333; +@folders-hover-rgba-background-color: false; +@folders-drop-color: #eee; +@folders-drop-background-color: #333; +@folders-drop-rgba-background-color: false; + +// SETTINGS +@settings-menu-color: #333; +@settings-menu-disabled-color: #666; +@settings-menu-selected-color: #eee; +@settings-menu-selected-background-color: #333; +@settings-menu-selected-rgba-background-color: false; +@settings-menu-hover-color: #eee; +@settings-menu-hover-background-color: #333; +@settings-menu-hover-rgba-background-color: false; + +// MESSAGE LIST +@message-list-toolbar-background-color: #eee; +@message-list-toolbar-rgba-background-color: false; +@message-list-toolbar-gradient-start: none; // #f4f4f4 +@message-list-toolbar-gradient-end: none; // #dfdfdf + +// MESSAGE +@message-background-color: #fff; +@message-rgba-background-color: false; diff --git a/rainloop/v/1.2.5.406/app/templates/Views/AdminDomainListItem.html b/rainloop/v/1.2.5.406/app/templates/Views/AdminDomainListItem.html new file mode 100644 index 000000000..804041246 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/templates/Views/AdminDomainListItem.html @@ -0,0 +1,20 @@ + + + + + + + Are you sure? + + + + + + + + + + + + + \ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/templates/Views/AdminDomains.html b/rainloop/v/1.2.5.406/app/templates/Views/AdminDomains.html new file mode 100644 index 000000000..5735d6e78 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/templates/Views/AdminDomains.html @@ -0,0 +1,31 @@ +
+
+ Domains +
+
+
+

+ List of domains webmail is allowed to access. +

+
+ + +    + Add Domain + +
+ +    + loading... +
+ + + + + + + + +
+
+
\ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/templates/Views/AdminGeneral.html b/rainloop/v/1.2.5.406/app/templates/Views/AdminGeneral.html new file mode 100644 index 000000000..b732f22e2 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/templates/Views/AdminGeneral.html @@ -0,0 +1,56 @@ +
+
+
+ General +
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+
+ + +
+
+
+
+
+
+

Notice!

+
+ Contacts functions are not supported. +
+ You need to install or enable PDO (sqlite) exstenstion on your server. +
+
+
\ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/templates/Views/AdminLicensing.html b/rainloop/v/1.2.5.406/app/templates/Views/AdminLicensing.html new file mode 100644 index 000000000..e4c1331ec --- /dev/null +++ b/rainloop/v/1.2.5.406/app/templates/Views/AdminLicensing.html @@ -0,0 +1,60 @@ +
+
+
+ RainLoop Webmail is licensed under Creative Commons Attribution-NonCommercial 3.0 (CC BY-NC 3.0) license. +
+ You are free to use it for your personal or non-profit projects. +
+
+ Commercial use of RainLoop Webmail requires getting a permission. +
+
+
+
+ +
+ + + +
+
+
+
+
+ +    + checking... +
+
+
+ This domain isn't licensed for commercial use. +
+
+
+

+ This domain is licensed for commercial use +

+

+ Subscription expires: +   + +

+
+
+
+
+
+
+
+
+ +
+
+
+
\ No newline at end of file diff --git a/rainloop/v/1.2.5.406/app/templates/Views/AdminLogin.html b/rainloop/v/1.2.5.406/app/templates/Views/AdminLogin.html new file mode 100644 index 000000000..b781617e8 --- /dev/null +++ b/rainloop/v/1.2.5.406/app/templates/Views/AdminLogin.html @@ -0,0 +1,35 @@ +